Make GrGLShaderVar objects aware of whether they are uniform, varying, or
attribute varibles. Extract GLSL generation enum and utility function into
new GrGLSL header.



git-svn-id: http://skia.googlecode.com/svn/trunk@2827 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrGLProgram.cpp b/src/gpu/GrGLProgram.cpp
index 9395c0e..b7e902d 100644
--- a/src/gpu/GrGLProgram.cpp
+++ b/src/gpu/GrGLProgram.cpp
@@ -369,9 +369,9 @@
 namespace {
 
 const char* glsl_version_string(const GrGLInterface* gl,
-                                GrGLProgram::GLSLVersion v) {
+                                GrGLSLGeneration v) {
     switch (v) {
-        case GrGLProgram::k110_GLSLVersion:
+        case k110_GLSLGeneration:
             if (gl->supportsES2()) {
                 // ES2s shader language is based on version 1.20 but is version
                 // 1.00 of the ES language.
@@ -379,10 +379,10 @@
             } else {
                 return "#version 110\n";
             }
-        case GrGLProgram::k130_GLSLVersion:
+        case k130_GLSLGeneration:
             GrAssert(!gl->supportsES2());
             return "#version 130\n";
-        case GrGLProgram::k150_GLSLVersion:
+        case k150_GLSLGeneration:
             GrAssert(!gl->supportsES2());
             return "#version 150\n";
         default:
@@ -400,6 +400,8 @@
                     const char** fsInName = NULL) {
     segments->fVSOutputs.push_back();
     segments->fVSOutputs.back().setType(type);
+    segments->fVSOutputs.back().setTypeModifier(
+        GrGLShaderVar::kOut_TypeModifier);
     segments->fVSOutputs.back().accessName()->printf("v%s", name);
     if (vsOutName) {
         *vsOutName = segments->fVSOutputs.back().getName().c_str();
@@ -411,11 +413,15 @@
         // and output as non-array.
         segments->fGSInputs.push_back();
         segments->fGSInputs.back().setType(type);
+        segments->fGSInputs.back().setTypeModifier(
+            GrGLShaderVar::kIn_TypeModifier);
         segments->fGSInputs.back().setUnsizedArray();
         *segments->fGSInputs.back().accessName() =
             segments->fVSOutputs.back().getName();
         segments->fGSOutputs.push_back();
         segments->fGSOutputs.back().setType(type);
+        segments->fGSOutputs.back().setTypeModifier(
+            GrGLShaderVar::kOut_TypeModifier);
         segments->fGSOutputs.back().accessName()->printf("g%s", name);
         fsName = segments->fGSOutputs.back().accessName();
     } else {
@@ -423,6 +429,8 @@
     }
     segments->fFSInputs.push_back();
     segments->fFSInputs.back().setType(type);
+    segments->fFSInputs.back().setTypeModifier(
+        GrGLShaderVar::kIn_TypeModifier);
     segments->fFSInputs.back().setName(*fsName);
     if (fsInName) {
         *fsInName = fsName->c_str();
@@ -450,6 +458,7 @@
                                   ShaderCodeSegments* segments) const {
     if (fProgramDesc.fEdgeAANumEdges > 0) {
         segments->fFSUnis.push_back().set(GrGLShaderVar::kVec3f_Type,
+                                          GrGLShaderVar::kUniform_TypeModifier,
                                           EDGES_UNI_NAME,
                                           fProgramDesc.fEdgeAANumEdges);
         programData->fUniLocations.fEdgesUni = kUseUniform;
@@ -499,8 +508,10 @@
         *coverageVar = "edgeAlpha";
     } else  if (layout & GrDrawTarget::kEdge_VertexLayoutBit) {
         const char *vsName, *fsName;
-        append_varying(GrGLShaderVar::kVec4f_Type, "Edge", segments, &vsName, &fsName);
-        segments->fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type, EDGE_ATTR_NAME);
+        append_varying(GrGLShaderVar::kVec4f_Type, "Edge", segments,
+            &vsName, &fsName);
+        segments->fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
+            GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME);
         segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
         if (GrDrawState::kHairLine_EdgeType == fProgramDesc.fVertexEdgeType) {
             segments->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), %s.xyz));\n", fsName);
@@ -528,18 +539,19 @@
 namespace {
 
 // returns true if the color output was explicitly declared or not.
-bool decl_and_get_fs_color_output(GrGLProgram::GLSLVersion v,
+bool decl_and_get_fs_color_output(GrGLSLGeneration v,
                                   VarArray* fsOutputs,
                                   const char** name) {
     switch (v) {
-        case GrGLProgram::k110_GLSLVersion:
+        case k110_GLSLGeneration:
             *name = "gl_FragColor";
             return false;
             break;
-        case GrGLProgram::k130_GLSLVersion: // fallthru
-        case GrGLProgram::k150_GLSLVersion:
+        case k130_GLSLGeneration: // fallthru
+        case k150_GLSLGeneration:
             *name = declared_color_output_name();
             fsOutputs->push_back().set(GrGLShaderVar::kVec4f_Type,
+                                       GrGLShaderVar::kOut_TypeModifier,
                                        declared_color_output_name());
             return true;
             break;
@@ -556,7 +568,8 @@
     switch (colorInput) {
         case GrGLProgram::ProgramDesc::kAttribute_ColorInput: {
             segments->fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
-                                               COL_ATTR_NAME);
+                GrGLShaderVar::kAttribute_TypeModifier,
+                COL_ATTR_NAME);
             const char *vsName, *fsName;
             append_varying(GrGLShaderVar::kVec4f_Type, "Color", segments, &vsName, &fsName);
             segments->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
@@ -564,7 +577,8 @@
             } break;
         case GrGLProgram::ProgramDesc::kUniform_ColorInput:
             segments->fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
-                                              COL_UNI_NAME);
+                GrGLShaderVar::kUniform_TypeModifier,
+                COL_UNI_NAME);
             programData->fUniLocations.fColorUni = kUseUniform;
             *inColor = COL_UNI_NAME;
             break;
@@ -582,6 +596,7 @@
 void genPerVertexCoverage(ShaderCodeSegments* segments,
                           GrStringBuilder* inCoverage) {
     segments->fVSAttrs.push_back().set(GrGLShaderVar::kFloat_Type,
+                                       GrGLShaderVar::kAttribute_TypeModifier,
                                        COV_ATTR_NAME);
     const char *vsName, *fsName;
     append_varying(GrGLShaderVar::kFloat_Type, "Coverage", 
@@ -599,11 +614,11 @@
 }
 
 void GrGLProgram::genGeometryShader(const GrGLInterface* gl,
-                                    GLSLVersion glslVersion,
+                                    GrGLSLGeneration glslGeneration,
                                     ShaderCodeSegments* segments) const {
 #if GR_GL_EXPERIMENTAL_GS
     if (fProgramDesc.fExperimentalGS) {
-        GrAssert(glslVersion >= k150_GLSLVersion);
+        GrAssert(glslGeneration >= k150_GLSLGeneration);
         segments->fGSHeader.append("layout(triangles) in;\n"
                                    "layout(triangle_strip, max_vertices = 6) out;\n");
         segments->fGSCode.append("void main() {\n"
@@ -628,7 +643,7 @@
 }
 
 bool GrGLProgram::genProgram(const GrGLInterface* gl,
-                             GLSLVersion glslVersion,
+                             GrGLSLGeneration glslGeneration,
                              GrGLProgram::CachedData* programData) const {
 
     ShaderCodeSegments segments;
@@ -676,19 +691,22 @@
     // declare an output, which is incompatible with gl_FragColor/gl_FragData.
     const char* fsColorOutput = NULL;
     bool dualSourceOutputWritten = false;
-    segments.fHeader.printf(glsl_version_string(gl, glslVersion));
-    bool isColorDeclared = decl_and_get_fs_color_output(glslVersion,
+    segments.fHeader.printf(glsl_version_string(gl, glslGeneration));
+    bool isColorDeclared = decl_and_get_fs_color_output(glslGeneration,
                                                         &segments.fFSOutputs,
                                                         &fsColorOutput);
 
 #if GR_GL_ATTRIBUTE_MATRICES
-    segments.fVSAttrs.push_back().set(GrGLShaderVar::kMat33f_Type, VIEW_MATRIX_NAME);
+    segments.fVSAttrs.push_back().set(GrGLShaderVar::kMat33f_Type,
+        GrGLShaderVar::kAttribute_TypeModifier, VIEW_MATRIX_NAME);
     programData->fUniLocations.fViewMatrixUni = kSetAsAttribute;
 #else
-    segments.fVSUnis.push_back().set(GrGLShaderVar::kMat33f_Type, VIEW_MATRIX_NAME);
+    segments.fVSUnis.push_back().set(GrGLShaderVar::kMat33f_Type,
+        GrGLShaderVar::kUniform_TypeModifier, VIEW_MATRIX_NAME);
     programData->fUniLocations.fViewMatrixUni = kUseUniform;
 #endif
-    segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec2f_Type, POS_ATTR_NAME);
+    segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec2f_Type,
+        GrGLShaderVar::kAttribute_TypeModifier, POS_ATTR_NAME);
 
     segments.fVSCode.append(
         "void main() {\n"
@@ -716,7 +734,8 @@
         if (GrDrawTarget::VertexUsesTexCoordIdx(t, layout)) {
             tex_attr_name(t, texCoordAttrs + t);
             segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec2f_Type,
-                                              texCoordAttrs[t].c_str());
+                GrGLShaderVar::kAttribute_TypeModifier,
+                texCoordAttrs[t].c_str());
         }
     }
 
@@ -775,6 +794,7 @@
     }
     if (needColorFilterUniform) {
         segments.fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
+                                         GrGLShaderVar::kUniform_TypeModifier,
                                          COL_FILTER_UNI_NAME);
         programData->fUniLocations.fColorFilterUni = kUseUniform;
     }
@@ -854,7 +874,8 @@
         }
         if (ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
             segments.fFSOutputs.push_back().set(GrGLShaderVar::kVec4f_Type,
-                                                dual_source_output_name());
+                GrGLShaderVar::kOut_TypeModifier,
+                dual_source_output_name());
             bool outputIsZero = false;
             GrStringBuilder coeff;
             if (ProgramDesc::kCoverage_DualSrcOutput !=
@@ -908,13 +929,13 @@
     ///////////////////////////////////////////////////////////////////////////
     // insert GS
 #if GR_DEBUG
-    this->genGeometryShader(gl, glslVersion, &segments);
+    this->genGeometryShader(gl, glslGeneration, &segments);
 #endif
 
     ///////////////////////////////////////////////////////////////////////////
     // compile and setup attribs and unis
 
-    if (!CompileShaders(gl, glslVersion, segments, programData)) {
+    if (!CompileShaders(gl, glslGeneration, segments, programData)) {
         return false;
     }
 
@@ -934,14 +955,11 @@
 
 inline void expand_decls(const VarArray& vars,
                          const GrGLInterface* gl,
-                         const char* prefix,
-                         GrStringBuilder* string) {
+                         GrStringBuilder* string,
+                         GrGLSLGeneration gen) {
     const int count = vars.count();
     for (int i = 0; i < count; ++i) {
-        string->append(prefix);
-        string->append(" ");
-        vars[i].appendDecl(gl, string);
-        string->append(";\n");
+        vars[i].appendDecl(gl, string, gen);
     }
 }
 
@@ -980,18 +998,18 @@
 
 inline void append_decls(const VarArray& vars,
                          const GrGLInterface* gl,
-                         const char* prefix,
                          StrArray* strings,
                          LengthArray* lengths,
-                         TempArray* temp) {
-    expand_decls(vars, gl, prefix, &temp->push_back());
+                         TempArray* temp,
+                         GrGLSLGeneration gen) {
+    expand_decls(vars, gl, &temp->push_back(), gen);
     append_string(temp->back(), strings, lengths);
 }
 
 }
 
 bool GrGLProgram::CompileShaders(const GrGLInterface* gl,
-                                 GLSLVersion glslVersion,
+                                 GrGLSLGeneration glslGeneration,
                                  const ShaderCodeSegments& segments,
                                  CachedData* programData) {
     enum { kPreAllocStringCnt = 8 };
@@ -1004,19 +1022,12 @@
     GrStringBuilder inputs;
     GrStringBuilder outputs;
 
-    static const char* gVaryingPrefixes[2][2] = {{"varying", "varying"},
-                                                 {"out", "in"}};
-    const char** varyingPrefixes = k110_GLSLVersion == glslVersion ?
-                                                    gVaryingPrefixes[0] :
-                                                    gVaryingPrefixes[1];
-    const char* attributePrefix = k110_GLSLVersion == glslVersion ?
-                                                    "attribute" :
-                                                    "in";
-
     append_string(segments.fHeader, &strs, &lengths);
-    append_decls(segments.fVSUnis, gl, "uniform", &strs, &lengths, &temps);
-    append_decls(segments.fVSAttrs, gl, attributePrefix, &strs, &lengths, &temps);
-    append_decls(segments.fVSOutputs, gl, varyingPrefixes[0], &strs, &lengths, &temps);
+    append_decls(segments.fVSUnis, gl, &strs, &lengths, &temps, glslGeneration);
+    append_decls(segments.fVSAttrs, gl, &strs, &lengths,
+                 &temps, glslGeneration);
+    append_decls(segments.fVSOutputs, gl, &strs, &lengths,
+                 &temps, glslGeneration);
     append_string(segments.fVSCode, &strs, &lengths);
 
 #if PRINT_SHADERS
@@ -1037,8 +1048,10 @@
         temps.reset();
         append_string(segments.fHeader, &strs, &lengths);
         append_string(segments.fGSHeader, &strs, &lengths);
-        append_decls(segments.fGSInputs, gl, "in", &strs, &lengths, &temps);
-        append_decls(segments.fGSOutputs, gl, "out", &strs, &lengths, &temps);
+        append_decls(segments.fGSInputs, gl, &strs, &lengths,
+                     &temps, glslGeneration);
+        append_decls(segments.fGSOutputs, gl, &strs, &lengths,
+                     &temps, glslGeneration);
         append_string(segments.fGSCode, &strs, &lengths);
 #if PRINT_SHADERS
         print_shader(strs.count(), &strs[0], &lengths[0]);
@@ -1058,11 +1071,14 @@
     append_string(segments.fHeader, &strs, &lengths);
     GrStringBuilder precisionStr(GrShaderPrecision(gl));
     append_string(precisionStr, &strs, &lengths);
-    append_decls(segments.fFSUnis, gl, "uniform", &strs, &lengths, &temps);
-    append_decls(segments.fFSInputs, gl, varyingPrefixes[1], &strs, &lengths, &temps);
+    append_decls(segments.fFSUnis, gl, &strs, &lengths, &temps, glslGeneration);
+    append_decls(segments.fFSInputs, gl, &strs, &lengths,
+                 &temps, glslGeneration);
     // We shouldn't have declared outputs on 1.10
-    GrAssert(k110_GLSLVersion != glslVersion || segments.fFSOutputs.empty());
-    append_decls(segments.fFSOutputs, gl, "out", &strs, &lengths, &temps);
+    GrAssert(k110_GLSLGeneration != glslGeneration ||
+             segments.fFSOutputs.empty());
+    append_decls(segments.fFSOutputs, gl, &strs, &lengths,
+                 &temps, glslGeneration);
     append_string(segments.fFSFunctions, &strs, &lengths);
     append_string(segments.fFSCode, &strs, &lengths);
 
@@ -1334,6 +1350,7 @@
 
     GrGLShaderVar* radial2FSParams = &segments->fFSUnis.push_back();
     radial2FSParams->setType(GrGLShaderVar::kFloat_Type);
+    radial2FSParams->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
     radial2FSParams->setArrayCount(6);
     radial2_param_name(stageNum, radial2FSParams->accessName());
     segments->fVSUnis.push_back(*radial2FSParams).setEmitPrecision(true);
@@ -1523,9 +1540,11 @@
     //GrGLShaderVar* kernel = &segments->fFSUnis.push_back();
     *kernel = &segments->fFSUnis.push_back();
     (*kernel)->setType(GrGLShaderVar::kFloat_Type);
+    (*kernel)->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
     (*kernel)->setArrayCount(desc.fKernelWidth);
     GrGLShaderVar* imgInc = &segments->fFSUnis.push_back();
     imgInc->setType(GrGLShaderVar::kVec2f_Type);
+    imgInc->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
 
     convolve_param_names(stageNum,
                          (*kernel)->accessName(),
@@ -1612,9 +1631,11 @@
         GrGLShaderVar* mat;
     #if GR_GL_ATTRIBUTE_MATRICES
         mat = &segments->fVSAttrs.push_back();
+        mat->setTypeModifier(GrGLShaderVar::kAttribute_TypeModifier);
         locations->fTextureMatrixUni = kSetAsAttribute;
     #else
         mat = &segments->fVSUnis.push_back();
+        mat->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
         locations->fTextureMatrixUni = kUseUniform;
     #endif
         tex_matrix_name(stageNum, mat->accessName());
@@ -1628,14 +1649,16 @@
         }
     }
 
-    segments->fFSUnis.push_back().setType(GrGLShaderVar::kSampler2D_Type);
+    segments->fFSUnis.push_back().set(GrGLShaderVar::kSampler2D_Type,
+        GrGLShaderVar::kUniform_TypeModifier, "");
     sampler_name(stageNum, segments->fFSUnis.back().accessName());
     locations->fSamplerUni = kUseUniform;
     const char* samplerName = segments->fFSUnis.back().getName().c_str();
 
     const char* texelSizeName = NULL;
     if (StageDesc::k2x2_FetchMode == desc.fFetchMode) {
-        segments->fFSUnis.push_back().setType(GrGLShaderVar::kVec2f_Type);
+        segments->fFSUnis.push_back().set(GrGLShaderVar::kVec2f_Type,
+            GrGLShaderVar::kUniform_TypeModifier, "");
         normalized_texel_size_name(stageNum, segments->fFSUnis.back().accessName());
         texelSizeName = segments->fFSUnis.back().getName().c_str();
     }
@@ -1758,7 +1781,8 @@
         StageDesc::kCustomTextureDomain_OptFlagBit) {
         GrStringBuilder texDomainName;
         tex_domain_name(stageNum, &texDomainName);
-        segments->fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type, texDomainName);
+        segments->fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
+            GrGLShaderVar::kUniform_TypeModifier, texDomainName);
         GrStringBuilder coordVar("clampCoord");
         segments->fFSCode.appendf("\t%s %s = clamp(%s, %s.xy, %s.zw);\n",
                                   float_vector_type_str(coordDims),