Add a requiresVertexShader method to GrGLEffect

Adds requiresVertexShader to GrGLEffect and updates the necessary
effects to override it and return true. Also reworks GrGLProgram
and GrGLShaderBuilder so the program creates all the GL effects
at the beginning, and determines if it needs a vertex shader before
creating the shader builder.

R=bsalomon@google.com

Author: cdalton@nvidia.com

Review URL: https://chromiumcodereview.appspot.com/23471008

git-svn-id: http://skia.googlecode.com/svn/trunk@11140 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index ac9794d..ebc5782 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -446,10 +446,32 @@
     SkASSERT(0 == fProgramID);
 
     const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
+    bool hasExplicitLocalCoords = -1 != header.fLocalCoordAttributeIndex;
 
-    bool needsVertexShader = true;
+    // Get the coeffs for the Mode-based color filter, determine if color is needed.
+    SkXfermode::Coeff colorCoeff;
+    SkXfermode::Coeff filterColorCoeff;
+    SkAssertResult(
+        SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>(header.fColorFilterXfermode),
+                                &filterColorCoeff,
+                                &colorCoeff));
+    bool needColor, needFilterColor;
+    need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
 
-    GrGLShaderBuilder builder(fGpu->ctxInfo(), fUniformManager, fDesc, needsVertexShader);
+    // Create the GL effects.
+    bool hasVertexShaderEffects = false;
+
+    SkTArray<GrDrawEffect> colorDrawEffects(needColor ? fDesc.numColorEffects() : 0);
+    if (needColor) {
+        this->buildGLEffects(&GrGLProgram::fColorEffects, colorStages, fDesc.numColorEffects(),
+                             hasExplicitLocalCoords, &colorDrawEffects, &hasVertexShaderEffects);
+    }
+
+    SkTArray<GrDrawEffect> coverageDrawEffects(fDesc.numCoverageEffects());
+    this->buildGLEffects(&GrGLProgram::fCoverageEffects, coverageStages, fDesc.numCoverageEffects(),
+                         hasExplicitLocalCoords, &coverageDrawEffects, &hasVertexShaderEffects);
+
+    GrGLShaderBuilder builder(fGpu->ctxInfo(), fUniformManager, fDesc, hasVertexShaderEffects);
 
     if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
         const char* viewMName;
@@ -486,16 +508,6 @@
     SkString inColor;
     GrSLConstantVec knownColorValue = this->genInputColor(&builder, &inColor);
 
-    // Get the coeffs for the Mode-based color filter, determine if color is needed.
-    SkXfermode::Coeff colorCoeff;
-    SkXfermode::Coeff filterColorCoeff;
-    SkAssertResult(
-        SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>(header.fColorFilterXfermode),
-                                &filterColorCoeff,
-                                &colorCoeff));
-    bool needColor, needFilterColor;
-    need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
-
     // used in order for builder to return the per-stage uniform handles.
     typedef SkTArray<GrGLUniformManager::UniformHandle, true>* UniHandleArrayPtr;
     int maxColorOrCovEffectCnt = GrMax(fDesc.numColorEffects(), fDesc.numCoverageEffects());
@@ -504,20 +516,17 @@
 
     if (needColor) {
         for (int e = 0; e < fDesc.numColorEffects(); ++e) {
+            glEffects[e] = fColorEffects[e].fGLEffect;
             effectUniformArrays[e] = &fColorEffects[e].fSamplerUnis;
         }
 
-        builder.emitEffects(colorStages,
+        builder.emitEffects(glEffects.get(),
+                            colorDrawEffects.begin(),
                             fDesc.effectKeys(),
                             fDesc.numColorEffects(),
                             &inColor,
                             &knownColorValue,
-                            effectUniformArrays.get(),
-                            glEffects.get());
-
-        for (int e = 0; e < fDesc.numColorEffects(); ++e) {
-            fColorEffects[e].fGLEffect = glEffects[e];
-        }
+                            effectUniformArrays.get());
     }
 
     // Insert the color filter. This will soon be replaced by a color effect.
@@ -548,19 +557,17 @@
     GrSLConstantVec knownCoverageValue = this->genInputCoverage(&builder, &inCoverage);
 
     for (int e = 0; e < fDesc.numCoverageEffects(); ++e) {
+        glEffects[e] = fCoverageEffects[e].fGLEffect;
         effectUniformArrays[e] = &fCoverageEffects[e].fSamplerUnis;
     }
 
-    builder.emitEffects(coverageStages,
+    builder.emitEffects(glEffects.get(),
+                        coverageDrawEffects.begin(),
                         fDesc.getEffectKeys() + fDesc.numColorEffects(),
                         fDesc.numCoverageEffects(),
                         &inCoverage,
                         &knownCoverageValue,
-                        effectUniformArrays.get(),
-                        glEffects.get());
-    for (int e = 0; e < fDesc.numCoverageEffects(); ++e) {
-        fCoverageEffects[e].fGLEffect = glEffects[e];
-    }
+                        effectUniformArrays.get());
 
     // discard if coverage is zero
     if (header.fDiscardIfZeroCoverage && kOnes_GrSLConstantVec != knownCoverageValue) {
@@ -689,6 +696,28 @@
     return true;
 }
 
+void GrGLProgram::buildGLEffects(SkTArray<EffectAndSamplers> GrGLProgram::* effectSet,
+                                 const GrEffectStage* stages[],
+                                 int count,
+                                 bool hasExplicitLocalCoords,
+                                 SkTArray<GrDrawEffect>* drawEffects,
+                                 bool* hasVertexShaderEffects) {
+    for (int e = 0; e < count; ++e) {
+        SkASSERT(NULL != stages[e] && NULL != stages[e]->getEffect());
+
+        const GrEffectStage& stage = *stages[e];
+        SkNEW_APPEND_TO_TARRAY(drawEffects, GrDrawEffect, (stage, hasExplicitLocalCoords));
+
+        const GrDrawEffect& drawEffect = (*drawEffects)[e];
+        GrGLEffect* effect = (this->*effectSet)[e].fGLEffect =
+            (*stage.getEffect())->getFactory().createGLInstance(drawEffect);
+
+        if (!*hasVertexShaderEffects && effect->requiresVertexShader(drawEffect)) {
+            *hasVertexShaderEffects = true;
+        }
+    }
+}
+
 bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
                                                    bool bindColorOut,
                                                    bool bindDualSrcOut) {