Move all code generation from GrGLProgram to GrGLShaderBuilder

R=robertphillips@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/306663003

git-svn-id: http://skia.googlecode.com/svn/trunk@14974 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index efd6e46..c639148 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -47,19 +47,18 @@
 
     fColor = GrColor_ILLEGAL;
 
-    if (fDesc.getHeader().fHasVertexCode ||
-        !fGpu->shouldUseFixedFunctionTexturing()) {
-        GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc);
-        if (this->genProgram(&fullBuilder, colorStages, coverageStages)) {
-            fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform();
-            fUniformHandles.fRTAdjustmentUni = fullBuilder.getRTAdjustmentVecUniform();
-            fHasVertexShader = true;
-        }
-    } else {
-        GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager, fDesc);
-        if (this->genProgram(&fragmentOnlyBuilder, colorStages, coverageStages)) {
-            fNumTexCoordSets = fragmentOnlyBuilder.getNumTexCoordSets();
-        }
+    GrGLShaderBuilder::GenProgramOutput output;
+
+    if (GrGLShaderBuilder::GenProgram(gpu, fUniformManager, desc, colorStages, coverageStages,
+                                      &output)) {
+        fProgramID = output.fProgramID;
+        fUniformHandles = output.fUniformHandles;
+        fColorEffects.reset(output.fColorEffects);
+        fCoverageEffects.reset(output.fCoverageEffects);
+        fHasVertexShader = output.fHasVS;
+        fNumTexCoordSets = output.fNumTexCoordSets;
+        fGpu = gpu;
+        this->initSamplerUniforms();
     }
 }
 
@@ -95,79 +94,6 @@
     }
 }
 
-bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
-                             const GrEffectStage* colorStages[],
-                             const GrEffectStage* coverageStages[]) {
-    SkASSERT(0 == fProgramID);
-
-    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
-
-    // incoming color to current stage being processed.
-    GrGLSLExpr4 inColor = builder->getInputColor();
-
-    fColorEffects.reset(
-        builder->createAndEmitEffects(colorStages,
-                                      fDesc.effectKeys(),
-                                      fDesc.numColorEffects(),
-                                      &inColor));
-
-    ///////////////////////////////////////////////////////////////////////////
-    // compute the partial coverage
-    GrGLSLExpr4 inCoverage = builder->getInputCoverage();
-
-    fCoverageEffects.reset(
-        builder->createAndEmitEffects(coverageStages,
-                                      fDesc.getEffectKeys() + fDesc.numColorEffects(),
-                                      fDesc.numCoverageEffects(),
-                                      &inCoverage));
-
-    if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
-        const char* secondaryOutputName = builder->enableSecondaryOutput();
-
-        // default coeff to ones for kCoverage_DualSrcOutput
-        GrGLSLExpr4 coeff(1);
-        if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
-            // Get (1-A) into coeff
-            coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inColor.a());
-        } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) {
-            // Get (1-RGBA) into coeff
-            coeff = GrGLSLExpr4(1) - inColor;
-        }
-        // Get coeff * coverage into modulate and then write that to the dual source output.
-        builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str());
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // combine color and coverage as frag color
-
-    // Get "color * coverage" into fragColor
-    GrGLSLExpr4 fragColor = inColor * inCoverage;
-    // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
-    if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
-        GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inCoverage;
-
-        GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(builder->dstColor());
-
-        fragColor = fragColor + dstContribution;
-    }
-    builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragColor.c_str());
-
-    if (!builder->finish(&fProgramID)) {
-        return false;
-    }
-
-    fUniformHandles.fRTHeightUni = builder->getRTHeightUniform();
-    fUniformHandles.fDstCopyTopLeftUni = builder->getDstCopyTopLeftUniform();
-    fUniformHandles.fDstCopyScaleUni = builder->getDstCopyScaleUniform();
-    fUniformHandles.fColorUni = builder->getColorUniform();
-    fUniformHandles.fCoverageUni = builder->getCoverageUniform();
-    fUniformHandles.fDstCopySamplerUni = builder->getDstCopySamplerUniform();
-    // This must be called after we set fDstCopySamplerUni above.
-    this->initSamplerUniforms();
-
-    return true;
-}
-
 void GrGLProgram::initSamplerUniforms() {
     GL_CALL(UseProgram(fProgramID));
     GrGLint texUnitIdx = 0;
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index b6d9a8e..a9a2da2 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -164,23 +164,6 @@
 private:
     typedef GrGLUniformManager::UniformHandle UniformHandle;
 
-    // handles for uniforms (aside from per-effect samplers)
-    struct UniformHandles {
-        UniformHandle       fViewMatrixUni;
-        UniformHandle       fRTAdjustmentUni;
-        UniformHandle       fColorUni;
-        UniformHandle       fCoverageUni;
-
-        // We use the render target height to provide a y-down frag coord when specifying
-        // origin_upper_left is not supported.
-        UniformHandle       fRTHeightUni;
-
-        // Uniforms for computing texture coords to do the dst-copy lookup
-        UniformHandle       fDstCopyTopLeftUni;
-        UniformHandle       fDstCopyScaleUni;
-        UniformHandle       fDstCopySamplerUni;
-    };
-
     GrGLProgram(GrGpuGL* gpu,
                 const GrGLProgramDesc& desc,
                 const GrEffectStage* colorStages[],
@@ -226,7 +209,7 @@
     GrGpuGL*                          fGpu;
 
     GrGLUniformManager                fUniformManager;
-    UniformHandles                    fUniformHandles;
+    GrGLShaderBuilder::UniformHandles fUniformHandles;
 
     bool                              fHasVertexShader;
     int                               fNumTexCoordSets;
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 1fd1967..52644f8 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -89,10 +89,108 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+bool GrGLShaderBuilder::GenProgram(GrGpuGL* gpu,
+                                   GrGLUniformManager& uman,
+                                   const GrGLProgramDesc& desc,
+                                   const GrEffectStage* inColorStages[],
+                                   const GrEffectStage* inCoverageStages[],
+                                   GenProgramOutput* output) {
+    if (desc.getHeader().fHasVertexCode ||!gpu->shouldUseFixedFunctionTexturing()) {
+        GrGLFullShaderBuilder fullBuilder(gpu, uman, desc);
+        if (fullBuilder.genProgram(inColorStages, inCoverageStages, output)) {
+            output->fHasVS = true;
+            output->fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform();
+            output->fUniformHandles.fRTAdjustmentUni = fullBuilder.getRTAdjustmentVecUniform();
+            return true;
+        }
+    } else {
+        GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(gpu, uman, desc);
+        if (fragmentOnlyBuilder.genProgram(inColorStages, inCoverageStages, output)) {
+            output->fHasVS = false;
+            output->fNumTexCoordSets = fragmentOnlyBuilder.getNumTexCoordSets();
+            return true;
+        }
+    }
+    return false;
+}
+
+bool GrGLShaderBuilder::genProgram(const GrEffectStage* colorStages[],
+                                   const GrEffectStage* coverageStages[],
+                                   GenProgramOutput* output) {
+    const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
+
+    // incoming color to current stage being processed.
+    GrGLSLExpr4 inColor = this->getInputColor();
+
+    output->fColorEffects =
+        this->createAndEmitEffects(colorStages,
+                                   this->desc().getEffectKeys(),
+                                   this->desc().numColorEffects(),
+                                   &inColor);
+
+    ///////////////////////////////////////////////////////////////////////////
+    // compute the partial coverage
+    GrGLSLExpr4 inCoverage = this->getInputCoverage();
+
+    output->fCoverageEffects =
+        this->createAndEmitEffects(coverageStages,
+                                    this->desc().getEffectKeys() + this->desc().numColorEffects(),
+                                    this->desc().numCoverageEffects(),
+                                    &inCoverage);
+
+    if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
+        const char* secondaryOutputName = this->enableSecondaryOutput();
+
+        // default coeff to ones for kCoverage_DualSrcOutput
+        GrGLSLExpr4 coeff(1);
+        if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
+            // Get (1-A) into coeff
+            coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inColor.a());
+        } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == 
+                   header.fCoverageOutput){
+            // Get (1-RGBA) into coeff
+            coeff = GrGLSLExpr4(1) - inColor;
+        }
+        // Get coeff * coverage into modulate and then write that to the dual source output.
+        this->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str());
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // combine color and coverage as frag color
+
+    // Get "color * coverage" into fragColor
+    GrGLSLExpr4 fragColor = inColor * inCoverage;
+    // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
+    if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
+        GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inCoverage;
+
+        GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->dstColor());
+
+        fragColor = fragColor + dstContribution;
+    }
+    this->fsCodeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str());
+
+    if (!this->finish(&output->fProgramID)) {
+        return false;
+    }
+
+    output->fUniformHandles.fRTHeightUni = this->getRTHeightUniform();
+    output->fUniformHandles.fDstCopyTopLeftUni = this->getDstCopyTopLeftUniform();
+    output->fUniformHandles.fDstCopyScaleUni = this->getDstCopyScaleUniform();
+    output->fUniformHandles.fColorUni = this->getColorUniform();
+    output->fUniformHandles.fCoverageUni = this->getCoverageUniform();
+    output->fUniformHandles.fDstCopySamplerUni = this->getDstCopySamplerUniform();
+
+    return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
 GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
                                      GrGLUniformManager& uniformManager,
                                      const GrGLProgramDesc& desc)
-    : fGpu(gpu)
+    : fDesc(desc)
+    , fGpu(gpu)
     , fUniformManager(uniformManager)
     , fFSFeaturesAddedMask(0)
     , fFSInputs(kVarsPerBlock)
@@ -735,13 +833,12 @@
                                              GrGLUniformManager& uniformManager,
                                              const GrGLProgramDesc& desc)
     : INHERITED(gpu, uniformManager, desc)
-    , fDesc(desc)
     , fVSAttrs(kVarsPerBlock)
     , fVSOutputs(kVarsPerBlock)
     , fGSInputs(kVarsPerBlock)
     , fGSOutputs(kVarsPerBlock) {
 
-    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
+    const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
 
     fPositionVar = &fVSAttrs.push_back();
     fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
@@ -837,7 +934,7 @@
     // input to FS comes either from VS or GS
     const SkString* fsName;
 #if GR_GL_EXPERIMENTAL_GS
-    if (fDesc.getHeader().fExperimentalGS) {
+    if (this->desc().getHeader().fExperimentalGS) {
         // if we have a GS take each varying in as an array
         // and output as non-array.
         fGSInputs.push_back();
@@ -887,7 +984,8 @@
     return programEffectsBuilder.finish();
 }
 
-bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const {
+bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId,
+                                                    SkTDArray<GrGLuint>* shaderIds) const {
     const GrGLContext& glCtx = this->gpu()->glContext();
     SkString vertShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo()));
     this->appendUniformDecls(kVertex_Visibility, &vertShaderSrc);
@@ -903,7 +1001,7 @@
     *shaderIds->append() = vertShaderId;
 
 #if GR_GL_EXPERIMENTAL_GS
-    if (fDesc.getHeader().fExperimentalGS) {
+    if (this->desc().getHeader().fExperimentalGS) {
         SkASSERT(this->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration);
         SkString geomShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo()));
         geomShaderSrc.append("layout(triangles) in;\n"
@@ -913,7 +1011,7 @@
         geomShaderSrc.append("void main() {\n");
         geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n"
                              "\t\tgl_Position = gl_in[i].gl_Position;\n");
-        if (fDesc.getHeader().fEmitsPointSize) {
+        if (this->desc().getHeader().fEmitsPointSize) {
             geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n");
         }
         SkASSERT(fGSInputs.count() == fGSOutputs.count());
@@ -940,7 +1038,7 @@
 void GrGLFullShaderBuilder::bindProgramLocations(GrGLuint programId) const {
     this->INHERITED::bindProgramLocations(programId);
 
-    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
+    const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
 
     // Bind the attrib locations to same values for all shaders
     SkASSERT(-1 != header.fPositionAttributeIndex);
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index 1be9a88..90f1a94 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -41,7 +41,41 @@
         kFragment_Visibility = 0x4,
     };
 
-    GrGLShaderBuilder(GrGpuGL*, GrGLUniformManager&, const GrGLProgramDesc&);
+    typedef GrGLUniformManager::UniformHandle UniformHandle;
+
+    // Handles for program uniforms (other than per-effect uniforms)
+    struct UniformHandles {
+        UniformHandle       fViewMatrixUni;
+        UniformHandle       fRTAdjustmentUni;
+        UniformHandle       fColorUni;
+        UniformHandle       fCoverageUni;
+
+        // We use the render target height to provide a y-down frag coord when specifying
+        // origin_upper_left is not supported.
+        UniformHandle       fRTHeightUni;
+
+        // Uniforms for computing texture coords to do the dst-copy lookup
+        UniformHandle       fDstCopyTopLeftUni;
+        UniformHandle       fDstCopyScaleUni;
+        UniformHandle       fDstCopySamplerUni;
+    };
+
+    struct GenProgramOutput {
+        GrGLProgramEffects* fColorEffects;
+        GrGLProgramEffects* fCoverageEffects;
+        UniformHandles fUniformHandles;
+        bool fHasVS;
+        int fNumTexCoordSets;
+        GrGLuint fProgramID;
+    };
+
+    static bool GenProgram(GrGpuGL* gpu,
+                           GrGLUniformManager& uman,
+                           const GrGLProgramDesc& desc,
+                           const GrEffectStage* inColorStages[],
+                           const GrEffectStage* inCoverageStages[],
+                           GenProgramOutput* output);
+
     virtual ~GrGLShaderBuilder() {}
 
     /**
@@ -228,8 +262,12 @@
     };
 
 protected:
+    GrGLShaderBuilder(GrGpuGL*, GrGLUniformManager&, const GrGLProgramDesc&);
+
     GrGpuGL* gpu() const { return fGpu; }
 
+    const GrGLProgramDesc& desc() const { return fDesc; }
+
     void setInputColor(const GrGLSLExpr4& inputColor) { fInputColor = inputColor; }
     void setInputCoverage(const GrGLSLExpr4& inputCoverage) { fInputCoverage = inputCoverage; }
 
@@ -306,6 +344,10 @@
         const GrEffectStage*    fEffectStage;
     } fCodeStage;
 
+    bool genProgram(const GrEffectStage* colorStages[],
+                    const GrEffectStage* coverageStages[],
+                    GenProgramOutput* output);
+
     /**
      * Features that should only be enabled by GrGLShaderBuilder itself.
      */
@@ -334,6 +376,7 @@
         kBottomLeftFragPosRead_FragPosKey   = 0x2,// Read frag pos relative to bottom-left.
     };
 
+    const GrGLProgramDesc&                  fDesc;
     GrGpuGL*                                fGpu;
     GrGLUniformManager&                     fUniformManager;
     uint32_t                                fFSFeaturesAddedMask;
@@ -433,7 +476,6 @@
     virtual void bindProgramLocations(GrGLuint programId) const SK_OVERRIDE;
 
 private:
-    const GrGLProgramDesc&              fDesc;
     VarArray                            fVSAttrs;
     VarArray                            fVSOutputs;
     VarArray                            fGSInputs;