Use GrCustomStage to implement color matrix.

R=robertphillips@google.com
Review URL: https://codereview.appspot.com/6716044

git-svn-id: http://skia.googlecode.com/svn/trunk@5975 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 2703110..3c3d852 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -511,7 +511,6 @@
 #endif
 
     SkXfermode::Coeff colorCoeff, uniformCoeff;
-    bool applyColorMatrix = SkToBool(fDesc.fColorMatrixEnabled);
     // The rest of transfer mode color filters have not been implemented
     if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
         GR_DEBUGCODE(bool success =)
@@ -524,17 +523,15 @@
         uniformCoeff = SkXfermode::kZero_Coeff;
     }
 
-    // no need to do the color filter / matrix at all if coverage is 0. The
-    // output color is scaled by the coverage. All the dual source outputs are
-    // scaled by the coverage as well.
+    // no need to do the color filter if coverage is 0. The output color is scaled by the coverage.
+    // All the dual source outputs are scaled by the coverage as well.
     if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) {
         colorCoeff = SkXfermode::kZero_Coeff;
         uniformCoeff = SkXfermode::kZero_Coeff;
-        applyColorMatrix = false;
     }
 
     // If we know the final color is going to be all zeros then we can
-    // simplify the color filter coeffecients. needComputedColor will then
+    // simplify the color filter coefficients. needComputedColor will then
     // come out false below.
     if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) {
         colorCoeff = SkXfermode::kZero_Coeff;
@@ -664,8 +661,7 @@
     }
     bool wroteFragColorZero = false;
     if (SkXfermode::kZero_Coeff == uniformCoeff &&
-        SkXfermode::kZero_Coeff == colorCoeff &&
-        !applyColorMatrix) {
+        SkXfermode::kZero_Coeff == colorCoeff) {
         builder.fFSCode.appendf("\t%s = %s;\n",
                                 colorOutput.getName().c_str(),
                                 GrGLSLZerosVecf(4));
@@ -677,22 +673,6 @@
                        colorCoeff, colorFilterColorUniName, color);
         inColor = "filteredColor";
     }
-    if (applyColorMatrix) {
-        const char* colMatrixName;
-        const char* colMatrixVecName;
-        fUniforms.fColorMatrixUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
-                                                       kMat44f_GrSLType, "ColorMatrix",
-                                                       &colMatrixName);
-        fUniforms.fColorMatrixVecUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
-                                                          kVec4f_GrSLType, "ColorMatrixVec",
-                                                          &colMatrixVecName);
-        const char* color = adjustInColor(inColor);
-        builder.fFSCode.appendf("\tvec4 matrixedColor = %s * vec4(%s.rgb / %s.a, %s.a) + %s;\n",
-                                colMatrixName, color, color, color, colMatrixVecName);
-        builder.fFSCode.append("\tmatrixedColor.rgb *= matrixedColor.a;\n");
-
-        inColor = "matrixedColor";
-    }
 
     ///////////////////////////////////////////////////////////////////////////
     // compute the partial coverage (coverage stages and edge aa)
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index e51f663..cdb2c4b 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -155,7 +155,6 @@
         uint8_t fDualSrcOutput;     // casts to enum DualSrcOutput
         int8_t fFirstCoverageStage;
         SkBool8 fEmitsPointSize;
-        SkBool8 fColorMatrixEnabled;
 
         uint8_t fColorFilterXfermode;  // casts to enum SkXfermode::Mode
     };
@@ -224,16 +223,12 @@
         UniformHandle fColorUni;
         UniformHandle fCoverageUni;
         UniformHandle fColorFilterUni;
-        UniformHandle fColorMatrixUni;
-        UniformHandle fColorMatrixVecUni;
         StageUniforms fStages[GrDrawState::kNumStages];
         Uniforms() {
             fViewMatrixUni = GrGLUniformManager::kInvalidUniformHandle;
             fColorUni = GrGLUniformManager::kInvalidUniformHandle;
             fCoverageUni = GrGLUniformManager::kInvalidUniformHandle;
             fColorFilterUni = GrGLUniformManager::kInvalidUniformHandle;
-            fColorMatrixUni = GrGLUniformManager::kInvalidUniformHandle;
-            fColorMatrixVecUni = GrGLUniformManager::kInvalidUniformHandle;
         }
     };
 
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 157d9bc..4df7a98 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -2020,10 +2020,12 @@
     GrDrawState* drawState = this->drawState();
     // FIXME: Assuming at most one texture per custom stage
     const GrCustomStage* customStage = drawState->sampler(stage)->getCustomStage();
-    GrGLTexture* nextTexture =  static_cast<GrGLTexture*>(customStage->texture(0));
-    if (NULL != nextTexture) {
-        const GrTextureParams& texParams = customStage->textureAccess(0).getParams();
-        this->flushBoundTextureAndParams(stage, texParams, nextTexture);
+    if (customStage->numTextures() > 0) {
+        GrGLTexture* nextTexture =  static_cast<GrGLTexture*>(customStage->texture(0));
+        if (NULL != nextTexture) {
+            const GrTextureParams& texParams = customStage->textureAccess(0).getParams();
+            this->flushBoundTextureAndParams(stage, texParams, nextTexture);
+        }
     }
 }
 
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 351ff53..0a0c52b 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -229,14 +229,6 @@
     // sets the MVP matrix uniform for currently bound program
     void flushViewMatrix(DrawType type);
 
-    // flushes the parameters to two point radial gradient
-    void flushRadial2(int stage);
-
-    // flushes the parameters for convolution
-    void flushConvolution(int stage);
-
-    // flushes the color matrix
-    void flushColorMatrix();
 
     // flushes dithering, color-mask, and face culling stat
     void flushMiscFixedFunctionState();
@@ -251,7 +243,7 @@
                       const GrCustomStage** customStages,
                       ProgramDesc* desc);
 
-    // Inits GrDrawTarget::Caps, sublcass may enable additional caps.
+    // Inits GrDrawTarget::Caps, subclass may enable additional caps.
     void initCaps();
 
     void initFSAASupport();
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index e579331..5f5a3a6 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -200,6 +200,9 @@
 
     // FIXME: Still assuming only a single texture per custom stage
     const GrCustomStage* stage = drawState.getSampler(s).getCustomStage();
+    if (0 == stage->numTextures()) {
+        return;
+    }
     const GrGLTexture* texture = static_cast<const GrGLTexture*>(stage->texture(0));
     if (NULL != texture) {
 
@@ -240,26 +243,6 @@
     }
 }
 
-void GrGpuGL::flushColorMatrix() {
-    UniformHandle matrixUni = fCurrentProgram->fUniforms.fColorMatrixUni;
-    UniformHandle vecUni = fCurrentProgram->fUniforms.fColorMatrixVecUni;
-    if (kInvalidUniformHandle != matrixUni && kInvalidUniformHandle != vecUni) {
-        const float* m = this->getDrawState().getColorMatrix();
-        GrGLfloat mt[]  = {
-            m[0], m[5], m[10], m[15],
-            m[1], m[6], m[11], m[16],
-            m[2], m[7], m[12], m[17],
-            m[3], m[8], m[13], m[18],
-        };
-        static float scale = 1.0f / 255.0f;
-        GrGLfloat vec[] = {
-            m[4] * scale, m[9] * scale, m[14] * scale, m[19] * scale,
-        };
-        fCurrentProgram->fUniformManager.setMatrix4f(matrixUni, mt);
-        fCurrentProgram->fUniformManager.set4fv(vecUni, 0, 1, vec);
-    }
-}
-
 void GrGpuGL::flushColor(GrColor color) {
     const ProgramDesc& desc = fCurrentProgram->getDesc();
     const GrDrawState& drawState = this->getDrawState();
@@ -414,7 +397,6 @@
                 }
             }
         }
-        this->flushColorMatrix();
     }
     this->flushStencil(type);
     this->flushViewMatrix(type);
@@ -645,8 +627,6 @@
                                 SkXfermode::kDst_Mode :
                                 drawState.getColorFilterMode();
 
-    desc->fColorMatrixEnabled = drawState.isStateFlagEnabled(GrDrawState::kColorMatrix_StateBit);
-
     // no reason to do edge aa or look at per-vertex coverage if coverage is
     // ignored
     if (skipCoverage) {
@@ -701,16 +681,23 @@
             const GrSamplerState& sampler = drawState.getSampler(s);
             // FIXME: Still assuming one texture per custom stage
             const GrCustomStage* customStage = drawState.getSampler(s).getCustomStage();
-            const GrGLTexture* texture = static_cast<const GrGLTexture*>(customStage->texture(0));
-            GrMatrix samplerMatrix;
-            sampler.getTotalMatrix(&samplerMatrix);
-            if (NULL != texture) {
-                // We call this helper function rather then simply checking the client-specified
-                // texture matrix. This is because we may have to concat a y-inversion to account
-                // for texture orientation.
-                stage.fOptFlags |= TextureMatrixOptFlags(texture, sampler);
-            }
 
+            if (customStage->numTextures() > 0) {
+                const GrGLTexture* texture =
+                    static_cast<const GrGLTexture*>(customStage->texture(0));
+                GrMatrix samplerMatrix;
+                sampler.getTotalMatrix(&samplerMatrix);
+                if (NULL != texture) {
+                    // We call this helper function rather then simply checking the client-specified
+                    // texture matrix. This is because we may have to concat a y-inversion to account
+                    // for texture orientation.
+                    stage.fOptFlags |= TextureMatrixOptFlags(texture, sampler);
+                }
+            } else {
+                // Set identity to do the minimal amount of extra work for the no texture case.
+                // This will go away when custom stages manage their own texture matrix.
+                stage.fOptFlags |= StageDesc::kIdentityMatrix_OptFlagBit;
+            }
             setup_custom_stage(&stage, sampler, this->glCaps(), customStages,
                                fCurrentProgram.get(), s);
 
@@ -724,7 +711,7 @@
     desc->fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
 
     // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
-    // other than pass through values fromthe VS to the FS anyway).
+    // other than pass through values from the VS to the FS anyway).
 #if 0 && GR_GL_EXPERIMENTAL_GS
     desc->fExperimentalGS = this->getCaps().fGeometryShaderSupport;
 #endif