Add static_use to shader variable info query.

BUG=249018
ANGLEBUG=465
R=kbr@chromium.org

Review URL: https://codereview.appspot.com/13158043
diff --git a/include/GLSLANG/ShaderLang.h b/include/GLSLANG/ShaderLang.h
index b9a056f..24a0b7c 100644
--- a/include/GLSLANG/ShaderLang.h
+++ b/include/GLSLANG/ShaderLang.h
@@ -37,7 +37,7 @@
 
 // Version number for shader translation API.
 // It is incremented everytime the API changes.
-#define ANGLE_SH_VERSION 111
+#define ANGLE_SH_VERSION 112
 
 //
 // The names of the following enums have been derived by replacing GL prefix
@@ -378,6 +378,10 @@
 // size: Returns the size of the variable.
 // type: Returns the data type of the variable.
 // precision: Returns the precision of the variable.
+// staticUse: Returns 1 if the variable is accessed in a statement after
+//            pre-processing, whether or not run-time flow of control will
+//            cause that statement to be executed.
+//            Returns 0 otherwise.
 // name: Returns a null terminated string containing the name of the
 //       variable. It is assumed that name has enough memory to accormodate
 //       the variable name. The size of the buffer required to store the
@@ -396,6 +400,7 @@
                                        int* size,
                                        ShDataType* type,
                                        ShPrecisionType* precision,
+                                       int* staticUse,
                                        char* name,
                                        char* mappedName);
 
diff --git a/src/common/version.h b/src/common/version.h
index 1688acf..bb8d7c7 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -1,7 +1,7 @@
 #define MAJOR_VERSION 1
 #define MINOR_VERSION 2
 #define BUILD_VERSION 0
-#define BUILD_REVISION 2440
+#define BUILD_REVISION 2441
 
 #define STRINGIFY(x) #x
 #define MACRO_STRINGIFY(x) STRINGIFY(x)
diff --git a/src/compiler/Compiler.cpp b/src/compiler/Compiler.cpp
index c2f1a54..4866fcc 100644
--- a/src/compiler/Compiler.cpp
+++ b/src/compiler/Compiler.cpp
@@ -271,6 +271,7 @@
 
     attribs.clear();
     uniforms.clear();
+    varyings.clear();
 
     builtInFunctionEmulator.Cleanup();
 
diff --git a/src/compiler/ShaderLang.cpp b/src/compiler/ShaderLang.cpp
index 7cafa34..c673fe2 100644
--- a/src/compiler/ShaderLang.cpp
+++ b/src/compiler/ShaderLang.cpp
@@ -248,10 +248,11 @@
                        int* size,
                        ShDataType* type,
                        ShPrecisionType* precision,
+                       int* staticUse,
                        char* name,
                        char* mappedName)
 {
-    if (!handle || !size || !type || !name)
+    if (!handle || !size || !type || !precision || !staticUse || !name)
         return;
     ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
            (varType == SH_ACTIVE_UNIFORMS) ||
@@ -288,6 +289,7 @@
         *precision = SH_PRECISION_UNDEFINED;
         break;
     }
+    *staticUse = varInfo.staticUse ? 1 : 0;
 
     // This size must match that queried by
     // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH
diff --git a/src/compiler/VariableInfo.cpp b/src/compiler/VariableInfo.cpp
index 4aaa948..f3f7b1e 100644
--- a/src/compiler/VariableInfo.cpp
+++ b/src/compiler/VariableInfo.cpp
@@ -6,15 +6,17 @@
 
 #include "compiler/VariableInfo.h"
 
-static TString arrayBrackets(int index)
+namespace {
+
+TString arrayBrackets(int index)
 {
     TStringStream stream;
     stream << "[" << index << "]";
     return stream.str();
 }
 
-// Returns the data type for an attribute or uniform.
-static ShDataType getVariableDataType(const TType& type)
+// Returns the data type for an attribute, uniform, or varying.
+ShDataType getVariableDataType(const TType& type)
 {
     switch (type.getBasicType()) {
       case EbtFloat:
@@ -70,22 +72,22 @@
     return SH_NONE;
 }
 
-static void getBuiltInVariableInfo(const TType& type,
-                                   const TString& name,
-                                   const TString& mappedName,
-                                   TVariableInfoList& infoList);
-static void getUserDefinedVariableInfo(const TType& type,
-                                       const TString& name,
-                                       const TString& mappedName,
-                                       TVariableInfoList& infoList,
-                                       ShHashFunction64 hashFunction);
-
-// Returns info for an attribute or uniform.
-static void getVariableInfo(const TType& type,
+void getBuiltInVariableInfo(const TType& type,
                             const TString& name,
                             const TString& mappedName,
-                            TVariableInfoList& infoList,
-                            ShHashFunction64 hashFunction)
+                            TVariableInfoList& infoList);
+void getUserDefinedVariableInfo(const TType& type,
+                                const TString& name,
+                                const TString& mappedName,
+                                TVariableInfoList& infoList,
+                                ShHashFunction64 hashFunction);
+
+// Returns info for an attribute, uniform, or varying.
+void getVariableInfo(const TType& type,
+                     const TString& name,
+                     const TString& mappedName,
+                     TVariableInfoList& infoList,
+                     ShHashFunction64 hashFunction)
 {
     if (type.getBasicType() == EbtStruct) {
         if (type.isArray()) {
@@ -144,13 +146,37 @@
     }
 }
 
+TVariableInfo* findVariable(const TType& type,
+                            const TString& name,
+                            TVariableInfoList& infoList)
+{
+    // TODO(zmo): optimize this function.
+    TString myName = name;
+    if (type.isArray())
+        myName += "[0]";
+    for (size_t ii = 0; ii < infoList.size(); ++ii)
+    {
+        if (infoList[ii].name.c_str() == myName)
+            return &(infoList[ii]);
+    }
+    return NULL;
+}
+
+}  // namespace anonymous
+
 TVariableInfo::TVariableInfo()
+    : type(SH_NONE),
+      size(0),
+      precision(EbpUndefined),
+      staticUse(false)
 {
 }
 
 TVariableInfo::TVariableInfo(ShDataType type, int size)
     : type(type),
-      size(size)
+      size(size),
+      precision(EbpUndefined),
+      staticUse(false)
 {
 }
 
@@ -161,44 +187,85 @@
     : mAttribs(attribs),
       mUniforms(uniforms),
       mVaryings(varyings),
+      mPointCoordAdded(false),
+      mFrontFacingAdded(false),
+      mFragCoordAdded(false),
       mHashFunction(hashFunction)
 {
 }
 
-// We are only interested in attribute and uniform variable declaration.
-void CollectVariables::visitSymbol(TIntermSymbol*)
+// We want to check whether a uniform/varying is statically used
+// because we only count the used ones in packing computing.
+// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
+// toward varying counting if they are statically used in a fragment
+// shader.
+void CollectVariables::visitSymbol(TIntermSymbol* symbol)
 {
-}
-
-void CollectVariables::visitConstantUnion(TIntermConstantUnion*)
-{
-}
-
-bool CollectVariables::visitBinary(Visit, TIntermBinary*)
-{
-    return false;
-}
-
-bool CollectVariables::visitUnary(Visit, TIntermUnary*)
-{
-    return false;
-}
-
-bool CollectVariables::visitSelection(Visit, TIntermSelection*)
-{
-    return false;
+    ASSERT(symbol != NULL);
+    TVariableInfo* var = NULL;
+    switch (symbol->getQualifier())
+    {
+    case EvqVaryingOut:
+    case EvqInvariantVaryingOut:
+    case EvqVaryingIn:
+    case EvqInvariantVaryingIn:
+        var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
+        break;
+    case EvqUniform:
+        var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
+        break;
+    case EvqFragCoord:
+        if (!mFragCoordAdded) {
+            TVariableInfo info;
+            info.name = "gl_FragCoord";
+            info.mappedName = "gl_FragCoord";
+            info.type = SH_FLOAT_VEC4;
+            info.size = 1;
+            info.precision = EbpMedium;  // Use mediump as it doesn't really matter.
+            info.staticUse = true;
+	    mVaryings.push_back(info);
+            mFragCoordAdded = true;
+        }
+        return;
+    case EvqFrontFacing:
+        if (!mFrontFacingAdded) {
+            TVariableInfo info;
+            info.name = "gl_FrontFacing";
+            info.mappedName = "gl_FrontFacing";
+            info.type = SH_BOOL;
+            info.size = 1;
+            info.precision = EbpUndefined;
+            info.staticUse = true;
+	    mVaryings.push_back(info);
+            mFrontFacingAdded = true;
+        }
+        return;
+    case EvqPointCoord:
+        if (!mPointCoordAdded) {
+            TVariableInfo info;
+            info.name = "gl_PointCoord";
+            info.mappedName = "gl_PointCoord";
+            info.type = SH_FLOAT_VEC2;
+            info.size = 1;
+            info.precision = EbpMedium;  // Use mediump as it doesn't really matter.
+            info.staticUse = true;
+	    mVaryings.push_back(info);
+            mPointCoordAdded = true;
+        }
+        return;
+    default:
+        break;
+    }
+    if (var)
+        var->staticUse = true;
 }
 
 bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
 {
-    bool visitChildren = false;
+    bool visitChildren = true;
 
     switch (node->getOp())
     {
-    case EOpSequence:
-        // We need to visit sequence children to get to variable declarations.
-        visitChildren = true;
-        break;
     case EOpDeclaration: {
         const TIntermSequence& sequence = node->getSequence();
         TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
@@ -214,9 +281,9 @@
                 const TIntermSymbol* variable = (*i)->getAsSymbolNode();
                 // The only case in which the sequence will not contain a
                 // TIntermSymbol node is initialization. It will contain a
-                // TInterBinary node in that case. Since attributes and unifroms
-                // cannot be initialized in a shader, we must have only
-                // TIntermSymbol nodes in the sequence.
+                // TInterBinary node in that case. Since attributes, uniforms,
+                // and varyings cannot be initialized in a shader, we must have
+                // only TIntermSymbol nodes in the sequence.
                 ASSERT(variable != NULL);
                 TString processedSymbol;
                 if (mHashFunction == NULL)
@@ -228,6 +295,7 @@
                                 processedSymbol,
                                 infoList,
                                 mHashFunction);
+                visitChildren = false;
             }
         }
         break;
@@ -238,13 +306,3 @@
     return visitChildren;
 }
 
-bool CollectVariables::visitLoop(Visit, TIntermLoop*)
-{
-    return false;
-}
-
-bool CollectVariables::visitBranch(Visit, TIntermBranch*)
-{
-    return false;
-}
-
diff --git a/src/compiler/VariableInfo.h b/src/compiler/VariableInfo.h
index bef196d..3c7f2a5 100644
--- a/src/compiler/VariableInfo.h
+++ b/src/compiler/VariableInfo.h
@@ -21,6 +21,7 @@
     ShDataType type;
     int size;
     TPrecision precision;
+    bool staticUse;
 };
 typedef std::vector<TVariableInfo> TVariableInfoList;
 
@@ -33,19 +34,17 @@
                      ShHashFunction64 hashFunction);
 
     virtual void visitSymbol(TIntermSymbol*);
-    virtual void visitConstantUnion(TIntermConstantUnion*);
-    virtual bool visitBinary(Visit, TIntermBinary*);
-    virtual bool visitUnary(Visit, TIntermUnary*);
-    virtual bool visitSelection(Visit, TIntermSelection*);
     virtual bool visitAggregate(Visit, TIntermAggregate*);
-    virtual bool visitLoop(Visit, TIntermLoop*);
-    virtual bool visitBranch(Visit, TIntermBranch*);
 
 private:
     TVariableInfoList& mAttribs;
     TVariableInfoList& mUniforms;
     TVariableInfoList& mVaryings;
 
+    bool mPointCoordAdded;
+    bool mFrontFacingAdded;
+    bool mFragCoordAdded;
+
     ShHashFunction64 mHashFunction;
 };