Move helper functions out of header file, write new genProgram helpers.
Review: codereview.appspot.com/5304045/



git-svn-id: http://skia.googlecode.com/svn/trunk@2532 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrGLProgram.cpp b/src/gpu/GrGLProgram.cpp
index 26ada9c..929ee50 100644
--- a/src/gpu/GrGLProgram.cpp
+++ b/src/gpu/GrGLProgram.cpp
@@ -16,6 +16,13 @@
 
 namespace {
 
+enum {
+    /// Used to mark a StageUniLocation field that should be bound
+    /// to a uniform during getUniformLocationsAndInitCache().
+    kUseUniform = 2000
+};
+
+
 const char* GrPrecision(const GrGLInterface* gl) {
     if (gl->supportsES()) {
         return "mediump";
@@ -541,6 +548,53 @@
     }
 }
 
+void genInputColor(GrGLProgram::ProgramDesc::ColorType colorType,
+                   GrGLProgram::CachedData* programData,
+                   ShaderCodeSegments* segments,
+                   GrStringBuilder* inColor) {
+    switch (colorType) {
+        case GrGLProgram::ProgramDesc::kAttribute_ColorType: {
+            segments->fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
+                                               COL_ATTR_NAME);
+            const char *vsName, *fsName;
+            append_varying(GrGLShaderVar::kVec4f_Type, "Color", segments, &vsName, &fsName);
+            segments->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
+            *inColor = fsName;
+            } break;
+        case GrGLProgram::ProgramDesc::kUniform_ColorType:
+            segments->fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
+                                              COL_UNI_NAME);
+            programData->fUniLocations.fColorUni = kUseUniform;
+            *inColor = COL_UNI_NAME;
+            break;
+        case GrGLProgram::ProgramDesc::kTransBlack_ColorType:
+            GrAssert(!"needComputedColor should be false.");
+            break;
+        case GrGLProgram::ProgramDesc::kSolidWhite_ColorType:
+            break;
+        default:
+            GrCrash("Unknown color type.");
+            break;
+    }
+}
+
+void genPerVertexCoverage(ShaderCodeSegments* segments,
+                          GrStringBuilder* inCoverage) {
+    segments->fVSAttrs.push_back().set(GrGLShaderVar::kFloat_Type,
+                                       COV_ATTR_NAME);
+    const char *vsName, *fsName;
+    append_varying(GrGLShaderVar::kFloat_Type, "Coverage", 
+                   segments, &vsName, &fsName);
+    segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
+    if (inCoverage->size()) {
+        segments->fFSCode.appendf("\tfloat edgeAndAttrCov = %s * %s;\n",
+                                  fsName, inCoverage->c_str());
+        *inCoverage = "edgeAndAttrCov";
+    } else {
+        *inCoverage = fsName;
+    }
+}
+
 }
 
 void GrGLProgram::genGeometryShader(const GrGLInterface* gl,
@@ -644,30 +698,8 @@
     GrStringBuilder inColor;
 
     if (needComputedColor) {
-        switch (fProgramDesc.fColorType) {
-            case ProgramDesc::kAttribute_ColorType: {
-                segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
-                                                  COL_ATTR_NAME);
-                const char *vsName, *fsName;
-                append_varying(GrGLShaderVar::kVec4f_Type, "Color", &segments, &vsName, &fsName);
-                segments.fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
-                inColor = fsName;
-                } break;
-            case ProgramDesc::kUniform_ColorType:
-                segments.fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
-                                                 COL_UNI_NAME);
-                programData->fUniLocations.fColorUni = kUseUniform;
-                inColor = COL_UNI_NAME;
-                break;
-            case ProgramDesc::kTransBlack_ColorType:
-                GrAssert(!"needComputedColor should be false.");
-                break;
-            case ProgramDesc::kSolidWhite_ColorType:
-                break;
-            default:
-                GrCrash("Unknown color type.");
-                break;
-        }
+        genInputColor((ProgramDesc::ColorType) fProgramDesc.fColorType,
+                      programData, &segments, &inColor);
     }
 
     // we output point size in the GS if present
@@ -714,14 +746,14 @@
                     inCoords = texCoordAttrs[tcIdx].c_str();
                 }
 
-                genStageCode(gl,
-                             s,
-                             fProgramDesc.fStages[s],
-                             inColor.size() ? inColor.c_str() : NULL,
-                             outColor.c_str(),
-                             inCoords,
-                             &segments,
-                             &programData->fUniLocations.fStages[s]);
+                this->genStageCode(gl,
+                                   s,
+                                   fProgramDesc.fStages[s],
+                                   inColor.size() ? inColor.c_str() : NULL,
+                                   outColor.c_str(),
+                                   inCoords,
+                                   &segments,
+                                   &programData->fUniLocations.fStages[s]);
                 inColor = outColor;
             }
         }
@@ -785,19 +817,7 @@
 
         // include explicit per-vertex coverage if we have it
         if (GrDrawTarget::kCoverage_VertexLayoutBit & layout) {
-            segments.fVSAttrs.push_back().set(GrGLShaderVar::kFloat_Type,
-                                              COV_ATTR_NAME);
-            const char *vsName, *fsName;
-            append_varying(GrGLShaderVar::kFloat_Type, "Coverage", 
-                           &segments, &vsName, &fsName);
-            segments.fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
-            if (inCoverage.size()) {
-                segments.fFSCode.appendf("\tfloat edgeAndAttrCov = %s * %s;\n",
-                                         fsName, inCoverage.c_str());
-                inCoverage = "edgeAndAttrCov";
-            } else {
-                inCoverage = fsName;
-            }
+            genPerVertexCoverage(&segments, &inCoverage);
         }
 
         GrStringBuilder outCoverage;
@@ -1287,14 +1307,59 @@
 // Stage code generation
 //============================================================================
 
-static bool genRadial2GradientCoordMapping(int stageNum,
-                                           ShaderCodeSegments* segments,
-                                           const char* radial2VaryingFSName,
-                                           const char* radial2ParamsName,
-                                           GrStringBuilder& sampleCoords,
-                                           GrStringBuilder& fsCoordName,
-                                           int varyingDims,
-                                           int coordDims) {
+namespace {
+
+bool isRadialMapping(GrGLProgram::StageDesc::CoordMapping mapping) {
+    return
+       (GrGLProgram::StageDesc::kRadial2Gradient_CoordMapping == mapping ||
+        GrGLProgram::StageDesc::kRadial2GradientDegenerate_CoordMapping == mapping);
+}
+
+const char* genRadialVS(int stageNum,
+                        ShaderCodeSegments* segments,
+                        GrGLProgram::StageUniLocations* locations,
+                        const char** radial2VaryingVSName,
+                        const char** radial2VaryingFSName,
+                        const char* varyingVSName,
+                        int varyingDims, int coordDims) {
+
+    GrGLShaderVar* radial2FSParams = &segments->fFSUnis.push_back();
+    radial2FSParams->setType(GrGLShaderVar::kFloat_Type);
+    radial2FSParams->setArrayCount(6);
+    radial2_param_name(stageNum, radial2FSParams->accessName());
+    segments->fVSUnis.push_back(*radial2FSParams).setEmitPrecision(true);
+
+    locations->fRadial2Uni = kUseUniform;
+
+    // for radial grads without perspective we can pass the linear
+    // part of the quadratic as a varying.
+    if (varyingDims == coordDims) {
+        GrAssert(2 == coordDims);
+        append_varying(GrGLShaderVar::kFloat_Type,
+                       "Radial2BCoeff",
+                       stageNum,
+                       segments,
+                       radial2VaryingVSName,
+                       radial2VaryingFSName);
+
+        // r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3])
+        const char* r2ParamName = radial2FSParams->getName().c_str();
+        segments->fVSCode.appendf("\t%s = 2.0 *(%s[2] * %s.x - %s[3]);\n",
+                                  *radial2VaryingVSName, r2ParamName,
+                                  varyingVSName, r2ParamName);
+    }
+
+    return radial2FSParams->getName().c_str();
+}
+
+bool genRadial2GradientCoordMapping(int stageNum,
+                                    ShaderCodeSegments* segments,
+                                    const char* radial2VaryingFSName,
+                                    const char* radial2ParamsName,
+                                    GrStringBuilder& sampleCoords,
+                                    GrStringBuilder& fsCoordName,
+                                    int varyingDims,
+                                    int coordDims) {
     GrStringBuilder cName("c");
     GrStringBuilder ac4Name("ac4");
     GrStringBuilder rootName("root");
@@ -1342,14 +1407,14 @@
     return true;
 }
 
-static bool genRadial2GradientDegenerateCoordMapping(int stageNum,
-                ShaderCodeSegments* segments,
-                const char* radial2VaryingFSName,
-                const char* radial2ParamsName,
-                GrStringBuilder& sampleCoords,
-                GrStringBuilder& fsCoordName,
-                int varyingDims,
-                int coordDims) {
+bool genRadial2GradientDegenerateCoordMapping(int stageNum,
+                                              ShaderCodeSegments* segments,
+                                              const char* radial2VaryingFSName,
+                                              const char* radial2ParamsName,
+                                              GrStringBuilder& sampleCoords,
+                                              GrStringBuilder& fsCoordName,
+                                              int varyingDims,
+                                              int coordDims) {
     GrStringBuilder cName("c");
 
     cName.appendS32(stageNum);
@@ -1381,6 +1446,106 @@
     return true;
 }
 
+void gen2x2FS(int stageNum,
+              ShaderCodeSegments* segments,
+              GrGLProgram::StageUniLocations* locations,
+              GrStringBuilder* sampleCoords,
+              const char* samplerName,
+              const char* texelSizeName,
+              const char* smear,
+              const char* fsOutColor,
+              GrStringBuilder& texFunc,
+              GrStringBuilder& modulate,
+              bool complexCoord,
+              int coordDims) {
+    locations->fNormalizedTexelSizeUni = kUseUniform;
+    if (complexCoord) {
+        // assign the coord to a var rather than compute 4x.
+        GrStringBuilder coordVar("tCoord");
+        coordVar.appendS32(stageNum);
+        segments->fFSCode.appendf("\t%s %s = %s;\n",
+                            float_vector_type_str(coordDims),
+                            coordVar.c_str(), sampleCoords->c_str());
+        *sampleCoords = coordVar;
+    }
+    GrAssert(2 == coordDims);
+    GrStringBuilder accumVar("accum");
+    accumVar.appendS32(stageNum);
+    segments->fFSCode.appendf("\tvec4 %s  = %s(%s, %s + vec2(-%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
+    segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
+    segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(-%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
+    segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
+    segments->fFSCode.appendf("\t%s = .25 * %s%s;\n", fsOutColor, accumVar.c_str(), modulate.c_str());
+
+}
+
+void genConvolutionVS(int stageNum,
+                      const GrGLProgram::ProgramDesc::StageDesc& desc,
+                      ShaderCodeSegments* segments,
+                      GrGLProgram::StageUniLocations* locations,
+                      const char** kernelName,
+                      const char** imageIncrementName,
+                      const char* varyingVSName) {
+    GrGLShaderVar* kernel = &segments->fFSUnis.push_back();
+    kernel->setType(GrGLShaderVar::kFloat_Type);
+    kernel->setArrayCount(desc.fKernelWidth);
+    GrGLShaderVar* imgInc = &segments->fFSUnis.push_back();
+    imgInc->setType(GrGLShaderVar::kVec2f_Type);
+
+    convolve_param_names(stageNum,
+                         kernel->accessName(),
+                         imgInc->accessName());
+    *kernelName = kernel->getName().c_str();
+    *imageIncrementName = imgInc->getName().c_str();
+
+    // need image increment in both VS and FS
+    segments->fVSUnis.push_back(*imgInc).setEmitPrecision(true);
+
+    locations->fKernelUni = kUseUniform;
+    locations->fImageIncrementUni = kUseUniform;
+    float scale = (desc.fKernelWidth - 1) * 0.5f;
+    segments->fVSCode.appendf("\t%s -= vec2(%g, %g) * %s;\n",
+                                  varyingVSName, scale, scale,
+                                  *imageIncrementName);
+}
+
+void genConvolutionFS(int stageNum,
+                      const GrGLProgram::ProgramDesc::StageDesc& desc,
+                      ShaderCodeSegments* segments,
+                      const char* samplerName,
+                      const char* kernelName,
+                      const char* smear,
+                      const char* imageIncrementName,
+                      const char* fsOutColor,
+                      GrStringBuilder& sampleCoords,
+                      GrStringBuilder& texFunc,
+                      GrStringBuilder& modulate) {
+    GrStringBuilder sumVar("sum");
+    sumVar.appendS32(stageNum);
+    GrStringBuilder coordVar("coord");
+    coordVar.appendS32(stageNum);
+
+    segments->fFSCode.appendf("\tvec4 %s = vec4(0, 0, 0, 0);\n",
+                              sumVar.c_str());
+    segments->fFSCode.appendf("\tvec2 %s = %s;\n", 
+                              coordVar.c_str(),
+                              sampleCoords.c_str());
+    segments->fFSCode.appendf("\tfor (int i = 0; i < %d; i++) {\n",
+                              desc.fKernelWidth);
+    segments->fFSCode.appendf("\t\t%s += %s(%s, %s)%s * %s[i];\n",
+                              sumVar.c_str(), texFunc.c_str(),
+                              samplerName, coordVar.c_str(), smear,
+                              kernelName);
+    segments->fFSCode.appendf("\t\t%s += %s;\n",
+                              coordVar.c_str(),
+                              imageIncrementName);
+    segments->fFSCode.appendf("\t}\n");
+    segments->fFSCode.appendf("\t%s = %s%s;\n", fsOutColor,
+                              sumVar.c_str(), modulate.c_str());
+}
+
+}
+
 void GrGLProgram::genStageCode(const GrGLInterface* gl,
                                int stageNum,
                                const GrGLProgram::StageDesc& desc,
@@ -1458,21 +1623,20 @@
     const char *radial2VaryingVSName = NULL;
     const char *radial2VaryingFSName = NULL;
 
-    if (StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping ||
-        StageDesc::kRadial2GradientDegenerate_CoordMapping == desc.fCoordMapping) {
-        radial2ParamsName = this->genRadialVS(stageNum, segments,
-                                              locations,
-                                              &radial2VaryingVSName,
-                                              &radial2VaryingFSName,
-                                              varyingVSName,
-                                              varyingDims, coordDims);
+    if (isRadialMapping((StageDesc::CoordMapping) desc.fCoordMapping)) {
+        radial2ParamsName = genRadialVS(stageNum, segments,
+                                        locations,
+                                        &radial2VaryingVSName,
+                                        &radial2VaryingFSName,
+                                        varyingVSName,
+                                        varyingDims, coordDims);
     }
 
     const char* kernelName = NULL;
     const char* imageIncrementName = NULL;
     if (ProgramDesc::StageDesc::kConvolution_FetchMode == desc.fFetchMode) {
-        this->genConvolutionVS(stageNum, desc, segments, locations,
-                               &kernelName, &imageIncrementName, varyingVSName);
+        genConvolutionVS(stageNum, desc, segments, locations,
+                         &kernelName, &imageIncrementName, varyingVSName);
     }
 
     /// Fragment Shader Stuff
@@ -1565,12 +1729,12 @@
 
     switch (desc.fFetchMode) {
     case StageDesc::k2x2_FetchMode:
-        this->gen2x2FS(stageNum, segments, locations, &sampleCoords,
+        gen2x2FS(stageNum, segments, locations, &sampleCoords,
             samplerName, texelSizeName, smear, fsOutColor,
             texFunc, modulate, complexCoord, coordDims);
         break;
     case ProgramDesc::StageDesc::kConvolution_FetchMode:
-        this->genConvolutionFS(stageNum, desc, segments,
+        genConvolutionFS(stageNum, desc, segments,
             samplerName, kernelName, smear, imageIncrementName, fsOutColor,
             sampleCoords, texFunc, modulate);
         break;
@@ -1582,139 +1746,4 @@
     }
 }
 
-const char* GrGLProgram::genRadialVS(int stageNum,
-                                     ShaderCodeSegments* segments,
-                                     StageUniLocations* locations,
-                                     const char** radial2VaryingVSName,
-                                     const char** radial2VaryingFSName,
-                                     const char* varyingVSName,
-                                     int varyingDims, int coordDims) const {
-
-    GrGLShaderVar* radial2FSParams = &segments->fFSUnis.push_back();
-    radial2FSParams->setType(GrGLShaderVar::kFloat_Type);
-    radial2FSParams->setArrayCount(6);
-    radial2_param_name(stageNum, radial2FSParams->accessName());
-    segments->fVSUnis.push_back(*radial2FSParams).setEmitPrecision(true);
-
-    locations->fRadial2Uni = kUseUniform;
-
-    // for radial grads without perspective we can pass the linear
-    // part of the quadratic as a varying.
-    if (varyingDims == coordDims) {
-        GrAssert(2 == coordDims);
-        append_varying(GrGLShaderVar::kFloat_Type,
-                       "Radial2BCoeff",
-                       stageNum,
-                       segments,
-                       radial2VaryingVSName,
-                       radial2VaryingFSName);
-
-        // r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3])
-        const char* r2ParamName = radial2FSParams->getName().c_str();
-        segments->fVSCode.appendf("\t%s = 2.0 *(%s[2] * %s.x - %s[3]);\n",
-                                  *radial2VaryingVSName, r2ParamName,
-                                  varyingVSName, r2ParamName);
-    }
-
-    return radial2FSParams->getName().c_str();
-}
-
-
-void GrGLProgram::gen2x2FS(int stageNum,
-                           ShaderCodeSegments* segments,
-                           StageUniLocations* locations,
-                           GrStringBuilder* sampleCoords,
-                           const char* samplerName,
-                           const char* texelSizeName,
-                           const char* smear,
-                           const char* fsOutColor,
-                           GrStringBuilder& texFunc,
-                           GrStringBuilder& modulate,
-                           bool complexCoord,
-                           int coordDims) const {
-    locations->fNormalizedTexelSizeUni = kUseUniform;
-    if (complexCoord) {
-        // assign the coord to a var rather than compute 4x.
-        GrStringBuilder coordVar("tCoord");
-        coordVar.appendS32(stageNum);
-        segments->fFSCode.appendf("\t%s %s = %s;\n",
-                            float_vector_type_str(coordDims),
-                            coordVar.c_str(), sampleCoords->c_str());
-        *sampleCoords = coordVar;
-    }
-    GrAssert(2 == coordDims);
-    GrStringBuilder accumVar("accum");
-    accumVar.appendS32(stageNum);
-    segments->fFSCode.appendf("\tvec4 %s  = %s(%s, %s + vec2(-%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
-    segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
-    segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(-%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
-    segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
-    segments->fFSCode.appendf("\t%s = .25 * %s%s;\n", fsOutColor, accumVar.c_str(), modulate.c_str());
-
-}
-
-void GrGLProgram::genConvolutionVS(int stageNum,
-                                   const ProgramDesc::StageDesc& desc,
-                                   ShaderCodeSegments* segments,
-                                   StageUniLocations* locations,
-                                   const char** kernelName,
-                                   const char** imageIncrementName,
-                                   const char* varyingVSName) const {
-    GrGLShaderVar* kernel = &segments->fFSUnis.push_back();
-    kernel->setType(GrGLShaderVar::kFloat_Type);
-    kernel->setArrayCount(desc.fKernelWidth);
-    GrGLShaderVar* imgInc = &segments->fFSUnis.push_back();
-    imgInc->setType(GrGLShaderVar::kVec2f_Type);
-
-    convolve_param_names(stageNum,
-                         kernel->accessName(),
-                         imgInc->accessName());
-    *kernelName = kernel->getName().c_str();
-    *imageIncrementName = imgInc->getName().c_str();
-
-    // need image increment in both VS and FS
-    segments->fVSUnis.push_back(*imgInc).setEmitPrecision(true);
-
-    locations->fKernelUni = kUseUniform;
-    locations->fImageIncrementUni = kUseUniform;
-    float scale = (desc.fKernelWidth - 1) * 0.5f;
-    segments->fVSCode.appendf("\t%s -= vec2(%g, %g) * %s;\n",
-                                  varyingVSName, scale, scale,
-                                  *imageIncrementName);
-}
-
-void GrGLProgram::genConvolutionFS(int stageNum,
-                                   const ProgramDesc::StageDesc& desc,
-                                   ShaderCodeSegments* segments,
-                                   const char* samplerName,
-                                   const char* kernelName,
-                                   const char* smear,
-                                   const char* imageIncrementName,
-                                   const char* fsOutColor,
-                                   GrStringBuilder& sampleCoords,
-                                   GrStringBuilder& texFunc,
-                                   GrStringBuilder& modulate) const {
-    GrStringBuilder sumVar("sum");
-    sumVar.appendS32(stageNum);
-    GrStringBuilder coordVar("coord");
-    coordVar.appendS32(stageNum);
-
-    segments->fFSCode.appendf("\tvec4 %s = vec4(0, 0, 0, 0);\n",
-                              sumVar.c_str());
-    segments->fFSCode.appendf("\tvec2 %s = %s;\n", 
-                              coordVar.c_str(),
-                              sampleCoords.c_str());
-    segments->fFSCode.appendf("\tfor (int i = 0; i < %d; i++) {\n",
-                              desc.fKernelWidth);
-    segments->fFSCode.appendf("\t\t%s += %s(%s, %s)%s * %s[i];\n",
-                              sumVar.c_str(), texFunc.c_str(),
-                              samplerName, coordVar.c_str(), smear,
-                              kernelName);
-    segments->fFSCode.appendf("\t\t%s += %s;\n",
-                              coordVar.c_str(),
-                              imageIncrementName);
-    segments->fFSCode.appendf("\t}\n");
-    segments->fFSCode.appendf("\t%s = %s%s;\n", fsOutColor,
-                              sumVar.c_str(), modulate.c_str());
-}