Revert 2289. GLSL version detection not robust enough. May think we don't have GLSL 1.50 support based on OpenGL version. We have to look at the available extensions, not just GL version.




git-svn-id: http://skia.googlecode.com/svn/trunk@2290 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrGLProgram.cpp b/gpu/src/GrGLProgram.cpp
index 07a2e04..0efb99f 100644
--- a/gpu/src/GrGLProgram.cpp
+++ b/gpu/src/GrGLProgram.cpp
@@ -9,8 +9,8 @@
 
 #include "GrGLProgram.h"
 
-#include "GrAllocator.h"
-#include "GrGLShaderVar.h"
+#include "GrGLConfig.h"
+
 #include "SkTrace.h"
 #include "SkXfermode.h"
 
@@ -36,32 +36,6 @@
 
 #define PRINT_SHADERS 0
 
-typedef GrTAllocator<GrGLShaderVar> VarArray;
-
-// number of each input/output type in a single allocation block
-static const int gVarsPerBlock = 8;
-// except FS outputs where we expect 2 at most.
-static const int gMaxFSOutputs = 2;
-
-struct ShaderCodeSegments {
-    ShaderCodeSegments() 
-    : fVSUnis(gVarsPerBlock)
-    , fVSAttrs(gVarsPerBlock)
-    , fVaryings(gVarsPerBlock)
-    , fFSUnis(gVarsPerBlock)
-    , fFSOutputs(gMaxFSOutputs) {}
-    GrStringBuilder fHeader; // VS+FS, GLSL version, etc
-    VarArray        fVSUnis;
-    VarArray        fVSAttrs;
-    VarArray        fVaryings;
-    VarArray        fFSUnis;
-    VarArray        fFSOutputs;
-    GrStringBuilder fFSFunctions;
-    GrStringBuilder fVSCode;
-    GrStringBuilder fFSCode;
-};
-
-
 #if GR_GL_ATTRIBUTE_MATRICES
     #define VIEW_MATRIX_NAME "aViewM"
 #else
@@ -75,61 +49,53 @@
 #define EDGES_UNI_NAME "uEdges"
 #define COL_FILTER_UNI_NAME "uColorFilter"
 
-namespace {
-inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
+static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
     *s = "aTexCoord";
     s->appendS32(coordIdx);
 }
 
-inline GrGLShaderVar::Type float_vector_type(int count) {
-    GR_STATIC_ASSERT(GrGLShaderVar::kFloat_Type == 0);
-    GR_STATIC_ASSERT(GrGLShaderVar::kVec2f_Type == 1);
-    GR_STATIC_ASSERT(GrGLShaderVar::kVec3f_Type == 2);
-    GR_STATIC_ASSERT(GrGLShaderVar::kVec4f_Type == 3);
-    GrAssert(count > 0 && count <= 4);
-    return (GrGLShaderVar::Type)(count - 1);
+static inline const char* float_vector_type(int count) {
+    static const char* FLOAT_VECS[] = {"ERROR", "float", "vec2", "vec3", "vec4"};
+    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(FLOAT_VECS));
+    return FLOAT_VECS[count];
 }
 
-inline const char* float_vector_type_str(int count) {
-    return GrGLShaderVar::TypeString(float_vector_type(count));
-}
-
-inline const char* vector_homog_coord(int count) {
+static inline const char* vector_homog_coord(int count) {
     static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
     GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS));
     return HOMOGS[count];
 }
 
-inline const char* vector_nonhomog_coords(int count) {
+static inline const char* vector_nonhomog_coords(int count) {
     static const char* NONHOMOGS[] = {"ERROR", "", ".x", ".xy", ".xyz"};
     GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(NONHOMOGS));
     return NONHOMOGS[count];
 }
 
-inline const char* vector_all_coords(int count) {
+static inline const char* vector_all_coords(int count) {
     static const char* ALL[] = {"ERROR", "", ".xy", ".xyz", ".xyzw"};
     GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ALL));
     return ALL[count];
 }
 
-inline const char* all_ones_vec(int count) {
+static inline const char* all_ones_vec(int count) {
     static const char* ONESVEC[] = {"ERROR", "1.0", "vec2(1,1)",
                                     "vec3(1,1,1)", "vec4(1,1,1,1)"};
     GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ONESVEC));
     return ONESVEC[count];
 }
 
-inline const char* all_zeros_vec(int count) {
+static inline const char* all_zeros_vec(int count) {
     static const char* ZEROSVEC[] = {"ERROR", "0.0", "vec2(0,0)",
                                     "vec3(0,0,0)", "vec4(0,0,0,0)"};
     GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ZEROSVEC));
     return ZEROSVEC[count];
 }
 
-inline const char* declared_color_output_name() { return "fsColorOut"; }
-inline const char* dual_source_output_name() { return "dualSourceOut"; }
+static inline const char* declared_color_output_name() { return "fsColorOut"; }
+static inline const char* dual_source_output_name() { return "dualSourceOut"; }
 
-inline void tex_matrix_name(int stage, GrStringBuilder* s) {
+static void tex_matrix_name(int stage, GrStringBuilder* s) {
 #if GR_GL_ATTRIBUTE_MATRICES
     *s = "aTexM";
 #else
@@ -138,43 +104,42 @@
     s->appendS32(stage);
 }
 
-inline void normalized_texel_size_name(int stage, GrStringBuilder* s) {
+static void normalized_texel_size_name(int stage, GrStringBuilder* s) {
     *s = "uTexelSize";
     s->appendS32(stage);
 }
 
-inline void sampler_name(int stage, GrStringBuilder* s) {
+static void sampler_name(int stage, GrStringBuilder* s) {
     *s = "uSampler";
     s->appendS32(stage);
 }
 
-inline void stage_varying_name(int stage, GrStringBuilder* s) {
+static void stage_varying_name(int stage, GrStringBuilder* s) {
     *s = "vStage";
     s->appendS32(stage);
 }
 
-inline void radial2_param_name(int stage, GrStringBuilder* s) {
+static void radial2_param_name(int stage, GrStringBuilder* s) {
     *s = "uRadial2Params";
     s->appendS32(stage);
 }
 
-inline void radial2_varying_name(int stage, GrStringBuilder* s) {
+static void radial2_varying_name(int stage, GrStringBuilder* s) {
     *s = "vB";
     s->appendS32(stage);
 }
 
-inline void convolve_param_names(int stage, GrStringBuilder* k, GrStringBuilder* i) {
+static void convolve_param_names(int stage, GrStringBuilder* k, GrStringBuilder* i) {
     *k = "uKernel";
     k->appendS32(stage);
     *i = "uImageIncrement";
     i->appendS32(stage);
 }
 
-inline void tex_domain_name(int stage, GrStringBuilder* s) {
+static void tex_domain_name(int stage, GrStringBuilder* s) {
     *s = "uTexDom";
     s->appendS32(stage);
 }
-}
 
 GrGLProgram::GrGLProgram() {
 }
@@ -356,39 +321,15 @@
     add_helper(outputVar, colorStr.c_str(), constStr.c_str(), fsCode);
 }
 
-namespace {
-
-const char* glsl_version_string(const GrGLInterface* gl,
-                                GrGLProgram::GLSLVersion v) {
-    switch (v) {
-        case GrGLProgram::k120_GLSLVersion:
-            if (gl->supportsES()) {
-                // ES2s shader language is based on version 1.20 but is version
-                // 1.00 of the ES language.
-                return "#version 100\n";
-            } else {
-                return "#version 120\n";
-            }
-        case GrGLProgram::k150_GLSLVersion:
-            GrAssert(!gl->supportsES());
-            return "#version 150\n";
-        default:
-            GrCrash("Unknown GL version.");
-            return ""; // suppress warning
-    }
-}
-
-}
-
 void GrGLProgram::genEdgeCoverage(const GrGLInterface* gl,
                                   GrVertexLayout layout,
                                   CachedData* programData,
                                   GrStringBuilder* coverageVar,
                                   ShaderCodeSegments* segments) const {
     if (fProgramDesc.fEdgeAANumEdges > 0) {
-        segments->fFSUnis.push_back().set(GrGLShaderVar::kVec3f_Type,
-                                          EDGES_UNI_NAME,
-                                          fProgramDesc.fEdgeAANumEdges);
+        segments->fFSUnis.append("uniform vec3 " EDGES_UNI_NAME "[");
+        segments->fFSUnis.appendS32(fProgramDesc.fEdgeAANumEdges);
+        segments->fFSUnis.append("];\n");
         programData->fUniLocations.fEdgesUni = kUseUniform;
         int count = fProgramDesc.fEdgeAANumEdges;
         segments->fFSCode.append(
@@ -435,8 +376,8 @@
         }
         *coverageVar = "edgeAlpha";
     } else  if (layout & GrDrawTarget::kEdge_VertexLayoutBit) {
-        segments->fVaryings.push_back().set(GrGLShaderVar::kVec4f_Type, "vEdge");
-        segments->fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type, EDGE_ATTR_NAME);
+        segments->fVSAttrs.append("attribute vec4 " EDGE_ATTR_NAME ";\n");
+        segments->fVaryings.append("varying vec4 vEdge;\n");
         segments->fVSCode.append("\tvEdge = " EDGE_ATTR_NAME ";\n");
         if (GrDrawTarget::kHairLine_EdgeType == fProgramDesc.fVertexEdgeType) {
             segments->fFSCode.append("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), vEdge.xyz));\n");
@@ -461,33 +402,7 @@
     }
 }
 
-namespace {
-
-// returns true if the color output was explicitly declared or not.
-bool decl_and_get_fs_color_output(GrGLProgram::GLSLVersion v,
-                                  VarArray* fsOutputs,
-                                  const char** name) {
-    switch (v) {
-        case GrGLProgram::k120_GLSLVersion:
-            *name = "gl_FragColor";
-            return false;
-            break;
-        case GrGLProgram::k150_GLSLVersion:
-            *name = declared_color_output_name();
-            fsOutputs->push_back().set(GrGLShaderVar::kVec4f_Type,
-                                       declared_color_output_name());
-            return true;
-            break;
-        default:
-            GrCrash("Unknown GLSL version.");
-            return false; // suppress warning
-    }
-}
-
-}
-
-bool GrGLProgram::genProgram(const GrGLInterface* gl,
-                             GLSLVersion glslVersion,
+bool GrGLProgram::genProgram(const GrGLInterface* gl, 
                              GrGLProgram::CachedData* programData) const {
 
     ShaderCodeSegments segments;
@@ -517,19 +432,25 @@
     // declare an output, which is incompatible with gl_FragColor/gl_FragData.
     const char* fsColorOutput;
     bool dualSourceOutputWritten = false;
-    segments.fHeader.printf(glsl_version_string(gl, glslVersion));
-    bool isColorDeclared = decl_and_get_fs_color_output(glslVersion,
-                                                        &segments.fFSOutputs,
-                                                        &fsColorOutput);
+    bool usingDeclaredOutputs = ProgramDesc::kNone_DualSrcOutput !=
+                                fProgramDesc.fDualSrcOutput;
+    if (usingDeclaredOutputs) {
+        GrAssert(0 == segments.fHeader.size());
+        segments.fHeader.printf("#version 150\n");
+        fsColorOutput = declared_color_output_name();
+        segments.fFSOutputs.appendf("out vec4 %s;\n", fsColorOutput);
+    } else {
+        fsColorOutput = "gl_FragColor";
+    }
 
 #if GR_GL_ATTRIBUTE_MATRICES
-    segments.fVSAttrs.push_back().set(GrGLShaderVar::kMat33f_Type, VIEW_MATRIX_NAME);
+    segments.fVSAttrs += "attribute mat3 " VIEW_MATRIX_NAME ";\n";
     programData->fUniLocations.fViewMatrixUni = kSetAsAttribute;
 #else
-    segments.fVSUnis.push_back().set(GrGLShaderVar::kMat33f_Type, VIEW_MATRIX_NAME);
+    segments.fVSUnis  += "uniform mat3 " VIEW_MATRIX_NAME ";\n";
     programData->fUniLocations.fViewMatrixUni = kUseUniform;
 #endif
-    segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec2f_Type, POS_ATTR_NAME);
+    segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n";
 
     segments.fVSCode.append(
         "void main() {\n"
@@ -542,16 +463,13 @@
     if (needComputedColor) {
         switch (fProgramDesc.fColorType) {
             case ProgramDesc::kAttribute_ColorType:
-                segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
-                                                  COL_ATTR_NAME);
-                segments.fVaryings.push_back().set(GrGLShaderVar::kVec4f_Type,
-                                                   "vColor");
-                segments.fVSCode.append("\tvColor = " COL_ATTR_NAME ";\n");
+                segments.fVSAttrs.append( "attribute vec4 " COL_ATTR_NAME ";\n");
+                segments.fVaryings.append("varying vec4 vColor;\n");
+                segments.fVSCode.append(    "\tvColor = " COL_ATTR_NAME ";\n");
                 inColor = "vColor";
                 break;
             case ProgramDesc::kUniform_ColorType:
-                segments.fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
-                                                 COL_UNI_NAME);
+                segments.fFSUnis.append(  "uniform vec4 " COL_UNI_NAME ";\n");
                 programData->fUniLocations.fColorUni = kUseUniform;
                 inColor = COL_UNI_NAME;
                 break;
@@ -572,8 +490,7 @@
     for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) {
         if (GrDrawTarget::VertexUsesTexCoordIdx(t, layout)) {
             tex_attr_name(t, texCoordAttrs + t);
-            segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec2f_Type,
-                                              texCoordAttrs[t].c_str());
+            segments.fVSAttrs.appendf("attribute vec2 %s;\n", texCoordAttrs[t].c_str());
         }
     }
 
@@ -604,8 +521,7 @@
                     inCoords = texCoordAttrs[tcIdx].c_str();
                 }
 
-                genStageCode(gl,
-                             s,
+                genStageCode(gl, s,
                              fProgramDesc.fStages[s],
                              inColor.size() ? inColor.c_str() : NULL,
                              outColor.c_str(),
@@ -628,8 +544,7 @@
                           &needColorFilterUniform, &bogus);
     }
     if (needColorFilterUniform) {
-        segments.fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
-                                         COL_FILTER_UNI_NAME);
+        segments.fFSUnis.append(  "uniform vec4 " COL_FILTER_UNI_NAME ";\n");
         programData->fUniLocations.fColorFilterUni = kUseUniform;
     }
 
@@ -693,8 +608,8 @@
             }
         }
         if (ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
-            segments.fFSOutputs.push_back().set(GrGLShaderVar::kVec4f_Type,
-                                                dual_source_output_name());
+            segments.fFSOutputs.appendf("out vec4 %s;\n",
+                                        dual_source_output_name());
             bool outputIsZero = false;
             GrStringBuilder coeff;
             if (ProgramDesc::kCoverage_DualSrcOutput !=
@@ -729,9 +644,9 @@
 
     if (!wroteFragColorZero) {
         modulate_helper(fsColorOutput,
-                        inColor.c_str(),
-                        inCoverage.c_str(),
-                        &segments.fFSCode);
+                         inColor.c_str(),
+                         inCoverage.c_str(),
+                         &segments.fFSCode);
     }
 
     segments.fVSCode.append("}\n");
@@ -740,12 +655,12 @@
     ///////////////////////////////////////////////////////////////////////////
     // compile and setup attribs and unis
 
-    if (!CompileFSAndVS(gl, glslVersion, segments, programData)) {
+    if (!CompileFSAndVS(gl, segments, programData)) {
         return false;
     }
 
     if (!this->bindOutputsAttribsAndLinkProgram(gl, texCoordAttrs,
-                                                isColorDeclared,
+                                                usingDeclaredOutputs,
                                                 dualSourceOutputWritten,
                                                 programData)) {
         return false;
@@ -756,36 +671,7 @@
     return true;
 }
 
-namespace {
-
-void expand_decls(const VarArray& unis,
-                  const GrGLInterface* gl,
-                  const char* prefix,
-                  GrStringBuilder* string) {
-    const int count = unis.count();
-    for (int i = 0; i < count; ++i) {
-        string->append(prefix);
-        string->append(" ");
-        unis[i].appendDecl(gl, string);
-        string->append(";\n");
-    }
-}
-
-void print_shader(int stringCnt,
-                  const char** strings,
-                  int* stringLengths) {
-    for (int i = 0; i < stringCnt; ++i) {
-        if (NULL == stringLengths || stringLengths[i] < 0) {
-            GrPrintf(strings[i]);
-        } else {
-            GrPrintf("%.*s", stringLengths[i], strings[i]);
-        }
-    }
-}
-}
-
 bool GrGLProgram::CompileFSAndVS(const GrGLInterface* gl,
-                                 GLSLVersion glslVersion,
                                  const ShaderCodeSegments& segments,
                                  CachedData* programData) {
 
@@ -793,41 +679,25 @@
     const char* strings[MAX_STRINGS];
     int lengths[MAX_STRINGS];
     int stringCnt = 0;
-    GrStringBuilder attrs;
-    GrStringBuilder varyings;
-    GrStringBuilder unis;
-    GrStringBuilder fsOutputs;
-
-    static const char* gVaryingPrefixes[2][2] = {{"varying", "varying"},
-                                                 {"out", "in"}};
-    const char** varyingPrefixes = glslVersion == k120_GLSLVersion ?
-                                                    gVaryingPrefixes[0] :
-                                                    gVaryingPrefixes[1];
-    const char* attributePrefix = glslVersion == k120_GLSLVersion ?
-                                                    "attribute" :
-                                                    "in";
 
     if (segments.fHeader.size()) {
         strings[stringCnt] = segments.fHeader.c_str();
         lengths[stringCnt] = segments.fHeader.size();
         ++stringCnt;
     }
-    expand_decls(segments.fVSUnis, gl, "uniform", &unis);
-    if (unis.size()) {
-        strings[stringCnt] = unis.c_str();
-        lengths[stringCnt] = unis.size();
+    if (segments.fVSUnis.size()) {
+        strings[stringCnt] = segments.fVSUnis.c_str();
+        lengths[stringCnt] = segments.fVSUnis.size();
         ++stringCnt;
     }
-    expand_decls(segments.fVSAttrs, gl, attributePrefix, &attrs);
-    if (attrs.size()) {
-        strings[stringCnt] = attrs.c_str();
-        lengths[stringCnt] = attrs.size();
+    if (segments.fVSAttrs.size()) {
+        strings[stringCnt] = segments.fVSAttrs.c_str();
+        lengths[stringCnt] = segments.fVSAttrs.size();
         ++stringCnt;
     }
-    expand_decls(segments.fVaryings, gl, varyingPrefixes[0], &varyings);
-    if (varyings.size()) {
-        strings[stringCnt] = varyings.c_str();
-        lengths[stringCnt] = varyings.size();
+    if (segments.fVaryings.size()) {
+        strings[stringCnt] = segments.fVaryings.c_str();
+        lengths[stringCnt] = segments.fVaryings.size();
         ++stringCnt;
     }
 
@@ -837,10 +707,13 @@
     ++stringCnt;
 
 #if PRINT_SHADERS
-    print_shader(stringCnt, strings, lengths);
+    GrPrintf(segments.fHeader.c_str());
+    GrPrintf(segments.fVSUnis.c_str());
+    GrPrintf(segments.fVSAttrs.c_str());
+    GrPrintf(segments.fVaryings.c_str());
+    GrPrintf(segments.fVSCode.c_str());
     GrPrintf("\n");
 #endif
-
     GrAssert(stringCnt <= MAX_STRINGS);
     programData->fVShaderID = CompileShader(gl, GR_GL_VERTEX_SHADER,
                                             stringCnt, strings, lengths);
@@ -861,26 +734,19 @@
         lengths[stringCnt] = strlen(GrShaderPrecision(gl));
         ++stringCnt;
     }
-    unis.reset();
-    expand_decls(segments.fFSUnis, gl, "uniform", &unis);
-    if (unis.size()) {
-        strings[stringCnt] = unis.c_str();
-        lengths[stringCnt] = unis.size();
+    if (segments.fFSUnis.size()) {
+        strings[stringCnt] = segments.fFSUnis.c_str();
+        lengths[stringCnt] = segments.fFSUnis.size();
         ++stringCnt;
     }
-    varyings.reset();
-    expand_decls(segments.fVaryings, gl, varyingPrefixes[1], &varyings);
-    if (varyings.size()) {
-        strings[stringCnt] = varyings.c_str();
-        lengths[stringCnt] = varyings.size();
+    if (segments.fVaryings.size()) {
+        strings[stringCnt] = segments.fVaryings.c_str();
+        lengths[stringCnt] = segments.fVaryings.size();
         ++stringCnt;
     }
-    expand_decls(segments.fFSOutputs, gl, "out", &fsOutputs);
-    if (fsOutputs.size()) {
-        // We shouldn't have declared outputs on 1.2
-        GrAssert(k120_GLSLVersion != glslVersion);
-        strings[stringCnt] = fsOutputs.c_str();
-        lengths[stringCnt] = fsOutputs.size();
+    if (segments.fFSOutputs.size()) {
+        strings[stringCnt] = segments.fFSOutputs.c_str();
+        lengths[stringCnt] = segments.fFSOutputs.size();
         ++stringCnt;
     }
     if (segments.fFSFunctions.size()) {
@@ -895,10 +761,15 @@
     ++stringCnt;
 
 #if PRINT_SHADERS
-    print_shader(stringCnt, strings, lengths);
+    GrPrintf(segments.fHeader.c_str());
+    GrPrintf(GrShaderPrecision(gl));
+    GrPrintf(segments.fFSUnis.c_str());
+    GrPrintf(segments.fVaryings.c_str());
+    GrPrintf(segments.fFSOutputs.c_str());
+    GrPrintf(segments.fFSFunctions.c_str());
+    GrPrintf(segments.fFSCode.c_str());
     GrPrintf("\n");
 #endif
-
     GrAssert(stringCnt <= MAX_STRINGS);
     programData->fFShaderID = CompileShader(gl, GR_GL_FRAGMENT_SHADER,
                                             stringCnt, strings, lengths);
@@ -939,7 +810,13 @@
             GrGLsizei length = GR_GL_INIT_ZERO;
             GR_GL_CALL(gl, GetShaderInfoLog(shader, infoLen+1, 
                                             &length, (char*)log.get()));
-            print_shader(stringCnt, strings, stringLengths);
+            for (int i = 0; i < stringCnt; ++i) {
+                if (NULL == stringLengths || stringLengths[i] < 0) {
+                    GrPrintf(strings[i]);
+                } else {
+                    GrPrintf("%.*s", stringLengths[i], strings[i]);
+                }
+            }
             GrPrintf("\n%s", log.get());
         }
         GrAssert(!"Shader compilation failed!");
@@ -1150,6 +1027,9 @@
 
     GrAssert(stageNum >= 0 && stageNum <= 9);
 
+    GrStringBuilder varyingName;
+    stage_varying_name(stageNum, &varyingName);
+
     // First decide how many coords are needed to access the texture
     // Right now it's always 2 but we could start using 1D textures for
     // gradients.
@@ -1159,22 +1039,18 @@
 
     // decide whether we need a matrix to transform texture coords
     // and whether the varying needs a perspective coord.
-    const char* matName = NULL;
+    GrStringBuilder texMName;
+    tex_matrix_name(stageNum, &texMName);
     if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
         varyingDims = coordDims;
     } else {
-        GrGLShaderVar* mat;
     #if GR_GL_ATTRIBUTE_MATRICES
-        mat = &segments->fVSAttrs.push_back();
+        segments->fVSAttrs.appendf("attribute mat3 %s;\n", texMName.c_str());
         locations->fTextureMatrixUni = kSetAsAttribute;
     #else
-        mat = &segments->fVSUnis.push_back();
+        segments->fVSUnis.appendf("uniform mat3 %s;\n", texMName.c_str());
         locations->fTextureMatrixUni = kUseUniform;
     #endif
-        tex_matrix_name(stageNum, mat->accessName());
-        mat->setType(GrGLShaderVar::kMat33f_Type);
-        matName = mat->getName().c_str();
-
         if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
             varyingDims = coordDims;
         } else {
@@ -1182,93 +1058,75 @@
         }
     }
 
-    segments->fFSUnis.push_back().setType(GrGLShaderVar::kSampler2D_Type);
-    sampler_name(stageNum, segments->fFSUnis.back().accessName());
+    GrStringBuilder samplerName;
+    sampler_name(stageNum, &samplerName);
+    segments->fFSUnis.appendf("uniform sampler2D %s;\n", samplerName.c_str());
     locations->fSamplerUni = kUseUniform;
-    const char* samplerName = segments->fFSUnis.back().getName().c_str();
 
-    const char* texelSizeName = NULL;
+    GrStringBuilder texelSizeName;
     if (StageDesc::k2x2_FetchMode == desc.fFetchMode) {
-        segments->fFSUnis.push_back().setType(GrGLShaderVar::kVec2f_Type);
-        normalized_texel_size_name(stageNum, segments->fFSUnis.back().accessName());
-        texelSizeName = segments->fFSUnis.back().getName().c_str();
+        normalized_texel_size_name(stageNum, &texelSizeName);
+        segments->fFSUnis.appendf("uniform vec2 %s;\n", texelSizeName.c_str());
     }
 
-    const char* varyingName;
-    GrGLShaderVar* varying = &segments->fVaryings.push_back();
-    stage_varying_name(stageNum, varying->accessName());
-    varying->setType(float_vector_type(varyingDims));
-    varyingName = varying->getName().c_str();
+    segments->fVaryings.appendf("varying %s %s;\n",
+                                float_vector_type(varyingDims), varyingName.c_str());
 
-    if (!matName) {
+    if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
         GrAssert(varyingDims == coordDims);
-        segments->fVSCode.appendf("\t%s = %s;\n", varyingName, vsInCoord);
+        segments->fVSCode.appendf("\t%s = %s;\n", varyingName.c_str(), vsInCoord);
     } else {
         // varying = texMatrix * texCoord
         segments->fVSCode.appendf("\t%s = (%s * vec3(%s, 1))%s;\n",
-                                  varyingName, matName, vsInCoord,
-                                  vector_all_coords(varyingDims));
+                                  varyingName.c_str(), texMName.c_str(),
+                                  vsInCoord, vector_all_coords(varyingDims));
     }
 
-    const char* radial2ParamsName = NULL;
-    const char* radial2VaryingName = NULL;
+    GrStringBuilder radial2ParamsName;
+    radial2_param_name(stageNum, &radial2ParamsName);
+    // for radial grads without perspective we can pass the linear
+    // part of the quadratic as a varying.
+    GrStringBuilder radial2VaryingName;
+    radial2_varying_name(stageNum, &radial2VaryingName);
 
-    if (StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping ||
+    if (StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping || 
         StageDesc::kRadial2GradientDegenerate_CoordMapping == desc.fCoordMapping) {
 
-        GrGLShaderVar* radial2FSParams = &segments->fFSUnis.push_back();
-        radial2FSParams->setType(GrGLShaderVar::kFloat_Type);
-        radial2FSParams->setArrayCount(6);
-        radial2_param_name(stageNum, radial2FSParams->accessName());
-        segments->fVSUnis.push_back(*radial2FSParams).setEmitPrecision(true);
-        radial2ParamsName = radial2FSParams->getName().c_str();
-
+        segments->fVSUnis.appendf("uniform %s float %s[6];\n",
+                                  GrPrecision(gl), radial2ParamsName.c_str());
+        segments->fFSUnis.appendf("uniform float %s[6];\n",
+                                  radial2ParamsName.c_str());
         locations->fRadial2Uni = kUseUniform;
 
-        // for radial grads without perspective we can pass the linear
-        // part of the quadratic as a varying.
+        // if there is perspective we don't interpolate this
         if (varyingDims == coordDims) {
             GrAssert(2 == coordDims);
-
-            GrGLShaderVar* radial2Varying = &segments->fVaryings.push_back();
-            radial2Varying->setType(GrGLShaderVar::kFloat_Type);
-            radial2_varying_name(stageNum, radial2Varying->accessName());
-            radial2VaryingName = radial2Varying->getName().c_str();
+            segments->fVaryings.appendf("varying float %s;\n", radial2VaryingName.c_str());
 
             // r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3])
-            const char* r2ParamName = radial2FSParams->getName().c_str();
-            const char* r2VarName = radial2Varying->getName().c_str();
             segments->fVSCode.appendf("\t%s = 2.0 *(%s[2] * %s.x - %s[3]);\n",
-                                      r2VarName, r2ParamName, varyingName,
-                                      r2ParamName);
+                                      radial2VaryingName.c_str(), radial2ParamsName.c_str(),
+                                      varyingName.c_str(), radial2ParamsName.c_str());
         }
     }
 
-    const char* kernelName = NULL;
-    const char* imageIncrementName = NULL;
+    GrStringBuilder kernelName, kernelWidthName, imageIncrementName;
+    convolve_param_names(stageNum, &kernelName, &imageIncrementName);
+
     if (ProgramDesc::StageDesc::kConvolution_FetchMode == desc.fFetchMode) {
-
-        GrGLShaderVar* kernel = &segments->fFSUnis.push_back();
-        kernel->setType(GrGLShaderVar::kFloat_Type);
-        kernel->setArrayCount(desc.fKernelWidth);
-        GrGLShaderVar* imgInc = &segments->fFSUnis.push_back();
-        imgInc->setType(GrGLShaderVar::kVec2f_Type);
-
-        convolve_param_names(stageNum,
-                             kernel->accessName(),
-                             imgInc->accessName());
-        kernelName = kernel->getName().c_str();
-        imageIncrementName = imgInc->getName().c_str();
-
-        // need image increment in both VS and FS
-        segments->fVSUnis.push_back(*imgInc).setEmitPrecision(true);
-
+        segments->fFSUnis.appendf("uniform float %s[%d];\n",
+                                  kernelName.c_str(), desc.fKernelWidth);
+        segments->fFSUnis.appendf("uniform vec2 %s;\n",
+                                  imageIncrementName.c_str());
+        segments->fVSUnis.appendf("uniform %s vec2 %s;\n",
+                                  GrPrecision(gl),
+                                  imageIncrementName.c_str());
         locations->fKernelUni = kUseUniform;
         locations->fImageIncrementUni = kUseUniform;
         float scale = (desc.fKernelWidth - 1) * 0.5f;
         segments->fVSCode.appendf("\t%s -= vec2(%g, %g) * %s;\n",
-                                  varyingName, scale, scale,
-                                  imageIncrementName);
+                                  varyingName.c_str(), scale, scale,
+                                  imageIncrementName.c_str());
     }
 
     /// Fragment Shader Stuff
@@ -1291,12 +1149,12 @@
             fsCoordName = "inCoord";
             fsCoordName.appendS32(stageNum);
             segments->fFSCode.appendf("\t%s %s = %s%s / %s%s;\n",
-                                GrGLShaderVar::TypeString(float_vector_type(coordDims)),
-                                fsCoordName.c_str(),
-                                varyingName,
-                                vector_nonhomog_coords(varyingDims),
-                                varyingName,
-                                vector_homog_coord(varyingDims));
+                                       float_vector_type(coordDims),
+                                       fsCoordName.c_str(),
+                                       varyingName.c_str(),
+                                       vector_nonhomog_coords(varyingDims),
+                                       varyingName.c_str(),
+                                       vector_homog_coord(varyingDims));
         }
     }
 
@@ -1334,18 +1192,18 @@
             bVar = "b";
             bVar.appendS32(stageNum);
             segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s[2] * %s.x - %s[3]);\n",
-                                        bVar.c_str(), radial2ParamsName,
-                                        fsCoordName.c_str(), radial2ParamsName);
+                                        bVar.c_str(), radial2ParamsName.c_str(),
+                                        fsCoordName.c_str(), radial2ParamsName.c_str());
         }
 
         // c = (x^2)+(y^2) - params[4]
         segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s[4];\n",
                                   cName.c_str(), fsCoordName.c_str(),
                                   fsCoordName.c_str(),
-                                  radial2ParamsName);
+                                  radial2ParamsName.c_str());
         // ac4 = 4.0 * params[0] * c
         segments->fFSCode.appendf("\tfloat %s = %s[0] * 4.0 * %s;\n",
-                                  ac4Name.c_str(), radial2ParamsName,
+                                  ac4Name.c_str(), radial2ParamsName.c_str(),
                                   cName.c_str());
 
         // root = sqrt(b^2-4ac)
@@ -1357,8 +1215,8 @@
         // x coord is: (-b + params[5] * sqrt(b^2-4ac)) * params[1]
         // y coord is 0.5 (texture is effectively 1D)
         sampleCoords.printf("vec2((-%s + %s[5] * %s) * %s[1], 0.5)",
-                            bVar.c_str(), radial2ParamsName,
-                            rootName.c_str(), radial2ParamsName);
+                            bVar.c_str(), radial2ParamsName.c_str(),
+                            rootName.c_str(), radial2ParamsName.c_str());
         complexCoord = true;
         break;}
     case StageDesc::kRadial2GradientDegenerate_CoordMapping: {
@@ -1377,15 +1235,15 @@
             bVar = "b";
             bVar.appendS32(stageNum);
             segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s[2] * %s.x - %s[3]);\n",
-                                        bVar.c_str(), radial2ParamsName,
-                                        fsCoordName.c_str(), radial2ParamsName);
+                                        bVar.c_str(), radial2ParamsName.c_str(),
+                                        fsCoordName.c_str(), radial2ParamsName.c_str());
         }
 
         // c = (x^2)+(y^2) - params[4]
         segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s[4];\n",
                                   cName.c_str(), fsCoordName.c_str(),
                                   fsCoordName.c_str(),
-                                  radial2ParamsName);
+                                  radial2ParamsName.c_str());
 
         // x coord is: -c/b
         // y coord is 0.5 (texture is effectively 1D)
@@ -1409,10 +1267,12 @@
         StageDesc::kCustomTextureDomain_OptFlagBit) {
         GrStringBuilder texDomainName;
         tex_domain_name(stageNum, &texDomainName);
-        segments->fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type, texDomainName);
+        segments->fFSUnis.appendf("uniform %s %s;\n",
+                                  float_vector_type(4),
+                                  texDomainName.c_str());
         GrStringBuilder coordVar("clampCoord");
         segments->fFSCode.appendf("\t%s %s = clamp(%s, %s.xy, %s.zw);\n",
-                                  float_vector_type_str(coordDims),
+                                  float_vector_type(coordDims),
                                   coordVar.c_str(),
                                   sampleCoords.c_str(),
                                   texDomainName.c_str(),
@@ -1428,17 +1288,17 @@
             GrStringBuilder coordVar("tCoord");
             coordVar.appendS32(stageNum);
             segments->fFSCode.appendf("\t%s %s = %s;\n",
-                                float_vector_type_str(coordDims),
-                                coordVar.c_str(), sampleCoords.c_str());
+                                      float_vector_type(coordDims),
+                                      coordVar.c_str(), sampleCoords.c_str());
             sampleCoords = coordVar;
         }
         GrAssert(2 == coordDims);
         GrStringBuilder accumVar("accum");
         accumVar.appendS32(stageNum);
-        segments->fFSCode.appendf("\tvec4 %s  = %s(%s, %s + vec2(-%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords.c_str(), texelSizeName, texelSizeName, smear);
-        segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords.c_str(), texelSizeName, texelSizeName, smear);
-        segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(-%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords.c_str(), texelSizeName, texelSizeName, smear);
-        segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords.c_str(), texelSizeName, texelSizeName, smear);
+        segments->fFSCode.appendf("\tvec4 %s  = %s(%s, %s + vec2(-%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), texelSizeName.c_str(), texelSizeName.c_str(), smear);
+        segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), texelSizeName.c_str(), texelSizeName.c_str(), smear);
+        segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(-%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), texelSizeName.c_str(), texelSizeName.c_str(), smear);
+        segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName.c_str(), sampleCoords.c_str(), texelSizeName.c_str(), texelSizeName.c_str(), smear);
         segments->fFSCode.appendf("\t%s = .25 * %s%s;\n", fsOutColor, accumVar.c_str(), modulate.c_str());
     } else if (ProgramDesc::StageDesc::kConvolution_FetchMode == desc.fFetchMode) {
         GrStringBuilder sumVar("sum");
@@ -1455,18 +1315,18 @@
                                   desc.fKernelWidth);
         segments->fFSCode.appendf("\t\t%s += %s(%s, %s)%s * %s[i];\n",
                                   sumVar.c_str(), texFunc.c_str(),
-                                  samplerName, coordVar.c_str(), smear,
-                                  kernelName);
+                                  samplerName.c_str(), coordVar.c_str(), smear,
+                                  kernelName.c_str());
         segments->fFSCode.appendf("\t\t%s += %s;\n",
                                   coordVar.c_str(),
-                                  imageIncrementName);
+                                  imageIncrementName.c_str());
         segments->fFSCode.appendf("\t}\n");
         segments->fFSCode.appendf("\t%s = %s%s;\n", fsOutColor,
                                   sumVar.c_str(), modulate.c_str());
     } else {
         segments->fFSCode.appendf("\t%s = %s(%s, %s)%s%s;\n",
                                   fsOutColor, texFunc.c_str(), 
-                                  samplerName, sampleCoords.c_str(),
+                                  samplerName.c_str(), sampleCoords.c_str(),
                                   smear, modulate.c_str());
     }
 }