Extract ShaderCodeSegments from GrGLProgram into a new class,
GrGLShaderBuilder. Begin populating its interface.

Requires gyp changes.

http://codereview.appspot.com/6197076/



git-svn-id: http://skia.googlecode.com/svn/trunk@3916 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 27a0b12..7ffb4d4 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -10,6 +10,7 @@
 #include "GrAllocator.h"
 #include "GrCustomStage.h"
 #include "GrGLProgramStage.h"
+#include "gl/GrGLShaderBuilder.h"
 #include "GrGLShaderVar.h"
 #include "GrProgramStageFactory.h"
 #include "SkTrace.h"
@@ -27,42 +28,6 @@
 
 #define PRINT_SHADERS 0
 
-typedef GrTAllocator<GrGLShaderVar> VarArray;
-
-// number of each input/output type in a single allocation block
-static const int gVarsPerBlock = 8;
-// except FS outputs where we expect 2 at most.
-static const int gMaxFSOutputs = 2;
-
-struct ShaderCodeSegments {
-    ShaderCodeSegments() 
-    : fVSUnis(gVarsPerBlock)
-    , fVSAttrs(gVarsPerBlock)
-    , fVSOutputs(gVarsPerBlock)
-    , fGSInputs(gVarsPerBlock)
-    , fGSOutputs(gVarsPerBlock)
-    , fFSInputs(gVarsPerBlock)
-    , fFSUnis(gVarsPerBlock)
-    , fFSOutputs(gMaxFSOutputs)
-    , fUsesGS(false) {}
-    GrStringBuilder fHeader; // VS+FS, GLSL version, etc
-    VarArray        fVSUnis;
-    VarArray        fVSAttrs;
-    VarArray        fVSOutputs;
-    VarArray        fGSInputs;
-    VarArray        fGSOutputs;
-    VarArray        fFSInputs;
-    GrStringBuilder fGSHeader; // layout qualifiers specific to GS
-    VarArray        fFSUnis;
-    VarArray        fFSOutputs;
-    GrStringBuilder fFSFunctions;
-    GrStringBuilder fVSCode;
-    GrStringBuilder fGSCode;
-    GrStringBuilder fFSCode;
-
-    bool            fUsesGS;
-};
-
 typedef GrGLProgram::ProgramDesc::StageDesc StageDesc;
 
 #if GR_GL_ATTRIBUTE_MATRICES
@@ -346,77 +311,14 @@
     fsCode->appendf("\t%s.rgb *= %s.a;\n", outputVar, outputVar);
 }
 
-namespace {
-
-// Adds a var that is computed in the VS and read in FS.
-// If there is a GS it will just pass it through.
-void append_varying(GrSLType type,
-                    const char* name,
-                    ShaderCodeSegments* segments,
-                    const char** vsOutName = NULL,
-                    const char** fsInName = NULL) {
-    segments->fVSOutputs.push_back();
-    segments->fVSOutputs.back().setType(type);
-    segments->fVSOutputs.back().setTypeModifier(
-        GrGLShaderVar::kOut_TypeModifier);
-    segments->fVSOutputs.back().accessName()->printf("v%s", name);
-    if (vsOutName) {
-        *vsOutName = segments->fVSOutputs.back().getName().c_str();
-    }
-    // input to FS comes either from VS or GS
-    const GrStringBuilder* fsName;
-    if (segments->fUsesGS) {
-        // if we have a GS take each varying in as an array
-        // and output as non-array.
-        segments->fGSInputs.push_back();
-        segments->fGSInputs.back().setType(type);
-        segments->fGSInputs.back().setTypeModifier(
-            GrGLShaderVar::kIn_TypeModifier);
-        segments->fGSInputs.back().setUnsizedArray();
-        *segments->fGSInputs.back().accessName() =
-            segments->fVSOutputs.back().getName();
-        segments->fGSOutputs.push_back();
-        segments->fGSOutputs.back().setType(type);
-        segments->fGSOutputs.back().setTypeModifier(
-            GrGLShaderVar::kOut_TypeModifier);
-        segments->fGSOutputs.back().accessName()->printf("g%s", name);
-        fsName = segments->fGSOutputs.back().accessName();
-    } else {
-        fsName = segments->fVSOutputs.back().accessName();
-    }
-    segments->fFSInputs.push_back();
-    segments->fFSInputs.back().setType(type);
-    segments->fFSInputs.back().setTypeModifier(
-        GrGLShaderVar::kIn_TypeModifier);
-    segments->fFSInputs.back().setName(*fsName);
-    if (fsInName) {
-        *fsInName = fsName->c_str();
-    }
-}
-
-// version of above that adds a stage number to the
-// the var name (for uniqueness)
-void append_varying(GrSLType type,
-                    const char* name,
-                    int stageNum,
-                    ShaderCodeSegments* segments,
-                    const char** vsOutName = NULL,
-                    const char** fsInName = NULL) {
-    GrStringBuilder nameWithStage(name);
-    nameWithStage.appendS32(stageNum);
-    append_varying(type, nameWithStage.c_str(), segments, vsOutName, fsInName);
-}
-}
-
 void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl,
                                   GrVertexLayout layout,
                                   CachedData* programData,
                                   GrStringBuilder* coverageVar,
-                                  ShaderCodeSegments* segments) const {
+                                  GrGLShaderBuilder* segments) const {
     if (layout & GrDrawTarget::kEdge_VertexLayoutBit) {
         const char *vsName, *fsName;
-        append_varying(kVec4f_GrSLType, "Edge", segments,
-            &vsName, &fsName);
+        segments->appendVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName);
         segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
             GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME);
         segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
@@ -478,7 +380,7 @@
 
 void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput,
                    GrGLProgram::CachedData* programData,
-                   ShaderCodeSegments* segments,
+                   GrGLShaderBuilder* segments,
                    GrStringBuilder* inColor) {
     switch (colorInput) {
         case GrGLProgram::ProgramDesc::kAttribute_ColorInput: {
@@ -486,7 +388,7 @@
                 GrGLShaderVar::kAttribute_TypeModifier,
                 COL_ATTR_NAME);
             const char *vsName, *fsName;
-            append_varying(kVec4f_GrSLType, "Color", segments, &vsName, &fsName);
+            segments->appendVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
             segments->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
             *inColor = fsName;
             } break;
@@ -508,14 +410,13 @@
     }
 }
 
-void genAttributeCoverage(ShaderCodeSegments* segments,
+void genAttributeCoverage(GrGLShaderBuilder* segments,
                           GrStringBuilder* inOutCoverage) {
     segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
                                        GrGLShaderVar::kAttribute_TypeModifier,
                                        COV_ATTR_NAME);
     const char *vsName, *fsName;
-    append_varying(kVec4f_GrSLType, "Coverage", 
-                   segments, &vsName, &fsName);
+    segments->appendVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
     segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
     if (inOutCoverage->size()) {
         segments->fFSCode.appendf("\tvec4 attrCoverage = %s * %s;\n",
@@ -526,7 +427,7 @@
     }
 }
     
-void genUniformCoverage(ShaderCodeSegments* segments,
+void genUniformCoverage(GrGLShaderBuilder* segments,
                         GrGLProgram::CachedData* programData,
                         GrStringBuilder* inOutCoverage) {
     segments->fFSUnis.push_back().set(kVec4f_GrSLType,
@@ -545,7 +446,7 @@
 }
 
 void GrGLProgram::genGeometryShader(const GrGLContextInfo& gl,
-                                    ShaderCodeSegments* segments) const {
+                                    GrGLShaderBuilder* segments) const {
 #if GR_GL_EXPERIMENTAL_GS
     if (fProgramDesc.fExperimentalGS) {
         GrAssert(gl.glslGeneration() >= k150_GrGLSLGeneration);
@@ -596,7 +497,7 @@
 bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
                              GrCustomStage** customStages,
                              GrGLProgram::CachedData* programData) const {
-    ShaderCodeSegments segments;
+    GrGLShaderBuilder segments;
     const uint32_t& layout = fProgramDesc.fVertexLayout;
 
     programData->fUniLocations.reset();
@@ -1035,7 +936,7 @@
 }
 
 bool GrGLProgram::CompileShaders(const GrGLContextInfo& gl,
-                                 const ShaderCodeSegments& segments,
+                                 const GrGLShaderBuilder& segments,
                                  CachedData* programData) {
     enum { kPreAllocStringCnt = 8 };
 
@@ -1383,7 +1284,7 @@
 }
 
 GrGLShaderVar* genRadialVS(int stageNum,
-                        ShaderCodeSegments* segments,
+                        GrGLShaderBuilder* segments,
                         GrGLProgram::StageUniLocations* locations,
                         const char** radial2VaryingVSName,
                         const char** radial2VaryingFSName,
@@ -1403,12 +1304,11 @@
     // part of the quadratic as a varying.
     if (varyingDims == coordDims) {
         GrAssert(2 == coordDims);
-        append_varying(kFloat_GrSLType,
-                       "Radial2BCoeff",
-                       stageNum,
-                       segments,
-                       radial2VaryingVSName,
-                       radial2VaryingFSName);
+        segments->appendVarying(kFloat_GrSLType,
+                                "Radial2BCoeff",
+                                stageNum,
+                                radial2VaryingVSName,
+                                radial2VaryingFSName);
 
         GrStringBuilder radial2p2;
         GrStringBuilder radial2p3;
@@ -1426,7 +1326,7 @@
 }
 
 bool genRadial2GradientCoordMapping(int stageNum,
-                                    ShaderCodeSegments* segments,
+                                    GrGLShaderBuilder* segments,
                                     const char* radial2VaryingFSName,
                                     GrGLShaderVar* radial2Params,
                                     GrStringBuilder& sampleCoords,
@@ -1494,7 +1394,7 @@
 }
 
 bool genRadial2GradientDegenerateCoordMapping(int stageNum,
-                                              ShaderCodeSegments* segments,
+                                              GrGLShaderBuilder* segments,
                                               const char* radial2VaryingFSName,
                                               GrGLShaderVar* radial2Params,
                                               GrStringBuilder& sampleCoords,
@@ -1540,7 +1440,7 @@
 }
 
 void gen2x2FS(int stageNum,
-              ShaderCodeSegments* segments,
+              GrGLShaderBuilder* segments,
               GrGLProgram::StageUniLocations* locations,
               GrStringBuilder* sampleCoords,
               const char* samplerName,
@@ -1574,7 +1474,7 @@
 
 void genMorphologyVS(int stageNum,
                      const StageDesc& desc,
-                     ShaderCodeSegments* segments,
+                     GrGLShaderBuilder* segments,
                      GrGLProgram::StageUniLocations* locations,
                      const char** imageIncrementName,
                      const char* varyingVSName) {
@@ -1596,7 +1496,7 @@
  
 void genMorphologyFS(int stageNum,
                      const StageDesc& desc,
-                     ShaderCodeSegments* segments,
+                     GrGLShaderBuilder* segments,
                      const char* samplerName,
                      const char* swizzle,
                      const char* imageIncrementName,
@@ -1642,7 +1542,7 @@
                                const char* fsInColor, // NULL means no incoming color
                                const char* fsOutColor,
                                const char* vsInCoord,
-                               ShaderCodeSegments* segments,
+                               GrGLShaderBuilder* segments,
                                StageUniLocations* locations,
                                GrGLProgramStage* customStage) const {
 
@@ -1704,12 +1604,11 @@
     }
 
     const char *varyingVSName, *varyingFSName;
-    append_varying(GrSLFloatVectorType(varyingDims),
-                    "Stage",
-                   stageNum,
-                   segments,
-                   &varyingVSName,
-                   &varyingFSName);
+    segments->appendVarying(GrSLFloatVectorType(varyingDims),
+                            "Stage",
+                           stageNum,
+                           &varyingVSName,
+                           &varyingFSName);
 
     if (!matName) {
         GrAssert(varyingDims == coordDims);