Extract six functions from GrGLProgram::genStageCode() to shorten it by
~170 LOC.



git-svn-id: http://skia.googlecode.com/svn/trunk@2498 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrGLProgram.cpp b/src/gpu/GrGLProgram.cpp
index 4b4140d..e05b6c3 100644
--- a/src/gpu/GrGLProgram.cpp
+++ b/src/gpu/GrGLProgram.cpp
@@ -1287,6 +1287,100 @@
 // Stage code generation
 //============================================================================
 
+static 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");
+
+    cName.appendS32(stageNum);
+    ac4Name.appendS32(stageNum);
+    rootName.appendS32(stageNum);
+
+    // if we were able to interpolate the linear component bVar is the varying
+    // otherwise compute it
+    GrStringBuilder bVar;
+    if (coordDims == varyingDims) {
+        bVar = radial2VaryingFSName;
+        GrAssert(2 == varyingDims);
+    } else {
+        GrAssert(3 == varyingDims);
+        bVar = "b";
+        bVar.appendS32(stageNum);
+        segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s[2] * %s.x - %s[3]);\n",
+                                    bVar.c_str(), radial2ParamsName,
+                                    fsCoordName.c_str(), radial2ParamsName);
+    }
+
+    // c = (x^2)+(y^2) - params[4]
+    segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s[4];\n",
+                              cName.c_str(), fsCoordName.c_str(),
+                              fsCoordName.c_str(),
+                              radial2ParamsName);
+    // ac4 = 4.0 * params[0] * c
+    segments->fFSCode.appendf("\tfloat %s = %s[0] * 4.0 * %s;\n",
+                              ac4Name.c_str(), radial2ParamsName,
+                              cName.c_str());
+
+    // root = sqrt(b^2-4ac)
+    // (abs to avoid exception due to fp precision)
+    segments->fFSCode.appendf("\tfloat %s = sqrt(abs(%s*%s - %s));\n",
+                              rootName.c_str(), bVar.c_str(), bVar.c_str(),
+                              ac4Name.c_str());
+
+    // x coord is: (-b + params[5] * sqrt(b^2-4ac)) * params[1]
+    // y coord is 0.5 (texture is effectively 1D)
+    sampleCoords.printf("vec2((-%s + %s[5] * %s) * %s[1], 0.5)",
+                        bVar.c_str(), radial2ParamsName,
+                        rootName.c_str(), radial2ParamsName);
+    return true;
+}
+
+static 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);
+
+    // if we were able to interpolate the linear component bVar is the varying
+    // otherwise compute it
+    GrStringBuilder bVar;
+    if (coordDims == varyingDims) {
+        bVar = radial2VaryingFSName;
+        GrAssert(2 == varyingDims);
+    } else {
+        GrAssert(3 == varyingDims);
+        bVar = "b";
+        bVar.appendS32(stageNum);
+        segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s[2] * %s.x - %s[3]);\n",
+                                    bVar.c_str(), radial2ParamsName,
+                                    fsCoordName.c_str(), radial2ParamsName);
+    }
+
+    // c = (x^2)+(y^2) - params[4]
+    segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s[4];\n",
+                              cName.c_str(), fsCoordName.c_str(),
+                              fsCoordName.c_str(),
+                              radial2ParamsName);
+
+    // x coord is: -c/b
+    // y coord is 0.5 (texture is effectively 1D)
+    sampleCoords.printf("vec2((-%s / %s), 0.5)", cName.c_str(), bVar.c_str());
+    return true;
+}
+
 void GrGLProgram::genStageCode(const GrGLInterface* gl,
                                int stageNum,
                                const GrGLProgram::StageDesc& desc,
@@ -1366,60 +1460,19 @@
 
     if (StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping ||
         StageDesc::kRadial2GradientDegenerate_CoordMapping == desc.fCoordMapping) {
-
-        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);
-        radial2ParamsName = radial2FSParams->getName().c_str();
-
-        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);
-        }
+        radial2ParamsName = this->genRadialVS(stageNum, segments,
+                                              locations,
+                                              &radial2VaryingVSName,
+                                              &radial2VaryingFSName,
+                                              varyingVSName,
+                                              varyingDims, coordDims);
     }
 
     const char* kernelName = NULL;
     const char* imageIncrementName = NULL;
     if (ProgramDesc::StageDesc::kConvolution_FetchMode == desc.fFetchMode) {
-
-        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);
+        this->genConvolutionVS(stageNum, desc, segments, locations,
+                               &kernelName, &imageIncrementName, varyingVSName);
     }
 
     /// Fragment Shader Stuff
@@ -1465,84 +1518,22 @@
         sampleCoords.printf("vec2(length(%s.xy), 0.5)", fsCoordName.c_str());
         complexCoord = true;
         break;
-    case StageDesc::kRadial2Gradient_CoordMapping: {
-        GrStringBuilder cName("c");
-        GrStringBuilder ac4Name("ac4");
-        GrStringBuilder rootName("root");
+    case StageDesc::kRadial2Gradient_CoordMapping:
+        complexCoord = genRadial2GradientCoordMapping(
+                           stageNum, segments,
+                           radial2VaryingFSName, radial2ParamsName,
+                           sampleCoords, fsCoordName,
+                           varyingDims, coordDims);
 
-        cName.appendS32(stageNum);
-        ac4Name.appendS32(stageNum);
-        rootName.appendS32(stageNum);
+        break;
+    case StageDesc::kRadial2GradientDegenerate_CoordMapping:
+        complexCoord = genRadial2GradientDegenerateCoordMapping(
+                           stageNum, segments,
+                           radial2VaryingFSName, radial2ParamsName,
+                           sampleCoords, fsCoordName,
+                           varyingDims, coordDims);
+        break;
 
-        // if we were able to interpolate the linear component bVar is the varying
-        // otherwise compute it
-        GrStringBuilder bVar;
-        if (coordDims == varyingDims) {
-            bVar = radial2VaryingFSName;
-            GrAssert(2 == varyingDims);
-        } else {
-            GrAssert(3 == varyingDims);
-            bVar = "b";
-            bVar.appendS32(stageNum);
-            segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s[2] * %s.x - %s[3]);\n",
-                                        bVar.c_str(), radial2ParamsName,
-                                        fsCoordName.c_str(), radial2ParamsName);
-        }
-
-        // c = (x^2)+(y^2) - params[4]
-        segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s[4];\n",
-                                  cName.c_str(), fsCoordName.c_str(),
-                                  fsCoordName.c_str(),
-                                  radial2ParamsName);
-        // ac4 = 4.0 * params[0] * c
-        segments->fFSCode.appendf("\tfloat %s = %s[0] * 4.0 * %s;\n",
-                                  ac4Name.c_str(), radial2ParamsName,
-                                  cName.c_str());
-
-        // root = sqrt(b^2-4ac)
-        // (abs to avoid exception due to fp precision)
-        segments->fFSCode.appendf("\tfloat %s = sqrt(abs(%s*%s - %s));\n",
-                                  rootName.c_str(), bVar.c_str(), bVar.c_str(),
-                                  ac4Name.c_str());
-
-        // x coord is: (-b + params[5] * sqrt(b^2-4ac)) * params[1]
-        // y coord is 0.5 (texture is effectively 1D)
-        sampleCoords.printf("vec2((-%s + %s[5] * %s) * %s[1], 0.5)",
-                            bVar.c_str(), radial2ParamsName,
-                            rootName.c_str(), radial2ParamsName);
-        complexCoord = true;
-        break;}
-    case StageDesc::kRadial2GradientDegenerate_CoordMapping: {
-        GrStringBuilder cName("c");
-
-        cName.appendS32(stageNum);
-
-        // if we were able to interpolate the linear component bVar is the varying
-        // otherwise compute it
-        GrStringBuilder bVar;
-        if (coordDims == varyingDims) {
-            bVar = radial2VaryingFSName;
-            GrAssert(2 == varyingDims);
-        } else {
-            GrAssert(3 == varyingDims);
-            bVar = "b";
-            bVar.appendS32(stageNum);
-            segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s[2] * %s.x - %s[3]);\n",
-                                        bVar.c_str(), radial2ParamsName,
-                                        fsCoordName.c_str(), radial2ParamsName);
-        }
-
-        // c = (x^2)+(y^2) - params[4]
-        segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s[4];\n",
-                                  cName.c_str(), fsCoordName.c_str(),
-                                  fsCoordName.c_str(),
-                                  radial2ParamsName);
-
-        // x coord is: -c/b
-        // y coord is 0.5 (texture is effectively 1D)
-        sampleCoords.printf("vec2((-%s / %s), 0.5)", cName.c_str(), bVar.c_str());
-        complexCoord = true;
-        break;}
     };
 
     const char* smear;
@@ -1572,52 +1563,158 @@
         locations->fTexDomUni = kUseUniform;
     }
 
-    if (StageDesc::k2x2_FetchMode == desc.fFetchMode) {
-        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());
-    } else if (ProgramDesc::StageDesc::kConvolution_FetchMode == desc.fFetchMode) {
-        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());
-    } else {
+    switch (desc.fFetchMode) {
+    case StageDesc::k2x2_FetchMode:
+        this->gen2x2FS(stageNum, segments, locations, &sampleCoords,
+            samplerName, texelSizeName, smear, fsOutColor,
+            texFunc, modulate, complexCoord, coordDims);
+        break;
+    case ProgramDesc::StageDesc::kConvolution_FetchMode:
+        this->genConvolutionFS(stageNum, desc, segments,
+            samplerName, kernelName, smear, imageIncrementName, fsOutColor,
+            sampleCoords, texFunc, modulate);
+        break;
+    default:
         segments->fFSCode.appendf("\t%s = %s(%s, %s)%s%s;\n",
                                   fsOutColor, texFunc.c_str(), 
                                   samplerName, sampleCoords.c_str(),
                                   smear, modulate.c_str());
     }
 }
+
+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());
+}
+