Remove uniform var pointers from custom effects

Review URL: http://codereview.appspot.com/6374067/



git-svn-id: http://skia.googlecode.com/svn/trunk@4616 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index d4e2a3e..1e15155 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -18,6 +18,10 @@
 class GrGLDiffuseLightingEffect;
 class GrGLSpecularLightingEffect;
 
+// For brevity, and these definitions are likely to move to a different class soon.
+typedef GrGLShaderBuilder::UniformHandle UniformHandle;
+static const UniformHandle kInvalidUniformHandle = GrGLShaderBuilder::kInvalidUniformHandle;
+
 // FIXME:  Eventually, this should be implemented properly, and put in
 // SkScalar.h.
 #define SkScalarPow(x, y) SkFloatToScalar(powf(SkScalarToFloat(x), SkScalarToFloat(y)))
@@ -359,20 +363,24 @@
 class GrGLLight {
 public:
     virtual ~GrGLLight() {}
-    virtual void setupVariables(GrGLShaderBuilder* state, int stage);
-    virtual void emitVS(SkString* builder) const {}
-    virtual void emitFuncs(SkString* builder) const {}
-    virtual void emitSurfaceToLight(SkString* builder, const char* z) const = 0;
-    virtual void emitLightColor(SkString* builder, const char *surfaceToLight) const;
-    virtual void initUniforms(const GrGLInterface* gl, int programID);
+    virtual void setupVariables(GrGLShaderBuilder* builder, int stage);
+    virtual void emitVS(SkString* out) const {}
+    virtual void emitFuncs(const GrGLShaderBuilder* builder, SkString* out) const {}
+    virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
+                                    SkString* out,
+                                    const char* z) const = 0;
+    virtual void emitLightColor(const GrGLShaderBuilder*,
+                                SkString* out,
+                                const char *surfaceToLight) const;
+    virtual void initUniforms(const GrGLShaderBuilder*, const GrGLInterface* gl, int programID);
     virtual void setData(const GrGLInterface*, const GrRenderTarget* rt, const SkLight* light) const;
 
 private:
     typedef SkRefCnt INHERITED;
 
 protected:
-    const GrGLShaderVar* fColorVar;
-    int fColorVarLocation;
+    UniformHandle fColorUni;
+    int fColorLocation;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -380,14 +388,18 @@
 class GrGLDistantLight : public GrGLLight {
 public:
     virtual ~GrGLDistantLight() {}
-    virtual void setupVariables(GrGLShaderBuilder* state, int stage) SK_OVERRIDE;
-    virtual void initUniforms(const GrGLInterface* gl, int programID) SK_OVERRIDE;
+    virtual void setupVariables(GrGLShaderBuilder* builder, int stage) SK_OVERRIDE;
+    virtual void initUniforms(const GrGLShaderBuilder*,
+                              const GrGLInterface* gl,
+                              int programID) SK_OVERRIDE;
     virtual void setData(const GrGLInterface* gl, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
-    virtual void emitSurfaceToLight(SkString* builder, const char* z) const SK_OVERRIDE;
+    virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
+                                    SkString* out,
+                                    const char* z) const SK_OVERRIDE;
 
 private:
     typedef GrGLLight INHERITED;
-    const GrGLShaderVar* fDirectionVar;
+    UniformHandle fDirectionUni;
     int fDirectionLocation;
 };
 
@@ -396,16 +408,20 @@
 class GrGLPointLight : public GrGLLight {
 public:
     virtual ~GrGLPointLight() {}
-    virtual void setupVariables(GrGLShaderBuilder* state, int stage);
-    virtual void initUniforms(const GrGLInterface* gl, int programID);
+    virtual void setupVariables(GrGLShaderBuilder* builder, int stage) SK_OVERRIDE;
+    virtual void initUniforms(const GrGLShaderBuilder*,
+                              const GrGLInterface*,
+                              int programID) SK_OVERRIDE;
     virtual void setData(const GrGLInterface* gl, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
-    virtual void emitVS(SkString* builder) const;
-    virtual void emitSurfaceToLight(SkString* builder, const char* z) const SK_OVERRIDE;
+    virtual void emitVS(SkString* out) const SK_OVERRIDE;
+    virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
+                                    SkString* out,
+                                    const char* z) const SK_OVERRIDE;
 
 private:
     typedef GrGLLight INHERITED;
     SkPoint3 fLocation;
-    const GrGLShaderVar* fLocationVar;
+    UniformHandle fLocationUni;
     int fLocationLocation;
 };
 
@@ -414,29 +430,35 @@
 class GrGLSpotLight : public GrGLLight {
 public:
     virtual ~GrGLSpotLight() {}
-    virtual void setupVariables(GrGLShaderBuilder* state, int stage);
-    virtual void initUniforms(const GrGLInterface* gl, int programID);
+    virtual void setupVariables(GrGLShaderBuilder* builder, int stage) SK_OVERRIDE;
+    virtual void initUniforms(const GrGLShaderBuilder* builder,
+                              const GrGLInterface* gl,
+                              int programID) SK_OVERRIDE;
     virtual void setData(const GrGLInterface* gl, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
-    virtual void emitVS(SkString* builder) const;
-    virtual void emitFuncs(SkString* builder) const;
-    virtual void emitSurfaceToLight(SkString* builder, const char* z) const SK_OVERRIDE;
-    virtual void emitLightColor(SkString* builder, const char *surfaceToLight) const;
+    virtual void emitVS(SkString* out) const SK_OVERRIDE;
+    virtual void emitFuncs(const GrGLShaderBuilder* builder, SkString* out) const;
+    virtual void emitSurfaceToLight(const GrGLShaderBuilder* builder,
+                                    SkString* out,
+                                    const char* z) const SK_OVERRIDE;
+    virtual void emitLightColor(const GrGLShaderBuilder*,
+                                SkString* out,
+                                const char *surfaceToLight) const SK_OVERRIDE;
 
 private:
     typedef GrGLLight INHERITED;
 
-    const GrGLShaderVar* fLocationVar;
-    int                  fLocationLocation;
-    const GrGLShaderVar* fExponentVar;
-    int                  fExponentLocation;
-    const GrGLShaderVar* fCosOuterConeAngleVar;
-    int                  fCosOuterConeAngleLocation;
-    const GrGLShaderVar* fCosInnerConeAngleVar;
-    int                  fCosInnerConeAngleLocation;
-    const GrGLShaderVar* fConeScaleVar;
-    int                  fConeScaleLocation;
-    const GrGLShaderVar* fSVar;
-    int                  fSLocation;
+    UniformHandle   fLocationUni;
+    int             fLocationLocation;
+    UniformHandle   fExponentUni;
+    int             fExponentLocation;
+    UniformHandle   fCosOuterConeAngleUni;
+    int             fCosOuterConeAngleLocation;
+    UniformHandle   fCosInnerConeAngleUni;
+    int             fCosInnerConeAngleLocation;
+    UniformHandle   fConeScaleUni;
+    int             fConeScaleLocation;
+    UniformHandle   fSUni;
+    int             fSLocation;
 };
 
 };
@@ -870,20 +892,22 @@
                        const GrCustomStage& stage);
     virtual ~GrGLLightingEffect();
 
-    virtual void setupVariables(GrGLShaderBuilder* state,
+    virtual void setupVariables(GrGLShaderBuilder* builder,
                                 int stage) SK_OVERRIDE;
-    virtual void emitVS(GrGLShaderBuilder* state,
+    virtual void emitVS(GrGLShaderBuilder* builder,
                         const char* vertexCoords) SK_OVERRIDE;
-    virtual void emitFS(GrGLShaderBuilder* state,
+    virtual void emitFS(GrGLShaderBuilder* builder,
                         const char* outputColor,
                         const char* inputColor,
                         const char* samplerName) SK_OVERRIDE;
 
-    virtual void emitLightFunc(SkString* funcs) = 0;
+    virtual void emitLightFunc(const GrGLShaderBuilder*, SkString* funcs) = 0;
 
     static inline StageKey GenKey(const GrCustomStage& s);
 
-    virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
+    virtual void initUniforms(const GrGLShaderBuilder* builder,
+                              const GrGLInterface*,
+                              int programID) SK_OVERRIDE;
     virtual void setData(const GrGLInterface*, 
                          const GrCustomStage&,
                          const GrRenderTarget*,
@@ -892,11 +916,11 @@
 private:
     typedef GrGLProgramStage INHERITED;
 
-    const GrGLShaderVar*               fImageIncrementVar;
-    GrGLint                            fImageIncrementLocation;
-    const GrGLShaderVar*               fSurfaceScaleVar;
-    GrGLint                            fSurfaceScaleLocation;
-    GrGLLight*                         fLight;
+    UniformHandle   fImageIncrementUni;
+    GrGLint         fImageIncrementLocation;
+    UniformHandle   fSurfaceScaleUni;
+    GrGLint         fSurfaceScaleLocation;
+    GrGLLight*      fLight;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -905,10 +929,12 @@
 public:
     GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
                               const GrCustomStage& stage);
-    virtual void setupVariables(GrGLShaderBuilder* state,
+    virtual void setupVariables(GrGLShaderBuilder* builder,
                                 int stage) SK_OVERRIDE;
-    virtual void emitLightFunc(SkString* funcs) SK_OVERRIDE;
-    virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
+    virtual void emitLightFunc(const GrGLShaderBuilder*, SkString* funcs) SK_OVERRIDE;
+    virtual void initUniforms(const GrGLShaderBuilder*,
+                              const GrGLInterface*,
+                              int programID) SK_OVERRIDE;
     virtual void setData(const GrGLInterface*, 
                          const GrCustomStage&,
                          const GrRenderTarget*,
@@ -917,8 +943,8 @@
 private:
     typedef GrGLLightingEffect INHERITED;
 
-    const GrGLShaderVar*               fKDVar;
-    GrGLint                            fKDLocation;
+    UniformHandle   fKDUni;
+    GrGLint         fKDLocation;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -927,10 +953,12 @@
 public:
     GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
                                const GrCustomStage& stage);
-    virtual void setupVariables(GrGLShaderBuilder* state,
+    virtual void setupVariables(GrGLShaderBuilder* builder,
                                 int stage) SK_OVERRIDE;
-    virtual void emitLightFunc(SkString* funcs) SK_OVERRIDE;
-    virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
+    virtual void emitLightFunc(const GrGLShaderBuilder*, SkString* funcs) SK_OVERRIDE;
+    virtual void initUniforms(const GrGLShaderBuilder*,
+                              const GrGLInterface*,
+                              int programID) SK_OVERRIDE;
     virtual void setData(const GrGLInterface*, 
                          const GrCustomStage&,
                          const GrRenderTarget*,
@@ -939,10 +967,10 @@
 private:
     typedef GrGLLightingEffect INHERITED;
 
-    const GrGLShaderVar*               fKSVar;
-    GrGLint                            fKSLocation;
-    const GrGLShaderVar*               fShininessVar;
-    GrGLint                            fShininessLocation;
+    UniformHandle   fKSUni;
+    GrGLint         fKSLocation;
+    UniformHandle   fShininessUni;
+    GrGLint         fShininessLocation;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -988,9 +1016,9 @@
 GrGLLightingEffect::GrGLLightingEffect(const GrProgramStageFactory& factory,
                                        const GrCustomStage& stage)
     : GrGLProgramStage(factory)
-    , fImageIncrementVar(NULL)
+    , fImageIncrementUni(kInvalidUniformHandle)
     , fImageIncrementLocation(0)
-    , fSurfaceScaleVar(NULL)
+    , fSurfaceScaleUni(kInvalidUniformHandle)
     , fSurfaceScaleLocation(0) {
     const GrLightingEffect& m = static_cast<const GrLightingEffect&>(stage);
     fLight = m.light()->createGLLight();
@@ -1000,40 +1028,40 @@
     delete fLight;
 }
 
-void GrGLLightingEffect::setupVariables(GrGLShaderBuilder* state, int stage) {
-    fImageIncrementVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType,
-        kVec2f_GrSLType, "uImageIncrement", stage);
-    fSurfaceScaleVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType,
-        kFloat_GrSLType, "uSurfaceScale", stage);
-    fLight->setupVariables(state, stage);
+void GrGLLightingEffect::setupVariables(GrGLShaderBuilder* builder, int stage) {
+    fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                              kVec2f_GrSLType,
+                                             "uImageIncrement", stage);
+    fSurfaceScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                           kFloat_GrSLType,
+                                           "uSurfaceScale", stage);
+    fLight->setupVariables(builder, stage);
 }
 
-void GrGLLightingEffect::emitVS(GrGLShaderBuilder* state,
-                                    const char* vertexCoords) {
-    fLight->emitVS(&state->fVSCode);
+void GrGLLightingEffect::emitVS(GrGLShaderBuilder* builder,
+                                const char* vertexCoords) {
+    fLight->emitVS(&builder->fVSCode);
 }
 
-void GrGLLightingEffect::initUniforms(const GrGLInterface* gl,
-                                        int programID) {
-    GR_GL_CALL_RET(gl, fSurfaceScaleLocation,
-        GetUniformLocation(programID,
-            fSurfaceScaleVar->getName().c_str()));
-    GR_GL_CALL_RET(gl, fImageIncrementLocation,
-        GetUniformLocation(programID,
-            fImageIncrementVar->getName().c_str()));
-    fLight->initUniforms(gl, programID);
+void GrGLLightingEffect::initUniforms(const GrGLShaderBuilder* builder,
+                                      const GrGLInterface* gl,
+                                      int programID) {
+    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
+    const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni);
+
+    GR_GL_CALL_RET(gl, fSurfaceScaleLocation, GetUniformLocation(programID, surfScale));
+    GR_GL_CALL_RET(gl, fImageIncrementLocation, GetUniformLocation(programID, imgInc));
+    fLight->initUniforms(builder, gl, programID);
 }
 
-void GrGLLightingEffect::emitFS(GrGLShaderBuilder* state,
-                                       const char* outputColor,
-                                       const char* inputColor,
-                                       const char* samplerName) {
-    SkString* code = &state->fFSCode;
-    SkString* funcs = &state->fFSFunctions;
-    fLight->emitFuncs(funcs);
-    emitLightFunc(funcs);
+void GrGLLightingEffect::emitFS(GrGLShaderBuilder* builder,
+                                const char* outputColor,
+                                const char* inputColor,
+                                const char* samplerName) {
+    SkString* code = &builder->fFSCode;
+    SkString* funcs = &builder->fFSFunctions;
+    fLight->emitFuncs(builder, funcs);
+    this->emitLightFunc(builder, funcs);
     funcs->appendf("float sobel(float a, float b, float c, float d, float e, float f, float scale) {\n");
     funcs->appendf("\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n");
     funcs->appendf("}\n");
@@ -1046,26 +1074,30 @@
                          sobel(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n\
                          surfaceScale);\n}\n");
 
-    code->appendf("\t\tvec2 coord = %s;\n", state->fSampleCoords.c_str());
+    code->appendf("\t\tvec2 coord = %s;\n", builder->fSampleCoords.c_str());
     code->appendf("\t\tfloat m[9];\n");
+
+    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
+    const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni);
+
     int index = 0;
     for (int dy = -1; dy <= 1; dy++) {
         for (int dx = -1; dx <= 1; dx++) {
             SkString texCoords;
-            texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, fImageIncrementVar->getName().c_str());
+            texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc);
             code->appendf("\t\tm[%d] = ", index++);
-            state->emitTextureLookup(samplerName, texCoords.c_str());
+            builder->emitTextureLookup(samplerName, texCoords.c_str());
             code->appendf(".a;\n");
         }
     }
     code->appendf("\t\tvec3 surfaceToLight = ");
     SkString arg;
-    arg.appendf("%s * m[4]", fSurfaceScaleVar->getName().c_str());
-    fLight->emitSurfaceToLight(code, arg.c_str());
+    arg.appendf("%s * m[4]", surfScale);
+    fLight->emitSurfaceToLight(builder, code, arg.c_str());
     code->appendf(";\n");
-    code->appendf("\t\t%s = light(interiorNormal(m, %s), surfaceToLight, ", outputColor, fSurfaceScaleVar->getName().c_str());
-    fLight->emitLightColor(code, "surfaceToLight");
-    code->appendf(")%s;\n", state->fModulate.c_str());
+    code->appendf("\t\t%s = light(interiorNormal(m, %s), surfaceToLight, ", outputColor, surfScale);
+    fLight->emitLightColor(builder, code, "surfaceToLight");
+    code->appendf(")%s;\n", builder->fModulate.c_str());
 }
 
 GrGLProgramStage::StageKey GrGLLightingEffect::GenKey(
@@ -1093,28 +1125,28 @@
 GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
                                             const GrCustomStage& stage)
     : INHERITED(factory, stage)
-    , fKDVar(NULL)
+    , fKDUni(kInvalidUniformHandle)
     , fKDLocation(0) {
 }
 
-void GrGLDiffuseLightingEffect::setupVariables(GrGLShaderBuilder* state, int stage) {
-    INHERITED::setupVariables(state, stage);
-    fKDVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType,
-        kFloat_GrSLType, "uKD", stage);
+void GrGLDiffuseLightingEffect::setupVariables(GrGLShaderBuilder* builder, int stage) {
+    INHERITED::setupVariables(builder, stage);
+    fKDUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kFloat_GrSLType, "uKD",
+                                 stage);
 }
 
-void GrGLDiffuseLightingEffect::initUniforms(const GrGLInterface* gl,
+void GrGLDiffuseLightingEffect::initUniforms(const GrGLShaderBuilder* builder,
+                                             const GrGLInterface* gl,
                                              int programID) {
-    INHERITED::initUniforms(gl, programID);
-    GR_GL_CALL_RET(gl, fKDLocation,
-        GetUniformLocation(programID,
-            fKDVar->getName().c_str()));
+    INHERITED::initUniforms(builder, gl, programID);
+    const char* kd = builder->getUniformCStr(fKDUni);
+    GR_GL_CALL_RET(gl, fKDLocation, GetUniformLocation(programID, kd));
 }
 
-void GrGLDiffuseLightingEffect::emitLightFunc(SkString* funcs) {
+void GrGLDiffuseLightingEffect::emitLightFunc(const GrGLShaderBuilder* builder, SkString* funcs) {
+    const char* kd = builder->getUniformCStr(fKDUni);
     funcs->appendf("vec4 light(vec3 normal, vec3 surfaceToLight, vec3 lightColor) {\n");
-    funcs->appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", fKDVar->getName().c_str());
+    funcs->appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
     funcs->appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
     funcs->appendf("}\n");
 }
@@ -1154,37 +1186,37 @@
 GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
                                             const GrCustomStage& stage)
     : GrGLLightingEffect(factory, stage)
-    , fKSVar(NULL)
+    , fKSUni(kInvalidUniformHandle)
     , fKSLocation(0)
-    , fShininessVar(NULL)
+    , fShininessUni(kInvalidUniformHandle)
     , fShininessLocation(0) {
 }
 
-void GrGLSpecularLightingEffect::setupVariables(GrGLShaderBuilder* state, int stage) {
-    INHERITED::setupVariables(state, stage);
-    fKSVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType,
-        kFloat_GrSLType, "uKS", stage);
-    fShininessVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType,
-        kFloat_GrSLType, "uShininess", stage);
+void GrGLSpecularLightingEffect::setupVariables(GrGLShaderBuilder* builder, int stage) {
+    INHERITED::setupVariables(builder, stage);
+    fKSUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                 kFloat_GrSLType, "uKS", stage);
+    fShininessUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                        kFloat_GrSLType, "uShininess", stage);
 }
 
-void GrGLSpecularLightingEffect::initUniforms(const GrGLInterface* gl,
-                                        int programID) {
-    INHERITED::initUniforms(gl, programID);
-    GR_GL_CALL_RET(gl, fKSLocation,
-        GetUniformLocation(programID, fKSVar->getName().c_str()));
-    GR_GL_CALL_RET(gl, fShininessLocation,
-        GetUniformLocation(programID, fShininessVar->getName().c_str()));
+void GrGLSpecularLightingEffect::initUniforms(const GrGLShaderBuilder* builder,
+                                              const GrGLInterface* gl,
+                                              int programID) {
+    INHERITED::initUniforms(builder, gl, programID);
+    const char* ks = builder->getUniformCStr(fKSUni);
+    const char* shininess = builder->getUniformCStr(fShininessUni);
+    GR_GL_CALL_RET(gl, fKSLocation, GetUniformLocation(programID, ks));
+    GR_GL_CALL_RET(gl, fShininessLocation, GetUniformLocation(programID, shininess));
 }
 
-void GrGLSpecularLightingEffect::emitLightFunc(SkString* funcs) {
+void GrGLSpecularLightingEffect::emitLightFunc(const GrGLShaderBuilder* builder, SkString* funcs) {
     funcs->appendf("vec4 light(vec3 normal, vec3 surfaceToLight, vec3 lightColor) {\n");
     funcs->appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
 
-    funcs->appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n",
-        fKSVar->getName().c_str(), fShininessVar->getName().c_str());
+    const char* ks = builder->getUniformCStr(fKSUni);
+    const char* shininess = builder->getUniformCStr(fShininessUni);
+    funcs->appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess);
     funcs->appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
     funcs->appendf("}\n");
 }
@@ -1202,23 +1234,28 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrGLLight::emitLightColor(SkString* builder, const char *surfaceToLight) const {
-    builder->append(fColorVar->getName().c_str());
+void GrGLLight::emitLightColor(const GrGLShaderBuilder* builder,
+                               SkString* out,
+                               const char *surfaceToLight) const {
+    const char* color = builder->getUniformCStr(fColorUni);
+    out->append(color);
 }
 
-void GrGLLight::setupVariables(GrGLShaderBuilder* state, int stage) {
-    fColorVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType,
-        kVec3f_GrSLType, "uLightColor", stage);
+void GrGLLight::setupVariables(GrGLShaderBuilder* builder, int stage) {
+    const GrGLShaderVar& colorVar = builder->getUniformVariable(fColorUni);
+    fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                    kVec3f_GrSLType, "uLightColor", stage);
 }
 
-void GrGLLight::initUniforms(const GrGLInterface* gl, int programID) {
-    GR_GL_CALL_RET(gl, fColorVarLocation,
-        GetUniformLocation(programID, fColorVar->getName().c_str()));
+void GrGLLight::initUniforms(const GrGLShaderBuilder* builder,
+                             const GrGLInterface* gl,
+                             int programID) {
+    const char* color = builder->getUniformCStr(fColorUni);
+    GR_GL_CALL_RET(gl, fColorLocation, GetUniformLocation(programID, color));
 }
 
 void GrGLLight::setData(const GrGLInterface* gl, const GrRenderTarget* rt, const SkLight* light) const {
-    setUniformPoint3(gl, fColorVarLocation, light->color() * SkScalarInvert(SkIntToScalar(255)));
+    setUniformPoint3(gl, fColorLocation, light->color() * SkScalarInvert(SkIntToScalar(255)));
 }
 
 GrGLLight* SkDistantLight::createGLLight() const {
@@ -1227,17 +1264,18 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrGLDistantLight::setupVariables(GrGLShaderBuilder* state, int stage) {
-    INHERITED::setupVariables(state, stage);
-    fDirectionVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
-        "uLightDirection", stage);
+void GrGLDistantLight::setupVariables(GrGLShaderBuilder* builder, int stage) {
+    INHERITED::setupVariables(builder, stage);
+    fDirectionUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
+                                        "uLightDirection", stage);
 }
 
-void GrGLDistantLight::initUniforms(const GrGLInterface* gl, int programID) {
-    INHERITED::initUniforms(gl, programID);
-    GR_GL_CALL_RET(gl, fDirectionLocation,
-        GetUniformLocation(programID, fDirectionVar->getName().c_str()));
+void GrGLDistantLight::initUniforms(const GrGLShaderBuilder* builder,
+                                    const GrGLInterface* gl,
+                                    int programID) {
+    INHERITED::initUniforms(builder, gl, programID);
+    const char* dir = builder->getUniformCStr(fDirectionUni);
+    GR_GL_CALL_RET(gl, fDirectionLocation, GetUniformLocation(programID, dir));
 }
 
 void GrGLDistantLight::setData(const GrGLInterface* gl, const GrRenderTarget* rt, const SkLight* light) const {
@@ -1247,24 +1285,27 @@
     setUniformNormal3(gl, fDirectionLocation, distantLight->direction());
 }
 
-void GrGLDistantLight::emitSurfaceToLight(SkString* builder,
+void GrGLDistantLight::emitSurfaceToLight(const GrGLShaderBuilder* builder,
+                                          SkString* out,
                                           const char* z) const {
-    builder->append(fDirectionVar->getName().c_str());
+    const char* dir = builder->getUniformCStr(fDirectionUni);
+    out->append(dir);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrGLPointLight::setupVariables(GrGLShaderBuilder* state, int stage) {
-    INHERITED::setupVariables(state, stage);
-    fLocationVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
-        "uLightLocation", stage);
+void GrGLPointLight::setupVariables(GrGLShaderBuilder* builder, int stage) {
+    INHERITED::setupVariables(builder, stage);
+    fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
+                                       "uLightLocation", stage);
 }
 
-void GrGLPointLight::initUniforms(const GrGLInterface* gl, int programID) {
-    INHERITED::initUniforms(gl, programID);
-    GR_GL_CALL_RET(gl, fLocationLocation,
-        GetUniformLocation(programID, fLocationVar->getName().c_str()));
+void GrGLPointLight::initUniforms(const GrGLShaderBuilder* builder,
+                                  const GrGLInterface* gl,
+                                  int programID) {
+    INHERITED::initUniforms(builder, gl, programID);
+    const char* loc = builder->getUniformCStr(fLocationUni);
+    GR_GL_CALL_RET(gl, fLocationLocation, GetUniformLocation(programID, loc));
 }
 
 void GrGLPointLight::setData(const GrGLInterface* gl, const GrRenderTarget* rt, const SkLight* light) const {
@@ -1274,54 +1315,47 @@
     setUniformPoint3FlipY(gl, fLocationLocation, pointLight->location(), rt->height());
 }
 
-void GrGLPointLight::emitVS(SkString* builder) const {
+void GrGLPointLight::emitVS(SkString* out) const {
 }
 
-void GrGLPointLight::emitSurfaceToLight(SkString* builder,
-                                        const char* z) const {
-    const char *lName = fLocationVar->getName().c_str();
-    builder->appendf(
-        "normalize(%s - vec3(gl_FragCoord.xy, %s))", lName, z);
+void GrGLPointLight::emitSurfaceToLight(const GrGLShaderBuilder* builder, SkString* out, const char* z) const {
+    const char* loc = builder->getUniformCStr(fLocationUni);
+    out->appendf(
+        "normalize(%s - vec3(gl_FragCoord.xy, %s))", loc, z);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrGLSpotLight::setupVariables(GrGLShaderBuilder* state, int stage) {
-    INHERITED::setupVariables(state, stage);
-    fLocationVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType,
-        kVec3f_GrSLType, "uLightLocation", stage);
-    fExponentVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType,
-        kFloat_GrSLType, "uExponent", stage);
-    fCosInnerConeAngleVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType,
-        kFloat_GrSLType, "uCosInnerConeAngle", stage);
-    fCosOuterConeAngleVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType,
-        kFloat_GrSLType, "uCosOuterConeAngle", stage);
-    fConeScaleVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType,
-        kFloat_GrSLType, "uConeScale", stage);
-    fSVar = &state->addUniform(
-        GrGLShaderBuilder::kFragment_ShaderType,
-        kVec3f_GrSLType, "uS", stage);
+void GrGLSpotLight::setupVariables(GrGLShaderBuilder* builder, int stage) {
+    INHERITED::setupVariables(builder, stage);
+    fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                       kVec3f_GrSLType, "uLightLocation", stage);
+    fExponentUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                       kFloat_GrSLType, "uExponent", stage);
+    fCosInnerConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                                kFloat_GrSLType, "uCosInnerConeAngle", stage);
+    fCosOuterConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                                kFloat_GrSLType, "uCosOuterConeAngle", stage);
+    fConeScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                        kFloat_GrSLType, "uConeScale", stage);
+    fSUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                              kVec3f_GrSLType, "uS", stage);
 }
 
-void GrGLSpotLight::initUniforms(const GrGLInterface* gl, int programID) {
-    INHERITED::initUniforms(gl, programID);
-    GR_GL_CALL_RET(gl, fLocationLocation,
-        GetUniformLocation(programID, fLocationVar->getName().c_str()));
-    GR_GL_CALL_RET(gl, fExponentLocation,
-        GetUniformLocation(programID, fExponentVar->getName().c_str()));
-    GR_GL_CALL_RET(gl, fCosInnerConeAngleLocation,
-        GetUniformLocation(programID, fCosInnerConeAngleVar->getName().c_str()));
-    GR_GL_CALL_RET(gl, fCosOuterConeAngleLocation,
-        GetUniformLocation(programID, fCosOuterConeAngleVar->getName().c_str()));
-    GR_GL_CALL_RET(gl, fConeScaleLocation,
-        GetUniformLocation(programID, fConeScaleVar->getName().c_str()));
-    GR_GL_CALL_RET(gl, fSLocation,
-        GetUniformLocation(programID, fSVar->getName().c_str()));
+void GrGLSpotLight::initUniforms(const GrGLShaderBuilder* builder, const GrGLInterface* gl, int programID) {
+    INHERITED::initUniforms(builder, gl, programID);
+    const char* location = builder->getUniformCStr(fLocationUni);
+    const char* exponent = builder->getUniformCStr(fExponentUni);
+    const char* cosInner = builder->getUniformCStr(fCosInnerConeAngleUni);
+    const char* cosOuter = builder->getUniformCStr(fCosOuterConeAngleUni);
+    const char* coneScale = builder->getUniformCStr(fConeScaleUni);
+    const char* s = builder->getUniformCStr(fSUni);
+    GR_GL_CALL_RET(gl, fLocationLocation, GetUniformLocation(programID, location));
+    GR_GL_CALL_RET(gl, fExponentLocation, GetUniformLocation(programID, exponent));
+    GR_GL_CALL_RET(gl, fCosInnerConeAngleLocation, GetUniformLocation(programID, cosInner));
+    GR_GL_CALL_RET(gl, fCosOuterConeAngleLocation, GetUniformLocation(programID, cosOuter));
+    GR_GL_CALL_RET(gl, fConeScaleLocation, GetUniformLocation(programID, coneScale));
+    GR_GL_CALL_RET(gl, fSLocation, GetUniformLocation(programID, s));
 }
 
 void GrGLSpotLight::setData(const GrGLInterface* gl, const GrRenderTarget* rt, const SkLight* light) const {
@@ -1336,30 +1370,40 @@
     setUniformNormal3(gl, fSLocation, spotLight->s());
 }
 
-void GrGLSpotLight::emitVS(SkString* builder) const {
+void GrGLSpotLight::emitVS(SkString* out) const {
 }
 
-void GrGLSpotLight::emitFuncs(SkString* builder) const {
-    builder->appendf("vec3 lightColor(vec3 surfaceToLight) {\n");
-    builder->appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", fSVar->getName().c_str());
-    builder->appendf("\tif (cosAngle < %s) {\n", fCosOuterConeAngleVar->getName().c_str());
-    builder->appendf("\t\treturn vec3(0);\n");
-    builder->appendf("\t}\n");
-    builder->appendf("\tfloat scale = pow(cosAngle, %s);\n", fExponentVar->getName().c_str());
-    builder->appendf("\tif (cosAngle < %s) {\n", fCosInnerConeAngleVar->getName().c_str());
-    builder->appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n", fColorVar->getName().c_str(), fCosOuterConeAngleVar->getName().c_str(), fConeScaleVar->getName().c_str());
-    builder->appendf("\t}\n");
-    builder->appendf("\treturn %s;\n", fColorVar->getName().c_str());
-    builder->appendf("}\n");
+void GrGLSpotLight::emitFuncs(const GrGLShaderBuilder* builder, SkString* out) const {
+    const char* exponent = builder->getUniformCStr(fExponentUni);
+    const char* cosInner = builder->getUniformCStr(fCosInnerConeAngleUni);
+    const char* cosOuter = builder->getUniformCStr(fCosOuterConeAngleUni);
+    const char* coneScale = builder->getUniformCStr(fConeScaleUni);
+    const char* s = builder->getUniformCStr(fSUni);
+    const char* color = builder->getUniformCStr(fColorUni);
+
+    out->appendf("vec3 lightColor(vec3 surfaceToLight) {\n");
+    out->appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
+    out->appendf("\tif (cosAngle < %s) {\n", cosOuter);
+    out->appendf("\t\treturn vec3(0);\n");
+    out->appendf("\t}\n");
+    out->appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
+    out->appendf("\tif (cosAngle < %s) {\n", cosInner);
+    out->appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n", color, cosOuter, coneScale);
+    out->appendf("\t}\n");
+    out->appendf("\treturn %s;\n", color);
+    out->appendf("}\n");
 }
 
-void GrGLSpotLight::emitSurfaceToLight(SkString* builder, const char* z) const {
-    builder->appendf(
-        "normalize(%s - vec3(gl_FragCoord.xy, %s))", fLocationVar->getName().c_str(), z);
+void GrGLSpotLight::emitSurfaceToLight(const GrGLShaderBuilder* builder,
+                                       SkString* out,
+                                       const char* z) const {
+    const char* location= builder->getUniformCStr(fLocationUni);
+    out->appendf("normalize(%s - vec3(gl_FragCoord.xy, %s))", location, z);
 }
 
-void GrGLSpotLight::emitLightColor(SkString* builder, const char *surfaceToLight) const {
-    builder->appendf("lightColor(%s)", surfaceToLight);
+void GrGLSpotLight::emitLightColor(const GrGLShaderBuilder* builder,
+                                   SkString* out, const char *surfaceToLight) const {
+    out->appendf("lightColor(%s)", surfaceToLight);
 }
 
 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index 3804d57..a16313e 100644
--- a/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/src/gpu/effects/GrConvolutionEffect.cpp
@@ -11,21 +11,27 @@
 #include "gl/GrGLTexture.h"
 #include "GrProgramStageFactory.h"
 
+// For brevity, and these definitions are likely to move to a different class soon.
+typedef GrGLShaderBuilder::UniformHandle UniformHandle;
+static const UniformHandle kInvalidUniformHandle = GrGLShaderBuilder::kInvalidUniformHandle;
+
 class GrGLConvolutionEffect : public GrGLProgramStage {
 public:
     GrGLConvolutionEffect(const GrProgramStageFactory& factory,
                           const GrCustomStage& stage);
 
-    virtual void setupVariables(GrGLShaderBuilder* state,
+    virtual void setupVariables(GrGLShaderBuilder* builder,
                                 int stage) SK_OVERRIDE;
-    virtual void emitVS(GrGLShaderBuilder* state,
+    virtual void emitVS(GrGLShaderBuilder* builder,
                         const char* vertexCoords) SK_OVERRIDE;
-    virtual void emitFS(GrGLShaderBuilder* state,
+    virtual void emitFS(GrGLShaderBuilder* builder,
                         const char* outputColor,
                         const char* inputColor,
                         const char* samplerName) SK_OVERRIDE;
 
-    virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
+    virtual void initUniforms(const GrGLShaderBuilder*,
+                              const GrGLInterface*,
+                              int programID) SK_OVERRIDE;
 
     virtual void setData(const GrGLInterface*,
                          const GrCustomStage&,
@@ -37,11 +43,11 @@
 private:
     int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); }
 
-    int                   fRadius;
-    const GrGLShaderVar*  fKernelVar;
-    GrGLint               fKernelLocation;
-    const GrGLShaderVar*  fImageIncrementVar;
-    GrGLint               fImageIncrementLocation;
+    int             fRadius;
+    UniformHandle   fKernelUni;
+    GrGLint         fKernelLocation;
+    UniformHandle   fImageIncrementUni;
+    GrGLint         fImageIncrementLocation;
 
     typedef GrGLProgramStage INHERITED;
 };
@@ -49,72 +55,72 @@
 GrGLConvolutionEffect::GrGLConvolutionEffect(const GrProgramStageFactory& factory,
                                              const GrCustomStage& stage)
     : GrGLProgramStage(factory)
-    , fKernelVar(NULL)
+    , fKernelUni(kInvalidUniformHandle)
     , fKernelLocation(0)
-    , fImageIncrementVar(NULL)
+    , fImageIncrementUni(kInvalidUniformHandle)
     , fImageIncrementLocation(0) {
     const GrConvolutionEffect& c =
         static_cast<const GrConvolutionEffect&>(stage);
     fRadius = c.radius();
 }
 
-void GrGLConvolutionEffect::setupVariables(GrGLShaderBuilder* state,
+void GrGLConvolutionEffect::setupVariables(GrGLShaderBuilder* builder,
                                            int stage) {
-    fImageIncrementVar = &state->addUniform(GrGLShaderBuilder::kFragment_ShaderType |
-                                            GrGLShaderBuilder::kVertex_ShaderType,
-                                            kVec2f_GrSLType, "uImageIncrement", stage);
-    fKernelVar = &state->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
-                                    kFloat_GrSLType, "uKernel", stage, this->width());
+    fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType |
+                                             GrGLShaderBuilder::kVertex_ShaderType,
+                                             kVec2f_GrSLType, "uImageIncrement", stage);
+    fKernelUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                     kFloat_GrSLType, "uKernel", stage, this->width());
 
     fImageIncrementLocation = kUseUniform;
     fKernelLocation = kUseUniform;
 }
 
-void GrGLConvolutionEffect::emitVS(GrGLShaderBuilder* state,
+void GrGLConvolutionEffect::emitVS(GrGLShaderBuilder* builder,
                                    const char* vertexCoords) {
-    SkString* code = &state->fVSCode;
-    code->appendf("\t\t%s -= vec2(%d, %d) * %s;\n",
-                  vertexCoords, fRadius, fRadius,
-                  fImageIncrementVar->getName().c_str());
+    SkString* code = &builder->fVSCode;
+    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
+    code->appendf("\t\t%s -= vec2(%d, %d) * %s;\n", vertexCoords, fRadius, fRadius, imgInc);
 }
 
-void GrGLConvolutionEffect::emitFS(GrGLShaderBuilder* state,
+void GrGLConvolutionEffect::emitFS(GrGLShaderBuilder* builder,
                                    const char* outputColor,
                                    const char* inputColor,
                                    const char* samplerName) {
-    SkString* code = &state->fFSCode;
+    SkString* code = &builder->fFSCode;
 
     code->appendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor);
 
-    code->appendf("\t\tvec2 coord = %s;\n", state->fSampleCoords.c_str());
+    code->appendf("\t\tvec2 coord = %s;\n", builder->fSampleCoords.c_str());
     
     int width = this ->width();
+    const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni);
+    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
     // Manually unroll loop because some drivers don't; yields 20-30% speedup.
     for (int i = 0; i < width; i++) {
         SkString index;
         SkString kernelIndex;
         index.appendS32(i);
-        fKernelVar->appendArrayAccess(index.c_str(), &kernelIndex);
+        kernel.appendArrayAccess(index.c_str(), &kernelIndex);
         code->appendf("\t\t%s += ", outputColor);
-        state->emitTextureLookup(samplerName, "coord");
+        builder->emitTextureLookup(samplerName, "coord");
         code->appendf(" * %s;\n", kernelIndex.c_str());
-        code->appendf("\t\tcoord += %s;\n",
-                      fImageIncrementVar->getName().c_str());
+        code->appendf("\t\tcoord += %s;\n", imgInc);
     }
 
-    if (state->fModulate.size()) {
+    if (builder->fModulate.size()) {
         code->appendf("\t\t%s = %s%s;\n", outputColor, outputColor,
-                      state->fModulate.c_str());
+                      builder->fModulate.c_str());
     }
 }
 
-void GrGLConvolutionEffect::initUniforms(const GrGLInterface* gl,
+void GrGLConvolutionEffect::initUniforms(const GrGLShaderBuilder* builder,
+                                         const GrGLInterface* gl,
                                          int programID) {
-    GR_GL_CALL_RET(gl, fImageIncrementLocation,
-        GetUniformLocation(programID,
-            fImageIncrementVar->getName().c_str()));
-    GR_GL_CALL_RET(gl, fKernelLocation,
-        GetUniformLocation(programID, fKernelVar->getName().c_str()));
+    const char* kernel = builder->getUniformCStr(fKernelUni);
+    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
+    GR_GL_CALL_RET(gl, fImageIncrementLocation, GetUniformLocation(programID, imgInc));
+    GR_GL_CALL_RET(gl, fKernelLocation, GetUniformLocation(programID, kernel));
 }
 
 void GrGLConvolutionEffect::setData(const GrGLInterface* gl,
diff --git a/src/gpu/effects/GrGradientEffects.cpp b/src/gpu/effects/GrGradientEffects.cpp
index 3125657..57767b3 100644
--- a/src/gpu/effects/GrGradientEffects.cpp
+++ b/src/gpu/effects/GrGradientEffects.cpp
@@ -19,9 +19,9 @@
                        const GrCustomStage&) : INHERITED (factory) { }
     virtual ~GrGLRadialGradient() { }
 
-    virtual void emitVS(GrGLShaderBuilder* state,
+    virtual void emitVS(GrGLShaderBuilder* builder,
                         const char* vertexCoords) SK_OVERRIDE { }
-    virtual void emitFS(GrGLShaderBuilder* state,
+    virtual void emitFS(GrGLShaderBuilder* builder,
                         const char* outputColor,
                         const char* inputColor,
                         const char* samplerName) SK_OVERRIDE;
@@ -34,15 +34,15 @@
 
 };
 
-void GrGLRadialGradient::emitFS(GrGLShaderBuilder* state,
+void GrGLRadialGradient::emitFS(GrGLShaderBuilder* builder,
                                 const char* outputColor,
                                 const char* inputColor,
                                 const char* samplerName) {
-    state->fSampleCoords.printf("vec2(length(%s.xy), 0.5)",
-                                state->fSampleCoords.c_str());
-    state->fComplexCoord = true;
+    builder->fSampleCoords.printf("vec2(length(%s.xy), 0.5)",
+                                  builder->fSampleCoords.c_str());
+    builder->fComplexCoord = true;
 
-    state->emitDefaultFetch(outputColor, samplerName);
+    builder->emitDefaultFetch(outputColor, samplerName);
 }
 
 
@@ -69,6 +69,10 @@
 
 /////////////////////////////////////////////////////////////////////
 
+// For brevity, and these definitions are likely to move to a different class soon.
+typedef GrGLShaderBuilder::UniformHandle UniformHandle;
+static const UniformHandle kInvalidUniformHandle = GrGLShaderBuilder::kInvalidUniformHandle;
+
 class GrGLRadial2Gradient : public GrGLProgramStage {
 
 public:
@@ -77,15 +81,17 @@
                         const GrCustomStage&);
     virtual ~GrGLRadial2Gradient() { }
 
-    virtual void setupVariables(GrGLShaderBuilder* state,
+    virtual void setupVariables(GrGLShaderBuilder* builder,
                                 int stage) SK_OVERRIDE;
-    virtual void emitVS(GrGLShaderBuilder* state,
+    virtual void emitVS(GrGLShaderBuilder* builder,
                         const char* vertexCoords) SK_OVERRIDE;
-    virtual void emitFS(GrGLShaderBuilder* state,
+    virtual void emitFS(GrGLShaderBuilder* builder,
                         const char* outputColor,
                         const char* inputColor,
                         const char* samplerName) SK_OVERRIDE;
-    virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
+    virtual void initUniforms(const GrGLShaderBuilder* builder,
+                              const GrGLInterface*,
+                              int programID) SK_OVERRIDE;
     virtual void setData(const GrGLInterface*,
                          const GrCustomStage&,
                          const GrRenderTarget*,
@@ -97,10 +103,10 @@
 
 protected:
 
-    const GrGLShaderVar* fVSParamVar;
-    GrGLint fVSParamLocation;
-    const GrGLShaderVar* fFSParamVar;
-    GrGLint fFSParamLocation;
+    UniformHandle   fVSParamUni;
+    GrGLint         fVSParamLocation;
+    UniformHandle   fFSParamUni;
+    GrGLint         fFSParamLocation;
 
     const char* fVSVaryingName;
     const char* fFSVaryingName;
@@ -126,8 +132,8 @@
         const GrProgramStageFactory& factory,
         const GrCustomStage& baseData)
     : INHERITED(factory)
-    , fVSParamVar(NULL)
-    , fFSParamVar(NULL)
+    , fVSParamUni(kInvalidUniformHandle)
+    , fFSParamUni(kInvalidUniformHandle)
     , fVSVaryingName(NULL)
     , fFSVaryingName(NULL)
     , fCachedCenter(GR_ScalarMax)
@@ -139,37 +145,37 @@
     fIsDegenerate = data.isDegenerate();
 }
 
-void GrGLRadial2Gradient::setupVariables(GrGLShaderBuilder* state, int stage) {
+void GrGLRadial2Gradient::setupVariables(GrGLShaderBuilder* builder, int stage) {
     // 2 copies of uniform array, 1 for each of vertex & fragment shader,
     // to work around Xoom bug. Doesn't seem to cause performance decrease
     // in test apps, but need to keep an eye on it.
-    fVSParamVar = &state->addUniform(GrGLShaderBuilder::kVertex_ShaderType,
-                                     kFloat_GrSLType, "uRadial2VSParams", stage, 6);
-    fFSParamVar = &state->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
-                                     kFloat_GrSLType, "uRadial2FSParams", stage, 6);
+    fVSParamUni = builder->addUniform(GrGLShaderBuilder::kVertex_ShaderType,
+                                      kFloat_GrSLType, "uRadial2VSParams", stage, 6);
+    fFSParamUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                       kFloat_GrSLType, "uRadial2FSParams", stage, 6);
 
     fVSParamLocation = GrGLProgramStage::kUseUniform;
     fFSParamLocation = GrGLProgramStage::kUseUniform;
 
     // For radial gradients without perspective we can pass the linear
     // part of the quadratic as a varying.
-    if (state->fVaryingDims == state->fCoordDims) {
-        state->addVarying(kFloat_GrSLType, "Radial2BCoeff", stage,
+    if (builder->fVaryingDims == builder->fCoordDims) {
+        builder->addVarying(kFloat_GrSLType, "Radial2BCoeff", stage,
                           &fVSVaryingName, &fFSVaryingName);
     }
 }
 
-void GrGLRadial2Gradient::emitVS(GrGLShaderBuilder* state,
+void GrGLRadial2Gradient::emitVS(GrGLShaderBuilder* builder,
                                  const char* vertexCoords) {
-    SkString* code = &state->fVSCode;
+    SkString* code = &builder->fVSCode;
     SkString p2;
     SkString p3;
-    fVSParamVar->appendArrayAccess(2, &p2);
-    fVSParamVar->appendArrayAccess(3, &p3);
+    builder->getUniformVariable(fVSParamUni).appendArrayAccess(2, &p2);
+    builder->getUniformVariable(fVSParamUni).appendArrayAccess(3, &p3);
 
     // For radial gradients without perspective we can pass the linear
     // part of the quadratic as a varying.
-    if (state->fVaryingDims == state->fCoordDims) {
+    if (builder->fVaryingDims == builder->fCoordDims) {
         // r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3])
         code->appendf("\t%s = 2.0 *(%s * %s.x - %s);\n",
                       fVSVaryingName, p2.c_str(),
@@ -177,11 +183,11 @@
     }
 }
 
-void GrGLRadial2Gradient::emitFS(GrGLShaderBuilder* state,
+void GrGLRadial2Gradient::emitFS(GrGLShaderBuilder* builder,
                                  const char* outputColor,
                                  const char* inputColor,
                                  const char* samplerName) {
-    SkString* code = &state->fFSCode;
+    SkString* code = &builder->fFSCode;
     SkString cName("c");
     SkString ac4Name("ac4");
     SkString rootName("root");
@@ -191,32 +197,32 @@
     SkString p3;
     SkString p4;
     SkString p5;
-    fFSParamVar->appendArrayAccess(0, &p0);
-    fFSParamVar->appendArrayAccess(1, &p1);
-    fFSParamVar->appendArrayAccess(2, &p2);
-    fFSParamVar->appendArrayAccess(3, &p3);
-    fFSParamVar->appendArrayAccess(4, &p4);
-    fFSParamVar->appendArrayAccess(5, &p5);
+    builder->getUniformVariable(fFSParamUni).appendArrayAccess(0, &p0);
+    builder->getUniformVariable(fFSParamUni).appendArrayAccess(1, &p1);
+    builder->getUniformVariable(fFSParamUni).appendArrayAccess(2, &p2);
+    builder->getUniformVariable(fFSParamUni).appendArrayAccess(3, &p3);
+    builder->getUniformVariable(fFSParamUni).appendArrayAccess(4, &p4);
+    builder->getUniformVariable(fFSParamUni).appendArrayAccess(5, &p5);
 
     // If we we're able to interpolate the linear component,
     // bVar is the varying; otherwise compute it
     SkString bVar;
-    if (state->fCoordDims == state->fVaryingDims) {
+    if (builder->fCoordDims == builder->fVaryingDims) {
         bVar = fFSVaryingName;
-        GrAssert(2 == state->fVaryingDims);
+        GrAssert(2 == builder->fVaryingDims);
     } else {
-        GrAssert(3 == state->fVaryingDims);
+        GrAssert(3 == builder->fVaryingDims);
         bVar = "b";
         //bVar.appendS32(stageNum);
         code->appendf("\tfloat %s = 2.0 * (%s * %s.x - %s);\n",
                       bVar.c_str(), p2.c_str(),
-                      state->fSampleCoords.c_str(), p3.c_str());
+                      builder->fSampleCoords.c_str(), p3.c_str());
     }
 
     // c = (x^2)+(y^2) - params[4]
     code->appendf("\tfloat %s = dot(%s, %s) - %s;\n",
-                  cName.c_str(), state->fSampleCoords.c_str(),
-                  state->fSampleCoords.c_str(),
+                  cName.c_str(), builder->fSampleCoords.c_str(),
+                  builder->fSampleCoords.c_str(),
                   p4.c_str());
 
     // If we aren't degenerate, emit some extra code, and accept a slightly
@@ -236,25 +242,27 @@
 
         // x coord is: (-b + params[5] * sqrt(b^2-4ac)) * params[1]
         // y coord is 0.5 (texture is effectively 1D)
-        state->fSampleCoords.printf("vec2((-%s + %s * %s) * %s, 0.5)",
-                            bVar.c_str(), p5.c_str(),
-                            rootName.c_str(), p1.c_str());
+        builder->fSampleCoords.printf("vec2((-%s + %s * %s) * %s, 0.5)",
+                                      bVar.c_str(), p5.c_str(),
+                                      rootName.c_str(), p1.c_str());
     } else {
         // x coord is: -c/b
         // y coord is 0.5 (texture is effectively 1D)
-        state->fSampleCoords.printf("vec2((-%s / %s), 0.5)",
-                            cName.c_str(), bVar.c_str());
+        builder->fSampleCoords.printf("vec2((-%s / %s), 0.5)",
+                                      cName.c_str(), bVar.c_str());
     }
-    state->fComplexCoord = true;
+    builder->fComplexCoord = true;
 
-    state->emitDefaultFetch(outputColor, samplerName);
+    builder->emitDefaultFetch(outputColor, samplerName);
 }
 
-void GrGLRadial2Gradient::initUniforms(const GrGLInterface* gl, int programID) {
-    GR_GL_CALL_RET(gl, fVSParamLocation,
-        GetUniformLocation(programID, fVSParamVar->getName().c_str()));
-    GR_GL_CALL_RET(gl, fFSParamLocation,
-        GetUniformLocation(programID, fFSParamVar->getName().c_str()));
+void GrGLRadial2Gradient::initUniforms(const GrGLShaderBuilder* builder,
+                                       const GrGLInterface* gl,
+                                       int programID) {
+    const char* vsParam = builder->getUniformCStr(fVSParamUni);
+    const char* fsParam = builder->getUniformCStr(fFSParamUni);
+    GR_GL_CALL_RET(gl, fVSParamLocation, GetUniformLocation(programID, vsParam));
+    GR_GL_CALL_RET(gl, fFSParamLocation, GetUniformLocation(programID, fsParam));
 }
 
 void GrGLRadial2Gradient::setData(const GrGLInterface* gl,
@@ -335,15 +343,17 @@
                          const GrCustomStage&);
     virtual ~GrGLConical2Gradient() { }
 
-    virtual void setupVariables(GrGLShaderBuilder* state,
+    virtual void setupVariables(GrGLShaderBuilder* builder,
                                 int stage) SK_OVERRIDE;
-    virtual void emitVS(GrGLShaderBuilder* state,
+    virtual void emitVS(GrGLShaderBuilder* builder,
                         const char* vertexCoords) SK_OVERRIDE;
-    virtual void emitFS(GrGLShaderBuilder* state,
+    virtual void emitFS(GrGLShaderBuilder* builder,
                         const char* outputColor,
                         const char* inputColor,
                         const char* samplerName) SK_OVERRIDE;
-    virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
+    virtual void initUniforms(const GrGLShaderBuilder* builder,
+                              const GrGLInterface*,
+                              int programID) SK_OVERRIDE;
     virtual void setData(const GrGLInterface*,
                          const GrCustomStage&,
                          const GrRenderTarget*,
@@ -355,10 +365,10 @@
 
 protected:
 
-    const GrGLShaderVar* fVSParamVar;
-    GrGLint fVSParamLocation;
-    const GrGLShaderVar* fFSParamVar;
-    GrGLint fFSParamLocation;
+    UniformHandle           fVSParamUni;
+    GrGLint                 fVSParamLocation;
+    UniformHandle           fFSParamUni;
+    GrGLint                 fFSParamLocation;
 
     const char* fVSVaryingName;
     const char* fFSVaryingName;
@@ -384,8 +394,8 @@
         const GrProgramStageFactory& factory,
         const GrCustomStage& baseData)
     : INHERITED(factory)
-    , fVSParamVar(NULL)
-    , fFSParamVar(NULL)
+    , fVSParamUni(kInvalidUniformHandle)
+    , fFSParamUni(kInvalidUniformHandle)
     , fVSVaryingName(NULL)
     , fFSVaryingName(NULL)
     , fCachedCenter(GR_ScalarMax)
@@ -397,39 +407,39 @@
     fIsDegenerate = data.isDegenerate();
 }
 
-void GrGLConical2Gradient::setupVariables(GrGLShaderBuilder* state, int stage) {
+void GrGLConical2Gradient::setupVariables(GrGLShaderBuilder* builder, int stage) {
     // 2 copies of uniform array, 1 for each of vertex & fragment shader,
     // to work around Xoom bug. Doesn't seem to cause performance decrease
     // in test apps, but need to keep an eye on it.
-    fVSParamVar = &state->addUniform(GrGLShaderBuilder::kVertex_ShaderType,
-                                     kFloat_GrSLType, "uConical2VSParams", stage, 6);
-    fFSParamVar = &state->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
-                                     kFloat_GrSLType, "uConical2FSParams", stage, 6);
+    fVSParamUni = builder->addUniform(GrGLShaderBuilder::kVertex_ShaderType,
+                                      kFloat_GrSLType, "uConical2VSParams", stage, 6);
+    fFSParamUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                      kFloat_GrSLType, "uConical2FSParams", stage, 6);
 
     fVSParamLocation = GrGLProgramStage::kUseUniform;
     fFSParamLocation = GrGLProgramStage::kUseUniform;
 
     // For radial gradients without perspective we can pass the linear
     // part of the quadratic as a varying.
-    if (state->fVaryingDims == state->fCoordDims) {
-        state->addVarying(kFloat_GrSLType, "Conical2BCoeff", stage,
-                          &fVSVaryingName, &fFSVaryingName);
+    if (builder->fVaryingDims == builder->fCoordDims) {
+        builder->addVarying(kFloat_GrSLType, "Conical2BCoeff", stage,
+                            &fVSVaryingName, &fFSVaryingName);
     }
 }
 
-void GrGLConical2Gradient::emitVS(GrGLShaderBuilder* state,
+void GrGLConical2Gradient::emitVS(GrGLShaderBuilder* builder,
                                   const char* vertexCoords) {
-    SkString* code = &state->fVSCode;
+    SkString* code = &builder->fVSCode;
     SkString p2; // distance between centers
     SkString p3; // start radius
     SkString p5; // difference in radii (r1 - r0)
-    fVSParamVar->appendArrayAccess(2, &p2);
-    fVSParamVar->appendArrayAccess(3, &p3);
-    fVSParamVar->appendArrayAccess(5, &p5);
+    builder->getUniformVariable(fVSParamUni).appendArrayAccess(2, &p2);
+    builder->getUniformVariable(fVSParamUni).appendArrayAccess(3, &p3);
+    builder->getUniformVariable(fVSParamUni).appendArrayAccess(5, &p5);
 
     // For radial gradients without perspective we can pass the linear
     // part of the quadratic as a varying.
-    if (state->fVaryingDims == state->fCoordDims) {
+    if (builder->fVaryingDims == builder->fCoordDims) {
         // r2Var = -2 * (r2Parm[2] * varCoord.x - r2Param[3] * r2Param[5])
         code->appendf("\t%s = -2.0 * (%s * %s.x + %s * %s);\n",
                       fVSVaryingName, p2.c_str(),
@@ -437,11 +447,11 @@
     }
 }
 
-void GrGLConical2Gradient::emitFS(GrGLShaderBuilder* state,
+void GrGLConical2Gradient::emitFS(GrGLShaderBuilder* builder,
                                   const char* outputColor,
                                   const char* inputColor,
                                   const char* samplerName) {
-    SkString* code = &state->fFSCode;
+    SkString* code = &builder->fFSCode;
 
     SkString cName("c");
     SkString ac4Name("ac4");
@@ -456,24 +466,25 @@
     SkString p3; // start radius
     SkString p4; // start radius squared
     SkString p5; // difference in radii (r1 - r0)
-    fFSParamVar->appendArrayAccess(0, &p0);
-    fFSParamVar->appendArrayAccess(1, &p1);
-    fFSParamVar->appendArrayAccess(2, &p2);
-    fFSParamVar->appendArrayAccess(3, &p3);
-    fFSParamVar->appendArrayAccess(4, &p4);
-    fFSParamVar->appendArrayAccess(5, &p5);
+
+    builder->getUniformVariable(fVSParamUni).appendArrayAccess(0, &p0);
+    builder->getUniformVariable(fVSParamUni).appendArrayAccess(1, &p1);
+    builder->getUniformVariable(fVSParamUni).appendArrayAccess(2, &p2);
+    builder->getUniformVariable(fVSParamUni).appendArrayAccess(3, &p3);
+    builder->getUniformVariable(fVSParamUni).appendArrayAccess(4, &p4);
+    builder->getUniformVariable(fVSParamUni).appendArrayAccess(5, &p5);
 
     // If we we're able to interpolate the linear component,
     // bVar is the varying; otherwise compute it
     SkString bVar;
-    if (state->fCoordDims == state->fVaryingDims) {
+    if (builder->fCoordDims == builder->fVaryingDims) {
         bVar = fFSVaryingName;
-        GrAssert(2 == state->fVaryingDims);
+        GrAssert(2 == builder->fVaryingDims);
     } else {
-        GrAssert(3 == state->fVaryingDims);
+        GrAssert(3 == builder->fVaryingDims);
         bVar = "b";
         code->appendf("\tfloat %s = -2.0 * (%s * %s.x + %s * %s);\n", 
-                      bVar.c_str(), p2.c_str(), state->fSampleCoords.c_str(), 
+                      bVar.c_str(), p2.c_str(), builder->fSampleCoords.c_str(), 
                       p3.c_str(), p5.c_str());
     }
 
@@ -483,7 +494,7 @@
 
     // c = (x^2)+(y^2) - params[4]
     code->appendf("\tfloat %s = dot(%s, %s) - %s;\n", cName.c_str(), 
-                  state->fSampleCoords.c_str(), state->fSampleCoords.c_str(),
+                  builder->fSampleCoords.c_str(), builder->fSampleCoords.c_str(),
                   p4.c_str());
 
     // Non-degenerate case (quadratic)
@@ -527,8 +538,8 @@
 
         // y coord is 0.5 (texture is effectively 1D)
         code->appendf("\t\t");
-        state->fSampleCoords.printf("vec2(%s, 0.5)", tName.c_str());
-        state->emitDefaultFetch(outputColor, samplerName);
+        builder->fSampleCoords.printf("vec2(%s, 0.5)", tName.c_str());
+        builder->emitDefaultFetch(outputColor, samplerName);
 
         // otherwise, if r(t) for the larger root was <= 0, try the other root
         code->appendf("\t\t} else {\n");
@@ -541,8 +552,8 @@
 
         // y coord is 0.5 (texture is effectively 1D)
         code->appendf("\t\t\t");
-        state->fSampleCoords.printf("vec2(%s, 0.5)", tName.c_str());
-        state->emitDefaultFetch(outputColor, samplerName);
+        builder->fSampleCoords.printf("vec2(%s, 0.5)", tName.c_str());
+        builder->emitDefaultFetch(outputColor, samplerName);
 
         // end if (r(t) > 0) for smaller root 
         code->appendf("\t\t\t}\n");
@@ -560,18 +571,20 @@
         code->appendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
                       p5.c_str(), p3.c_str());
         code->appendf("\t");
-        state->fSampleCoords.printf("vec2(%s, 0.5)", tName.c_str());
-        state->emitDefaultFetch(outputColor, samplerName);
+        builder->fSampleCoords.printf("vec2(%s, 0.5)", tName.c_str());
+        builder->emitDefaultFetch(outputColor, samplerName);
         code->appendf("\t}\n");
     }
-    state->fComplexCoord = true;
+    builder->fComplexCoord = true;
 }
 
-void GrGLConical2Gradient::initUniforms(const GrGLInterface* gl, int programID) {
-    GR_GL_CALL_RET(gl, fVSParamLocation,
-        GetUniformLocation(programID, fVSParamVar->getName().c_str()));
-    GR_GL_CALL_RET(gl, fFSParamLocation,
-        GetUniformLocation(programID, fFSParamVar->getName().c_str()));
+void GrGLConical2Gradient::initUniforms(const GrGLShaderBuilder* builder,
+                                        const GrGLInterface* gl,
+                                        int programID) {
+    const char* vsParam = builder->getUniformCStr(fVSParamUni);
+    const char* fsParam = builder->getUniformCStr(fFSParamUni);
+    GR_GL_CALL_RET(gl, fVSParamLocation, GetUniformLocation(programID, vsParam));
+    GR_GL_CALL_RET(gl, fFSParamLocation, GetUniformLocation(programID, fsParam));
 }
 
 void GrGLConical2Gradient::setData(const GrGLInterface* gl,
@@ -655,9 +668,9 @@
                       const GrCustomStage&) : INHERITED (factory) { }
     virtual ~GrGLSweepGradient() { }
 
-    virtual void emitVS(GrGLShaderBuilder* state,
+    virtual void emitVS(GrGLShaderBuilder* builder,
                         const char* vertexCoords) SK_OVERRIDE { }
-    virtual void emitFS(GrGLShaderBuilder* state,
+    virtual void emitFS(GrGLShaderBuilder* builder,
                         const char* outputColor,
                         const char* inputColor,
                         const char* samplerName) SK_OVERRIDE;
@@ -670,16 +683,16 @@
 
 };
 
-void GrGLSweepGradient::emitFS(GrGLShaderBuilder* state,
+void GrGLSweepGradient::emitFS(GrGLShaderBuilder* builder,
                               const char* outputColor,
                               const char* inputColor,
                               const char* samplerName) {
-    state->fSampleCoords.printf(
+    builder->fSampleCoords.printf(
         "vec2(atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5, 0.5)",
-        state->fSampleCoords.c_str(), state->fSampleCoords.c_str());
-    state->fComplexCoord = true;
+        builder->fSampleCoords.c_str(), builder->fSampleCoords.c_str());
+    builder->fComplexCoord = true;
 
-    state->emitDefaultFetch(outputColor, samplerName);
+    builder->emitDefaultFetch(outputColor, samplerName);
 }
 
 /////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/effects/GrMorphologyEffect.cpp b/src/gpu/effects/GrMorphologyEffect.cpp
index 180b5eb..6699989 100644
--- a/src/gpu/effects/GrMorphologyEffect.cpp
+++ b/src/gpu/effects/GrMorphologyEffect.cpp
@@ -18,7 +18,7 @@
     GrGLMorphologyEffect (const GrProgramStageFactory& factory,
                           const GrCustomStage& stage);
 
-    virtual void setupVariables(GrGLShaderBuilder* state,
+    virtual void setupVariables(GrGLShaderBuilder* builder,
                                 int stage) SK_OVERRIDE;
     virtual void emitVS(GrGLShaderBuilder* state,
                         const char* vertexCoords) SK_OVERRIDE;
@@ -29,8 +29,10 @@
 
     static inline StageKey GenKey(const GrCustomStage& s);
 
-    virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
-    virtual void setData(const GrGLInterface*, 
+    virtual void initUniforms(const GrGLShaderBuilder*,
+                              const GrGLInterface*,
+                              int programID) SK_OVERRIDE;
+    virtual void setData(const GrGLInterface*,
                          const GrCustomStage&,
                          const GrRenderTarget*,
                          int stageNum) SK_OVERRIDE;
@@ -40,7 +42,7 @@
 
     int                                fRadius;
     GrMorphologyEffect::MorphologyType fType;
-    const GrGLShaderVar*               fImageIncrementVar;
+    GrGLShaderBuilder::UniformHandle   fImageIncrementUni;
     GrGLint                            fImageIncrementLocation;
 
     typedef GrGLProgramStage INHERITED;
@@ -49,50 +51,47 @@
 GrGLMorphologyEffect ::GrGLMorphologyEffect(const GrProgramStageFactory& factory,
                                             const GrCustomStage& stage)
     : GrGLProgramStage(factory)
-    , fImageIncrementVar(NULL)
+    , fImageIncrementUni(GrGLShaderBuilder::kInvalidUniformHandle)
     , fImageIncrementLocation(0) {
     const GrMorphologyEffect& m = static_cast<const GrMorphologyEffect&>(stage);
     fRadius = m.radius();
     fType = m.type();
 }
 
-void GrGLMorphologyEffect::setupVariables(GrGLShaderBuilder* state, int stage) {
-    fImageIncrementVar = &state->addUniform(GrGLShaderBuilder::kFragment_ShaderType |
-                                            GrGLShaderBuilder::kVertex_ShaderType,
-                                            kVec2f_GrSLType, "uImageIncrement", stage);
+void GrGLMorphologyEffect::setupVariables(GrGLShaderBuilder* builder, int stage) {
+    fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType |
+                                             GrGLShaderBuilder::kVertex_ShaderType,
+                                             kVec2f_GrSLType, "uImageIncrement", stage);
 }
 
-void GrGLMorphologyEffect::emitVS(GrGLShaderBuilder* state,
+void GrGLMorphologyEffect::emitVS(GrGLShaderBuilder* builder,
                                   const char* vertexCoords) {
-    SkString* code = &state->fVSCode;
-    code->appendf("\t\t%s -= vec2(%d, %d) * %s;\n",
-                  vertexCoords, fRadius, fRadius,
-                  fImageIncrementVar->getName().c_str());
+    SkString* code = &builder->fVSCode;
+    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
+    code->appendf("\t\t%s -= vec2(%d, %d) * %s;\n", vertexCoords, fRadius, fRadius, imgInc);
 }
 
-void GrGLMorphologyEffect::initUniforms(const GrGLInterface* gl,
+void GrGLMorphologyEffect::initUniforms(const GrGLShaderBuilder* builder,
+                                        const GrGLInterface* gl,
                                         int programID) {
-    GR_GL_CALL_RET(gl, fImageIncrementLocation,
-        GetUniformLocation(programID,
-            fImageIncrementVar->getName().c_str()));
+    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
+    GR_GL_CALL_RET(gl, fImageIncrementLocation, GetUniformLocation(programID, imgInc));
 }
 
-void GrGLMorphologyEffect ::emitFS(GrGLShaderBuilder* state,
+void GrGLMorphologyEffect ::emitFS(GrGLShaderBuilder* builder,
                                    const char* outputColor,
                                    const char* inputColor,
                                    const char* samplerName) {
-    SkString* code = &state->fFSCode;
-    // const char* texFunc = "texture2D";
-    // bool complexCoord = false;
+    SkString* code = &builder->fFSCode;
 
     const char* func;
     switch (fType) {
         case GrContext::kErode_MorphologyType:
-            state->fFSCode.appendf("\t\tvec4 value = vec4(1, 1, 1, 1);\n");
+            code->appendf("\t\tvec4 value = vec4(1, 1, 1, 1);\n");
             func = "min";
             break;
         case GrContext::kDilate_MorphologyType:
-            state->fFSCode.appendf("\t\tvec4 value = vec4(0, 0, 0, 0);\n");
+            code->appendf("\t\tvec4 value = vec4(0, 0, 0, 0);\n");
             func = "max";
             break;
         default:
@@ -100,19 +99,16 @@
             func = ""; // suppress warning
             break;
     }
+    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
 
-    code->appendf("\t\tvec2 coord = %s;\n", state->fSampleCoords.c_str());
+    code->appendf("\t\tvec2 coord = %s;\n", builder->fSampleCoords.c_str());
     code->appendf("\t\tfor (int i = 0; i < %d; i++) {\n", this->width());
-    state->fFSCode.appendf("\t\t\tvalue = %s(value, ", func);
-    state->emitTextureLookup(samplerName, "coord");
-    state->fFSCode.appendf(");\n");
-    code->appendf("\t\t\tcoord += %s;\n",
-                  fImageIncrementVar->getName().c_str());
+    code->appendf("\t\t\tvalue = %s(value, ", func);
+    builder->emitTextureLookup(samplerName, "coord");
+    code->appendf(");\n");
+    code->appendf("\t\t\tcoord += %s;\n", imgInc);
     code->appendf("\t\t}\n");
-
-    state->fFSCode.appendf("\t\t%s = value%s;\n",
-                           outputColor,
-                           state->fModulate.c_str());
+    code->appendf("\t\t%s = value%s;\n", outputColor, builder->fModulate.c_str());
 }
 
 GrGLProgramStage::StageKey GrGLMorphologyEffect::GenKey(
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 1ad9817..d13620c 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -932,7 +932,7 @@
         return false;
     }
 
-    this->getUniformLocationsAndInitCache(gl, programData);
+    this->getUniformLocationsAndInitCache(builder, gl, programData);
 
     return true;
 }
@@ -1003,7 +1003,8 @@
     return true;
 }
 
-void GrGLProgram::getUniformLocationsAndInitCache(const GrGLContextInfo& gl,
+void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& builder,
+                                                  const GrGLContextInfo& gl,
                                                   CachedData* programData) const {
     const GrGLint& progID = programData->fProgramID;
 
@@ -1066,8 +1067,7 @@
             }
 
             if (NULL != programData->fCustomStage[s]) {
-                programData->fCustomStage[s]->
-                    initUniforms(gl.interface(), progID);
+                programData->fCustomStage[s]->initUniforms(&builder, gl.interface(), progID);
             }
         }
     }
@@ -1118,10 +1118,12 @@
     } else {
         SkString texMatName;
         tex_matrix_name(stageNum, &texMatName);
-        const GrGLShaderVar* mat = &segments->addUniform(GrGLShaderBuilder::kVertex_ShaderType,
-                                                         kMat33f_GrSLType, texMatName.c_str());
+        GrGLShaderBuilder::UniformHandle m =
+            segments->addUniform(GrGLShaderBuilder::kVertex_ShaderType,
+                                 kMat33f_GrSLType, texMatName.c_str());
+        const GrGLShaderVar& mat = segments->getUniformVariable(m);
         // Can't use texMatName.c_str() because it's on the stack!
-        matName = mat->getName().c_str();
+        matName = mat.getName().c_str();
         locations->fTextureMatrixUni = kUseUniform;
 
         if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 0be08b3..bebaa58 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -366,7 +366,8 @@
                 CachedData* programData) const;
 
     // Binds uniforms; initializes cache to invalid values.
-    void getUniformLocationsAndInitCache(const GrGLContextInfo& gl,
+    void getUniformLocationsAndInitCache(const GrGLShaderBuilder& builder,
+                                         const GrGLContextInfo& gl,
                                          CachedData* programData) const;
 
     friend class GrGpuGL;
diff --git a/src/gpu/gl/GrGLProgramStage.cpp b/src/gpu/gl/GrGLProgramStage.cpp
index c1d4942..fe103ad 100644
--- a/src/gpu/gl/GrGLProgramStage.cpp
+++ b/src/gpu/gl/GrGLProgramStage.cpp
@@ -17,11 +17,13 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrGLProgramStage::setupVariables(GrGLShaderBuilder* state, int stage) {
+void GrGLProgramStage::setupVariables(GrGLShaderBuilder*, int stage) {
 
 }
 
-void GrGLProgramStage::initUniforms(const GrGLInterface*, int progID) {
+void GrGLProgramStage::initUniforms(const GrGLShaderBuilder*,
+                                    const GrGLInterface*,
+                                    int progID) {
 
 }
 
diff --git a/src/gpu/gl/GrGLProgramStage.h b/src/gpu/gl/GrGLProgramStage.h
index d5c79b4..6350ae3 100644
--- a/src/gpu/gl/GrGLProgramStage.h
+++ b/src/gpu/gl/GrGLProgramStage.h
@@ -48,7 +48,7 @@
     virtual ~GrGLProgramStage();
 
     /** Create any uniforms or varyings the vertex shader requires. */
-    virtual void setupVariables(GrGLShaderBuilder* state, int stage);
+    virtual void setupVariables(GrGLShaderBuilder* builder, int stage);
 
     /** Appends vertex code to the appropriate SkString
         on the state.
@@ -56,7 +56,7 @@
         Vertex shader input is a vec2 of coordinates, which may
         be altered.
         The code will be inside an otherwise-empty block. */
-    virtual void emitVS(GrGLShaderBuilder* state,
+    virtual void emitVS(GrGLShaderBuilder* builder,
                         const char* vertexCoords) = 0;
 
     /** Appends fragment code to the appropriate SkString
@@ -68,14 +68,16 @@
        a function here for them to call into that'll apply any texture
        domain - but do we force them to be honest about texture domain
        parameters? */
-    virtual void emitFS(GrGLShaderBuilder* state,
+    virtual void emitFS(GrGLShaderBuilder* builder,
                         const char* outputColor,
                         const char* inputColor,
                         const char* samplerName) = 0;
 
     /** Binds uniforms; we must have already bound the program and
         determined its GL program ID. */
-    virtual void initUniforms(const GrGLInterface* gl, int programID);
+    virtual void initUniforms(const GrGLShaderBuilder* builder,
+                              const GrGLInterface* gl,
+                              int programID);
 
     /** A GrGLCustomStage instance can be reused with any GrCustomStage
         that produces the same stage key; this function reads data from
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 3303bf2..7fa804a 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -23,13 +23,12 @@
 //const int GrGLShaderBuilder::fCoordDims = 2;
 
 GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctx)
-    : fVSUnis(kVarsPerBlock)
+    : fUniforms(kVarsPerBlock)
     , fVSAttrs(kVarsPerBlock)
     , fVSOutputs(kVarsPerBlock)
     , fGSInputs(kVarsPerBlock)
     , fGSOutputs(kVarsPerBlock)
     , fFSInputs(kVarsPerBlock)
-    , fFSUnis(kVarsPerBlock)
     , fFSOutputs(kMaxFSOutputs)
     , fUsesGS(false)
     , fVaryingDims(0)
@@ -116,38 +115,45 @@
     fFSCode.appendf("%s%s;\n", fSwizzle.c_str(), fModulate.c_str());
 }
 
-const GrGLShaderVar& GrGLShaderBuilder::addUniform(uint32_t visibility,
-                                                   GrSLType type,
-                                                   const char* name,
-                                                   int stageNum,
-                                                   int count) {
+namespace {
+inline int handle_to_index(GrGLShaderBuilder::UniformHandle h) { return ~h; }
+inline GrGLShaderBuilder::UniformHandle index_to_handle(int i) { return ~i; }
+}
+
+GrGLShaderBuilder::UniformHandle GrGLShaderBuilder::addUniform(uint32_t visibility,
+                                                               GrSLType type,
+                                                               const char* name,
+                                                               int stageNum,
+                                                               int count) {
     GrAssert(name && strlen(name));
     static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType;
     GrAssert(0 == (~kVisibilityMask & visibility));
     GrAssert(0 != visibility);
 
-    GrGLShaderVar* var = NULL;
-    if (kVertex_ShaderType & visibility) {
-        var = &fVSUnis.push_back();
-    } else {
-        GrAssert(kFragment_ShaderType & visibility);
-        var = &fFSUnis.push_back();
-    }
-    var->setType(type);
-    var->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
-    var->setName(name);
+    Uniform& uni = fUniforms.push_back();
+    UniformHandle h = index_to_handle(fUniforms.count() - 1);
+    uni.fVariable.setType(type);
+    uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
+    uni.fVariable.setName(name);
     if (stageNum >= 0) {
-        var->accessName()->appendS32(stageNum);
+        uni.fVariable.accessName()->appendS32(stageNum);
     }
-    var->setArrayCount(count);
+    uni.fVariable.setArrayCount(count);
+    uni.fVisibility = visibility;
 
+    // If it is visible in both the VS and FS, the precision must match.
+    // We declare a default FS precision, but not a default VS. So set the var
+    // to use the default FS precision.
     if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) {
         // the fragment and vertex precisions must match
-        var->setPrecision(kDefaultFragmentPrecision);
-        fFSUnis.push_back(*var);
+        uni.fVariable.setPrecision(kDefaultFragmentPrecision);
     }
 
-    return *var;
+    return h;
+}
+
+const GrGLShaderVar& GrGLShaderBuilder::getUniformVariable(UniformHandle u) const {
+    return fUniforms[handle_to_index(u)].fVariable;
 }
 
 void GrGLShaderBuilder::addVarying(GrSLType type,
@@ -222,31 +228,37 @@
         }
     }
 }
+}
 
-void append_decls(const GrGLShaderBuilder::VarArray& vars,
-                  const GrGLContextInfo& ctx,
-                  SkString* string) {
+void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
     for (int i = 0; i < vars.count(); ++i) {
-        vars[i].appendDecl(ctx, string);
+        vars[i].appendDecl(fContext, out);
     }
 }
+
+void GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) const {
+    for (int i = 0; i < fUniforms.count(); ++i) {
+        if (fUniforms[i].fVisibility & stype) {
+            fUniforms[i].fVariable.appendDecl(fContext, out);
+        }
+    }
 }
 
 void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
     switch (type) {
         case kVertex_ShaderType:
             *shaderStr = fHeader;
-            append_decls(fVSUnis, fContext, shaderStr);
-            append_decls(fVSAttrs, fContext, shaderStr);
-            append_decls(fVSOutputs, fContext, shaderStr);
+            this->appendUniformDecls(kVertex_ShaderType, shaderStr);
+            this->appendDecls(fVSAttrs, shaderStr);
+            this->appendDecls(fVSOutputs, shaderStr);
             shaderStr->append(fVSCode);
             break;
         case kGeometry_ShaderType:
             if (fUsesGS) {
                 *shaderStr = fHeader;
                 shaderStr->append(fGSHeader);
-                append_decls(fGSInputs, fContext, shaderStr);
-                append_decls(fGSOutputs, fContext, shaderStr);
+                this->appendDecls(fGSInputs, shaderStr);
+                this->appendDecls(fGSOutputs, shaderStr);
                 shaderStr->append(fGSCode);
             } else {
                 shaderStr->reset();
@@ -257,11 +269,11 @@
             append_default_precision_qualifier(kDefaultFragmentPrecision,
                                                fContext.binding(),
                                                shaderStr);
-            append_decls(fFSUnis, fContext, shaderStr);
-            append_decls(fFSInputs, fContext, shaderStr);
+            this->appendUniformDecls(kFragment_ShaderType, shaderStr);
+            this->appendDecls(fFSInputs, shaderStr);
             // We shouldn't have declared outputs on 1.10
             GrAssert(k110_GrGLSLGeneration != fContext.glslGeneration() || fFSOutputs.empty());
-            append_decls(fFSOutputs, fContext, shaderStr);
+            this->appendDecls(fFSOutputs, shaderStr);
             shaderStr->append(fFSFunctions);
             shaderStr->append(fFSCode);
             break;
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index 5884a90..892fcbe 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -22,7 +22,9 @@
 class GrGLShaderBuilder {
 
 public:
-    typedef GrTAllocator<GrGLShaderVar> VarArray;
+
+    typedef int UniformHandle;
+    static const UniformHandle kInvalidUniformHandle = 0;
 
     enum ShaderType {
         kVertex_ShaderType   = 0x1,
@@ -62,11 +64,20 @@
         from which shaders the uniform should be accessible. At least one bit must be set. Geometry
         shader uniforms are not supported at this time.
     */
-    const GrGLShaderVar& addUniform(uint32_t visibility,
-                                    GrSLType type,
-                                    const char* name,
-                                    int stageNum = -1,
-                                    int count = GrGLShaderVar::kNonArray);
+    UniformHandle addUniform(uint32_t visibility,
+                             GrSLType type,
+                             const char* name,
+                             int stageNum = -1,
+                             int count = GrGLShaderVar::kNonArray);
+
+    const GrGLShaderVar& getUniformVariable(UniformHandle) const;
+
+    /**
+     * Shorcut for getUniformVariable(u).c_str()
+     */
+    const char* getUniformCStr(UniformHandle u) const {
+        return this->getUniformVariable(u).c_str();
+    }
 
     /** Add a varying variable to the current program to pass values between vertex and fragment
         shaders. If the last two parameters are non-NULL, they are filled in with the name
@@ -88,17 +99,30 @@
     /** Called after building is complete to get the final shader string. */
     void getShader(ShaderType, SkString*) const;
 
+private:
+    typedef GrTAllocator<GrGLShaderVar> VarArray;
+
+    struct Uniform {
+        GrGLShaderVar fVariable;
+        uint32_t      fVisibility;
+    };
+
+    typedef GrTAllocator<Uniform> UniformArray;
+    void appendDecls(const VarArray&, SkString*) const;
+    void appendUniformDecls(ShaderType, SkString*) const;
+
+    UniformArray fUniforms;
+
     // TODO: Everything below here private.
+public:
 
     SkString    fHeader; // VS+FS, GLSL version, etc
-    VarArray    fVSUnis;
     VarArray    fVSAttrs;
     VarArray    fVSOutputs;
     VarArray    fGSInputs;
     VarArray    fGSOutputs;
     VarArray    fFSInputs;
     SkString    fGSHeader; // layout qualifiers specific to GS
-    VarArray    fFSUnis;
     VarArray    fFSOutputs;
     SkString    fFSFunctions;
     SkString    fVSCode;
diff --git a/src/gpu/gl/GrGLShaderVar.h b/src/gpu/gl/GrGLShaderVar.h
index 2eccd3b..0231d21 100644
--- a/src/gpu/gl/GrGLShaderVar.h
+++ b/src/gpu/gl/GrGLShaderVar.h
@@ -171,12 +171,18 @@
      */
     void setName(const SkString& n) { fName = n; }
     void setName(const char* n) { fName = n; }
+
     /**
      * Get the var name.
      */
     const SkString& getName() const { return fName; }
 
     /**
+     * Shortcut for this->getName().c_str();
+     */
+    const char* c_str() const { return this->getName().c_str(); }
+
+    /**
      * Get the type of the var
      */
     GrSLType getType() const { return fType; }