Make GrGLEffects use an interface to append their code.

A small step towards encapsulating GrGLShaderBuilder.
Review URL: https://codereview.chromium.org/12547012

git-svn-id: http://skia.googlecode.com/svn/trunk@8018 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 5c88441..2b6ccbd 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -398,7 +398,8 @@
  * Adds a line to the fragment shader code which modifies the color by
  * the specified color filter.
  */
-void add_color_filter(SkString* fsCode, const char * outputVar,
+void add_color_filter(GrGLShaderBuilder* builder,
+                      const char * outputVar,
                       SkXfermode::Coeff uniformCoeff,
                       SkXfermode::Coeff colorCoeff,
                       const char* filterColor,
@@ -407,9 +408,9 @@
     blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
     blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor);
 
-    fsCode->appendf("\t%s = ", outputVar);
-    GrGLSLAdd4f(fsCode, colorStr.c_str(), constStr.c_str());
-    fsCode->append(";\n");
+    SkString sum;
+    GrGLSLAdd4f(&sum, colorStr.c_str(), constStr.c_str());
+    builder->fsCodeAppendf("\t%s = %s;\n", outputVar, sum.c_str());
 }
 }
 
@@ -421,64 +422,64 @@
         builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
                                           GrGLShaderVar::kAttribute_TypeModifier,
                                           EDGE_ATTR_NAME);
-        builder->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
+        builder->vsCodeAppendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
         switch (fDesc.fVertexEdgeType) {
         case GrDrawState::kHairLine_EdgeType:
-            builder->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n", builder->fragmentPosition(), fsName);
-            builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
+            builder->fsCodeAppendf("\tfloat edgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n", builder->fragmentPosition(), fsName);
+            builder->fsCodeAppendf("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
             break;
         case GrDrawState::kQuad_EdgeType:
-            builder->fFSCode.append("\tfloat edgeAlpha;\n");
+            builder->fsCodeAppendf("\tfloat edgeAlpha;\n");
             // keep the derivative instructions outside the conditional
-            builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
-            builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
-            builder->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName);
+            builder->fsCodeAppendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
+            builder->fsCodeAppendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
+            builder->fsCodeAppendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName);
             // today we know z and w are in device space. We could use derivatives
-            builder->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName);
-            builder->fFSCode.append ("\t} else {\n");
-            builder->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
-                                     "\t\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
-                                     fsName, fsName);
-            builder->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
-            builder->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n"
-                                    "\t}\n");
+            builder->fsCodeAppendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName);
+            builder->fsCodeAppendf ("\t} else {\n");
+            builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
+                                   "\t\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
+                                    fsName, fsName);
+            builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
+            builder->fsCodeAppendf("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n"
+                                   "\t}\n");
             if (kES2_GrGLBinding == fContext.info().binding()) {
-                builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
+                builder->fHeader.append("#extension GL_OES_standard_derivatives: enable\n");
             }
             break;
         case GrDrawState::kHairQuad_EdgeType:
-            builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
-            builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
-            builder->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
-                                     "\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
-                                     fsName, fsName);
-            builder->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
-            builder->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
-            builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
+            builder->fsCodeAppendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
+            builder->fsCodeAppendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
+            builder->fsCodeAppendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
+                                   "\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
+                                   fsName, fsName);
+            builder->fsCodeAppendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
+            builder->fsCodeAppend("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
+            builder->fsCodeAppend("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
             if (kES2_GrGLBinding == fContext.info().binding()) {
                 builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
             }
             break;
         case GrDrawState::kCircle_EdgeType:
-            builder->fFSCode.append("\tfloat edgeAlpha;\n");
-            builder->fFSCode.appendf("\tfloat d = distance(%s.xy, %s.xy);\n", builder->fragmentPosition(), fsName);
-            builder->fFSCode.appendf("\tfloat outerAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
-            builder->fFSCode.appendf("\tfloat innerAlpha = %s.w == 0.0 ? 1.0 : smoothstep(%s.w - 0.5, %s.w + 0.5, d);\n", fsName, fsName, fsName);
-            builder->fFSCode.append("\tedgeAlpha = outerAlpha * innerAlpha;\n");
+            builder->fsCodeAppend("\tfloat edgeAlpha;\n");
+            builder->fsCodeAppendf("\tfloat d = distance(%s.xy, %s.xy);\n", builder->fragmentPosition(), fsName);
+            builder->fsCodeAppendf("\tfloat outerAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
+            builder->fsCodeAppendf("\tfloat innerAlpha = %s.w == 0.0 ? 1.0 : smoothstep(%s.w - 0.5, %s.w + 0.5, d);\n", fsName, fsName, fsName);
+            builder->fsCodeAppend("\tedgeAlpha = outerAlpha * innerAlpha;\n");
             break;
         case GrDrawState::kEllipse_EdgeType:
-            builder->fFSCode.append("\tfloat edgeAlpha;\n");
-            builder->fFSCode.appendf("\tvec2 offset = (%s.xy - %s.xy);\n", builder->fragmentPosition(), fsName);
-            builder->fFSCode.appendf("\toffset.y *= %s.w;\n", fsName);
-            builder->fFSCode.append("\tfloat d = length(offset);\n");
-            builder->fFSCode.appendf("\tedgeAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
+            builder->fsCodeAppend("\tfloat edgeAlpha;\n");
+            builder->fsCodeAppendf("\tvec2 offset = (%s.xy - %s.xy);\n", builder->fragmentPosition(), fsName);
+            builder->fsCodeAppendf("\toffset.y *= %s.w;\n", fsName);
+            builder->fsCodeAppend("\tfloat d = length(offset);\n");
+            builder->fsCodeAppendf("\tedgeAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
             break;
         default:
             GrCrash("Unknown Edge Type!");
             break;
         }
         if (fDesc.fDiscardIfOutsideEdge) {
-            builder->fFSCode.appendf("\tif (edgeAlpha <= 0.0) {\n\t\tdiscard;\n\t}\n");
+            builder->fsCodeAppend("\tif (edgeAlpha <= 0.0) {\n\t\tdiscard;\n\t}\n");
         }
         *coverageVar = "edgeAlpha";
         return true;
@@ -496,7 +497,7 @@
                 COL_ATTR_NAME);
             const char *vsName, *fsName;
             builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
-            builder->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
+            builder->vsCodeAppendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
             *inColor = fsName;
             } break;
         case GrGLProgram::Desc::kUniform_ColorInput: {
@@ -522,8 +523,8 @@
     fUniformHandles.fCoverageUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
                                                        kVec4f_GrSLType, "Coverage", &covUniName);
     if (inOutCoverage->size()) {
-        builder->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n",
-                                  covUniName, inOutCoverage->c_str());
+        builder->fsCodeAppendf("\tvec4 uniCoverage = %s * %s;\n",
+                               covUniName, inOutCoverage->c_str());
         *inOutCoverage = "uniCoverage";
     } else {
         *inOutCoverage = covUniName;
@@ -531,17 +532,16 @@
 }
 
 namespace {
-void gen_attribute_coverage(GrGLShaderBuilder* segments,
+void gen_attribute_coverage(GrGLShaderBuilder* builder,
                             SkString* inOutCoverage) {
-    segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
-                                       GrGLShaderVar::kAttribute_TypeModifier,
-                                       COV_ATTR_NAME);
+    builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
+                                      GrGLShaderVar::kAttribute_TypeModifier,
+                                      COV_ATTR_NAME);
     const char *vsName, *fsName;
-    segments->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
-    segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
+    builder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
+    builder->vsCodeAppendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
     if (inOutCoverage->size()) {
-        segments->fFSCode.appendf("\tvec4 attrCoverage = %s * %s;\n",
-                                  fsName, inOutCoverage->c_str());
+        builder->fsCodeAppendf("\tvec4 attrCoverage = %s * %s;\n", fsName, inOutCoverage->c_str());
         *inOutCoverage = "attrCoverage";
     } else {
         *inOutCoverage = fsName;
@@ -549,27 +549,28 @@
 }
 }
 
-void GrGLProgram::genGeometryShader(GrGLShaderBuilder* segments) const {
+void GrGLProgram::genGeometryShader(GrGLShaderBuilder* builder) const {
 #if GR_GL_EXPERIMENTAL_GS
+    // TODO: The builder should add all this glue code.
     if (fDesc.fExperimentalGS) {
         GrAssert(fContext.info().glslGeneration() >= k150_GrGLSLGeneration);
-        segments->fGSHeader.append("layout(triangles) in;\n"
+        builder->fGSHeader.append("layout(triangles) in;\n"
                                    "layout(triangle_strip, max_vertices = 6) out;\n");
-        segments->fGSCode.append("\tfor (int i = 0; i < 3; ++i) {\n"
-                                 "\t\tgl_Position = gl_in[i].gl_Position;\n");
+        builder->gsCodeAppend("\tfor (int i = 0; i < 3; ++i) {\n"
+                              "\t\tgl_Position = gl_in[i].gl_Position;\n");
         if (fDesc.fEmitsPointSize) {
-            segments->fGSCode.append("\t\tgl_PointSize = 1.0;\n");
+            builder->gsCodeAppend("\t\tgl_PointSize = 1.0;\n");
         }
-        GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count());
-        int count = segments->fGSInputs.count();
+        GrAssert(builder->fGSInputs.count() == builder->fGSOutputs.count());
+        int count = builder->fGSInputs.count();
         for (int i = 0; i < count; ++i) {
-            segments->fGSCode.appendf("\t\t%s = %s[i];\n",
-                                      segments->fGSOutputs[i].getName().c_str(),
-                                      segments->fGSInputs[i].getName().c_str());
+            builder->gsCodeAppendf("\t\t%s = %s[i];\n",
+                                   builder->fGSOutputs[i].getName().c_str(),
+                                   builder->fGSInputs[i].getName().c_str());
         }
-        segments->fGSCode.append("\t\tEmitVertex();\n"
-                                 "\t}\n"
-                                 "\tEndPrimitive();\n");
+        builder->gsCodeAppend("\t\tEmitVertex();\n"
+                              "\t}\n"
+                              "\tEndPrimitive();\n");
     }
 #endif
 }
@@ -758,9 +759,9 @@
                                                         kMat33f_GrSLType, "ViewM", &viewMName);
 
 
-    builder.fVSCode.appendf("\tvec3 pos3 = %s * vec3(%s, 1);\n"
-                            "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
-                            viewMName, builder.positionAttribute().getName().c_str());
+    builder.vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n"
+                          "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
+                          viewMName, builder.positionAttribute().getName().c_str());
 
     // incoming color to current stage being processed.
     SkString inColor;
@@ -771,7 +772,7 @@
 
     // we output point size in the GS if present
     if (fDesc.fEmitsPointSize && !builder.fUsesGS){
-        builder.fVSCode.append("\tgl_PointSize = 1.0;\n");
+        builder.vsCodeAppend("\tgl_PointSize = 1.0;\n");
     }
 
     // add texture coordinates that are used to the list of vertex attr decls
@@ -793,7 +794,7 @@
                 // create var to hold stage result
                 outColor = "color";
                 outColor.appendS32(s);
-                builder.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str());
+                builder.fsCodeAppendf("\tvec4 %s;\n", outColor.c_str());
 
                 const char* inCoords;
                 // figure out what our input coords are
@@ -840,15 +841,13 @@
     bool wroteFragColorZero = false;
     if (SkXfermode::kZero_Coeff == uniformCoeff &&
         SkXfermode::kZero_Coeff == colorCoeff) {
-        builder.fFSCode.appendf("\t%s = %s;\n",
-                                colorOutput.getName().c_str(),
-                                GrGLSLZerosVecf(4));
+        builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), GrGLSLZerosVecf(4));
         wroteFragColorZero = true;
     } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) {
-        builder.fFSCode.append("\tvec4 filteredColor;\n");
+        builder.fsCodeAppend("\tvec4 filteredColor;\n");
         const char* color = adjustInColor(inColor);
-        add_color_filter(&builder.fFSCode, "filteredColor", uniformCoeff,
-                       colorCoeff, colorFilterColorUniName, color);
+        add_color_filter(&builder, "filteredColor", uniformCoeff,
+                         colorCoeff, colorFilterColorUniName, color);
         inColor = "filteredColor";
     }
 
@@ -887,7 +886,7 @@
                     // create var to hold stage output
                     outCoverage = "coverage";
                     outCoverage.appendS32(s);
-                    builder.fFSCode.appendf("\tvec4 %s;\n", outCoverage.c_str());
+                    builder.fsCodeAppendf("\tvec4 %s;\n", outCoverage.c_str());
 
                     const char* inCoords;
                     // figure out what our input coords are
@@ -902,8 +901,8 @@
                     // stages don't know how to deal with a scalar input. (Maybe they should. We
                     // could pass a GrGLShaderVar)
                     if (inCoverageIsScalar) {
-                        builder.fFSCode.appendf("\tvec4 %s4 = vec4(%s);\n",
-                                                inCoverage.c_str(), inCoverage.c_str());
+                        builder.fsCodeAppendf("\tvec4 %s4 = vec4(%s);\n",
+                                              inCoverage.c_str(), inCoverage.c_str());
                         inCoverage.append("4");
                     }
                     builder.setCurrentStage(s);
@@ -939,13 +938,11 @@
                 }
             }
             if (outputIsZero) {
-                builder.fFSCode.appendf("\t%s = %s;\n",
-                                        dual_source_output_name(),
-                                        GrGLSLZerosVecf(4));
+                builder.fsCodeAppendf("\t%s = %s;\n", dual_source_output_name(), GrGLSLZerosVecf(4));
             } else {
-                builder.fFSCode.appendf("\t%s =", dual_source_output_name());
-                GrGLSLModulate4f(&builder.fFSCode, coeff.c_str(), inCoverage.c_str());
-                builder.fFSCode.append(";\n");
+                SkString modulate;
+                GrGLSLModulate4f(&modulate, coeff.c_str(), inCoverage.c_str());
+                builder.fsCodeAppendf("\t%s = %s;\n", dual_source_output_name(), modulate.c_str());
             }
             dualSourceOutputWritten = true;
         }
@@ -956,13 +953,11 @@
 
     if (!wroteFragColorZero) {
         if (coverageIsZero) {
-            builder.fFSCode.appendf("\t%s = %s;\n",
-                                    colorOutput.getName().c_str(),
-                                    GrGLSLZerosVecf(4));
+            builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), GrGLSLZerosVecf(4));
         } else {
-            builder.fFSCode.appendf("\t%s = ", colorOutput.getName().c_str());
-            GrGLSLModulate4f(&builder.fFSCode, inColor.c_str(), inCoverage.c_str());
-            builder.fFSCode.append(";\n");
+            SkString modulate;
+            GrGLSLModulate4f(&modulate, inColor.c_str(), inCoverage.c_str());
+            builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), modulate.c_str());
         }
     }