Initial refactor of shaderbuilder to prepare for geometry shaders

gitignore for eclipse

BUG=skia:
R=bsalomon@google.com, bsalomon@chromium.org

Author: joshualitt@chromium.org

Review URL: https://codereview.chromium.org/491673002
diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp
index 6f3772d..7384f62 100644
--- a/src/gpu/effects/GrBezierEffect.cpp
+++ b/src/gpu/effects/GrBezierEffect.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrBezierEffect.h"
 
 #include "gl/GrGLEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLVertexEffect.h"
 #include "GrTBackendEffectFactory.h"
@@ -17,7 +17,7 @@
 public:
     GrGLConicEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLFullShaderBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -42,7 +42,7 @@
     fEdgeType = ce.getEdgeType();
 }
 
-void GrGLConicEffect::emitCode(GrGLFullShaderBuilder* builder,
+void GrGLConicEffect::emitCode(GrGLFullProgramBuilder* builder,
                                const GrDrawEffect& drawEffect,
                                const GrEffectKey& key,
                                const char* outputColor,
@@ -53,67 +53,70 @@
 
     builder->addVarying(kVec4f_GrSLType, "ConicCoeffs",
                               &vsName, &fsName);
-    const SkString* attr0Name =
-        builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
-    builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str());
 
-    builder->fsCodeAppend("\t\tfloat edgeAlpha;\n");
+    GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
+    const SkString* attr0Name =
+        vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+    vsBuilder->codeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str());
+
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    fsBuilder->codeAppend("\t\tfloat edgeAlpha;\n");
 
     switch (fEdgeType) {
         case kHairlineAA_GrEffectEdgeType: {
-            SkAssertResult(builder->enableFeature(
-                    GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
-            builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
-            builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
-            builder->fsCodeAppendf("\t\tfloat dfdx =\n"
+            SkAssertResult(fsBuilder->enableFeature(
+                    GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
+            fsBuilder->codeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
+            fsBuilder->codeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
+            fsBuilder->codeAppendf("\t\tfloat dfdx =\n"
                                    "\t\t\t2.0*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n",
                                    fsName, fsName, fsName);
-            builder->fsCodeAppendf("\t\tfloat dfdy =\n"
+            fsBuilder->codeAppendf("\t\tfloat dfdy =\n"
                                    "\t\t\t2.0*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n",
                                    fsName, fsName, fsName);
-            builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
-            builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
-            builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName,
+            fsBuilder->codeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
+            fsBuilder->codeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
+            fsBuilder->codeAppendf("\t\tfloat func = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName,
                                    fsName, fsName);
-            builder->fsCodeAppend("\t\tfunc = abs(func);\n");
-            builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
-            builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
+            fsBuilder->codeAppend("\t\tfunc = abs(func);\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = func / gFM;\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
             // Add line below for smooth cubic ramp
-            // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
+            // fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
             break;
         }
         case kFillAA_GrEffectEdgeType: {
-            SkAssertResult(builder->enableFeature(
-                    GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
-            builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
-            builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
-            builder->fsCodeAppendf("\t\tfloat dfdx =\n"
+            SkAssertResult(fsBuilder->enableFeature(
+                    GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
+            fsBuilder->codeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
+            fsBuilder->codeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
+            fsBuilder->codeAppendf("\t\tfloat dfdx =\n"
                                    "\t\t\t2.0*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n",
                                    fsName, fsName, fsName);
-            builder->fsCodeAppendf("\t\tfloat dfdy =\n"
+            fsBuilder->codeAppendf("\t\tfloat dfdy =\n"
                                    "\t\t\t2.0*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n",
                                    fsName, fsName, fsName);
-            builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
-            builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
-            builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName,
+            fsBuilder->codeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
+            fsBuilder->codeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
+            fsBuilder->codeAppendf("\t\tfloat func = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName,
                                    fsName, fsName);
-            builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
-            builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = func / gFM;\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
             // Add line below for smooth cubic ramp
-            // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
+            // fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
             break;
         }
         case kFillBW_GrEffectEdgeType: {
-            builder->fsCodeAppendf("\t\tedgeAlpha = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName,
+            fsBuilder->codeAppendf("\t\tedgeAlpha = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName,
                                    fsName, fsName);
-            builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n");
             break;
         }
         default:
             SkFAIL("Shouldn't get here");
     }
 
-    builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
+    fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
 }
 
@@ -167,7 +170,7 @@
 public:
     GrGLQuadEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLFullShaderBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -192,7 +195,7 @@
     fEdgeType = ce.getEdgeType();
 }
 
-void GrGLQuadEffect::emitCode(GrGLFullShaderBuilder* builder,
+void GrGLQuadEffect::emitCode(GrGLFullProgramBuilder* builder,
                               const GrDrawEffect& drawEffect,
                               const GrEffectKey& key,
                               const char* outputColor,
@@ -200,61 +203,61 @@
                               const TransformedCoordsArray&,
                               const TextureSamplerArray& samplers) {
     const char *vsName, *fsName;
-
-    const SkString* attrName =
-        builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
-    builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
-
     builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
 
+    GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
+    const SkString* attrName =
+        vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+    vsBuilder->codeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
+
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    fsBuilder->codeAppendf("\t\tfloat edgeAlpha;\n");
+
     switch (fEdgeType) {
         case kHairlineAA_GrEffectEdgeType: {
-            SkAssertResult(builder->enableFeature(
-                    GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
-            builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
-            builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
-            builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
+            SkAssertResult(fsBuilder->enableFeature(
+                    GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
+            fsBuilder->codeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
+            fsBuilder->codeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
+            fsBuilder->codeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
                                    "\t\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
                                    fsName, fsName);
-            builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
+            fsBuilder->codeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
                                    fsName);
-            builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
-            builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
             // Add line below for smooth cubic ramp
-            // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
+            // fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
             break;
         }
         case kFillAA_GrEffectEdgeType: {
-            SkAssertResult(builder->enableFeature(
-                    GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
-            builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
-            builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
-            builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
+            SkAssertResult(fsBuilder->enableFeature(
+                    GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
+            fsBuilder->codeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
+            fsBuilder->codeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
+            fsBuilder->codeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
                                    "\t\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
                                    fsName, fsName);
-            builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
+            fsBuilder->codeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
                                    fsName);
-            builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha / sqrt(dot(gF, gF));\n");
-            builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha / sqrt(dot(gF, gF));\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
             // Add line below for smooth cubic ramp
-            // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
+            // fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
             break;
         }
         case kFillBW_GrEffectEdgeType: {
-            builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
+            fsBuilder->codeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
                                    fsName);
-            builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n");
             break;
         }
         default:
             SkFAIL("Shouldn't get here");
     }
 
-    builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
+    fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
-
-
-    builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
 }
 
 void GrGLQuadEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&,
@@ -307,7 +310,7 @@
 public:
     GrGLCubicEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLFullShaderBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -332,7 +335,7 @@
     fEdgeType = ce.getEdgeType();
 }
 
-void GrGLCubicEffect::emitCode(GrGLFullShaderBuilder* builder,
+void GrGLCubicEffect::emitCode(GrGLFullProgramBuilder* builder,
                                const GrDrawEffect& drawEffect,
                                const GrEffectKey& key,
                                const char* outputColor,
@@ -343,67 +346,70 @@
 
     builder->addVarying(kVec4f_GrSLType, "CubicCoeffs",
                               &vsName, &fsName);
-    const SkString* attr0Name =
-        builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
-    builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str());
 
-    builder->fsCodeAppend("\t\tfloat edgeAlpha;\n");
+    GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
+    const SkString* attr0Name =
+        vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+    vsBuilder->codeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str());
+
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    fsBuilder->codeAppend("\t\tfloat edgeAlpha;\n");
 
     switch (fEdgeType) {
         case kHairlineAA_GrEffectEdgeType: {
-            SkAssertResult(builder->enableFeature(
-                    GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
-            builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
-            builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
-            builder->fsCodeAppendf("\t\tfloat dfdx =\n"
+            SkAssertResult(fsBuilder->enableFeature(
+                    GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
+            fsBuilder->codeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
+            fsBuilder->codeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
+            fsBuilder->codeAppendf("\t\tfloat dfdx =\n"
                                    "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n",
                                    fsName, fsName, fsName, fsName);
-            builder->fsCodeAppendf("\t\tfloat dfdy =\n"
+            fsBuilder->codeAppendf("\t\tfloat dfdy =\n"
                                    "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n",
                                    fsName, fsName, fsName, fsName);
-            builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
-            builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
-            builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n",
+            fsBuilder->codeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
+            fsBuilder->codeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
+            fsBuilder->codeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n",
                                    fsName, fsName, fsName, fsName, fsName);
-            builder->fsCodeAppend("\t\tfunc = abs(func);\n");
-            builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
-            builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
+            fsBuilder->codeAppend("\t\tfunc = abs(func);\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = func / gFM;\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
             // Add line below for smooth cubic ramp
-            // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
+            // fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
             break;
         }
         case kFillAA_GrEffectEdgeType: {
-            SkAssertResult(builder->enableFeature(
-                    GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
-            builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
-            builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
-            builder->fsCodeAppendf("\t\tfloat dfdx =\n"
+            SkAssertResult(fsBuilder->enableFeature(
+                    GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
+            fsBuilder->codeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
+            fsBuilder->codeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
+            fsBuilder->codeAppendf("\t\tfloat dfdx =\n"
                                    "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n",
                                    fsName, fsName, fsName, fsName);
-            builder->fsCodeAppendf("\t\tfloat dfdy =\n"
+            fsBuilder->codeAppendf("\t\tfloat dfdy =\n"
                                    "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n",
                                    fsName, fsName, fsName, fsName);
-            builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
-            builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
-            builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n",
+            fsBuilder->codeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
+            fsBuilder->codeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
+            fsBuilder->codeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n",
                                    fsName, fsName, fsName, fsName, fsName);
-            builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
-            builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = func / gFM;\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
             // Add line below for smooth cubic ramp
-            // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
+            // fsBuilder->codeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
             break;
         }
         case kFillBW_GrEffectEdgeType: {
-            builder->fsCodeAppendf("\t\tedgeAlpha = %s.x*%s.x*%s.x - %s.y*%s.z;\n",
+            fsBuilder->codeAppendf("\t\tedgeAlpha = %s.x*%s.x*%s.x - %s.y*%s.z;\n",
                                    fsName, fsName, fsName, fsName, fsName);
-            builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n");
+            fsBuilder->codeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n");
             break;
         }
         default:
             SkFAIL("Shouldn't get here");
     }
 
-    builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
+    fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
 }
 
diff --git a/src/gpu/effects/GrBicubicEffect.cpp b/src/gpu/effects/GrBicubicEffect.cpp
index fb98b4a..27d482a 100644
--- a/src/gpu/effects/GrBicubicEffect.cpp
+++ b/src/gpu/effects/GrBicubicEffect.cpp
@@ -5,9 +5,9 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrBicubicEffect.h"
 
-#include "gl/GrGLShaderBuilder.h"
 
 #define DS(x) SkDoubleToScalar(x)
 
@@ -24,7 +24,7 @@
     GrGLBicubicEffect(const GrBackendEffectFactory& factory,
                       const GrDrawEffect&);
 
-    virtual void emitCode(GrGLShaderBuilder*,
+    virtual void emitCode(GrGLProgramBuilder*,
                           const GrDrawEffect&,
                           const GrEffectKey&,
                           const char* outputColor,
@@ -54,7 +54,7 @@
     : INHERITED(factory) {
 }
 
-void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder,
+void GrGLBicubicEffect::emitCode(GrGLProgramBuilder* builder,
                                  const GrDrawEffect& drawEffect,
                                  const GrEffectKey& key,
                                  const char* outputColor,
@@ -63,10 +63,9 @@
                                  const TextureSamplerArray& samplers) {
     const GrTextureDomain& domain = drawEffect.castEffect<GrBicubicEffect>().domain();
 
-    SkString coords2D = builder->ensureFSCoords2D(coords, 0);
-    fCoefficientsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fCoefficientsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                            kMat44f_GrSLType, "Coefficients");
-    fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                              kVec2f_GrSLType, "ImageIncrement");
 
     const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
@@ -82,7 +81,9 @@
         GrGLShaderVar("c2",            kVec4f_GrSLType),
         GrGLShaderVar("c3",            kVec4f_GrSLType),
     };
-    builder->fsEmitFunction(kVec4f_GrSLType,
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
+    fsBuilder->emitFunction(kVec4f_GrSLType,
                             "cubicBlend",
                             SK_ARRAY_COUNT(gCubicBlendArgs),
                             gCubicBlendArgs,
@@ -90,28 +91,28 @@
                             "\tvec4 c = coefficients * ts;\n"
                             "\treturn c.x * c0 + c.y * c1 + c.z * c2 + c.w * c3;\n",
                             &cubicBlendName);
-    builder->fsCodeAppendf("\tvec2 coord = %s - %s * vec2(0.5);\n", coords2D.c_str(), imgInc);
+    fsBuilder->codeAppendf("\tvec2 coord = %s - %s * vec2(0.5);\n", coords2D.c_str(), imgInc);
     // We unnormalize the coord in order to determine our fractional offset (f) within the texel
     // We then snap coord to a texel center and renormalize. The snap prevents cases where the
     // starting coords are near a texel boundary and accumulations of imgInc would cause us to skip/
     // double hit a texel.
-    builder->fsCodeAppendf("\tcoord /= %s;\n", imgInc);
-    builder->fsCodeAppend("\tvec2 f = fract(coord);\n");
-    builder->fsCodeAppendf("\tcoord = (coord - f + vec2(0.5)) * %s;\n", imgInc);
-    builder->fsCodeAppend("\tvec4 rowColors[4];\n");
+    fsBuilder->codeAppendf("\tcoord /= %s;\n", imgInc);
+    fsBuilder->codeAppend("\tvec2 f = fract(coord);\n");
+    fsBuilder->codeAppendf("\tcoord = (coord - f + vec2(0.5)) * %s;\n", imgInc);
+    fsBuilder->codeAppend("\tvec4 rowColors[4];\n");
     for (int y = 0; y < 4; ++y) {
         for (int x = 0; x < 4; ++x) {
             SkString coord;
             coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1);
             SkString sampleVar;
             sampleVar.printf("rowColors[%d]", x);
-            fDomain.sampleTexture(builder, domain, sampleVar.c_str(), coord, samplers[0]);
+            fDomain.sampleTexture(fsBuilder, domain, sampleVar.c_str(), coord, samplers[0]);
         }
-        builder->fsCodeAppendf("\tvec4 s%d = %s(%s, f.x, rowColors[0], rowColors[1], rowColors[2], rowColors[3]);\n", y, cubicBlendName.c_str(), coeff);
+        fsBuilder->codeAppendf("\tvec4 s%d = %s(%s, f.x, rowColors[0], rowColors[1], rowColors[2], rowColors[3]);\n", y, cubicBlendName.c_str(), coeff);
     }
     SkString bicubicColor;
     bicubicColor.printf("%s(%s, f.y, s0, s1, s2, s3)", cubicBlendName.c_str(), coeff);
-    builder->fsCodeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(bicubicColor.c_str()) * GrGLSLExpr4(inputColor)).c_str());
+    fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(bicubicColor.c_str()) * GrGLSLExpr4(inputColor)).c_str());
 }
 
 void GrGLBicubicEffect::setData(const GrGLProgramDataManager& pdman,
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index d7ba686..84e60cd 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -10,7 +10,7 @@
 #include "GrTBackendEffectFactory.h"
 #include "GrSimpleTextureEffect.h"
 #include "gl/GrGLEffect.h"
-#include "gl/GrGLShaderBuilder.h"
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "SkMatrix.h"
 
 class GrGLConfigConversionEffect : public GrGLEffect {
@@ -23,7 +23,7 @@
         fPMConversion = effect.pmConversion();
     }
 
-    virtual void emitCode(GrGLShaderBuilder* builder,
+    virtual void emitCode(GrGLProgramBuilder* builder,
                           const GrDrawEffect&,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -34,20 +34,23 @@
         GrGLShaderVar tmpVar("tmpColor", kVec4f_GrSLType, 0, GrGLShaderVar::kHigh_Precision);
         SkString tmpDecl;
         tmpVar.appendDecl(builder->ctxInfo(), &tmpDecl);
-        builder->fsCodeAppendf("%s;", tmpDecl.c_str());
 
-        builder->fsCodeAppendf("%s = ", tmpVar.c_str());
-        builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
-        builder->fsCodeAppend(";");
+        GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+
+        fsBuilder->codeAppendf("%s;", tmpDecl.c_str());
+
+        fsBuilder->codeAppendf("%s = ", tmpVar.c_str());
+        fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
+        fsBuilder->codeAppend(";");
 
         if (GrConfigConversionEffect::kNone_PMConversion == fPMConversion) {
             SkASSERT(fSwapRedAndBlue);
-            builder->fsCodeAppendf("%s = %s.bgra;", outputColor, tmpVar.c_str());
+            fsBuilder->codeAppendf("%s = %s.bgra;", outputColor, tmpVar.c_str());
         } else {
             const char* swiz = fSwapRedAndBlue ? "bgr" : "rgb";
             switch (fPMConversion) {
                 case GrConfigConversionEffect::kMulByAlpha_RoundUp_PMConversion:
-                    builder->fsCodeAppendf(
+                    fsBuilder->codeAppendf(
                         "%s = vec4(ceil(%s.%s * %s.a * 255.0) / 255.0, %s.a);",
                         tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
                     break;
@@ -56,17 +59,17 @@
                     // In Intel GPUs, the integer value converted from floor(%s.r * 255.0) / 255.0
                     // is less than the integer value converted from  %s.r by 1 when the %s.r is
                     // converted from the integer value 2^n, such as 1, 2, 4, 8, etc.
-                    builder->fsCodeAppendf(
+                    fsBuilder->codeAppendf(
                         "%s = vec4(floor(%s.%s * %s.a * 255.0 + 0.001) / 255.0, %s.a);",
                         tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
                     break;
                 case GrConfigConversionEffect::kDivByAlpha_RoundUp_PMConversion:
-                    builder->fsCodeAppendf(
+                    fsBuilder->codeAppendf(
                         "%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.%s / %s.a * 255.0) / 255.0, %s.a);",
                         tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
                     break;
                 case GrConfigConversionEffect::kDivByAlpha_RoundDown_PMConversion:
-                    builder->fsCodeAppendf(
+                    fsBuilder->codeAppendf(
                         "%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.%s / %s.a * 255.0) / 255.0, %s.a);",
                         tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
                     break;
@@ -74,11 +77,11 @@
                     SkFAIL("Unknown conversion op.");
                     break;
             }
-            builder->fsCodeAppendf("%s = %s;", outputColor, tmpVar.c_str());
+            fsBuilder->codeAppendf("%s = %s;", outputColor, tmpVar.c_str());
         }
         SkString modulate;
         GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor);
-        builder->fsCodeAppend(modulate.c_str());
+        fsBuilder->codeAppend(modulate.c_str());
     }
 
     static inline void GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&,
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp
index 41911c1..71a8bef 100644
--- a/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrConvexPolyEffect.h"
 
 #include "gl/GrGLEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "GrTBackendEffectFactory.h"
 
@@ -89,7 +89,7 @@
 public:
     GLAARectEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLShaderBuilder* builder,
+    virtual void emitCode(GrGLProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -113,7 +113,7 @@
     fPrevRect.fLeft = SK_ScalarNaN;
 }
 
-void GLAARectEffect::emitCode(GrGLShaderBuilder* builder,
+void GLAARectEffect::emitCode(GrGLProgramBuilder* builder,
                               const GrDrawEffect& drawEffect,
                               const GrEffectKey& key,
                               const char* outputColor,
@@ -124,34 +124,36 @@
     const char *rectName;
     // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
     // respectively.
-    fRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                        kVec4f_GrSLType,
                                        "rect",
                                        &rectName);
-    const char* fragmentPos = builder->fragmentPosition();
+
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    const char* fragmentPos = fsBuilder->fragmentPosition();
     if (GrEffectEdgeTypeIsAA(aare.getEdgeType())) {
         // The amount of coverage removed in x and y by the edges is computed as a pair of negative
         // numbers, xSub and ySub.
-        builder->fsCodeAppend("\t\tfloat xSub, ySub;\n");
-        builder->fsCodeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName);
-        builder->fsCodeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos);
-        builder->fsCodeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName);
-        builder->fsCodeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos);
+        fsBuilder->codeAppend("\t\tfloat xSub, ySub;\n");
+        fsBuilder->codeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName);
+        fsBuilder->codeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos);
+        fsBuilder->codeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName);
+        fsBuilder->codeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos);
         // Now compute coverage in x and y and multiply them to get the fraction of the pixel
         // covered.
-        builder->fsCodeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
+        fsBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
     } else {
-        builder->fsCodeAppendf("\t\tfloat alpha = 1.0;\n");
-        builder->fsCodeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
-        builder->fsCodeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
-        builder->fsCodeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
-        builder->fsCodeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
+        fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n");
+        fsBuilder->codeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
+        fsBuilder->codeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
+        fsBuilder->codeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
+        fsBuilder->codeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
     }
 
     if (GrEffectEdgeTypeIsInverseFill(aare.getEdgeType())) {
-        builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n");
+        fsBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n");
     }
-    builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+    fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
 }
 
@@ -181,7 +183,7 @@
 public:
     GrGLConvexPolyEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLShaderBuilder* builder,
+    virtual void emitCode(GrGLProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -205,7 +207,7 @@
     fPrevEdges[0] = SK_ScalarNaN;
 }
 
-void GrGLConvexPolyEffect::emitCode(GrGLShaderBuilder* builder,
+void GrGLConvexPolyEffect::emitCode(GrGLProgramBuilder* builder,
                                     const GrDrawEffect& drawEffect,
                                     const GrEffectKey& key,
                                     const char* outputColor,
@@ -215,34 +217,35 @@
     const GrConvexPolyEffect& cpe = drawEffect.castEffect<GrConvexPolyEffect>();
 
     const char *edgeArrayName;
-    fEdgeUniform = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility,
+    fEdgeUniform = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec3f_GrSLType,
                                             "edges",
                                             cpe.getEdgeCount(),
                                             &edgeArrayName);
-    builder->fsCodeAppend("\t\tfloat alpha = 1.0;\n");
-    builder->fsCodeAppend("\t\tfloat edge;\n");
-    const char* fragmentPos = builder->fragmentPosition();
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    fsBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
+    fsBuilder->codeAppend("\t\tfloat edge;\n");
+    const char* fragmentPos = fsBuilder->fragmentPosition();
     for (int i = 0; i < cpe.getEdgeCount(); ++i) {
-        builder->fsCodeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n",
+        fsBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n",
                                edgeArrayName, i, fragmentPos, fragmentPos);
         if (GrEffectEdgeTypeIsAA(cpe.getEdgeType())) {
-            builder->fsCodeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n");
+            fsBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n");
         } else {
-            builder->fsCodeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n");
+            fsBuilder->codeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n");
         }
-        builder->fsCodeAppend("\t\talpha *= edge;\n");
+        fsBuilder->codeAppend("\t\talpha *= edge;\n");
     }
 
     // Woe is me. See skbug.com/2149.
     if (kTegra2_GrGLRenderer == builder->ctxInfo().renderer()) {
-        builder->fsCodeAppend("\t\tif (-1.0 == alpha) {\n\t\t\tdiscard;\n\t\t}\n");
+        fsBuilder->codeAppend("\t\tif (-1.0 == alpha) {\n\t\t\tdiscard;\n\t\t}\n");
     }
 
     if (GrEffectEdgeTypeIsInverseFill(cpe.getEdgeType())) {
-        builder->fsCodeAppend("\talpha = 1.0 - alpha;\n");
+        fsBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
     }
-    builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
+    fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
 }
 
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index e0cf35b..ba9f814 100644
--- a/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/src/gpu/effects/GrConvolutionEffect.cpp
@@ -5,9 +5,9 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrConvolutionEffect.h"
 #include "gl/GrGLEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
 #include "GrTBackendEffectFactory.h"
@@ -19,7 +19,7 @@
 public:
     GrGLConvolutionEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLShaderBuilder*,
+    virtual void emitCode(GrGLProgramBuilder*,
                           const GrDrawEffect&,
                           const GrEffectKey&,
                           const char* outputColor,
@@ -55,30 +55,32 @@
     fDirection = c.direction();
 }
 
-void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
+void GrGLConvolutionEffect::emitCode(GrGLProgramBuilder* builder,
                                      const GrDrawEffect&,
                                      const GrEffectKey& key,
                                      const char* outputColor,
                                      const char* inputColor,
                                      const TransformedCoordsArray& coords,
                                      const TextureSamplerArray& samplers) {
-    SkString coords2D = builder->ensureFSCoords2D(coords, 0);
-    fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                              kVec2f_GrSLType, "ImageIncrement");
     if (this->useBounds()) {
-        fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+        fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                          kVec2f_GrSLType, "Bounds");
     }
-    fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility,
+    fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
                                           kFloat_GrSLType, "Kernel", this->width());
 
-    builder->fsCodeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor);
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
+
+    fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor);
 
     int width = this->width();
     const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni);
     const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
 
-    builder->fsCodeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), fRadius, imgInc);
+    fsBuilder->codeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), fRadius, imgInc);
 
     // Manually unroll loop because some drivers don't; yields 20-30% speedup.
     for (int i = 0; i < width; i++) {
@@ -86,21 +88,21 @@
         SkString kernelIndex;
         index.appendS32(i);
         kernel.appendArrayAccess(index.c_str(), &kernelIndex);
-        builder->fsCodeAppendf("\t\t%s += ", outputColor);
-        builder->fsAppendTextureLookup(samplers[0], "coord");
+        fsBuilder->codeAppendf("\t\t%s += ", outputColor);
+        fsBuilder->appendTextureLookup(samplers[0], "coord");
         if (this->useBounds()) {
             const char* bounds = builder->getUniformCStr(fBoundsUni);
             const char* component = this->direction() == Gr1DKernelEffect::kY_Direction ? "y" : "x";
-            builder->fsCodeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s.y)",
+            fsBuilder->codeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s.y)",
                 component, bounds, component, bounds);
         }
-        builder->fsCodeAppendf(" * %s;\n", kernelIndex.c_str());
-        builder->fsCodeAppendf("\t\tcoord += %s;\n", imgInc);
+        fsBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str());
+        fsBuilder->codeAppendf("\t\tcoord += %s;\n", imgInc);
     }
 
     SkString modulate;
     GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor);
-    builder->fsCodeAppend(modulate.c_str());
+    fsBuilder->codeAppend(modulate.c_str());
 }
 
 void GrGLConvolutionEffect::setData(const GrGLProgramDataManager& pdman,
diff --git a/src/gpu/effects/GrCustomCoordsTextureEffect.cpp b/src/gpu/effects/GrCustomCoordsTextureEffect.cpp
index d235d5f..0401c6c 100644
--- a/src/gpu/effects/GrCustomCoordsTextureEffect.cpp
+++ b/src/gpu/effects/GrCustomCoordsTextureEffect.cpp
@@ -5,9 +5,9 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrCustomCoordsTextureEffect.h"
 #include "gl/GrGLEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
 #include "gl/GrGLVertexEffect.h"
@@ -19,7 +19,7 @@
     GrGLCustomCoordsTextureEffect(const GrBackendEffectFactory& factory, const GrDrawEffect& drawEffect)
         : INHERITED (factory) {}
 
-    virtual void emitCode(GrGLFullShaderBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -34,16 +34,18 @@
         builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsVaryingName, &fsVaryingNamePtr);
         fsCoordName = fsVaryingNamePtr;
 
-        const char* attrName =
-            builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str();
-        builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, attrName);
+        GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
+        const SkString* attr0Name =
+            vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+        vsBuilder->codeAppendf("\t%s = %s;\n", vsVaryingName, attr0Name->c_str());
 
-        builder->fsCodeAppendf("\t%s = ", outputColor);
-        builder->fsAppendTextureLookupAndModulate(inputColor,
+        GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+        fsBuilder->codeAppendf("\t%s = ", outputColor);
+        fsBuilder->appendTextureLookupAndModulate(inputColor,
                                                   samplers[0],
                                                   fsCoordName.c_str(),
                                                   kVec2f_GrSLType);
-        builder->fsCodeAppend(";\n");
+        fsBuilder->codeAppend(";\n");
     }
 
     virtual void setData(const GrGLProgramDataManager& pdman,
diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp
index f3af65e..4b2bafe 100644
--- a/src/gpu/effects/GrDashingEffect.cpp
+++ b/src/gpu/effects/GrDashingEffect.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrDashingEffect.h"
 
 #include "../GrAARectRenderer.h"
@@ -12,7 +13,6 @@
 #include "effects/GrVertexEffect.h"
 #include "gl/GrGLEffect.h"
 #include "gl/GrGLVertexEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "GrContext.h"
 #include "GrCoordTransform.h"
@@ -468,7 +468,7 @@
 public:
     GLDashingCircleEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLFullShaderBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -496,7 +496,7 @@
     fPrevIntervalLength = SK_ScalarMax;
 }
 
-void GLDashingCircleEffect::emitCode(GrGLFullShaderBuilder* builder,
+void GLDashingCircleEffect::emitCode(GrGLFullProgramBuilder* builder,
                                     const GrDrawEffect& drawEffect,
                                     const GrEffectKey& key,
                                     const char* outputColor,
@@ -507,32 +507,35 @@
     const char *paramName;
     // The param uniforms, xyz, refer to circle radius - 0.5, cicles center x coord, and
     // the total interval length of the dash.
-    fParamUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fParamUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                        kVec3f_GrSLType,
                                        "params",
                                        &paramName);
 
     const char *vsCoordName, *fsCoordName;
     builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
+
+    GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
     const SkString* attr0Name =
-        builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
-    builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str());
+        vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+    vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str());
 
     // transforms all points so that we can compare them to our test circle
-    builder->fsCodeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s.z) * %s.z;\n",
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s.z) * %s.z;\n",
                            fsCoordName, fsCoordName, paramName, paramName);
-    builder->fsCodeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
-    builder->fsCodeAppendf("\t\tvec2 center = vec2(%s.y, 0.0);\n", paramName);
-    builder->fsCodeAppend("\t\tfloat dist = length(center - fragPosShifted);\n");
+    fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
+    fsBuilder->codeAppendf("\t\tvec2 center = vec2(%s.y, 0.0);\n", paramName);
+    fsBuilder->codeAppend("\t\tfloat dist = length(center - fragPosShifted);\n");
     if (GrEffectEdgeTypeIsAA(dce.getEdgeType())) {
-        builder->fsCodeAppendf("\t\tfloat diff = dist - %s.x;\n", paramName);
-        builder->fsCodeAppend("\t\tdiff = 1.0 - diff;\n");
-        builder->fsCodeAppend("\t\tfloat alpha = clamp(diff, 0.0, 1.0);\n");
+        fsBuilder->codeAppendf("\t\tfloat diff = dist - %s.x;\n", paramName);
+        fsBuilder->codeAppend("\t\tdiff = 1.0 - diff;\n");
+        fsBuilder->codeAppend("\t\tfloat alpha = clamp(diff, 0.0, 1.0);\n");
     } else {
-        builder->fsCodeAppendf("\t\tfloat alpha = 1.0;\n");
-        builder->fsCodeAppendf("\t\talpha *=  dist < %s.x + 0.5 ? 1.0 : 0.0;\n", paramName);
+        fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n");
+        fsBuilder->codeAppendf("\t\talpha *=  dist < %s.x + 0.5 ? 1.0 : 0.0;\n", paramName);
     }
-    builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+    fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
 }
 
@@ -673,7 +676,7 @@
 public:
     GLDashingLineEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLFullShaderBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -700,7 +703,7 @@
     fPrevIntervalLength = SK_ScalarMax;
 }
 
-void GLDashingLineEffect::emitCode(GrGLFullShaderBuilder* builder,
+void GLDashingLineEffect::emitCode(GrGLFullProgramBuilder* builder,
                                     const GrDrawEffect& drawEffect,
                                     const GrEffectKey& key,
                                     const char* outputColor,
@@ -711,45 +714,47 @@
     const char *rectName;
     // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
     // respectively.
-    fRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                        kVec4f_GrSLType,
                                        "rect",
                                        &rectName);
     const char *intervalName;
     // The interval uniform's refers to the total length of the interval (on + off)
-    fIntervalUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fIntervalUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                        kFloat_GrSLType,
                                        "interval",
                                        &intervalName);
 
     const char *vsCoordName, *fsCoordName;
     builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
+    GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
     const SkString* attr0Name =
-        builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
-    builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str());
+        vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+    vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str());
 
     // transforms all points so that we can compare them to our test rect
-    builder->fsCodeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n",
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n",
                            fsCoordName, fsCoordName, intervalName, intervalName);
-    builder->fsCodeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
+    fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
     if (GrEffectEdgeTypeIsAA(de.getEdgeType())) {
         // The amount of coverage removed in x and y by the edges is computed as a pair of negative
         // numbers, xSub and ySub.
-        builder->fsCodeAppend("\t\tfloat xSub, ySub;\n");
-        builder->fsCodeAppendf("\t\txSub = min(fragPosShifted.x - %s.x, 0.0);\n", rectName);
-        builder->fsCodeAppendf("\t\txSub += min(%s.z - fragPosShifted.x, 0.0);\n", rectName);
-        builder->fsCodeAppendf("\t\tySub = min(fragPosShifted.y - %s.y, 0.0);\n", rectName);
-        builder->fsCodeAppendf("\t\tySub += min(%s.w - fragPosShifted.y, 0.0);\n", rectName);
+        fsBuilder->codeAppend("\t\tfloat xSub, ySub;\n");
+        fsBuilder->codeAppendf("\t\txSub = min(fragPosShifted.x - %s.x, 0.0);\n", rectName);
+        fsBuilder->codeAppendf("\t\txSub += min(%s.z - fragPosShifted.x, 0.0);\n", rectName);
+        fsBuilder->codeAppendf("\t\tySub = min(fragPosShifted.y - %s.y, 0.0);\n", rectName);
+        fsBuilder->codeAppendf("\t\tySub += min(%s.w - fragPosShifted.y, 0.0);\n", rectName);
         // Now compute coverage in x and y and multiply them to get the fraction of the pixel
         // covered.
-        builder->fsCodeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
+        fsBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
     } else {
         // Assuming the bounding geometry is tight so no need to check y values
-        builder->fsCodeAppendf("\t\tfloat alpha = 1.0;\n");
-        builder->fsCodeAppendf("\t\talpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName);
-        builder->fsCodeAppendf("\t\talpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;\n", rectName);
+        fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n");
+        fsBuilder->codeAppendf("\t\talpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName);
+        fsBuilder->codeAppendf("\t\talpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;\n", rectName);
     }
-    builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+    fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
 }
 
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
index 7ef1cbb..eaaefeb 100755
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
@@ -5,9 +5,9 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrDistanceFieldTextureEffect.h"
 #include "gl/GrGLEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
 #include "gl/GrGLVertexEffect.h"
@@ -36,7 +36,7 @@
         : INHERITED (factory)
         , fTextureSize(SkISize::Make(-1,-1)) {}
 
-    virtual void emitCode(GrGLFullShaderBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -45,7 +45,9 @@
                           const TextureSamplerArray& samplers) SK_OVERRIDE {
         SkASSERT(1 == drawEffect.castEffect<GrDistanceFieldTextureEffect>().numVertexAttribs());
 
-        SkAssertResult(builder->enableFeature(GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
+        GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+        SkAssertResult(fsBuilder->enableFeature(
+                GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
         const GrDistanceFieldTextureEffect& dfTexEffect =
                                               drawEffect.castEffect<GrDistanceFieldTextureEffect>();
 
@@ -55,73 +57,74 @@
         builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
         fsCoordName = fsCoordNamePtr;
 
-        const char* attrName0 =
-            builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str();
-        builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attrName0);
+        GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
+        const SkString* attr0Name =
+            vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+        vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str());
 
         const char* textureSizeUniName = NULL;
-        fTextureSizeUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+        fTextureSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                               kVec2f_GrSLType, "TextureSize",
                                               &textureSizeUniName);
 
-        builder->fsCodeAppend("\tvec4 texColor = ");
-        builder->fsAppendTextureLookup(samplers[0],
+        fsBuilder->codeAppend("\tvec4 texColor = ");
+        fsBuilder->appendTextureLookup(samplers[0],
                                        fsCoordName.c_str(),
                                        kVec2f_GrSLType);
-        builder->fsCodeAppend(";\n");
-        builder->fsCodeAppend("\tfloat distance = "
+        fsBuilder->codeAppend(";\n");
+        fsBuilder->codeAppend("\tfloat distance = "
                           SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ")"
                           "+ " SK_DistanceFieldNonLCDFactor ";\n");
 
         // we adjust for the effect of the transformation on the distance by using
         // the length of the gradient of the texture coordinates. We use st coordinates
         // to ensure we're mapping 1:1 from texel space to pixel space.
-        builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
-        builder->fsCodeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName);
-        builder->fsCodeAppend("\tfloat afwidth;\n");
+        fsBuilder->codeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
+        fsBuilder->codeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName);
+        fsBuilder->codeAppend("\tfloat afwidth;\n");
         if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
             // this gives us a smooth step across approximately one fragment
-            builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dFdx(st.x);\n");
+            fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dFdx(st.x);\n");
         } else {
-            builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n");
-            builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n");
+            fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n");
+            fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n");
 
-            builder->fsCodeAppend("\tvec2 uv_grad;\n");
+            fsBuilder->codeAppend("\tvec2 uv_grad;\n");
             if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) {
                 // this is to compensate for the Adreno, which likes to drop tiles on division by 0
-                builder->fsCodeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
-                builder->fsCodeAppend("\tif (uv_len2 < 0.0001) {\n");
-                builder->fsCodeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
-                builder->fsCodeAppend("\t} else {\n");
-                builder->fsCodeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
-                builder->fsCodeAppend("\t}\n");
+                fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
+                fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n");
+                fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
+                fsBuilder->codeAppend("\t} else {\n");
+                fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
+                fsBuilder->codeAppend("\t}\n");
             } else {
-                builder->fsCodeAppend("\tuv_grad = normalize(uv);\n");
+                fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n");
             }
-            builder->fsCodeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
-            builder->fsCodeAppend("\t                 uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
+            fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
+            fsBuilder->codeAppend("\t                 uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
 
             // this gives us a smooth step across approximately one fragment
-            builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
+            fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
         }
-        builder->fsCodeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n");
+        fsBuilder->codeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n");
 
 #ifdef SK_GAMMA_APPLY_TO_A8
         // adjust based on gamma
         const char* luminanceUniName = NULL;
         // width, height, 1/(3*width)
-        fLuminanceUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+        fLuminanceUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kFloat_GrSLType, "Luminance",
                                             &luminanceUniName);
 
-        builder->fsCodeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName);
-        builder->fsCodeAppend("\tvec4 gammaColor = ");
-        builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
-        builder->fsCodeAppend(";\n");
-        builder->fsCodeAppend("\tval = gammaColor.r;\n");
+        fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName);
+        fsBuilder->codeAppend("\tvec4 gammaColor = ");
+        fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
+        fsBuilder->codeAppend(";\n");
+        fsBuilder->codeAppend("\tval = gammaColor.r;\n");
 #endif
 
-        builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
+        fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
                                    (GrGLSLExpr4(inputColor) * GrGLSLExpr1("val")).c_str());
     }
 
@@ -261,7 +264,7 @@
     : INHERITED (factory)
     , fTextureSize(SkISize::Make(-1,-1)) {}
 
-    virtual void emitCode(GrGLFullShaderBuilder* builder,
+    virtual void emitCode(GrGLFullProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -270,7 +273,6 @@
                           const TextureSamplerArray& samplers) SK_OVERRIDE {
         SkASSERT(1 == drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>().numVertexAttribs());
 
-        SkAssertResult(builder->enableFeature(GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
         const GrDistanceFieldLCDTextureEffect& dfTexEffect =
                                            drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>();
 
@@ -280,49 +282,55 @@
         builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
         fsCoordName = fsCoordNamePtr;
 
-        const char* attrName0 =
-                   builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str();
-        builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attrName0);
+        GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
+        const SkString* attr0Name =
+            vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+        vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str());
 
         const char* textureSizeUniName = NULL;
         // width, height, 1/(3*width)
-        fTextureSizeUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+        fTextureSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                               kVec3f_GrSLType, "TextureSize",
                                               &textureSizeUniName);
 
+        GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+
+        SkAssertResult(fsBuilder->enableFeature(
+                GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
+
         // create LCD offset adjusted by inverse of transform
-        builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
-        builder->fsCodeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName);
+        fsBuilder->codeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
+        fsBuilder->codeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName);
         bool isUniformScale = !!(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask);
         if (isUniformScale) {
-            builder->fsCodeAppend("\tfloat dx = dFdx(st.x);\n");
-            builder->fsCodeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", textureSizeUniName);
+            fsBuilder->codeAppend("\tfloat dx = dFdx(st.x);\n");
+            fsBuilder->codeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", textureSizeUniName);
         } else {
-            builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n");
-            builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n");
-            builder->fsCodeAppendf("\tvec2 offset = %s.z*Jdx;\n", textureSizeUniName);
+            fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n");
+            fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n");
+            fsBuilder->codeAppendf("\tvec2 offset = %s.z*Jdx;\n", textureSizeUniName);
         }
 
         // green is distance to uv center
-        builder->fsCodeAppend("\tvec4 texColor = ");
-        builder->fsAppendTextureLookup(samplers[0], "uv", kVec2f_GrSLType);
-        builder->fsCodeAppend(";\n");
-        builder->fsCodeAppend("\tvec3 distance;\n");
-        builder->fsCodeAppend("\tdistance.y = texColor.r;\n");
+        fsBuilder->codeAppend("\tvec4 texColor = ");
+        fsBuilder->appendTextureLookup(samplers[0], "uv", kVec2f_GrSLType);
+        fsBuilder->codeAppend(";\n");
+        fsBuilder->codeAppend("\tvec3 distance;\n");
+        fsBuilder->codeAppend("\tdistance.y = texColor.r;\n");
         // red is distance to left offset
-        builder->fsCodeAppend("\tvec2 uv_adjusted = uv - offset;\n");
-        builder->fsCodeAppend("\ttexColor = ");
-        builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType);
-        builder->fsCodeAppend(";\n");
-        builder->fsCodeAppend("\tdistance.x = texColor.r;\n");
+        fsBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n");
+        fsBuilder->codeAppend("\ttexColor = ");
+        fsBuilder->appendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType);
+        fsBuilder->codeAppend(";\n");
+        fsBuilder->codeAppend("\tdistance.x = texColor.r;\n");
         // blue is distance to right offset
-        builder->fsCodeAppend("\tuv_adjusted = uv + offset;\n");
-        builder->fsCodeAppend("\ttexColor = ");
-        builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType);
-        builder->fsCodeAppend(";\n");
-        builder->fsCodeAppend("\tdistance.z = texColor.r;\n");
+        fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n");
+        fsBuilder->codeAppend("\ttexColor = ");
+        fsBuilder->appendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType);
+        fsBuilder->codeAppend(";\n");
+        fsBuilder->codeAppend("\tdistance.z = texColor.r;\n");
 
-        builder->fsCodeAppend("\tdistance = "
+        fsBuilder->codeAppend("\tdistance = "
             "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"))"
             "+ vec3(" SK_DistanceFieldLCDFactor ");\n");
 
@@ -334,58 +342,58 @@
         // for each color component. However, this is only important when using perspective
         // transformations, and even then using a single factor seems like a reasonable
         // trade-off between quality and speed.
-        builder->fsCodeAppend("\tfloat afwidth;\n");
+        fsBuilder->codeAppend("\tfloat afwidth;\n");
         if (isUniformScale) {
             // this gives us a smooth step across approximately one fragment
-            builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dx;\n");
+            fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dx;\n");
         } else {
-            builder->fsCodeAppend("\tvec2 uv_grad;\n");
+            fsBuilder->codeAppend("\tvec2 uv_grad;\n");
             if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) {
                 // this is to compensate for the Adreno, which likes to drop tiles on division by 0
-                builder->fsCodeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
-                builder->fsCodeAppend("\tif (uv_len2 < 0.0001) {\n");
-                builder->fsCodeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
-                builder->fsCodeAppend("\t} else {\n");
-                builder->fsCodeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
-                builder->fsCodeAppend("\t}\n");
+                fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
+                fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n");
+                fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
+                fsBuilder->codeAppend("\t} else {\n");
+                fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
+                fsBuilder->codeAppend("\t}\n");
             } else {
-                builder->fsCodeAppend("\tuv_grad = normalize(uv);\n");
+                fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n");
             }
-            builder->fsCodeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
-            builder->fsCodeAppend("\t                 uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
+            fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
+            fsBuilder->codeAppend("\t                 uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
 
             // this gives us a smooth step across approximately one fragment
-            builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
+            fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
         }
 
-        builder->fsCodeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);\n");
+        fsBuilder->codeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);\n");
 
         // adjust based on gamma
         const char* textColorUniName = NULL;
         // width, height, 1/(3*width)
-        fTextColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+        fTextColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec3f_GrSLType, "TextColor",
                                             &textColorUniName);
 
-        builder->fsCodeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName);
-        builder->fsCodeAppend("\tvec4 gammaColor = ");
-        builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
-        builder->fsCodeAppend(";\n");
-        builder->fsCodeAppend("\tval.x = gammaColor.r;\n");
+        fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName);
+        fsBuilder->codeAppend("\tvec4 gammaColor = ");
+        fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
+        fsBuilder->codeAppend(";\n");
+        fsBuilder->codeAppend("\tval.x = gammaColor.r;\n");
 
-        builder->fsCodeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName);
-        builder->fsCodeAppend("\tgammaColor = ");
-        builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
-        builder->fsCodeAppend(";\n");
-        builder->fsCodeAppend("\tval.y = gammaColor.r;\n");
+        fsBuilder->codeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName);
+        fsBuilder->codeAppend("\tgammaColor = ");
+        fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
+        fsBuilder->codeAppend(";\n");
+        fsBuilder->codeAppend("\tval.y = gammaColor.r;\n");
 
-        builder->fsCodeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName);
-        builder->fsCodeAppend("\tgammaColor = ");
-        builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
-        builder->fsCodeAppend(";\n");
-        builder->fsCodeAppend("\tval.z = gammaColor.r;\n");
+        fsBuilder->codeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName);
+        fsBuilder->codeAppend("\tgammaColor = ");
+        fsBuilder->appendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
+        fsBuilder->codeAppend(";\n");
+        fsBuilder->codeAppend("\tval.z = gammaColor.r;\n");
 
-        builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
+        fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
                                (GrGLSLExpr4(inputColor) * GrGLSLExpr4("val")).c_str());
     }
 
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.h b/src/gpu/effects/GrDistanceFieldTextureEffect.h
index ab84753..dca1949 100644
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.h
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.h
@@ -86,7 +86,7 @@
 
     GR_DECLARE_EFFECT_TEST;
 
-    typedef GrVertexEffect INHERITED;
+    typedef GrEffect INHERITED;
 };
 
 /**
@@ -131,7 +131,7 @@
 
     GR_DECLARE_EFFECT_TEST;
 
-    typedef GrVertexEffect INHERITED;
+    typedef GrEffect INHERITED;
 };
 
 #endif
diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp
index a431897..443df9e 100644
--- a/src/gpu/effects/GrDitherEffect.cpp
+++ b/src/gpu/effects/GrDitherEffect.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrDitherEffect.h"
 
 #include "gl/GrGLEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "GrTBackendEffectFactory.h"
 
@@ -70,7 +70,7 @@
 public:
     GLDitherEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLShaderBuilder* builder,
+    virtual void emitCode(GrGLProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -87,13 +87,14 @@
     : INHERITED (factory) {
 }
 
-void GLDitherEffect::emitCode(GrGLShaderBuilder* builder,
+void GLDitherEffect::emitCode(GrGLProgramBuilder* builder,
                               const GrDrawEffect& drawEffect,
                               const GrEffectKey& key,
                               const char* outputColor,
                               const char* inputColor,
                               const TransformedCoordsArray&,
                               const TextureSamplerArray& samplers) {
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
     // Generate a random number based on the fragment position. For this
     // random number generator, we use the "GLSL rand" function
     // that seems to be floating around on the internet. It works under
@@ -103,10 +104,10 @@
 
     // For each channel c, add the random offset to the pixel to either bump
     // it up or let it remain constant during quantization.
-    builder->fsCodeAppendf("\t\tfloat r = "
+    fsBuilder->codeAppendf("\t\tfloat r = "
                            "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n",
-                           builder->fragmentPosition());
-    builder->fsCodeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n",
+                           fsBuilder->fragmentPosition());
+    fsBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n",
                            outputColor, GrGLSLExpr4(inputColor).c_str());
 }
 
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index 01cf944..e573996 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -4,8 +4,8 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrMatrixConvolutionEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLEffect.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
@@ -15,7 +15,7 @@
 public:
     GrGLMatrixConvolutionEffect(const GrBackendEffectFactory& factory,
                                 const GrDrawEffect& effect);
-    virtual void emitCode(GrGLShaderBuilder*,
+    virtual void emitCode(GrGLProgramBuilder*,
                           const GrDrawEffect&,
                           const GrEffectKey&,
                           const char* outputColor,
@@ -51,7 +51,7 @@
     fConvolveAlpha = m.convolveAlpha();
 }
 
-void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
+void GrGLMatrixConvolutionEffect::emitCode(GrGLProgramBuilder* builder,
                                            const GrDrawEffect& drawEffect,
                                            const GrEffectKey& key,
                                            const char* outputColor,
@@ -60,20 +60,20 @@
                                            const TextureSamplerArray& samplers) {
     sk_ignore_unused_variable(inputColor);
     const GrTextureDomain& domain = drawEffect.castEffect<GrMatrixConvolutionEffect>().domain();
-    SkString coords2D = builder->ensureFSCoords2D(coords, 0);
-    fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+
+    fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                      kVec4f_GrSLType, "Bounds");
-    fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                              kVec2f_GrSLType, "ImageIncrement");
-    fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility,
+    fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
                                           kFloat_GrSLType,
                                           "Kernel",
                                           fKernelSize.width() * fKernelSize.height());
-    fKernelOffsetUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fKernelOffsetUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                            kVec2f_GrSLType, "KernelOffset");
-    fGainUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fGainUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                    kFloat_GrSLType, "Gain");
-    fBiasUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fBiasUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                    kFloat_GrSLType, "Bias");
 
     const char* kernelOffset = builder->getUniformCStr(fKernelOffsetUni);
@@ -84,38 +84,40 @@
     int kWidth = fKernelSize.width();
     int kHeight = fKernelSize.height();
 
-    builder->fsCodeAppend("vec4 sum = vec4(0, 0, 0, 0);");
-    builder->fsCodeAppendf("vec2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset,
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
+    fsBuilder->codeAppend("vec4 sum = vec4(0, 0, 0, 0);");
+    fsBuilder->codeAppendf("vec2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset,
                            imgInc);
-    builder->fsCodeAppend("vec4 c;");
+    fsBuilder->codeAppend("vec4 c;");
 
     for (int y = 0; y < kHeight; y++) {
         for (int x = 0; x < kWidth; x++) {
-            GrGLShaderBuilder::FSBlock block(builder);
-            builder->fsCodeAppendf("float k = %s[%d * %d + %d];", kernel, y, kWidth, x);
+            GrGLShaderBuilder::ShaderBlock block(fsBuilder);
+            fsBuilder->codeAppendf("float k = %s[%d * %d + %d];", kernel, y, kWidth, x);
             SkString coord;
             coord.printf("coord + vec2(%d, %d) * %s", x, y, imgInc);
-            fDomain.sampleTexture(builder, domain, "c", coord, samplers[0]);
+            fDomain.sampleTexture(fsBuilder, domain, "c", coord, samplers[0]);
             if (!fConvolveAlpha) {
-                builder->fsCodeAppend("c.rgb /= c.a;");
+                fsBuilder->codeAppend("c.rgb /= c.a;");
             }
-            builder->fsCodeAppend("sum += c * k;");
+            fsBuilder->codeAppend("sum += c * k;");
         }
     }
     if (fConvolveAlpha) {
-        builder->fsCodeAppendf("%s = sum * %s + %s;", outputColor, gain, bias);
-        builder->fsCodeAppendf("%s.rgb = clamp(%s.rgb, 0.0, %s.a);",
+        fsBuilder->codeAppendf("%s = sum * %s + %s;", outputColor, gain, bias);
+        fsBuilder->codeAppendf("%s.rgb = clamp(%s.rgb, 0.0, %s.a);",
                                outputColor, outputColor, outputColor);
     } else {
-        fDomain.sampleTexture(builder, domain, "c", coords2D, samplers[0]);
-        builder->fsCodeAppendf("%s.a = c.a;", outputColor);
-        builder->fsCodeAppendf("%s.rgb = sum.rgb * %s + %s;", outputColor, gain, bias);
-        builder->fsCodeAppendf("%s.rgb *= %s.a;", outputColor, outputColor);
+        fDomain.sampleTexture(fsBuilder, domain, "c", coords2D, samplers[0]);
+        fsBuilder->codeAppendf("%s.a = c.a;", outputColor);
+        fsBuilder->codeAppendf("%s.rgb = sum.rgb * %s + %s;", outputColor, gain, bias);
+        fsBuilder->codeAppendf("%s.rgb *= %s.a;", outputColor, outputColor);
     }
 
     SkString modulate;
     GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor);
-    builder->fsCodeAppend(modulate.c_str());
+    fsBuilder->codeAppend(modulate.c_str());
 }
 
 void GrGLMatrixConvolutionEffect::GenKey(const GrDrawEffect& drawEffect,
diff --git a/src/gpu/effects/GrOvalEffect.cpp b/src/gpu/effects/GrOvalEffect.cpp
index d915250..369b780 100644
--- a/src/gpu/effects/GrOvalEffect.cpp
+++ b/src/gpu/effects/GrOvalEffect.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrOvalEffect.h"
 
 #include "gl/GrGLEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "GrTBackendEffectFactory.h"
 
@@ -100,7 +100,7 @@
 public:
     GLCircleEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLShaderBuilder* builder,
+    virtual void emitCode(GrGLProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -126,7 +126,7 @@
     fPrevRadius = -1.f;
 }
 
-void GLCircleEffect::emitCode(GrGLShaderBuilder* builder,
+void GLCircleEffect::emitCode(GrGLProgramBuilder* builder,
                               const GrDrawEffect& drawEffect,
                               const GrEffectKey& key,
                               const char* outputColor,
@@ -137,27 +137,29 @@
     const char *circleName;
     // The circle uniform is (center.x, center.y, radius + 0.5) for regular fills and
     // (... ,radius - 0.5) for inverse fills.
-    fCircleUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fCircleUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                          kVec3f_GrSLType,
                                          "circle",
                                          &circleName);
-    const char* fragmentPos = builder->fragmentPosition();
+
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    const char* fragmentPos = fsBuilder->fragmentPosition();
 
     SkASSERT(kHairlineAA_GrEffectEdgeType != ce.getEdgeType());
     if (GrEffectEdgeTypeIsInverseFill(ce.getEdgeType())) {
-        builder->fsCodeAppendf("\t\tfloat d = length(%s.xy - %s.xy) - %s.z;\n",
+        fsBuilder->codeAppendf("\t\tfloat d = length(%s.xy - %s.xy) - %s.z;\n",
                                 circleName, fragmentPos, circleName);
     } else {
-        builder->fsCodeAppendf("\t\tfloat d = %s.z - length(%s.xy - %s.xy);\n",
+        fsBuilder->codeAppendf("\t\tfloat d = %s.z - length(%s.xy - %s.xy);\n",
                                circleName, fragmentPos, circleName);
     }
     if (GrEffectEdgeTypeIsAA(ce.getEdgeType())) {
-        builder->fsCodeAppend("\t\td = clamp(d, 0.0, 1.0);\n");
+        fsBuilder->codeAppend("\t\td = clamp(d, 0.0, 1.0);\n");
     } else {
-        builder->fsCodeAppend("\t\td = d > 0.5 ? 1.0 : 0.0;\n");
+        fsBuilder->codeAppend("\t\td = d > 0.5 ? 1.0 : 0.0;\n");
     }
 
-    builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+    fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("d")).c_str());
 }
 
@@ -272,7 +274,7 @@
 public:
     GLEllipseEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLShaderBuilder* builder,
+    virtual void emitCode(GrGLProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -298,7 +300,7 @@
     fPrevRadii.fX = -1.f;
 }
 
-void GLEllipseEffect::emitCode(GrGLShaderBuilder* builder,
+void GLEllipseEffect::emitCode(GrGLProgramBuilder* builder,
                                const GrDrawEffect& drawEffect,
                                const GrEffectKey& key,
                                const char* outputColor,
@@ -308,41 +310,43 @@
     const EllipseEffect& ee = drawEffect.castEffect<EllipseEffect>();
     const char *ellipseName;
     // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
-    fEllipseUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fEllipseUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                          kVec4f_GrSLType,
                                          "ellipse",
                                          &ellipseName);
-    const char* fragmentPos = builder->fragmentPosition();
+
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    const char* fragmentPos = fsBuilder->fragmentPosition();
 
     // d is the offset to the ellipse center
-    builder->fsCodeAppendf("\t\tvec2 d = %s.xy - %s.xy;\n", fragmentPos, ellipseName);
-    builder->fsCodeAppendf("\t\tvec2 Z = d * %s.zw;\n", ellipseName);
+    fsBuilder->codeAppendf("\t\tvec2 d = %s.xy - %s.xy;\n", fragmentPos, ellipseName);
+    fsBuilder->codeAppendf("\t\tvec2 Z = d * %s.zw;\n", ellipseName);
     // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
-    builder->fsCodeAppend("\t\tfloat implicit = dot(Z, d) - 1.0;\n");
+    fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, d) - 1.0;\n");
     // grad_dot is the squared length of the gradient of the implicit.
-    builder->fsCodeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
+    fsBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
     // avoid calling inversesqrt on zero.
-    builder->fsCodeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
-    builder->fsCodeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
+    fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
+    fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
 
     switch (ee.getEdgeType()) {
         case kFillAA_GrEffectEdgeType:
-            builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
+            fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
             break;
         case kInverseFillAA_GrEffectEdgeType:
-            builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
+            fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
             break;
         case kFillBW_GrEffectEdgeType:
-            builder->fsCodeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n");
+            fsBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n");
             break;
         case kInverseFillBW_GrEffectEdgeType:
-            builder->fsCodeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n");
+            fsBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n");
             break;
         case kHairlineAA_GrEffectEdgeType:
             SkFAIL("Hairline not expected here.");
     }
 
-    builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+    fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
 }
 
diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp
index 5a2b0c3..8a3fc44 100644
--- a/src/gpu/effects/GrRRectEffect.cpp
+++ b/src/gpu/effects/GrRRectEffect.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrRRectEffect.h"
 
 #include "gl/GrGLEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "GrConvexPolyEffect.h"
 #include "GrOvalEffect.h"
@@ -134,7 +134,7 @@
 public:
     GLCircularRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLShaderBuilder* builder,
+    virtual void emitCode(GrGLProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -159,7 +159,7 @@
     fPrevRRect.setEmpty();
 }
 
-void GLCircularRRectEffect::emitCode(GrGLShaderBuilder* builder,
+void GLCircularRRectEffect::emitCode(GrGLProgramBuilder* builder,
                              const GrDrawEffect& drawEffect,
                              const GrEffectKey& key,
                              const char* outputColor,
@@ -173,15 +173,17 @@
     // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has
     // only rectangular corners, that side's value corresponds to the rect edge's value outset by
     // half a pixel.
-    fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fInnerRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec4f_GrSLType,
                                             "innerRect",
                                             &rectName);
-    fRadiusPlusHalfUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fRadiusPlusHalfUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                  kFloat_GrSLType,
                                                  "radiusPlusHalf",
                                                  &radiusPlusHalfName);
-    const char* fragmentPos = builder->fragmentPosition();
+
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    const char* fragmentPos = fsBuilder->fragmentPosition();
     // At each quarter-circle corner we compute a vector that is the offset of the fragment position
     // from the circle center. The vector is pinned in x and y to be in the quarter-plane relevant
     // to that corner. This means that points near the interior near the rrect top edge will have
@@ -199,95 +201,95 @@
     // alphas together.
     switch (crre.getCircularCornerFlags()) {
         case CircularRRectEffect::kAll_CornerFlags:
-            builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
-            builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
-            builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
+            fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
+            fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
+            fsBuilder->codeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.0, 1.0);\n",
                                    radiusPlusHalfName);
             break;
         case CircularRRectEffect::kTopLeft_CornerFlag:
-            builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.xy, 0.0);\n",
+            fsBuilder->codeAppendf("\t\tvec2 dxy = max(%s.xy - %s.xy, 0.0);\n",
                                    rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n",
                                     rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n",
                                     rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat alpha = bottomAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
                                    radiusPlusHalfName);
             break;
         case CircularRRectEffect::kTopRight_CornerFlag:
-            builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);\n",
+            fsBuilder->codeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);\n",
                                    fragmentPos, rectName, rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n",
                                    fragmentPos, rectName);
-            builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n",
                                     rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat alpha = bottomAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
                                    radiusPlusHalfName);
             break;
         case CircularRRectEffect::kBottomRight_CornerFlag:
-            builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.zw, 0.0);\n",
+            fsBuilder->codeAppendf("\t\tvec2 dxy = max(%s.xy - %s.zw, 0.0);\n",
                                    fragmentPos, rectName);
-            builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n",
                                    fragmentPos, rectName);
-            builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
                                    fragmentPos, rectName);
-            builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat alpha = topAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
                                    radiusPlusHalfName);
             break;
         case CircularRRectEffect::kBottomLeft_CornerFlag:
-            builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);\n",
+            fsBuilder->codeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);\n",
                                    rectName, fragmentPos, fragmentPos, rectName);
-            builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n",
                                     rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
                                    fragmentPos, rectName);
-            builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat alpha = topAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
                                    radiusPlusHalfName);
             break;
         case CircularRRectEffect::kLeft_CornerFlags:
-            builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos, rectName);
-            builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, dy1)), 0.0);\n");
-            builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
+            fsBuilder->codeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos, rectName);
+            fsBuilder->codeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, dy1)), 0.0);\n");
+            fsBuilder->codeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n",
                                     rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
                                    radiusPlusHalfName);
             break;
         case CircularRRectEffect::kTop_CornerFlags:
-            builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos, rectName);
-            builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy0.y), 0.0);\n");
-            builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
+            fsBuilder->codeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos, rectName);
+            fsBuilder->codeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy0.y), 0.0);\n");
+            fsBuilder->codeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n",
                                    rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
                                    radiusPlusHalfName);
             break;
         case CircularRRectEffect::kRight_CornerFlags:
-            builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
-            builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1.y)), 0.0);\n");
-            builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, fragmentPos);
+            fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
+            fsBuilder->codeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1.y)), 0.0);\n");
+            fsBuilder->codeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n",
                                    fragmentPos, rectName);
-            builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
                                    radiusPlusHalfName);
             break;
         case CircularRRectEffect::kBottom_CornerFlags:
-            builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, fragmentPos);
-            builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
-            builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy1.y), 0.0);\n");
-            builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, fragmentPos);
+            fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
+            fsBuilder->codeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy1.y), 0.0);\n");
+            fsBuilder->codeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
                                    fragmentPos, rectName);
-            builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+            fsBuilder->codeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
                                    radiusPlusHalfName);
             break;
     }
 
     if (kInverseFillAA_GrEffectEdgeType == crre.getEdgeType()) {
-        builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n");
+        fsBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n");
     }
 
-    builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+    fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
 }
 
@@ -486,7 +488,7 @@
 public:
     GLEllipticalRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLShaderBuilder* builder,
+    virtual void emitCode(GrGLProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
@@ -511,7 +513,7 @@
     fPrevRRect.setEmpty();
 }
 
-void GLEllipticalRRectEffect::emitCode(GrGLShaderBuilder* builder,
+void GLEllipticalRRectEffect::emitCode(GrGLProgramBuilder* builder,
                                        const GrDrawEffect& drawEffect,
                                        const GrEffectKey& key,
                                        const char* outputColor,
@@ -521,11 +523,13 @@
     const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEffect>();
     const char *rectName;
     // The inner rect is the rrect bounds inset by the x/y radii
-    fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+    fInnerRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec4f_GrSLType,
                                             "innerRect",
                                             &rectName);
-    const char* fragmentPos = builder->fragmentPosition();
+
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    const char* fragmentPos = fsBuilder->fragmentPosition();
     // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos
     // to the ellipse center. The vector is pinned in x and y to be in the quarter-plane relevant
     // to that corner. This means that points near the interior near the rrect top edge will have
@@ -537,31 +541,31 @@
     // The code below is a simplified version of the above that performs maxs on the vector
     // components before computing distances and alpha values so that only one distance computation
     // need be computed to determine the min alpha.
-    builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
-    builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
+    fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
+    fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
     switch (erre.getRRect().getType()) {
         case SkRRect::kSimple_Type: {
             const char *invRadiiXYSqdName;
-            fInvRadiiSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+            fInvRadiiSqdUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                       kVec2f_GrSLType,
                                                       "invRadiiXY",
                                                       &invRadiiXYSqdName);
-            builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
+            fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
             // Z is the x/y offsets divided by squared radii.
-            builder->fsCodeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName);
+            fsBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName);
             break;
         }
         case SkRRect::kNinePatch_Type: {
             const char *invRadiiLTRBSqdName;
-            fInvRadiiSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+            fInvRadiiSqdUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                       kVec4f_GrSLType,
                                                       "invRadiiLTRB",
                                                       &invRadiiLTRBSqdName);
-            builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
+            fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
             // Z is the x/y offsets divided by squared radii. We only care about the (at most) one
             // corner where both the x and y offsets are positive, hence the maxes. (The inverse
             // squared radii will always be positive.)
-            builder->fsCodeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);\n",
+            fsBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);\n",
                                    invRadiiLTRBSqdName, invRadiiLTRBSqdName);
             break;
         }
@@ -569,20 +573,20 @@
             SkFAIL("RRect should always be simple or nine-patch.");
     }
     // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1.
-    builder->fsCodeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n");
+    fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n");
     // grad_dot is the squared length of the gradient of the implicit.
-    builder->fsCodeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
+    fsBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
     // avoid calling inversesqrt on zero.
-    builder->fsCodeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
-    builder->fsCodeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
+    fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
+    fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
 
     if (kFillAA_GrEffectEdgeType == erre.getEdgeType()) {
-        builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
+        fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
     } else {
-        builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
+        fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
     }
 
-    builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+    fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
 }
 
diff --git a/src/gpu/effects/GrSimpleTextureEffect.cpp b/src/gpu/effects/GrSimpleTextureEffect.cpp
index 74926bc..fe55ce9 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.cpp
+++ b/src/gpu/effects/GrSimpleTextureEffect.cpp
@@ -5,9 +5,9 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrSimpleTextureEffect.h"
 #include "gl/GrGLEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
 #include "GrTBackendEffectFactory.h"
@@ -19,19 +19,20 @@
         : INHERITED (factory) {
     }
 
-    virtual void emitCode(GrGLShaderBuilder* builder,
+    virtual void emitCode(GrGLProgramBuilder* builder,
                           const GrDrawEffect& drawEffect,
                           const GrEffectKey& key,
                           const char* outputColor,
                           const char* inputColor,
                           const TransformedCoordsArray& coords,
                           const TextureSamplerArray& samplers) SK_OVERRIDE {
-        builder->fsCodeAppendf("\t%s = ", outputColor);
-        builder->fsAppendTextureLookupAndModulate(inputColor,
+        GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+        fsBuilder->codeAppendf("\t%s = ", outputColor);
+        fsBuilder->appendTextureLookupAndModulate(inputColor,
                                                   samplers[0],
                                                   coords[0].c_str(),
                                                   coords[0].type());
-        builder->fsCodeAppend(";\n");
+        fsBuilder->codeAppend(";\n");
     }
 
 private:
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index 2bad5e8..40006a3 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -5,11 +5,11 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrTextureDomain.h"
 #include "GrSimpleTextureEffect.h"
 #include "GrTBackendEffectFactory.h"
 #include "gl/GrGLEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "SkFloatingPoint.h"
 
 
@@ -49,23 +49,25 @@
     SkASSERT((Mode)-1 == fMode || textureDomain.mode() == fMode);
     SkDEBUGCODE(fMode = textureDomain.mode();)
 
+    GrGLProgramBuilder* program = builder->getProgramBuilder();
+
     if (textureDomain.mode() != kIgnore_Mode && !fDomainUni.isValid()) {
         const char* name;
         SkString uniName("TexDom");
         if (textureDomain.fIndex >= 0) {
             uniName.appendS32(textureDomain.fIndex);
         }
-        fDomainUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
-                                         kVec4f_GrSLType, uniName.c_str(), &name);
+        fDomainUni = program->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType,
+                uniName.c_str(), &name);
         fDomainName = name;
     }
 
     switch (textureDomain.mode()) {
         case kIgnore_Mode: {
-            builder->fsCodeAppendf("\t%s = ", outColor);
-            builder->fsAppendTextureLookupAndModulate(inModulateColor, sampler,
+            builder->codeAppendf("\t%s = ", outColor);
+            builder->appendTextureLookupAndModulate(inModulateColor, sampler,
                                                       inCoords.c_str());
-            builder->fsCodeAppend(";\n");
+            builder->codeAppend(";\n");
             break;
         }
         case kClamp_Mode: {
@@ -73,49 +75,49 @@
             clampedCoords.appendf("\tclamp(%s, %s.xy, %s.zw)",
                                   inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str());
 
-            builder->fsCodeAppendf("\t%s = ", outColor);
-            builder->fsAppendTextureLookupAndModulate(inModulateColor, sampler,
+            builder->codeAppendf("\t%s = ", outColor);
+            builder->appendTextureLookupAndModulate(inModulateColor, sampler,
                                                       clampedCoords.c_str());
-            builder->fsCodeAppend(";\n");
+            builder->codeAppend(";\n");
             break;
         }
         case kDecal_Mode: {
             // Add a block since we're going to declare variables.
-            GrGLShaderBuilder::FSBlock block(builder);
+            GrGLShaderBuilder::ShaderBlock block(builder);
 
             const char* domain = fDomainName.c_str();
-            if (kImagination_GrGLVendor == builder->ctxInfo().vendor()) {
+            if (kImagination_GrGLVendor == program->ctxInfo().vendor()) {
                 // On the NexusS and GalaxyNexus, the other path (with the 'any'
                 // call) causes the compilation error "Calls to any function that
                 // may require a gradient calculation inside a conditional block
                 // may return undefined results". This appears to be an issue with
                 // the 'any' call since even the simple "result=black; if (any())
                 // result=white;" code fails to compile.
-                builder->fsCodeAppend("\tvec4 outside = vec4(0.0, 0.0, 0.0, 0.0);\n");
-                builder->fsCodeAppend("\tvec4 inside = ");
-                builder->fsAppendTextureLookupAndModulate(inModulateColor, sampler,
+                builder->codeAppend("\tvec4 outside = vec4(0.0, 0.0, 0.0, 0.0);\n");
+                builder->codeAppend("\tvec4 inside = ");
+                builder->appendTextureLookupAndModulate(inModulateColor, sampler,
                                                           inCoords.c_str());
-                builder->fsCodeAppend(";\n");
-                builder->fsCodeAppendf("\tfloat x = (%s).x;\n", inCoords.c_str());
-                builder->fsCodeAppendf("\tfloat y = (%s).y;\n", inCoords.c_str());
+                builder->codeAppend(";\n");
+                builder->codeAppendf("\tfloat x = (%s).x;\n", inCoords.c_str());
+                builder->codeAppendf("\tfloat y = (%s).y;\n", inCoords.c_str());
 
-                builder->fsCodeAppendf("\tx = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);\n",
+                builder->codeAppendf("\tx = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);\n",
                                        domain, domain, domain);
-                builder->fsCodeAppendf("\ty = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);\n",
+                builder->codeAppendf("\ty = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);\n",
                                        domain, domain, domain);
-                builder->fsCodeAppend("\tfloat blend = step(1.0, max(x, y));\n");
-                builder->fsCodeAppendf("\t%s = mix(inside, outside, blend);\n", outColor);
+                builder->codeAppend("\tfloat blend = step(1.0, max(x, y));\n");
+                builder->codeAppendf("\t%s = mix(inside, outside, blend);\n", outColor);
             } else {
-                builder->fsCodeAppend("\tbvec4 outside;\n");
-                builder->fsCodeAppendf("\toutside.xy = lessThan(%s, %s.xy);\n", inCoords.c_str(),
+                builder->codeAppend("\tbvec4 outside;\n");
+                builder->codeAppendf("\toutside.xy = lessThan(%s, %s.xy);\n", inCoords.c_str(),
                                        domain);
-                builder->fsCodeAppendf("\toutside.zw = greaterThan(%s, %s.zw);\n", inCoords.c_str(),
+                builder->codeAppendf("\toutside.zw = greaterThan(%s, %s.zw);\n", inCoords.c_str(),
                                        domain);
-                builder->fsCodeAppendf("\t%s = any(outside) ? vec4(0.0, 0.0, 0.0, 0.0) : ",
+                builder->codeAppendf("\t%s = any(outside) ? vec4(0.0, 0.0, 0.0, 0.0) : ",
                                        outColor);
-                builder->fsAppendTextureLookupAndModulate(inModulateColor, sampler,
+                builder->appendTextureLookupAndModulate(inModulateColor, sampler,
                                                           inCoords.c_str());
-                builder->fsCodeAppend(";\n");
+                builder->codeAppend(";\n");
             }
             break;
         }
@@ -125,10 +127,10 @@
                                  inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str(),
                                  fDomainName.c_str(), fDomainName.c_str());
 
-            builder->fsCodeAppendf("\t%s = ", outColor);
-            builder->fsAppendTextureLookupAndModulate(inModulateColor, sampler,
+            builder->codeAppendf("\t%s = ", outColor);
+            builder->appendTextureLookupAndModulate(inModulateColor, sampler,
                                                       clampedCoords.c_str());
-            builder->fsCodeAppend(";\n");
+            builder->codeAppend(";\n");
             break;
         }
     }
@@ -167,7 +169,7 @@
 public:
     GrGLTextureDomainEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
 
-    virtual void emitCode(GrGLShaderBuilder*,
+    virtual void emitCode(GrGLProgramBuilder*,
                           const GrDrawEffect&,
                           const GrEffectKey&,
                           const char* outputColor,
@@ -189,7 +191,7 @@
     : INHERITED(factory) {
 }
 
-void GrGLTextureDomainEffect::emitCode(GrGLShaderBuilder* builder,
+void GrGLTextureDomainEffect::emitCode(GrGLProgramBuilder* builder,
                                        const GrDrawEffect& drawEffect,
                                        const GrEffectKey& key,
                                        const char* outputColor,
@@ -199,8 +201,9 @@
     const GrTextureDomainEffect& effect = drawEffect.castEffect<GrTextureDomainEffect>();
     const GrTextureDomain& domain = effect.textureDomain();
 
-    SkString coords2D = builder->ensureFSCoords2D(coords, 0);
-    fGLDomain.sampleTexture(builder, domain, outputColor, coords2D, samplers[0], inputColor);
+    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
+    fGLDomain.sampleTexture(fsBuilder, domain, outputColor, coords2D, samplers[0], inputColor);
 }
 
 void GrGLTextureDomainEffect::setData(const GrGLProgramDataManager& pdman,
diff --git a/src/gpu/effects/GrTextureDomain.h b/src/gpu/effects/GrTextureDomain.h
index 577098a..6cb5ad4 100644
--- a/src/gpu/effects/GrTextureDomain.h
+++ b/src/gpu/effects/GrTextureDomain.h
@@ -11,6 +11,7 @@
 #include "GrSingleTextureEffect.h"
 #include "gl/GrGLEffect.h"
 
+class GrGLProgramBuilder;
 class GrGLShaderBuilder;
 struct SkRect;
 
diff --git a/src/gpu/effects/GrYUVtoRGBEffect.cpp b/src/gpu/effects/GrYUVtoRGBEffect.cpp
index 15e51a2..41d75c3 100644
--- a/src/gpu/effects/GrYUVtoRGBEffect.cpp
+++ b/src/gpu/effects/GrYUVtoRGBEffect.cpp
@@ -5,12 +5,12 @@
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrYUVtoRGBEffect.h"
 
 #include "GrCoordTransform.h"
 #include "GrEffect.h"
 #include "gl/GrGLEffect.h"
-#include "gl/GrGLShaderBuilder.h"
 #include "GrTBackendEffectFactory.h"
 
 namespace {
@@ -44,26 +44,27 @@
         : INHERITED(factory) {
         }
 
-        virtual void emitCode(GrGLShaderBuilder* builder,
+        virtual void emitCode(GrGLProgramBuilder* builder,
                               const GrDrawEffect&,
                               const GrEffectKey&,
                               const char* outputColor,
                               const char* inputColor,
                               const TransformedCoordsArray& coords,
                               const TextureSamplerArray& samplers) SK_OVERRIDE {
+            GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
             const char* yuvMatrix   = "yuvMatrix";
-            builder->fsCodeAppendf("\tconst mat4 %s = mat4(1.0,  0.0,    1.402, -0.701,\n\t\t\t"
+            fsBuilder->codeAppendf("\tconst mat4 %s = mat4(1.0,  0.0,    1.402, -0.701,\n\t\t\t"
                                                           "1.0, -0.344, -0.714,  0.529,\n\t\t\t"
                                                           "1.0,  1.772,  0.0,   -0.886,\n\t\t\t"
                                                           "0.0,  0.0,    0.0,    1.0);\n",
                                    yuvMatrix);
-            builder->fsCodeAppendf("\t%s = vec4(\n\t\t", outputColor);
-            builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
-            builder->fsCodeAppend(".r,\n\t\t");
-            builder->fsAppendTextureLookup(samplers[1], coords[0].c_str(), coords[0].type());
-            builder->fsCodeAppend(".r,\n\t\t");
-            builder->fsAppendTextureLookup(samplers[2], coords[0].c_str(), coords[0].type());
-            builder->fsCodeAppendf(".r,\n\t\t1.0) * %s;\n", yuvMatrix);
+            fsBuilder->codeAppendf("\t%s = vec4(\n\t\t", outputColor);
+            fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
+            fsBuilder->codeAppend(".r,\n\t\t");
+            fsBuilder->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].type());
+            fsBuilder->codeAppend(".r,\n\t\t");
+            fsBuilder->appendTextureLookup(samplers[2], coords[0].c_str(), coords[0].type());
+            fsBuilder->codeAppendf(".r,\n\t\t1.0) * %s;\n", yuvMatrix);
         }
 
         typedef GrGLEffect INHERITED;