Added GrGLFragmentProcessor::EmitArgs struct for use with emitCode()

BUG=skia:

Review URL: https://codereview.chromium.org/1251173002
diff --git a/gm/dcshader.cpp b/gm/dcshader.cpp
index 744ea9d..c60c28a 100644
--- a/gm/dcshader.cpp
+++ b/gm/dcshader.cpp
@@ -65,14 +65,9 @@
 
     GrGLFragmentProcessor* createGLInstance() const override {
         class DCGLFP : public GrGLFragmentProcessor {
-            void emitCode(GrGLFPBuilder* builder,
-                            const GrFragmentProcessor& fp,
-                            const char* outputColor,
-                            const char* inputColor,
-                            const TransformedCoordsArray& coords,
-                            const TextureSamplerArray& samplers) override {
-                GrGLFragmentBuilder* fpb = builder->getFragmentShaderBuilder();
-                fpb->codeAppendf("vec2 c = %s;", fpb->ensureFSCoords2D(coords, 0).c_str());
+            void emitCode(EmitArgs& args) override {
+                GrGLFragmentBuilder* fpb = args.fBuilder->getFragmentShaderBuilder();
+                fpb->codeAppendf("vec2 c = %s;", fpb->ensureFSCoords2D(args.fCoords, 0).c_str());
                 fpb->codeAppend("vec2 r = mod(c, vec2(20.0));");
                 fpb->codeAppend("vec4 color = vec4(0.5*sin(c.x / 15.0) + 0.5,"
                                                     "0.5*cos((c.x + c.y) / 15.0) + 0.5,"
@@ -80,7 +75,7 @@
                                                     "distance(r, vec2(15.0)) / 20.0 + 0.2);");
                 fpb->codeAppendf("color.rgb *= color.a;"
                                     "%s = color * %s;",
-                                    outputColor, GrGLSLExpr4(inputColor).c_str());
+                                    args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str());
             }
             void setData(const GrGLProgramDataManager&, const GrProcessor&) override {}
         };
diff --git a/samplecode/SampleLighting.cpp b/samplecode/SampleLighting.cpp
index a002a93..53a542e 100755
--- a/samplecode/SampleLighting.cpp
+++ b/samplecode/SampleLighting.cpp
@@ -129,38 +129,34 @@
             fLightDir.fX = 10000.0f;
         }
 
-        void emitCode(GrGLFPBuilder* builder,
-                      const GrFragmentProcessor& fp,
-                      const char* outputColor,
-                      const char* inputColor,
-                      const TransformedCoordsArray& coords,
-                      const TextureSamplerArray& samplers) override {
+        void emitCode(EmitArgs& args) override {
 
-            GrGLFragmentBuilder* fpb = builder->getFragmentShaderBuilder();
+            GrGLFragmentBuilder* fpb = args.fBuilder->getFragmentShaderBuilder();
 
             // add uniforms
             const char* lightDirUniName = NULL;
-            fLightDirUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+            fLightDirUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                kVec3f_GrSLType, kDefault_GrSLPrecision,
                                                "LightDir", &lightDirUniName);
 
             const char* lightColorUniName = NULL;
-            fLightColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+            fLightColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                  kVec4f_GrSLType, kDefault_GrSLPrecision,
                                                  "LightColor", &lightColorUniName);
 
             const char* ambientColorUniName = NULL;
-            fAmbientColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+            fAmbientColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                    kVec4f_GrSLType, kDefault_GrSLPrecision,
                                                    "AmbientColor", &ambientColorUniName);
 
             fpb->codeAppend("vec4 diffuseColor = ");
-            fpb->appendTextureLookupAndModulate(inputColor, samplers[0], 
-                                                coords[0].c_str(), coords[0].getType());
+            fpb->appendTextureLookupAndModulate(args.fInputColor, args.fSamplers[0],
+                                                args.fCoords[0].c_str(), args.fCoords[0].getType());
             fpb->codeAppend(";");
 
             fpb->codeAppend("vec4 normalColor = ");
-            fpb->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].getType());
+            fpb->appendTextureLookup(args.fSamplers[1], args.fCoords[0].c_str(), 
+                                     args.fCoords[0].getType());
             fpb->codeAppend(";");
 
             fpb->codeAppend("vec3 normal = normalize(2.0*(normalColor.rgb - vec3(0.5)));");
@@ -170,7 +166,7 @@
             fpb->codeAppendf("vec3 result = %s.rgb*diffuseColor.rgb*NdotL;", lightColorUniName);
             // ambient light
             fpb->codeAppendf("result += %s.rgb;", ambientColorUniName);
-            fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", outputColor);
+            fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", args.fOutputColor);
         }
 
         void setData(const GrGLProgramDataManager& pdman, const GrProcessor& proc) override {
diff --git a/src/effects/SkAlphaThresholdFilter.cpp b/src/effects/SkAlphaThresholdFilter.cpp
index 55e113e..c9d72bb 100644
--- a/src/effects/SkAlphaThresholdFilter.cpp
+++ b/src/effects/SkAlphaThresholdFilter.cpp
@@ -128,12 +128,7 @@
 public:
     GrGLAlphaThresholdEffect(const GrFragmentProcessor&) {}
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
@@ -145,38 +140,33 @@
     typedef GrGLFragmentProcessor INHERITED;
 };
 
-void GrGLAlphaThresholdEffect::emitCode(GrGLFPBuilder* builder,
-                                        const GrFragmentProcessor&,
-                                        const char* outputColor,
-                                        const char* inputColor,
-                                        const TransformedCoordsArray& coords,
-                                        const TextureSamplerArray& samplers) {
-    fInnerThresholdVar = builder->addUniform(
+void GrGLAlphaThresholdEffect::emitCode(EmitArgs& args) {
+    fInnerThresholdVar = args.fBuilder->addUniform(
         GrGLProgramBuilder::kFragment_Visibility,
         kFloat_GrSLType, kDefault_GrSLPrecision,
         "inner_threshold");
-    fOuterThresholdVar = builder->addUniform(
+    fOuterThresholdVar = args.fBuilder->addUniform(
         GrGLProgramBuilder::kFragment_Visibility,
         kFloat_GrSLType, kDefault_GrSLPrecision,
         "outer_threshold");
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
-    SkString maskCoords2D = fsBuilder->ensureFSCoords2D(coords, 1);
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
+    SkString maskCoords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 1);
 
     fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
     fsBuilder->codeAppendf("\t\tvec2 mask_coord = %s;\n", maskCoords2D.c_str());
     fsBuilder->codeAppend("\t\tvec4 input_color = ");
-    fsBuilder->appendTextureLookup(samplers[0], "coord");
+    fsBuilder->appendTextureLookup(args.fSamplers[0], "coord");
     fsBuilder->codeAppend(";\n");
     fsBuilder->codeAppend("\t\tvec4 mask_color = ");
-    fsBuilder->appendTextureLookup(samplers[1], "mask_coord");
+    fsBuilder->appendTextureLookup(args.fSamplers[1], "mask_coord");
     fsBuilder->codeAppend(";\n");
 
     fsBuilder->codeAppendf("\t\tfloat inner_thresh = %s;\n",
-                           builder->getUniformCStr(fInnerThresholdVar));
+                           args.fBuilder->getUniformCStr(fInnerThresholdVar));
     fsBuilder->codeAppendf("\t\tfloat outer_thresh = %s;\n",
-                           builder->getUniformCStr(fOuterThresholdVar));
+                           args.fBuilder->getUniformCStr(fOuterThresholdVar));
     fsBuilder->codeAppend("\t\tfloat mask = mask_color.a;\n");
 
     fsBuilder->codeAppend("vec4 color = input_color;\n");
@@ -192,8 +182,8 @@
                           "\t\t\tcolor.a = inner_thresh;\n"
                           "\t\t}\n");
 
-    fsBuilder->codeAppendf("%s = %s;\n", outputColor,
-                           (GrGLSLExpr4(inputColor) * GrGLSLExpr4("color")).c_str());
+    fsBuilder->codeAppendf("%s = %s;\n", args.fOutputColor,
+                           (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr4("color")).c_str());
 }
 
 void GrGLAlphaThresholdEffect::setData(const GrGLProgramDataManager& pdman,
diff --git a/src/effects/SkArithmeticMode_gpu.cpp b/src/effects/SkArithmeticMode_gpu.cpp
index 4f0107b..d2bec693 100644
--- a/src/effects/SkArithmeticMode_gpu.cpp
+++ b/src/effects/SkArithmeticMode_gpu.cpp
@@ -60,24 +60,21 @@
 
     ~GLArithmeticFP() override {}
 
-    void emitCode(GrGLFPBuilder* builder,
-                  const GrFragmentProcessor& fp,
-                  const char* outputColor,
-                  const char* inputColor,
-                  const TransformedCoordsArray& coords,
-                  const TextureSamplerArray& samplers) override {
-        GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    void emitCode(EmitArgs& args) override {
+        GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
         fsBuilder->codeAppend("vec4 bgColor = ");
-        fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
+        fsBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0].c_str(),
+                                       args.fCoords[0].getType());
         fsBuilder->codeAppendf(";");
         const char* dstColor = "bgColor";
 
-        fKUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+        fKUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                     kVec4f_GrSLType, kDefault_GrSLPrecision,
                                     "k");
-        const char* kUni = builder->getUniformCStr(fKUni);
+        const char* kUni = args.fBuilder->getUniformCStr(fKUni);
 
-        add_arithmetic_code(fsBuilder, inputColor, dstColor, outputColor, kUni, fEnforcePMColor);
+        add_arithmetic_code(fsBuilder, args.fInputColor, dstColor, args.fOutputColor, kUni,
+                            fEnforcePMColor);
     }
 
     void setData(const GrGLProgramDataManager& pdman, const GrProcessor& proc) override {
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index 5ae03e4..6a1a857 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -664,12 +664,7 @@
 class GrGLRectBlurEffect : public GrGLFragmentProcessor {
 public:
     GrGLRectBlurEffect(const GrProcessor&) {}
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
@@ -698,32 +693,27 @@
     fsBuilder->codeAppendf("\t\t}\n");
 }
 
-void GrGLRectBlurEffect::emitCode(GrGLFPBuilder* builder,
-                                 const GrFragmentProcessor&,
-                                 const char* outputColor,
-                                 const char* inputColor,
-                                 const TransformedCoordsArray& coords,
-                                 const TextureSamplerArray& samplers) {
+void GrGLRectBlurEffect::emitCode(EmitArgs& args) {
 
     const char *rectName;
     const char *profileSizeName;
 
-    fProxyRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fProxyRectUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec4f_GrSLType,
                                             kDefault_GrSLPrecision,
                                             "proxyRect",
                                             &rectName);
-    fProfileSizeUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fProfileSizeUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kFloat_GrSLType,
                                             kDefault_GrSLPrecision,
                                             "profileSize",
                                             &profileSizeName);
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
     const char *fragmentPos = fsBuilder->fragmentPosition();
 
-    if (inputColor) {
-        fsBuilder->codeAppendf("\tvec4 src=%s;\n", inputColor);
+    if (args.fInputColor) {
+        fsBuilder->codeAppendf("\tvec4 src=%s;\n", args.fInputColor);
     } else {
         fsBuilder->codeAppendf("\tvec4 src=vec4(1)\n;");
     }
@@ -736,11 +726,13 @@
     fsBuilder->codeAppendf("\tfloat center = 2.0 * floor(%s/2.0 + .25) - 1.0;\n", profileSizeName);
     fsBuilder->codeAppendf("\tvec2 wh = smallDims - vec2(center,center);\n");
 
-    OutputRectBlurProfileLookup(fsBuilder, samplers[0], "horiz_lookup", profileSizeName, "translatedPos.x", "width", "wh.x");
-    OutputRectBlurProfileLookup(fsBuilder, samplers[0], "vert_lookup", profileSizeName, "translatedPos.y", "height", "wh.y");
+    OutputRectBlurProfileLookup(fsBuilder, args.fSamplers[0], "horiz_lookup", profileSizeName,
+                                "translatedPos.x", "width", "wh.x");
+    OutputRectBlurProfileLookup(fsBuilder, args.fSamplers[0], "vert_lookup", profileSizeName,
+                                "translatedPos.y", "height", "wh.y");
 
     fsBuilder->codeAppendf("\tfloat final = horiz_lookup * vert_lookup;\n");
-    fsBuilder->codeAppendf("\t%s = src * final;\n", outputColor );
+    fsBuilder->codeAppendf("\t%s = src * final;\n", args.fOutputColor );
 }
 
 void GrGLRectBlurEffect::setData(const GrGLProgramDataManager& pdman,
@@ -1019,12 +1011,7 @@
 public:
     GrGLRRectBlurEffect(const GrProcessor&) {}
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
@@ -1035,12 +1022,7 @@
     typedef GrGLFragmentProcessor INHERITED;
 };
 
-void GrGLRRectBlurEffect::emitCode(GrGLFPBuilder* builder,
-                                   const GrFragmentProcessor&,
-                                   const char* outputColor,
-                                   const char* inputColor,
-                                   const TransformedCoordsArray&,
-                                   const TextureSamplerArray& samplers) {
+void GrGLRRectBlurEffect::emitCode(EmitArgs& args) {
     const char *rectName;
     const char *cornerRadiusName;
     const char *blurRadiusName;
@@ -1048,23 +1030,23 @@
     // The proxy rect has left, top, right, and bottom edges correspond to
     // components x, y, z, and w, respectively.
 
-    fProxyRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fProxyRectUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec4f_GrSLType,
                                             kDefault_GrSLPrecision,
                                             "proxyRect",
                                             &rectName);
-    fCornerRadiusUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fCornerRadiusUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                kFloat_GrSLType,
                                                kDefault_GrSLPrecision,
                                                "cornerRadius",
                                                &cornerRadiusName);
-    fBlurRadiusUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fBlurRadiusUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                              kFloat_GrSLType,
                                               kDefault_GrSLPrecision,
                                               "blurRadius",
                                               &blurRadiusName);
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
     const char* fragmentPos = fsBuilder->fragmentPosition();
 
     // warp the fragment position to the appropriate part of the 9patch blur texture
@@ -1089,8 +1071,8 @@
     fsBuilder->codeAppendf("\t\tvec2 proxyDims = vec2(2.0*threshold+1.0);\n");
     fsBuilder->codeAppendf("\t\tvec2 texCoord = translatedFragPos / proxyDims;\n");
 
-    fsBuilder->codeAppendf("\t%s = ", outputColor);
-    fsBuilder->appendTextureLookupAndModulate(inputColor, samplers[0], "texCoord");
+    fsBuilder->codeAppendf("\t%s = ", args.fOutputColor);
+    fsBuilder->appendTextureLookupAndModulate(args.fInputColor, args.fSamplers[0], "texCoord");
     fsBuilder->codeAppend(";\n");
 }
 
diff --git a/src/effects/SkColorCubeFilter.cpp b/src/effects/SkColorCubeFilter.cpp
index bce9a60..eeffb08 100644
--- a/src/effects/SkColorCubeFilter.cpp
+++ b/src/effects/SkColorCubeFilter.cpp
@@ -208,12 +208,7 @@
         GLProcessor(const GrProcessor&);
         virtual ~GLProcessor();
 
-        virtual void emitCode(GrGLFPBuilder*,
-                              const GrFragmentProcessor&,
-                              const char* outputColor,
-                              const char* inputColor,
-                              const TransformedCoordsArray&,
-                              const TextureSamplerArray&) override;
+        virtual void emitCode(EmitArgs&) override;
 
         static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
 
@@ -267,24 +262,19 @@
 GrColorCubeEffect::GLProcessor::~GLProcessor() {
 }
 
-void GrColorCubeEffect::GLProcessor::emitCode(GrGLFPBuilder* builder,
-                                              const GrFragmentProcessor&,
-                                              const char* outputColor,
-                                              const char* inputColor,
-                                              const TransformedCoordsArray& coords,
-                                              const TextureSamplerArray& samplers) {
-    if (NULL == inputColor) {
-        inputColor = "vec4(1)";
+void GrColorCubeEffect::GLProcessor::emitCode(EmitArgs& args) {
+    if (NULL == args.fInputColor) {
+        args.fInputColor = "vec4(1)";
     }
 
-    fColorCubeSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fColorCubeSizeUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kFloat_GrSLType, kDefault_GrSLPrecision,
                                             "Size");
-    const char* colorCubeSizeUni = builder->getUniformCStr(fColorCubeSizeUni);
-    fColorCubeInvSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    const char* colorCubeSizeUni = args.fBuilder->getUniformCStr(fColorCubeSizeUni);
+    fColorCubeInvSizeUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                kFloat_GrSLType, kDefault_GrSLPrecision,
                                                "InvSize");
-    const char* colorCubeInvSizeUni = builder->getUniformCStr(fColorCubeInvSizeUni);
+    const char* colorCubeInvSizeUni = args.fBuilder->getUniformCStr(fColorCubeInvSizeUni);
 
     const char* nonZeroAlpha = "nonZeroAlpha";
     const char* unPMColor = "unPMColor";
@@ -295,12 +285,12 @@
     // Note: if implemented using texture3D in OpenGL ES older than OpenGL ES 3.0,
     //       the shader might need "#extension GL_OES_texture_3D : enable".
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
 
     // Unpremultiply color
-    fsBuilder->codeAppendf("\tfloat %s = max(%s.a, 0.00001);\n", nonZeroAlpha, inputColor);
+    fsBuilder->codeAppendf("\tfloat %s = max(%s.a, 0.00001);\n", nonZeroAlpha, args.fInputColor);
     fsBuilder->codeAppendf("\tvec4 %s = vec4(%s.rgb / %s, %s);\n",
-                           unPMColor, inputColor, nonZeroAlpha, nonZeroAlpha);
+                           unPMColor, args.fInputColor, nonZeroAlpha, nonZeroAlpha);
 
     // Fit input color into the cube.
     fsBuilder->codeAppendf(
@@ -315,14 +305,14 @@
                            cCoords2, cubeIdx, cubeIdx, cubeIdx, colorCubeInvSizeUni);
 
     // Apply the cube.
-    fsBuilder->codeAppendf("%s = vec4(mix(", outputColor);
-    fsBuilder->appendTextureLookup(samplers[0], cCoords1);
+    fsBuilder->codeAppendf("%s = vec4(mix(", args.fOutputColor);
+    fsBuilder->appendTextureLookup(args.fSamplers[0], cCoords1);
     fsBuilder->codeAppend(".rgb, ");
-    fsBuilder->appendTextureLookup(samplers[0], cCoords2);
+    fsBuilder->appendTextureLookup(args.fSamplers[0], cCoords2);
 
     // Premultiply color by alpha. Note that the input alpha is not modified by this shader.
     fsBuilder->codeAppendf(".rgb, fract(%s.b)) * vec3(%s), %s.a);\n",
-                           cubeIdx, nonZeroAlpha, inputColor);
+                           cubeIdx, nonZeroAlpha, args.fInputColor);
 }
 
 void GrColorCubeEffect::GLProcessor::setData(const GrGLProgramDataManager& pdman,
diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp
index 92fe4d7..13ef7c6 100644
--- a/src/effects/SkColorFilters.cpp
+++ b/src/effects/SkColorFilters.cpp
@@ -166,18 +166,14 @@
         GLProcessor(const GrProcessor&) {
         }
 
-        virtual void emitCode(GrGLFPBuilder* builder,
-                              const GrFragmentProcessor& fp,
-                              const char* outputColor,
-                              const char* inputColor,
-                              const TransformedCoordsArray&,
-                              const TextureSamplerArray&) override {
-            SkXfermode::Mode mode = fp.cast<ModeColorFilterEffect>().mode();
+        virtual void emitCode(EmitArgs& args) override {
+            SkXfermode::Mode mode = args.fFp.cast<ModeColorFilterEffect>().mode();
 
             SkASSERT(SkXfermode::kDst_Mode != mode);
             const char* colorFilterColorUniName = NULL;
-            if (fp.cast<ModeColorFilterEffect>().willUseFilterColor()) {
-                fFilterColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+            if (args.fFp.cast<ModeColorFilterEffect>().willUseFilterColor()) {
+                fFilterColorUni = args.fBuilder->addUniform(
+                                                      GrGLProgramBuilder::kFragment_Visibility,
                                                       kVec4f_GrSLType, kDefault_GrSLPrecision,
                                                       "FilterColor",
                                                       &colorFilterColorUniName);
@@ -185,10 +181,10 @@
 
             GrGLSLExpr4 filter =
                 color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniName),
-                                        GrGLSLExpr4(inputColor));
+                                        GrGLSLExpr4(args.fInputColor));
 
-            builder->getFragmentShaderBuilder()->
-                    codeAppendf("\t%s = %s;\n", outputColor, filter.c_str());
+            args.fBuilder->getFragmentShaderBuilder()->
+                    codeAppendf("\t%s = %s;\n", args.fOutputColor, filter.c_str());
         }
 
         static void GenKey(const GrProcessor& fp, const GrGLSLCaps&,
diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp
index 205bcdb..d0bd162 100644
--- a/src/effects/SkColorMatrixFilter.cpp
+++ b/src/effects/SkColorMatrixFilter.cpp
@@ -413,34 +413,31 @@
 
         GLProcessor(const GrProcessor&) {}
 
-        virtual void emitCode(GrGLFPBuilder* builder,
-                              const GrFragmentProcessor&,
-                              const char* outputColor,
-                              const char* inputColor,
-                              const TransformedCoordsArray&,
-                              const TextureSamplerArray&) override {
-            fMatrixHandle = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+        virtual void emitCode(EmitArgs& args) override {
+            fMatrixHandle = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                 kMat44f_GrSLType, kDefault_GrSLPrecision,
                                                 "ColorMatrix");
-            fVectorHandle = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+            fVectorHandle = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                 kVec4f_GrSLType, kDefault_GrSLPrecision,
                                                 "ColorMatrixVector");
 
-            if (NULL == inputColor) {
+            if (NULL == args.fInputColor) {
                 // could optimize this case, but we aren't for now.
-                inputColor = "vec4(1)";
+                args.fInputColor = "vec4(1)";
             }
-            GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+            GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
             // The max() is to guard against 0 / 0 during unpremul when the incoming color is
             // transparent black.
-            fsBuilder->codeAppendf("\tfloat nonZeroAlpha = max(%s.a, 0.00001);\n", inputColor);
+            fsBuilder->codeAppendf("\tfloat nonZeroAlpha = max(%s.a, 0.00001);\n",
+                                   args.fInputColor);
             fsBuilder->codeAppendf("\t%s = %s * vec4(%s.rgb / nonZeroAlpha, nonZeroAlpha) + %s;\n",
-                                   outputColor,
-                                   builder->getUniformCStr(fMatrixHandle),
-                                   inputColor,
-                                   builder->getUniformCStr(fVectorHandle));
-            fsBuilder->codeAppendf("\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor);
-            fsBuilder->codeAppendf("\t%s.rgb *= %s.a;\n", outputColor, outputColor);
+                                   args.fOutputColor,
+                                   args.fBuilder->getUniformCStr(fMatrixHandle),
+                                   args.fInputColor,
+                                   args.fBuilder->getUniformCStr(fVectorHandle));
+            fsBuilder->codeAppendf("\t%s = clamp(%s, 0.0, 1.0);\n",
+                                   args.fOutputColor, args.fOutputColor);
+            fsBuilder->codeAppendf("\t%s.rgb *= %s.a;\n", args.fOutputColor, args.fOutputColor);
         }
 
         virtual void setData(const GrGLProgramDataManager& uniManager,
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 45137d5..11332b1 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -306,12 +306,7 @@
     GrGLDisplacementMapEffect(const GrProcessor&);
     virtual ~GrGLDisplacementMapEffect();
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
 
@@ -560,33 +555,28 @@
 GrGLDisplacementMapEffect::~GrGLDisplacementMapEffect() {
 }
 
-void GrGLDisplacementMapEffect::emitCode(GrGLFPBuilder* builder,
-                                         const GrFragmentProcessor& fp,
-                                         const char* outputColor,
-                                         const char* inputColor,
-                                         const TransformedCoordsArray& coords,
-                                         const TextureSamplerArray& samplers) {
-    const GrTextureDomain& domain = fp.cast<GrDisplacementMapEffect>().domain();
-    sk_ignore_unused_variable(inputColor);
+void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
+    const GrTextureDomain& domain = args.fFp.cast<GrDisplacementMapEffect>().domain();
 
-    fScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fScaleUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                     kVec2f_GrSLType, kDefault_GrSLPrecision, "Scale");
-    const char* scaleUni = builder->getUniformCStr(fScaleUni);
+    const char* scaleUni = args.fBuilder->getUniformCStr(fScaleUni);
     const char* dColor = "dColor";
     const char* cCoords = "cCoords";
     const char* nearZero = "1e-6"; // Since 6.10352e−5 is the smallest half float, use
                                    // a number smaller than that to approximate 0, but
                                    // leave room for 32-bit float GPU rounding errors.
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
     fsBuilder->codeAppendf("\t\tvec4 %s = ", dColor);
-    fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
+    fsBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0].c_str(),
+                                   args.fCoords[0].getType());
     fsBuilder->codeAppend(";\n");
 
     // Unpremultiply the displacement
     fsBuilder->codeAppendf("\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);",
                            dColor, dColor, nearZero, dColor, dColor);
-    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 1);
+    SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 1);
     fsBuilder->codeAppendf("\t\tvec2 %s = %s + %s*(%s.",
                            cCoords, coords2D.c_str(), scaleUni, dColor);
 
@@ -627,7 +617,8 @@
     }
     fsBuilder->codeAppend("-vec2(0.5));\t\t");
 
-    fGLDomain.sampleTexture(fsBuilder, domain, outputColor, SkString(cCoords), samplers[1]);
+    fGLDomain.sampleTexture(fsBuilder, domain, args.fOutputColor, SkString(cCoords),
+                            args.fSamplers[1]);
     fsBuilder->codeAppend(";\n");
 }
 
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index 3cac4fc..a30955f 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -1514,12 +1514,7 @@
     GrGLLightingEffect(const GrProcessor&);
     virtual ~GrGLLightingEffect();
 
-    void emitCode(GrGLFPBuilder*,
-                  const GrFragmentProcessor&,
-                  const char* outputColor,
-                  const char* inputColor,
-                  const TransformedCoordsArray&,
-                  const TextureSamplerArray&) override;
+    void emitCode(EmitArgs&) override;
 
     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b);
 
@@ -1656,21 +1651,16 @@
     delete fLight;
 }
 
-void GrGLLightingEffect::emitCode(GrGLFPBuilder* builder,
-                                  const GrFragmentProcessor&,
-                                  const char* outputColor,
-                                  const char* inputColor,
-                                  const TransformedCoordsArray& coords,
-                                  const TextureSamplerArray& samplers) {
-    fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+void GrGLLightingEffect::emitCode(EmitArgs& args) {
+    fImageIncrementUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                               kVec2f_GrSLType, kDefault_GrSLPrecision,
                                              "ImageIncrement");
-    fSurfaceScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fSurfaceScaleUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                            kFloat_GrSLType, kDefault_GrSLPrecision,
                                            "SurfaceScale");
-    fLight->emitLightColorUniform(builder);
+    fLight->emitLightColorUniform(args.fBuilder);
     SkString lightFunc;
-    this->emitLightFunc(builder, &lightFunc);
+    this->emitLightFunc(args.fBuilder, &lightFunc);
     static const GrGLShaderVar gSobelArgs[] =  {
         GrGLShaderVar("a", kFloat_GrSLType),
         GrGLShaderVar("b", kFloat_GrSLType),
@@ -1681,8 +1671,8 @@
         GrGLShaderVar("scale", kFloat_GrSLType),
     };
     SkString sobelFuncName;
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
 
     fsBuilder->emitFunction(kFloat_GrSLType,
                             "sobel",
@@ -1721,8 +1711,8 @@
     fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
     fsBuilder->codeAppend("\t\tfloat m[9];\n");
 
-    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
-    const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni);
+    const char* imgInc = args.fBuilder->getUniformCStr(fImageIncrementUni);
+    const char* surfScale = args.fBuilder->getUniformCStr(fSurfaceScaleUni);
 
     int index = 0;
     for (int dy = 1; dy >= -1; dy--) {
@@ -1730,21 +1720,21 @@
             SkString texCoords;
             texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc);
             fsBuilder->codeAppendf("\t\tm[%d] = ", index++);
-            fsBuilder->appendTextureLookup(samplers[0], texCoords.c_str());
+            fsBuilder->appendTextureLookup(args.fSamplers[0], texCoords.c_str());
             fsBuilder->codeAppend(".a;\n");
         }
     }
     fsBuilder->codeAppend("\t\tvec3 surfaceToLight = ");
     SkString arg;
     arg.appendf("%s * m[4]", surfScale);
-    fLight->emitSurfaceToLight(builder, arg.c_str());
+    fLight->emitSurfaceToLight(args.fBuilder, arg.c_str());
     fsBuilder->codeAppend(";\n");
     fsBuilder->codeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
-                           outputColor, lightFunc.c_str(), normalName.c_str(), surfScale);
-    fLight->emitLightColor(builder, "surfaceToLight");
+                           args.fOutputColor, lightFunc.c_str(), normalName.c_str(), surfScale);
+    fLight->emitLightColor(args.fBuilder, "surfaceToLight");
     fsBuilder->codeAppend(");\n");
     SkString modulate;
-    GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
+    GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
     fsBuilder->codeAppend(modulate.c_str());
 }
 
diff --git a/src/effects/SkLumaColorFilter.cpp b/src/effects/SkLumaColorFilter.cpp
index 9939909..34cfdad 100644
--- a/src/effects/SkLumaColorFilter.cpp
+++ b/src/effects/SkLumaColorFilter.cpp
@@ -80,24 +80,19 @@
 
         static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b) {}
 
-        virtual void emitCode(GrGLFPBuilder* builder,
-                              const GrFragmentProcessor&,
-                              const char* outputColor,
-                              const char* inputColor,
-                              const TransformedCoordsArray&,
-                              const TextureSamplerArray&) override {
-            if (NULL == inputColor) {
-                inputColor = "vec4(1)";
+        virtual void emitCode(EmitArgs& args) override {
+            if (NULL == args.fInputColor) {
+                args.fInputColor = "vec4(1)";
             }
 
-            GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+            GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
             fsBuilder->codeAppendf("\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb);\n",
                                    SK_ITU_BT709_LUM_COEFF_R,
                                    SK_ITU_BT709_LUM_COEFF_G,
                                    SK_ITU_BT709_LUM_COEFF_B,
-                                   inputColor);
+                                   args.fInputColor);
             fsBuilder->codeAppendf("\t%s = vec4(0, 0, 0, luma);\n",
-                                   outputColor);
+                                   args.fOutputColor);
 
         }
 
diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp
index 9efd252..a397689 100644
--- a/src/effects/SkMagnifierImageFilter.cpp
+++ b/src/effects/SkMagnifierImageFilter.cpp
@@ -109,12 +109,7 @@
 public:
     GrGLMagnifierEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
@@ -130,40 +125,36 @@
 GrGLMagnifierEffect::GrGLMagnifierEffect(const GrProcessor&) {
 }
 
-void GrGLMagnifierEffect::emitCode(GrGLFPBuilder* builder,
-                                   const GrFragmentProcessor&,
-                                   const char* outputColor,
-                                   const char* inputColor,
-                                   const TransformedCoordsArray& coords,
-                                   const TextureSamplerArray& samplers) {
-    fOffsetVar = builder->addUniform(
+void GrGLMagnifierEffect::emitCode(EmitArgs& args) {
+    fOffsetVar = args.fBuilder->addUniform(
         GrGLProgramBuilder::kFragment_Visibility |
         GrGLProgramBuilder::kVertex_Visibility,
         kVec2f_GrSLType, kDefault_GrSLPrecision, "Offset");
-    fInvZoomVar = builder->addUniform(
+    fInvZoomVar = args.fBuilder->addUniform(
         GrGLProgramBuilder::kFragment_Visibility |
         GrGLProgramBuilder::kVertex_Visibility,
         kVec2f_GrSLType, kDefault_GrSLPrecision, "InvZoom");
-    fInvInsetVar = builder->addUniform(
+    fInvInsetVar = args.fBuilder->addUniform(
         GrGLProgramBuilder::kFragment_Visibility |
         GrGLProgramBuilder::kVertex_Visibility,
         kVec2f_GrSLType, kDefault_GrSLPrecision, "InvInset");
-    fBoundsVar = builder->addUniform(
+    fBoundsVar = args.fBuilder->addUniform(
         GrGLProgramBuilder::kFragment_Visibility |
         GrGLProgramBuilder::kVertex_Visibility,
         kVec4f_GrSLType, kDefault_GrSLPrecision, "Bounds");
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
     fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
     fsBuilder->codeAppendf("\t\tvec2 zoom_coord = %s + %s * %s;\n",
-                           builder->getUniformCStr(fOffsetVar),
+                           args.fBuilder->getUniformCStr(fOffsetVar),
                            coords2D.c_str(),
-                           builder->getUniformCStr(fInvZoomVar));
-    const char* bounds = builder->getUniformCStr(fBoundsVar);
+                           args.fBuilder->getUniformCStr(fInvZoomVar));
+    const char* bounds = args.fBuilder->getUniformCStr(fBoundsVar);
     fsBuilder->codeAppendf("\t\tvec2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds);
     fsBuilder->codeAppendf("\t\tdelta = min(delta, vec2(1.0, 1.0) - delta);\n");
-    fsBuilder->codeAppendf("\t\tdelta = delta * %s;\n", builder->getUniformCStr(fInvInsetVar));
+    fsBuilder->codeAppendf("\t\tdelta = delta * %s;\n",
+                           args.fBuilder->getUniformCStr(fInvInsetVar));
 
     fsBuilder->codeAppend("\t\tfloat weight = 0.0;\n");
     fsBuilder->codeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n");
@@ -178,12 +169,12 @@
 
     fsBuilder->codeAppend("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\n");
     fsBuilder->codeAppend("\t\tvec4 output_color = ");
-    fsBuilder->appendTextureLookup(samplers[0], "mix_coord");
+    fsBuilder->appendTextureLookup(args.fSamplers[0], "mix_coord");
     fsBuilder->codeAppend(";\n");
 
-    fsBuilder->codeAppendf("\t\t%s = output_color;", outputColor);
+    fsBuilder->codeAppendf("\t\t%s = output_color;", args.fOutputColor);
     SkString modulate;
-    GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
+    GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
     fsBuilder->codeAppend(modulate.c_str());
 }
 
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index b156186..388dfcd 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -348,12 +348,7 @@
 public:
     GrGLMorphologyEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b);
 
@@ -380,31 +375,26 @@
     fType = m.type();
 }
 
-void GrGLMorphologyEffect::emitCode(GrGLFPBuilder* builder,
-                                    const GrFragmentProcessor&,
-                                    const char* outputColor,
-                                    const char* inputColor,
-                                    const TransformedCoordsArray& coords,
-                                    const TextureSamplerArray& samplers) {
-    fPixelSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+void GrGLMorphologyEffect::emitCode(EmitArgs& args) {
+    fPixelSizeUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kFloat_GrSLType, kDefault_GrSLPrecision,
                                             "PixelSize");
-    const char* pixelSizeInc = builder->getUniformCStr(fPixelSizeUni);
-    fRangeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    const char* pixelSizeInc = args.fBuilder->getUniformCStr(fPixelSizeUni);
+    fRangeUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec2f_GrSLType, kDefault_GrSLPrecision,
                                             "Range");
-    const char* range = builder->getUniformCStr(fRangeUni);
+    const char* range = args.fBuilder->getUniformCStr(fRangeUni);
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
     const char* func;
     switch (fType) {
         case GrMorphologyEffect::kErode_MorphologyType:
-            fsBuilder->codeAppendf("\t\t%s = vec4(1, 1, 1, 1);\n", outputColor);
+            fsBuilder->codeAppendf("\t\t%s = vec4(1, 1, 1, 1);\n", args.fOutputColor);
             func = "min";
             break;
         case GrMorphologyEffect::kDilate_MorphologyType:
-            fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor);
+            fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", args.fOutputColor);
             func = "max";
             break;
         default:
@@ -438,8 +428,8 @@
         fsBuilder->codeAppendf("\t\tcoord.%s = max(%s.x, coord.%s);", dir, range, dir);
     }
     fsBuilder->codeAppendf("\t\tfor (int i = 0; i < %d; i++) {\n", width());
-    fsBuilder->codeAppendf("\t\t\t%s = %s(%s, ", outputColor, func, outputColor);
-    fsBuilder->appendTextureLookup(samplers[0], "coord");
+    fsBuilder->codeAppendf("\t\t\t%s = %s(%s, ", args.fOutputColor, func, args.fOutputColor);
+    fsBuilder->appendTextureLookup(args.fSamplers[0], "coord");
     fsBuilder->codeAppend(");\n");
     // coord.x += pixelSize;
     fsBuilder->codeAppendf("\t\t\tcoord.%s += %s;\n", dir, pixelSizeInc);
@@ -449,7 +439,7 @@
     }
     fsBuilder->codeAppend("\t\t}\n");
     SkString modulate;
-    GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
+    GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
     fsBuilder->codeAppend(modulate.c_str());
 }
 
diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp
index 116c947..dba1778 100644
--- a/src/effects/SkPerlinNoiseShader.cpp
+++ b/src/effects/SkPerlinNoiseShader.cpp
@@ -487,12 +487,7 @@
     GrGLPerlinNoise(const GrProcessor&);
     virtual ~GrGLPerlinNoise() {}
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
@@ -639,32 +634,25 @@
   , fNumOctaves(processor.cast<GrPerlinNoiseEffect>().numOctaves()) {
 }
 
-void GrGLPerlinNoise::emitCode(GrGLFPBuilder* builder,
-                               const GrFragmentProcessor&,
-                               const char* outputColor,
-                               const char* inputColor,
-                               const TransformedCoordsArray& coords,
-                               const TextureSamplerArray& samplers) {
-    sk_ignore_unused_variable(inputColor);
+void GrGLPerlinNoise::emitCode(EmitArgs& args) {
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString vCoords = fsBuilder->ensureFSCoords2D(coords, 0);
-
-    fBaseFrequencyUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fBaseFrequencyUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec2f_GrSLType, kDefault_GrSLPrecision,
                                             "baseFrequency");
-    const char* baseFrequencyUni = builder->getUniformCStr(fBaseFrequencyUni);
-    fAlphaUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    const char* baseFrequencyUni = args.fBuilder->getUniformCStr(fBaseFrequencyUni);
+    fAlphaUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                     kFloat_GrSLType, kDefault_GrSLPrecision,
                                     "alpha");
-    const char* alphaUni = builder->getUniformCStr(fAlphaUni);
+    const char* alphaUni = args.fBuilder->getUniformCStr(fAlphaUni);
 
     const char* stitchDataUni = NULL;
     if (fStitchTiles) {
-        fStitchDataUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+        fStitchDataUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                              kVec2f_GrSLType, kDefault_GrSLPrecision,
                                              "stitchData");
-        stitchDataUni = builder->getUniformCStr(fStitchDataUni);
+        stitchDataUni = args.fBuilder->getUniformCStr(fStitchDataUni);
     }
 
     // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
@@ -734,7 +722,8 @@
         xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
 
         noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
-        fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
+        fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[0], xCoords.c_str(),
+                                       kVec2f_GrSLType);
         noiseCode.append(".r;");
     }
 
@@ -744,7 +733,8 @@
         xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
 
         noiseCode.appendf("\n\t%s.y = ", latticeIdx);
-        fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
+        fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[0], xCoords.c_str(),
+                                       kVec2f_GrSLType);
         noiseCode.append(".r;");
     }
 
@@ -768,7 +758,7 @@
         SkString latticeCoords("");
         latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
         noiseCode.appendf("\n\tvec4 %s = ", lattice);
-        fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
+        fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
             kVec2f_GrSLType);
         noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
@@ -780,7 +770,7 @@
         SkString latticeCoords("");
         latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
         noiseCode.append("\n\tlattice = ");
-        fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
+        fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
             kVec2f_GrSLType);
         noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
@@ -796,7 +786,7 @@
         SkString latticeCoords("");
         latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
         noiseCode.append("\n\tlattice = ");
-        fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
+        fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
             kVec2f_GrSLType);
         noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
@@ -808,7 +798,7 @@
         SkString latticeCoords("");
         latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
         noiseCode.append("\n\tlattice = ");
-        fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
+        fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
             kVec2f_GrSLType);
         noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
@@ -835,7 +825,7 @@
                            noiseVec, vCoords.c_str(), baseFrequencyUni);
 
     // Clear the color accumulator
-    fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", outputColor);
+    fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
 
     if (fStitchTiles) {
         // Set up TurbulenceInitial stitch values.
@@ -847,7 +837,7 @@
     // Loop over all octaves
     fsBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves);
 
-    fsBuilder->codeAppendf("\n\t\t\t%s += ", outputColor);
+    fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
     if (fType != SkPerlinNoiseShader::kFractalNoise_Type) {
         fsBuilder->codeAppend("abs(");
     }
@@ -884,17 +874,19 @@
     if (fType == SkPerlinNoiseShader::kFractalNoise_Type) {
         // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
         // by fractalNoise and (turbulenceFunctionResult) by turbulence.
-        fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", outputColor, outputColor);
+        fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
+                               args.fOutputColor,args.fOutputColor);
     }
 
-    fsBuilder->codeAppendf("\n\t\t%s.a *= %s;", outputColor, alphaUni);
+    fsBuilder->codeAppendf("\n\t\t%s.a *= %s;", args.fOutputColor, alphaUni);
 
     // Clamp values
-    fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", outputColor, outputColor);
+    fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
 
     // Pre-multiply the result
     fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
-                  outputColor, outputColor, outputColor, outputColor);
+                           args.fOutputColor, args.fOutputColor,
+                           args.fOutputColor, args.fOutputColor);
 }
 
 void GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index 11fdb89..8314f30 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -379,12 +379,7 @@
 public:
     GLColorTableEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
@@ -417,28 +412,24 @@
     pdm.set4fv(fRGBAYValuesUni, 1, rgbaYValues);
 }
 
-void GLColorTableEffect::emitCode(GrGLFPBuilder* builder,
-                                  const GrFragmentProcessor&,
-                                  const char* outputColor,
-                                  const char* inputColor,
-                                  const TransformedCoordsArray&,
-                                  const TextureSamplerArray& samplers) {
+void GLColorTableEffect::emitCode(EmitArgs& args) {
     const char* yoffsets;
-    fRGBAYValuesUni = builder->addUniform(GrGLFPBuilder::kFragment_Visibility,
+    fRGBAYValuesUni = args.fBuilder->addUniform(GrGLFPBuilder::kFragment_Visibility,
                                           kVec4f_GrSLType, kDefault_GrSLPrecision,
                                           "yoffsets", &yoffsets);
     static const float kColorScaleFactor = 255.0f / 256.0f;
     static const float kColorOffsetFactor = 1.0f / 512.0f;
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    if (NULL == inputColor) {
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    if (NULL == args.fInputColor) {
         // the input color is solid white (all ones).
         static const float kMaxValue = kColorScaleFactor + kColorOffsetFactor;
         fsBuilder->codeAppendf("\t\tvec4 coord = vec4(%f, %f, %f, %f);\n",
                                kMaxValue, kMaxValue, kMaxValue, kMaxValue);
 
     } else {
-        fsBuilder->codeAppendf("\t\tfloat nonZeroAlpha = max(%s.a, .0001);\n", inputColor);
-        fsBuilder->codeAppendf("\t\tvec4 coord = vec4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n", inputColor);
+        fsBuilder->codeAppendf("\t\tfloat nonZeroAlpha = max(%s.a, .0001);\n", args.fInputColor);
+        fsBuilder->codeAppendf("\t\tvec4 coord = vec4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n",
+                               args.fInputColor);
         fsBuilder->codeAppendf("\t\tcoord = coord * %f + vec4(%f, %f, %f, %f);\n",
                               kColorScaleFactor,
                               kColorOffsetFactor, kColorOffsetFactor,
@@ -447,27 +438,27 @@
 
     SkString coord;
 
-    fsBuilder->codeAppendf("\t\t%s.a = ", outputColor);
+    fsBuilder->codeAppendf("\t\t%s.a = ", args.fOutputColor);
     coord.printf("vec2(coord.a, %s.a)", yoffsets);
-    fsBuilder->appendTextureLookup(samplers[0], coord.c_str());
+    fsBuilder->appendTextureLookup(args.fSamplers[0], coord.c_str());
     fsBuilder->codeAppend(";\n");
 
-    fsBuilder->codeAppendf("\t\t%s.r = ", outputColor);
+    fsBuilder->codeAppendf("\t\t%s.r = ", args.fOutputColor);
     coord.printf("vec2(coord.r, %s.r)", yoffsets);
-    fsBuilder->appendTextureLookup(samplers[0], coord.c_str());
+    fsBuilder->appendTextureLookup(args.fSamplers[0], coord.c_str());
     fsBuilder->codeAppend(";\n");
 
-    fsBuilder->codeAppendf("\t\t%s.g = ", outputColor);
+    fsBuilder->codeAppendf("\t\t%s.g = ", args.fOutputColor);
     coord.printf("vec2(coord.g, %s.g)", yoffsets);
-    fsBuilder->appendTextureLookup(samplers[0], coord.c_str());
+    fsBuilder->appendTextureLookup(args.fSamplers[0], coord.c_str());
     fsBuilder->codeAppend(";\n");
 
-    fsBuilder->codeAppendf("\t\t%s.b = ", outputColor);
+    fsBuilder->codeAppendf("\t\t%s.b = ", args.fOutputColor);
     coord.printf("vec2(coord.b, %s.b)", yoffsets);
-    fsBuilder->appendTextureLookup(samplers[0], coord.c_str());
+    fsBuilder->appendTextureLookup(args.fSamplers[0], coord.c_str());
     fsBuilder->codeAppend(";\n");
 
-    fsBuilder->codeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
+    fsBuilder->codeAppendf("\t\t%s.rgb *= %s.a;\n", args.fOutputColor, args.fOutputColor);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp
index e5d6c6e..f6b6f6a 100644
--- a/src/effects/gradients/SkLinearGradient.cpp
+++ b/src/effects/gradients/SkLinearGradient.cpp
@@ -467,12 +467,7 @@
 
     virtual ~GrGLLinearGradient() { }
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     static void GenKey(const GrProcessor& processor, const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
         b->add32(GenBaseGradientKey(processor));
@@ -550,17 +545,13 @@
 
 /////////////////////////////////////////////////////////////////////
 
-void GrGLLinearGradient::emitCode(GrGLFPBuilder* builder,
-                                  const GrFragmentProcessor& fp,
-                                  const char* outputColor,
-                                  const char* inputColor,
-                                  const TransformedCoordsArray& coords,
-                                  const TextureSamplerArray& samplers) {
-    const GrLinearGradient& ge = fp.cast<GrLinearGradient>();
-    this->emitUniforms(builder, ge);
-    SkString t = builder->getFragmentShaderBuilder()->ensureFSCoords2D(coords, 0);
+void GrGLLinearGradient::emitCode(EmitArgs& args) {
+    const GrLinearGradient& ge = args.fFp.cast<GrLinearGradient>();
+    this->emitUniforms(args.fBuilder, ge);
+    SkString t = args.fBuilder->getFragmentShaderBuilder()->ensureFSCoords2D(args.fCoords, 0);
     t.append(".x");
-    this->emitColor(builder, ge, t.c_str(), outputColor, inputColor, samplers);
+    this->emitColor(args.fBuilder, ge, t.c_str(), args.fOutputColor, args.fInputColor,
+                    args.fSamplers);
 }
 
 /////////////////////////////////////////////////////////////////////
diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp
index d9f24c0..1976382 100644
--- a/src/effects/gradients/SkRadialGradient.cpp
+++ b/src/effects/gradients/SkRadialGradient.cpp
@@ -440,12 +440,7 @@
     GrGLRadialGradient(const GrProcessor&) {}
     virtual ~GrGLRadialGradient() { }
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     static void GenKey(const GrProcessor& processor, const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
         b->add32(GenBaseGradientKey(processor));
@@ -524,18 +519,14 @@
 
 /////////////////////////////////////////////////////////////////////
 
-void GrGLRadialGradient::emitCode(GrGLFPBuilder* builder,
-                                  const GrFragmentProcessor& fp,
-                                  const char* outputColor,
-                                  const char* inputColor,
-                                  const TransformedCoordsArray& coords,
-                                  const TextureSamplerArray& samplers) {
-    const GrRadialGradient& ge = fp.cast<GrRadialGradient>();
-    this->emitUniforms(builder, ge);
+void GrGLRadialGradient::emitCode(EmitArgs& args) {
+    const GrRadialGradient& ge = args.fFp.cast<GrRadialGradient>();
+    this->emitUniforms(args.fBuilder, ge);
     SkString t("length(");
-    t.append(builder->getFragmentShaderBuilder()->ensureFSCoords2D(coords, 0));
+    t.append(args.fBuilder->getFragmentShaderBuilder()->ensureFSCoords2D(args.fCoords, 0));
     t.append(")");
-    this->emitColor(builder, ge, t.c_str(), outputColor, inputColor, samplers);
+    this->emitColor(args.fBuilder, ge, t.c_str(), args.fOutputColor, args.fInputColor,
+                    args.fSamplers);
 }
 
 /////////////////////////////////////////////////////////////////////
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp
index 8a5de75..c3278b2 100644
--- a/src/effects/gradients/SkSweepGradient.cpp
+++ b/src/effects/gradients/SkSweepGradient.cpp
@@ -190,12 +190,7 @@
     GrGLSweepGradient(const GrProcessor&) {}
     virtual ~GrGLSweepGradient() { }
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     static void GenKey(const GrProcessor& processor, const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
         b->add32(GenBaseGradientKey(processor));
@@ -266,16 +261,12 @@
 
 /////////////////////////////////////////////////////////////////////
 
-void GrGLSweepGradient::emitCode(GrGLFPBuilder* builder,
-                                 const GrFragmentProcessor& fp,
-                                 const char* outputColor,
-                                 const char* inputColor,
-                                 const TransformedCoordsArray& coords,
-                                 const TextureSamplerArray& samplers) {
-    const GrSweepGradient& ge = fp.cast<GrSweepGradient>();
-    this->emitUniforms(builder, ge);
-    SkString coords2D = builder->getFragmentShaderBuilder()->ensureFSCoords2D(coords, 0);
-    const GrGLContextInfo& ctxInfo = builder->ctxInfo();
+void GrGLSweepGradient::emitCode(EmitArgs& args) {
+    const GrSweepGradient& ge = args.fFp.cast<GrSweepGradient>();
+    this->emitUniforms(args.fBuilder, ge);
+    SkString coords2D = args.fBuilder->getFragmentShaderBuilder()
+                                        ->ensureFSCoords2D(args.fCoords, 0);
+    const GrGLContextInfo& ctxInfo = args.fBuilder->ctxInfo();
     SkString t;
     // 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi]
     // On Intel GPU there is an issue where it reads the second arguement to atan "- %s.x" as an int
@@ -287,7 +278,8 @@
         t.printf("atan(- %s.y, -1.0 * %s.x) * 0.1591549430918 + 0.5",
                  coords2D.c_str(), coords2D.c_str());
     }
-    this->emitColor(builder, ge, t.c_str(), outputColor, inputColor, samplers);
+    this->emitColor(args.fBuilder, ge, t.c_str(), args.fOutputColor, args.fInputColor,
+                    args.fSamplers);
 }
 
 /////////////////////////////////////////////////////////////////////
diff --git a/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp b/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp
index 1e4a060..9461f13 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp
@@ -144,12 +144,7 @@
     GLEdge2PtConicalEffect(const GrProcessor&);
     virtual ~GLEdge2PtConicalEffect() { }
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
     static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
@@ -228,15 +223,10 @@
     , fCachedRadius(-SK_ScalarMax)
     , fCachedDiffRadius(-SK_ScalarMax) {}
 
-void GLEdge2PtConicalEffect::emitCode(GrGLFPBuilder* builder,
-                                      const GrFragmentProcessor& fp,
-                                      const char* outputColor,
-                                      const char* inputColor,
-                                      const TransformedCoordsArray& coords,
-                                      const TextureSamplerArray& samplers) {
-    const Edge2PtConicalEffect& ge = fp.cast<Edge2PtConicalEffect>();
-    this->emitUniforms(builder, ge);
-    fParamUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
+void GLEdge2PtConicalEffect::emitCode(EmitArgs& args) {
+    const Edge2PtConicalEffect& ge = args.fFp.cast<Edge2PtConicalEffect>();
+    this->emitUniforms(args.fBuilder, ge);
+    fParamUni = args.fBuilder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
                                          kFloat_GrSLType, kDefault_GrSLPrecision,
                                          "Conical2FSParams", 3);
 
@@ -246,29 +236,29 @@
     SkString p1; // start radius squared
     SkString p2; // difference in radii (r1 - r0)
 
-    builder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0);
-    builder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1);
-    builder->getUniformVariable(fParamUni).appendArrayAccess(2, &p2);
+    args.fBuilder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0);
+    args.fBuilder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1);
+    args.fBuilder->getUniformVariable(fParamUni).appendArrayAccess(2, &p2);
 
     // We interpolate the linear component in coords[1].
-    SkASSERT(coords[0].getType() == coords[1].getType());
+    SkASSERT(args.fCoords[0].getType() == args.fCoords[1].getType());
     const char* coords2D;
     SkString bVar;
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    if (kVec3f_GrSLType == coords[0].getType()) {
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    if (kVec3f_GrSLType == args.fCoords[0].getType()) {
         fsBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy / %s.z, %s.x / %s.z);\n",
-                               coords[0].c_str(), coords[0].c_str(), coords[1].c_str(),
-                               coords[1].c_str());
+                               args.fCoords[0].c_str(), args.fCoords[0].c_str(),
+                               args.fCoords[1].c_str(), args.fCoords[1].c_str());
         coords2D = "interpolants.xy";
         bVar = "interpolants.z";
     } else {
-        coords2D = coords[0].c_str();
-        bVar.printf("%s.x", coords[1].c_str());
+        coords2D = args.fCoords[0].c_str();
+        bVar.printf("%s.x", args.fCoords[1].c_str());
     }
 
     // output will default to transparent black (we simply won't write anything
     // else to it if invalid, instead of discarding or returning prematurely)
-    fsBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor);
+    fsBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
 
     // c = (x^2)+(y^2) - params[1]
     fsBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
@@ -282,7 +272,8 @@
     fsBuilder->codeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
                            p2.c_str(), p0.c_str());
     fsBuilder->codeAppend("\t");
-    this->emitColor(builder, ge, tName.c_str(), outputColor, inputColor, samplers);
+    this->emitColor(args.fBuilder, ge, tName.c_str(), args.fOutputColor, args.fInputColor,
+                    args.fSamplers);
     fsBuilder->codeAppend("\t}\n");
 }
 
@@ -434,12 +425,7 @@
     GLFocalOutside2PtConicalEffect(const GrProcessor&);
     virtual ~GLFocalOutside2PtConicalEffect() { }
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
     static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
@@ -520,34 +506,29 @@
     fIsFlipped = data.isFlipped();
 }
 
-void GLFocalOutside2PtConicalEffect::emitCode(GrGLFPBuilder* builder,
-                                              const GrFragmentProcessor& fp,
-                                              const char* outputColor,
-                                              const char* inputColor,
-                                              const TransformedCoordsArray& coords,
-                                              const TextureSamplerArray& samplers) {
-    const FocalOutside2PtConicalEffect& ge = fp.cast<FocalOutside2PtConicalEffect>();
-    this->emitUniforms(builder, ge);
-    fParamUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
+void GLFocalOutside2PtConicalEffect::emitCode(EmitArgs& args) {
+    const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>();
+    this->emitUniforms(args.fBuilder, ge);
+    fParamUni = args.fBuilder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
                                          kFloat_GrSLType, kDefault_GrSLPrecision,
                                          "Conical2FSParams", 2);
     SkString tName("t");
     SkString p0; // focalX
     SkString p1; // 1 - focalX * focalX
 
-    builder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0);
-    builder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1);
+    args.fBuilder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0);
+    args.fBuilder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1);
 
     // if we have a vec3 from being in perspective, convert it to a vec2 first
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString coords2DString = fsBuilder->ensureFSCoords2D(coords, 0);
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString coords2DString = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
     const char* coords2D = coords2DString.c_str();
 
     // t = p.x * focal.x +/- sqrt(p.x^2 + (1 - focal.x^2) * p.y^2)
 
     // output will default to transparent black (we simply won't write anything
     // else to it if invalid, instead of discarding or returning prematurely)
-    fsBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor);
+    fsBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
 
     fsBuilder->codeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D);
     fsBuilder->codeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D);
@@ -565,7 +546,8 @@
 
     fsBuilder->codeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str());
     fsBuilder->codeAppend("\t\t");
-    this->emitColor(builder, ge, tName.c_str(), outputColor, inputColor, samplers);
+    this->emitColor(args.fBuilder, ge, tName.c_str(), args.fOutputColor, args.fInputColor,
+                    args.fSamplers);
     fsBuilder->codeAppend("\t}\n");
 }
 
@@ -656,12 +638,7 @@
     GLFocalInside2PtConicalEffect(const GrProcessor&);
     virtual ~GLFocalInside2PtConicalEffect() {}
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
     static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
@@ -737,33 +714,29 @@
     , fFSVaryingName(NULL)
     , fCachedFocal(SK_ScalarMax) {}
 
-void GLFocalInside2PtConicalEffect::emitCode(GrGLFPBuilder* builder,
-                                             const GrFragmentProcessor& fp,
-                                             const char* outputColor,
-                                             const char* inputColor,
-                                             const TransformedCoordsArray& coords,
-                                             const TextureSamplerArray& samplers) {
-    const FocalInside2PtConicalEffect& ge = fp.cast<FocalInside2PtConicalEffect>();
-    this->emitUniforms(builder, ge);
-    fFocalUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+void GLFocalInside2PtConicalEffect::emitCode(EmitArgs& args) {
+    const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>();
+    this->emitUniforms(args.fBuilder, ge);
+    fFocalUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                     kFloat_GrSLType, kDefault_GrSLPrecision,
                                     "Conical2FSParams");
     SkString tName("t");
 
     // this is the distance along x-axis from the end center to focal point in
     // transformed coordinates
-    GrGLShaderVar focal = builder->getUniformVariable(fFocalUni);
+    GrGLShaderVar focal = args.fBuilder->getUniformVariable(fFocalUni);
 
     // if we have a vec3 from being in perspective, convert it to a vec2 first
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString coords2DString = fsBuilder->ensureFSCoords2D(coords, 0);
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString coords2DString = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
     const char* coords2D = coords2DString.c_str();
 
     // t = p.x * focalX + length(p)
     fsBuilder->codeAppendf("\tfloat %s = %s.x * %s  + length(%s);\n", tName.c_str(),
                            coords2D, focal.c_str(), coords2D);
 
-    this->emitColor(builder, ge, tName.c_str(), outputColor, inputColor, samplers);
+    this->emitColor(args.fBuilder, ge, tName.c_str(), args.fOutputColor, args.fInputColor,
+                    args.fSamplers);
 }
 
 void GLFocalInside2PtConicalEffect::setData(const GrGLProgramDataManager& pdman,
@@ -907,12 +880,7 @@
     GLCircleInside2PtConicalEffect(const GrProcessor&);
     virtual ~GLCircleInside2PtConicalEffect() {}
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
     static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
@@ -997,31 +965,26 @@
     , fCachedB(SK_ScalarMax)
     , fCachedC(SK_ScalarMax) {}
 
-void GLCircleInside2PtConicalEffect::emitCode(GrGLFPBuilder* builder,
-                                              const GrFragmentProcessor& fp,
-                                              const char* outputColor,
-                                              const char* inputColor,
-                                              const TransformedCoordsArray& coords,
-                                              const TextureSamplerArray& samplers) {
-    const CircleInside2PtConicalEffect& ge = fp.cast<CircleInside2PtConicalEffect>();
-    this->emitUniforms(builder, ge);
-    fCenterUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+void GLCircleInside2PtConicalEffect::emitCode(EmitArgs& args) {
+    const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
+    this->emitUniforms(args.fBuilder, ge);
+    fCenterUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                      kVec2f_GrSLType, kDefault_GrSLPrecision,
                                      "Conical2FSCenter");
-    fParamUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fParamUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                     kVec3f_GrSLType, kDefault_GrSLPrecision,
                                     "Conical2FSParams");
     SkString tName("t");
 
-    GrGLShaderVar center = builder->getUniformVariable(fCenterUni);
+    GrGLShaderVar center = args.fBuilder->getUniformVariable(fCenterUni);
     // params.x = A
     // params.y = B
     // params.z = C
-    GrGLShaderVar params = builder->getUniformVariable(fParamUni);
+    GrGLShaderVar params = args.fBuilder->getUniformVariable(fParamUni);
 
     // if we have a vec3 from being in perspective, convert it to a vec2 first
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString coords2DString = fsBuilder->ensureFSCoords2D(coords, 0);
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString coords2DString = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
     const char* coords2D = coords2DString.c_str();
 
     // p = coords2D
@@ -1038,7 +1001,8 @@
     fsBuilder->codeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
                            tName.c_str(), params.c_str(), params.c_str());
 
-    this->emitColor(builder, ge, tName.c_str(), outputColor, inputColor, samplers);
+    this->emitColor(args.fBuilder, ge, tName.c_str(), args.fOutputColor, args.fInputColor,
+                    args.fSamplers);
 }
 
 void GLCircleInside2PtConicalEffect::setData(const GrGLProgramDataManager& pdman,
@@ -1144,12 +1108,7 @@
     GLCircleOutside2PtConicalEffect(const GrProcessor&);
     virtual ~GLCircleOutside2PtConicalEffect() {}
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
     static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
@@ -1241,36 +1200,31 @@
     fIsFlipped = data.isFlipped();
     }
 
-void GLCircleOutside2PtConicalEffect::emitCode(GrGLFPBuilder* builder,
-                                               const GrFragmentProcessor& fp,
-                                               const char* outputColor,
-                                               const char* inputColor,
-                                               const TransformedCoordsArray& coords,
-                                               const TextureSamplerArray& samplers) {
-    const CircleOutside2PtConicalEffect& ge = fp.cast<CircleOutside2PtConicalEffect>();
-    this->emitUniforms(builder, ge);
-    fCenterUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+void GLCircleOutside2PtConicalEffect::emitCode(EmitArgs& args) {
+    const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
+    this->emitUniforms(args.fBuilder, ge);
+    fCenterUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                      kVec2f_GrSLType, kDefault_GrSLPrecision,
                                      "Conical2FSCenter");
-    fParamUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fParamUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                     kVec4f_GrSLType, kDefault_GrSLPrecision,
                                     "Conical2FSParams");
     SkString tName("t");
 
-    GrGLShaderVar center = builder->getUniformVariable(fCenterUni);
+    GrGLShaderVar center = args.fBuilder->getUniformVariable(fCenterUni);
     // params.x = A
     // params.y = B
     // params.z = C
-    GrGLShaderVar params = builder->getUniformVariable(fParamUni);
+    GrGLShaderVar params = args.fBuilder->getUniformVariable(fParamUni);
 
     // if we have a vec3 from being in perspective, convert it to a vec2 first
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString coords2DString = fsBuilder->ensureFSCoords2D(coords, 0);
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString coords2DString = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
     const char* coords2D = coords2DString.c_str();
 
     // output will default to transparent black (we simply won't write anything
     // else to it if invalid, instead of discarding or returning prematurely)
-    fsBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor);
+    fsBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
 
     // p = coords2D
     // e = center end
@@ -1297,7 +1251,8 @@
 
     fsBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n", tName.c_str(), params.c_str());
     fsBuilder->codeAppend("\t\t");
-    this->emitColor(builder, ge, tName.c_str(), outputColor, inputColor, samplers);
+    this->emitColor(args.fBuilder, ge, tName.c_str(), args.fOutputColor, args.fInputColor,
+                    args.fSamplers);
     fsBuilder->codeAppend("\t}\n");
 }
 
diff --git a/src/gpu/effects/GrBicubicEffect.cpp b/src/gpu/effects/GrBicubicEffect.cpp
index 027a3c7..cb82ea5 100644
--- a/src/gpu/effects/GrBicubicEffect.cpp
+++ b/src/gpu/effects/GrBicubicEffect.cpp
@@ -23,12 +23,7 @@
 public:
     GrGLBicubicEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
@@ -51,23 +46,18 @@
 GrGLBicubicEffect::GrGLBicubicEffect(const GrProcessor&) {
 }
 
-void GrGLBicubicEffect::emitCode(GrGLFPBuilder* builder,
-                                 const GrFragmentProcessor& effect,
-                                 const char* outputColor,
-                                 const char* inputColor,
-                                 const TransformedCoordsArray& coords,
-                                 const TextureSamplerArray& samplers) {
-    const GrTextureDomain& domain = effect.cast<GrBicubicEffect>().domain();
+void GrGLBicubicEffect::emitCode(EmitArgs& args) {
+    const GrTextureDomain& domain = args.fFp.cast<GrBicubicEffect>().domain();
 
-    fCoefficientsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fCoefficientsUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                            kMat44f_GrSLType, kDefault_GrSLPrecision,
                                            "Coefficients");
-    fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fImageIncrementUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                              kVec2f_GrSLType, kDefault_GrSLPrecision,
                                              "ImageIncrement");
 
-    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
-    const char* coeff = builder->getUniformCStr(fCoefficientsUni);
+    const char* imgInc = args.fBuilder->getUniformCStr(fImageIncrementUni);
+    const char* coeff = args.fBuilder->getUniformCStr(fCoefficientsUni);
 
     SkString cubicBlendName;
 
@@ -79,8 +69,8 @@
         GrGLShaderVar("c2",            kVec4f_GrSLType),
         GrGLShaderVar("c3",            kVec4f_GrSLType),
     };
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
     fsBuilder->emitFunction(kVec4f_GrSLType,
                             "cubicBlend",
                             SK_ARRAY_COUNT(gCubicBlendArgs),
@@ -104,13 +94,14 @@
             coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1);
             SkString sampleVar;
             sampleVar.printf("rowColors[%d]", x);
-            fDomain.sampleTexture(fsBuilder, domain, sampleVar.c_str(), coord, samplers[0]);
+            fDomain.sampleTexture(fsBuilder, domain, sampleVar.c_str(), coord, args.fSamplers[0]);
         }
         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);
-    fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(bicubicColor.c_str()) * GrGLSLExpr4(inputColor)).c_str());
+    fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutputColor,(GrGLSLExpr4(bicubicColor.c_str()) *
+                           GrGLSLExpr4(args.fInputColor)).c_str());
 }
 
 void GrGLBicubicEffect::setData(const GrGLProgramDataManager& pdman,
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index 82ac5df..8238dcd 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -23,28 +23,24 @@
         fPMConversion = configConversionEffect.pmConversion();
     }
 
-    virtual void emitCode(GrGLFPBuilder* builder,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray& coords,
-                          const TextureSamplerArray& samplers) override {
+    virtual void emitCode(EmitArgs& args) override {
         // Using highp for GLES here in order to avoid some precision issues on specific GPUs.
         GrGLShaderVar tmpVar("tmpColor", kVec4f_GrSLType, 0, kHigh_GrSLPrecision);
         SkString tmpDecl;
-        tmpVar.appendDecl(builder->ctxInfo(), &tmpDecl);
+        tmpVar.appendDecl(args.fBuilder->ctxInfo(), &tmpDecl);
 
-        GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+        GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
 
         fsBuilder->codeAppendf("%s;", tmpDecl.c_str());
 
         fsBuilder->codeAppendf("%s = ", tmpVar.c_str());
-        fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
+        fsBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0].c_str(),
+                                       args.fCoords[0].getType());
         fsBuilder->codeAppend(";");
 
         if (GrConfigConversionEffect::kNone_PMConversion == fPMConversion) {
             SkASSERT(fSwapRedAndBlue);
-            fsBuilder->codeAppendf("%s = %s.bgra;", outputColor, tmpVar.c_str());
+            fsBuilder->codeAppendf("%s = %s.bgra;", args.fOutputColor, tmpVar.c_str());
         } else {
             const char* swiz = fSwapRedAndBlue ? "bgr" : "rgb";
             switch (fPMConversion) {
@@ -76,10 +72,10 @@
                     SkFAIL("Unknown conversion op.");
                     break;
             }
-            fsBuilder->codeAppendf("%s = %s;", outputColor, tmpVar.c_str());
+            fsBuilder->codeAppendf("%s = %s;", args.fOutputColor, tmpVar.c_str());
         }
         SkString modulate;
-        GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
+        GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
         fsBuilder->codeAppend(modulate.c_str());
     }
 
diff --git a/src/gpu/effects/GrConstColorProcessor.cpp b/src/gpu/effects/GrConstColorProcessor.cpp
index bc09156..e98a1ff 100644
--- a/src/gpu/effects/GrConstColorProcessor.cpp
+++ b/src/gpu/effects/GrConstColorProcessor.cpp
@@ -13,26 +13,23 @@
 public:
     GLConstColorProcessor() : fPrevColor(GrColor_ILLEGAL) {}
 
-    void emitCode(GrGLFPBuilder* builder,
-                  const GrFragmentProcessor& fp,
-                  const char* outputColor,
-                  const char* inputColor,
-                  const TransformedCoordsArray& coords,
-                  const TextureSamplerArray& samplers) override {
-        GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    void emitCode(EmitArgs& args) override {
+        GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
         const char* colorUni;
-        fColorUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+        fColorUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec4f_GrSLType, kMedium_GrSLPrecision, "constantColor",
                                             &colorUni);
-        switch (fp.cast<GrConstColorProcessor>().inputMode()) {
+        switch (args.fFp.cast<GrConstColorProcessor>().inputMode()) {
             case GrConstColorProcessor::kIgnore_InputMode:
-                fsBuilder->codeAppendf("%s = %s;", outputColor, colorUni);
+                fsBuilder->codeAppendf("%s = %s;", args.fOutputColor, colorUni);
                 break;
             case GrConstColorProcessor::kModulateRGBA_InputMode:
-                fsBuilder->codeAppendf("%s = %s * %s;", outputColor, inputColor, colorUni);
+                fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputColor, args.fInputColor,
+                                       colorUni);
                 break;
             case GrConstColorProcessor::kModulateA_InputMode:
-                fsBuilder->codeAppendf("%s = %s.a * %s;", outputColor, inputColor, colorUni);
+                fsBuilder->codeAppendf("%s = %s.a * %s;", args.fOutputColor, args.fInputColor,
+                                       colorUni);
                 break;
         }
     }
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp
index 6ecba24..69c5862 100644
--- a/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -81,12 +81,7 @@
 public:
     GLAARectEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder* builder,
-                          const GrFragmentProcessor& fp,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
 
@@ -102,23 +97,18 @@
     fPrevRect.fLeft = SK_ScalarNaN;
 }
 
-void GLAARectEffect::emitCode(GrGLFPBuilder* builder,
-                              const GrFragmentProcessor& fp,
-                              const char* outputColor,
-                              const char* inputColor,
-                              const TransformedCoordsArray&,
-                              const TextureSamplerArray& samplers) {
-    const AARectEffect& aare = fp.cast<AARectEffect>();
+void GLAARectEffect::emitCode(EmitArgs& args) {
+    const AARectEffect& aare = args.fFp.cast<AARectEffect>();
     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(GrGLProgramBuilder::kFragment_Visibility,
+    fRectUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                        kVec4f_GrSLType,
                                        kDefault_GrSLPrecision,
                                        "rect",
                                        &rectName);
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
     const char* fragmentPos = fsBuilder->fragmentPosition();
     if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) {
         // The amount of coverage removed in x and y by the edges is computed as a pair of negative
@@ -142,8 +132,8 @@
     if (GrProcessorEdgeTypeIsInverseFill(aare.getEdgeType())) {
         fsBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n");
     }
-    fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
-                           (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
+    fsBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
+                           (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
 }
 
 void GLAARectEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& processor) {
@@ -176,12 +166,7 @@
 public:
     GrGLConvexPolyEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder* builder,
-                          const GrFragmentProcessor& fp,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
 
@@ -197,22 +182,17 @@
     fPrevEdges[0] = SK_ScalarNaN;
 }
 
-void GrGLConvexPolyEffect::emitCode(GrGLFPBuilder* builder,
-                                    const GrFragmentProcessor& fp,
-                                    const char* outputColor,
-                                    const char* inputColor,
-                                    const TransformedCoordsArray&,
-                                    const TextureSamplerArray& samplers) {
-    const GrConvexPolyEffect& cpe = fp.cast<GrConvexPolyEffect>();
+void GrGLConvexPolyEffect::emitCode(EmitArgs& args) {
+    const GrConvexPolyEffect& cpe = args.fFp.cast<GrConvexPolyEffect>();
 
     const char *edgeArrayName;
-    fEdgeUniform = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
+    fEdgeUniform = args.fBuilder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec3f_GrSLType,
                                              kDefault_GrSLPrecision,
                                              "edges",
                                             cpe.getEdgeCount(),
                                             &edgeArrayName);
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
     fsBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
     fsBuilder->codeAppend("\t\tfloat edge;\n");
     const char* fragmentPos = fsBuilder->fragmentPosition();
@@ -228,15 +208,15 @@
     }
 
     // Woe is me. See skbug.com/2149.
-    if (kTegra2_GrGLRenderer == builder->ctxInfo().renderer()) {
+    if (kTegra2_GrGLRenderer == args.fBuilder->ctxInfo().renderer()) {
         fsBuilder->codeAppend("\t\tif (-1.0 == alpha) {\n\t\t\tdiscard;\n\t\t}\n");
     }
 
     if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) {
         fsBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
     }
-    fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
-                           (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
+    fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutputColor,
+                           (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
 }
 
 void GrGLConvexPolyEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& effect) {
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index 7bb5434..0f32c9c 100644
--- a/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/src/gpu/effects/GrConvolutionEffect.cpp
@@ -17,12 +17,7 @@
 public:
     GrGLConvolutionEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) override;
 
@@ -50,32 +45,27 @@
     fDirection = c.direction();
 }
 
-void GrGLConvolutionEffect::emitCode(GrGLFPBuilder* builder,
-                                     const GrFragmentProcessor&,
-                                     const char* outputColor,
-                                     const char* inputColor,
-                                     const TransformedCoordsArray& coords,
-                                     const TextureSamplerArray& samplers) {
-    fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+void GrGLConvolutionEffect::emitCode(EmitArgs& args) {
+    fImageIncrementUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                              kVec2f_GrSLType, kDefault_GrSLPrecision,
                                              "ImageIncrement");
     if (this->useBounds()) {
-        fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+        fBoundsUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                          kVec2f_GrSLType, kDefault_GrSLPrecision,
                                          "Bounds");
     }
-    fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
+    fKernelUni = args.fBuilder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
                                           kFloat_GrSLType, kDefault_GrSLPrecision,
                                           "Kernel", this->width());
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
 
-    fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor);
+    fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", args.fOutputColor);
 
     int width = this->width();
-    const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni);
-    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
+    const GrGLShaderVar& kernel = args.fBuilder->getUniformVariable(fKernelUni);
+    const char* imgInc = args.fBuilder->getUniformCStr(fImageIncrementUni);
 
     fsBuilder->codeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), fRadius, imgInc);
 
@@ -90,13 +80,13 @@
             // We used to compute a bool indicating whether we're in bounds or not, cast it to a
             // float, and then mul weight*texture_sample by the float. However, the Adreno 430 seems
             // to have a bug that caused corruption.
-            const char* bounds = builder->getUniformCStr(fBoundsUni);
+            const char* bounds = args.fBuilder->getUniformCStr(fBoundsUni);
             const char* component = this->direction() == Gr1DKernelEffect::kY_Direction ? "y" : "x";
             fsBuilder->codeAppendf("if (coord.%s >= %s.x && coord.%s <= %s.y) {",
                 component, bounds, component, bounds);
         }
-        fsBuilder->codeAppendf("\t\t%s += ", outputColor);
-        fsBuilder->appendTextureLookup(samplers[0], "coord");
+        fsBuilder->codeAppendf("\t\t%s += ", args.fOutputColor);
+        fsBuilder->appendTextureLookup(args.fSamplers[0], "coord");
         fsBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str());
         if (this->useBounds()) {
             fsBuilder->codeAppend("}");
@@ -105,7 +95,7 @@
     }
 
     SkString modulate;
-    GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
+    GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
     fsBuilder->codeAppend(modulate.c_str());
 }
 
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index 350243e..76c285f 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -447,20 +447,16 @@
     GLCustomXferFP(const GrFragmentProcessor&) {}
     ~GLCustomXferFP() override {};
 
-    void emitCode(GrGLFPBuilder* builder,
-                  const GrFragmentProcessor& fp,
-                  const char* outputColor,
-                  const char* inputColor,
-                  const TransformedCoordsArray& coords,
-                  const TextureSamplerArray& samplers) override {
-        SkXfermode::Mode mode = fp.cast<GrCustomXferFP>().mode();
-        GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    void emitCode(EmitArgs& args) override {
+        SkXfermode::Mode mode = args.fFp.cast<GrCustomXferFP>().mode();
+        GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
         const char* dstColor = "bgColor";
         fsBuilder->codeAppendf("vec4 %s = ", dstColor);
-        fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
+        fsBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0].c_str(),
+                                       args.fCoords[0].getType());
         fsBuilder->codeAppendf(";");
 
-        emit_custom_xfermode_code(mode, fsBuilder, outputColor, inputColor, dstColor); 
+        emit_custom_xfermode_code(mode, fsBuilder, args.fOutputColor, args.fInputColor, dstColor);
     }
 
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override {}
diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp
index 1638b1f..e870140 100644
--- a/src/gpu/effects/GrDitherEffect.cpp
+++ b/src/gpu/effects/GrDitherEffect.cpp
@@ -63,12 +63,7 @@
 public:
     GLDitherEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder* builder,
-                          const GrFragmentProcessor& fp,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs& args) override;
 
 private:
     typedef GrGLFragmentProcessor INHERITED;
@@ -77,13 +72,8 @@
 GLDitherEffect::GLDitherEffect(const GrProcessor&) {
 }
 
-void GLDitherEffect::emitCode(GrGLFPBuilder* builder,
-                              const GrFragmentProcessor& fp,
-                              const char* outputColor,
-                              const char* inputColor,
-                              const TransformedCoordsArray&,
-                              const TextureSamplerArray& samplers) {
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+void GLDitherEffect::emitCode(EmitArgs& args) {
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->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
@@ -97,7 +87,7 @@
                            "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n",
                            fsBuilder->fragmentPosition());
     fsBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n",
-                           outputColor, GrGLSLExpr4(inputColor).c_str());
+                           args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str());
 }
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index 87b38ee..fb1b39c 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -12,12 +12,7 @@
 class GrGLMatrixConvolutionEffect : public GrGLFragmentProcessor {
 public:
     GrGLMatrixConvolutionEffect(const GrProcessor&);
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
 
@@ -44,37 +39,32 @@
     fConvolveAlpha = m.convolveAlpha();
 }
 
-void GrGLMatrixConvolutionEffect::emitCode(GrGLFPBuilder* builder,
-                                           const GrFragmentProcessor& fp,
-                                           const char* outputColor,
-                                           const char* inputColor,
-                                           const TransformedCoordsArray& coords,
-                                           const TextureSamplerArray& samplers) {
-    const GrTextureDomain& domain = fp.cast<GrMatrixConvolutionEffect>().domain();
-    fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+void GrGLMatrixConvolutionEffect::emitCode(EmitArgs& args) {
+    const GrTextureDomain& domain = args.fFp.cast<GrMatrixConvolutionEffect>().domain();
+    fImageIncrementUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                              kVec2f_GrSLType, kDefault_GrSLPrecision,
                                              "ImageIncrement");
-    fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
+    fKernelUni = args.fBuilder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
                                           kFloat_GrSLType, kDefault_GrSLPrecision,
                                           "Kernel",
                                           fKernelSize.width() * fKernelSize.height());
-    fKernelOffsetUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fKernelOffsetUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                            kVec2f_GrSLType, kDefault_GrSLPrecision, "KernelOffset");
-    fGainUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fGainUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                    kFloat_GrSLType, kDefault_GrSLPrecision, "Gain");
-    fBiasUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fBiasUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                    kFloat_GrSLType, kDefault_GrSLPrecision, "Bias");
 
-    const char* kernelOffset = builder->getUniformCStr(fKernelOffsetUni);
-    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
-    const char* kernel = builder->getUniformCStr(fKernelUni);
-    const char* gain = builder->getUniformCStr(fGainUni);
-    const char* bias = builder->getUniformCStr(fBiasUni);
+    const char* kernelOffset = args.fBuilder->getUniformCStr(fKernelOffsetUni);
+    const char* imgInc = args.fBuilder->getUniformCStr(fImageIncrementUni);
+    const char* kernel = args.fBuilder->getUniformCStr(fKernelUni);
+    const char* gain = args.fBuilder->getUniformCStr(fGainUni);
+    const char* bias = args.fBuilder->getUniformCStr(fBiasUni);
     int kWidth = fKernelSize.width();
     int kHeight = fKernelSize.height();
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
     fsBuilder->codeAppend("vec4 sum = vec4(0, 0, 0, 0);");
     fsBuilder->codeAppendf("vec2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset,
                            imgInc);
@@ -86,7 +76,7 @@
             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(fsBuilder, domain, "c", coord, samplers[0]);
+            fDomain.sampleTexture(fsBuilder, domain, "c", coord, args.fSamplers[0]);
             if (!fConvolveAlpha) {
                 fsBuilder->codeAppend("c.rgb /= c.a;");
                 fsBuilder->codeAppend("c.rgb = clamp(c.rgb, 0.0, 1.0);");
@@ -95,18 +85,18 @@
         }
     }
     if (fConvolveAlpha) {
-        fsBuilder->codeAppendf("%s = sum * %s + %s;", outputColor, gain, bias);
+        fsBuilder->codeAppendf("%s = sum * %s + %s;", args.fOutputColor, gain, bias);
         fsBuilder->codeAppendf("%s.rgb = clamp(%s.rgb, 0.0, %s.a);",
-                               outputColor, outputColor, outputColor);
+                               args.fOutputColor, args.fOutputColor, args.fOutputColor);
     } else {
-        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);
+        fDomain.sampleTexture(fsBuilder, domain, "c", coords2D, args.fSamplers[0]);
+        fsBuilder->codeAppendf("%s.a = c.a;", args.fOutputColor);
+        fsBuilder->codeAppendf("%s.rgb = sum.rgb * %s + %s;", args.fOutputColor, gain, bias);
+        fsBuilder->codeAppendf("%s.rgb *= %s.a;", args.fOutputColor, args.fOutputColor);
     }
 
     SkString modulate;
-    GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
+    GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
     fsBuilder->codeAppend(modulate.c_str());
 }
 
diff --git a/src/gpu/effects/GrOvalEffect.cpp b/src/gpu/effects/GrOvalEffect.cpp
index e7b5235..729e8a5 100644
--- a/src/gpu/effects/GrOvalEffect.cpp
+++ b/src/gpu/effects/GrOvalEffect.cpp
@@ -93,12 +93,7 @@
 public:
     GLCircleEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder* builder,
-                          const GrFragmentProcessor& fp,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
 
@@ -116,22 +111,17 @@
     fPrevRadius = -1.f;
 }
 
-void GLCircleEffect::emitCode(GrGLFPBuilder* builder,
-                              const GrFragmentProcessor& fp,
-                              const char* outputColor,
-                              const char* inputColor,
-                              const TransformedCoordsArray&,
-                              const TextureSamplerArray& samplers) {
-    const CircleEffect& ce = fp.cast<CircleEffect>();
+void GLCircleEffect::emitCode(EmitArgs& args) {
+    const CircleEffect& ce = args.fFp.cast<CircleEffect>();
     const char *circleName;
     // The circle uniform is (center.x, center.y, radius + 0.5, 1 / (radius + 0.5)) for regular
     // fills and (..., radius - 0.5, 1 / (radius - 0.5)) for inverse fills.
-    fCircleUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fCircleUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                          kVec4f_GrSLType, kDefault_GrSLPrecision,
                                          "circle",
                                          &circleName);
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
     const char* fragmentPos = fsBuilder->fragmentPosition();
 
     SkASSERT(kHairlineAA_GrProcessorEdgeType != ce.getEdgeType());
@@ -152,8 +142,8 @@
         fsBuilder->codeAppend("\t\td = d > 0.5 ? 1.0 : 0.0;\n");
     }
 
-    fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
-                           (GrGLSLExpr4(inputColor) * GrGLSLExpr1("d")).c_str());
+    fsBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
+                           (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("d")).c_str());
 }
 
 void GLCircleEffect::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
@@ -273,12 +263,7 @@
 public:
     GLEllipseEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder* builder,
-                          const GrFragmentProcessor& fp,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
 
@@ -296,21 +281,16 @@
     fPrevRadii.fX = -1.f;
 }
 
-void GLEllipseEffect::emitCode(GrGLFPBuilder* builder,
-                               const GrFragmentProcessor& fp,
-                               const char* outputColor,
-                               const char* inputColor,
-                               const TransformedCoordsArray&,
-                               const TextureSamplerArray& samplers) {
-    const EllipseEffect& ee = fp.cast<EllipseEffect>();
+void GLEllipseEffect::emitCode(EmitArgs& args) {
+    const EllipseEffect& ee = args.fFp.cast<EllipseEffect>();
     const char *ellipseName;
     // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
-    fEllipseUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fEllipseUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                          kVec4f_GrSLType, kDefault_GrSLPrecision,
                                          "ellipse",
                                          &ellipseName);
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
     const char* fragmentPos = fsBuilder->fragmentPosition();
 
     // d is the offset to the ellipse center
@@ -341,8 +321,8 @@
             SkFAIL("Hairline not expected here.");
     }
 
-    fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
-                           (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
+    fsBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
+                           (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
 }
 
 void GLEllipseEffect::GenKey(const GrProcessor& effect, const GrGLSLCaps&,
diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp
index 432e6ff..c95690f 100644
--- a/src/gpu/effects/GrRRectEffect.cpp
+++ b/src/gpu/effects/GrRRectEffect.cpp
@@ -128,12 +128,7 @@
 public:
     GLCircularRRectEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder* builder,
-                          const GrFragmentProcessor& fp,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
 
@@ -150,29 +145,24 @@
     fPrevRRect.setEmpty();
 }
 
-void GLCircularRRectEffect::emitCode(GrGLFPBuilder* builder,
-                                     const GrFragmentProcessor& fp,
-                                     const char* outputColor,
-                                     const char* inputColor,
-                                     const TransformedCoordsArray&,
-                                     const TextureSamplerArray& samplers) {
-    const CircularRRectEffect& crre = fp.cast<CircularRRectEffect>();
+void GLCircularRRectEffect::emitCode(EmitArgs& args) {
+    const CircularRRectEffect& crre = args.fFp.cast<CircularRRectEffect>();
     const char *rectName;
     const char *radiusPlusHalfName;
     // The inner rect is the rrect bounds inset by the radius. Its left, top, right, and bottom
     // 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(GrGLProgramBuilder::kFragment_Visibility,
+    fInnerRectUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec4f_GrSLType, kDefault_GrSLPrecision,
                                             "innerRect",
                                             &rectName);
-    fRadiusPlusHalfUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fRadiusPlusHalfUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                  kFloat_GrSLType, kDefault_GrSLPrecision,
                                                  "radiusPlusHalf",
                                                  &radiusPlusHalfName);
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->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
@@ -279,8 +269,8 @@
         fsBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n");
     }
 
-    fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
-                           (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
+    fsBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
+                           (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
 }
 
 void GLCircularRRectEffect::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
@@ -483,12 +473,7 @@
 public:
     GLEllipticalRRectEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder* builder,
-                          const GrFragmentProcessor& effect,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
 
@@ -505,21 +490,16 @@
     fPrevRRect.setEmpty();
 }
 
-void GLEllipticalRRectEffect::emitCode(GrGLFPBuilder* builder,
-                                       const GrFragmentProcessor& effect,
-                                       const char* outputColor,
-                                       const char* inputColor,
-                                       const TransformedCoordsArray&,
-                                       const TextureSamplerArray& samplers) {
-    const EllipticalRRectEffect& erre = effect.cast<EllipticalRRectEffect>();
+void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
+    const EllipticalRRectEffect& erre = args.fFp.cast<EllipticalRRectEffect>();
     const char *rectName;
     // The inner rect is the rrect bounds inset by the x/y radii
-    fInnerRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+    fInnerRectUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec4f_GrSLType, kDefault_GrSLPrecision,
                                             "innerRect",
                                             &rectName);
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->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
@@ -537,7 +517,7 @@
     switch (erre.getRRect().getType()) {
         case SkRRect::kSimple_Type: {
             const char *invRadiiXYSqdName;
-            fInvRadiiSqdUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+            fInvRadiiSqdUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                       kVec2f_GrSLType, kDefault_GrSLPrecision,
                                                       "invRadiiXY",
                                                       &invRadiiXYSqdName);
@@ -548,7 +528,7 @@
         }
         case SkRRect::kNinePatch_Type: {
             const char *invRadiiLTRBSqdName;
-            fInvRadiiSqdUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+            fInvRadiiSqdUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                       kVec4f_GrSLType, kDefault_GrSLPrecision,
                                                       "invRadiiLTRB",
                                                       &invRadiiLTRBSqdName);
@@ -577,8 +557,8 @@
         fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
     }
 
-    fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
-                           (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
+    fsBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
+                           (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
 }
 
 void GLEllipticalRRectEffect::GenKey(const GrProcessor& effect, const GrGLSLCaps&,
diff --git a/src/gpu/effects/GrSimpleTextureEffect.cpp b/src/gpu/effects/GrSimpleTextureEffect.cpp
index 8e6243d..066ccf7 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.cpp
+++ b/src/gpu/effects/GrSimpleTextureEffect.cpp
@@ -17,18 +17,13 @@
 public:
     GrGLSimpleTextureEffect(const GrProcessor&) {}
 
-    virtual void emitCode(GrGLFPBuilder* builder,
-                          const GrFragmentProcessor& fp,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray& coords,
-                          const TextureSamplerArray& samplers) override {
-        GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-        fsBuilder->codeAppendf("\t%s = ", outputColor);
-        fsBuilder->appendTextureLookupAndModulate(inputColor,
-                                                  samplers[0],
-                                                  coords[0].c_str(),
-                                                  coords[0].getType());
+    virtual void emitCode(EmitArgs& args) override {
+        GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+        fsBuilder->codeAppendf("\t%s = ", args.fOutputColor);
+        fsBuilder->appendTextureLookupAndModulate(args.fInputColor,
+                                                  args.fSamplers[0],
+                                                  args.fCoords[0].c_str(),
+                                                  args.fCoords[0].getType());
         fsBuilder->codeAppend(";\n");
     }
 
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index 1ebbea8..bbc5dc9 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -174,12 +174,7 @@
 public:
     GrGLTextureDomainEffect(const GrProcessor&);
 
-    virtual void emitCode(GrGLFPBuilder*,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) override;
+    virtual void emitCode(EmitArgs&) override;
 
     void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
 
@@ -193,18 +188,14 @@
 GrGLTextureDomainEffect::GrGLTextureDomainEffect(const GrProcessor&) {
 }
 
-void GrGLTextureDomainEffect::emitCode(GrGLFPBuilder* builder,
-                                       const GrFragmentProcessor& fp,
-                                       const char* outputColor,
-                                       const char* inputColor,
-                                       const TransformedCoordsArray& coords,
-                                       const TextureSamplerArray& samplers) {
-    const GrTextureDomainEffect& textureDomainEffect = fp.cast<GrTextureDomainEffect>();
+void GrGLTextureDomainEffect::emitCode(EmitArgs& args) {
+    const GrTextureDomainEffect& textureDomainEffect = args.fFp.cast<GrTextureDomainEffect>();
     const GrTextureDomain& domain = textureDomainEffect.textureDomain();
 
-    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
-    fGLDomain.sampleTexture(fsBuilder, domain, outputColor, coords2D, samplers[0], inputColor);
+    GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+    SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
+    fGLDomain.sampleTexture(fsBuilder, domain, args.fOutputColor, coords2D, args.fSamplers[0],
+                            args.fInputColor);
 }
 
 void GrGLTextureDomainEffect::setData(const GrGLProgramDataManager& pdman,
diff --git a/src/gpu/effects/GrYUVtoRGBEffect.cpp b/src/gpu/effects/GrYUVtoRGBEffect.cpp
index 7e62868..3bfc216 100644
--- a/src/gpu/effects/GrYUVtoRGBEffect.cpp
+++ b/src/gpu/effects/GrYUVtoRGBEffect.cpp
@@ -61,24 +61,22 @@
 
         GLProcessor(const GrProcessor&) {}
 
-        virtual void emitCode(GrGLFPBuilder* builder,
-                              const GrFragmentProcessor&,
-                              const char* outputColor,
-                              const char* inputColor,
-                              const TransformedCoordsArray& coords,
-                              const TextureSamplerArray& samplers) override {
-            GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+        virtual void emitCode(EmitArgs& args) override {
+            GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
 
             const char* yuvMatrix   = NULL;
-            fMatrixUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+            fMatrixUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                              kMat44f_GrSLType, kDefault_GrSLPrecision,
                                              "YUVMatrix", &yuvMatrix);
-            fsBuilder->codeAppendf("\t%s = vec4(\n\t\t", outputColor);
-            fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
+            fsBuilder->codeAppendf("\t%s = vec4(\n\t\t", args.fOutputColor);
+            fsBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0].c_str(),
+                                           args.fCoords[0].getType());
             fsBuilder->codeAppend(".r,\n\t\t");
-            fsBuilder->appendTextureLookup(samplers[1], coords[1].c_str(), coords[1].getType());
+            fsBuilder->appendTextureLookup(args.fSamplers[1], args.fCoords[1].c_str(),
+                                           args.fCoords[1].getType());
             fsBuilder->codeAppend(".r,\n\t\t");
-            fsBuilder->appendTextureLookup(samplers[2], coords[2].c_str(), coords[2].getType());
+            fsBuilder->appendTextureLookup(args.fSamplers[2], args.fCoords[2].c_str(),
+                                           args.fCoords[2].getType());
             fsBuilder->codeAppendf(".r,\n\t\t1.0) * %s;\n", yuvMatrix);
         }
 
diff --git a/src/gpu/gl/GrGLFragmentProcessor.h b/src/gpu/gl/GrGLFragmentProcessor.h
index 723806f..e130dba 100644
--- a/src/gpu/gl/GrGLFragmentProcessor.h
+++ b/src/gpu/gl/GrGLFragmentProcessor.h
@@ -41,14 +41,30 @@
         @param samplers     Contains one entry for each GrTextureAccess of the GrProcessor. These
                             can be passed to the builder to emit texture reads in the generated
                             code.
-        TODO this should take a struct
         */
-    virtual void emitCode(GrGLFPBuilder* builder,
-                          const GrFragmentProcessor&,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray& coords,
-                          const TextureSamplerArray& samplers) = 0;
+
+    struct EmitArgs {
+        EmitArgs(GrGLFPBuilder* builder,
+                 const GrFragmentProcessor& fp,
+                 const char* outputColor,
+                 const char* inputColor,
+                 const TransformedCoordsArray& coords,
+                 const TextureSamplerArray& samplers)
+            : fBuilder(builder)
+            , fFp(fp)
+            , fOutputColor(outputColor)
+            , fInputColor(inputColor)
+            , fCoords(coords)
+            , fSamplers(samplers) {}
+        GrGLFPBuilder* fBuilder;
+        const GrFragmentProcessor& fFp;
+        const char* fOutputColor;
+        const char* fInputColor;
+        const TransformedCoordsArray& fCoords;
+        const TextureSamplerArray& fSamplers;
+    };
+
+    virtual void emitCode(EmitArgs&) = 0;
 
     /** A GrGLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces
         the same stage key; this function reads data from a GrFragmentProcessor and uploads any
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index a07bd73..b0d68fb 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -286,7 +286,8 @@
     SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures());
     this->emitSamplers(fp, &samplers, ifp);
 
-    ifp->fGLProc->emitCode(this, fp, outColor, inColor, fOutCoords[index], samplers);
+    GrGLFragmentProcessor::EmitArgs args(this, fp, outColor, inColor, fOutCoords[index], samplers);
+    ifp->fGLProc->emitCode(args);
 
     // We have to check that effects and the code they emit are consistent, ie if an effect
     // asks for dst color, then the emit code needs to follow suit
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index d21ae5d..d36c48d 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -40,15 +40,10 @@
 public:
     GLBigKeyProcessor(const GrProcessor&) {}
 
-    virtual void emitCode(GrGLFPBuilder* builder,
-                          const GrFragmentProcessor& fp,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) {
+    virtual void emitCode(EmitArgs& args) override {
         // pass through
-        GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
-        fsBuilder->codeAppendf("%s = %s;\n", outputColor, inputColor);
+        GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+        fsBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, args.fInputColor);
     }
 
     static void GenKey(const GrProcessor& processor, const GrGLSLCaps&, GrProcessorKeyBuilder* b) {