Calculate Primary and Secondary output types in the GrOptDrawState

Follow up CL to https://codereview.chromium.org/545693004/

BUG=skia:
R=bsalomon@google.com

Author: egdaniel@google.com

Review URL: https://codereview.chromium.org/554833002
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index a695173..1639a84 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -74,28 +74,6 @@
     fProgramID = 0;
 }
 
-void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
-                                GrBlendCoeff* dstCoeff) const {
-    switch (fDesc.getHeader().fCoverageOutput) {
-        case GrGLProgramDesc::kModulate_CoverageOutput:
-            break;
-        // The prog will write a coverage value to the secondary
-        // output and the dst is blended by one minus that value.
-        case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput:
-        case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput:
-        case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput:
-            *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
-            break;
-        case GrGLProgramDesc::kCombineWithDst_CoverageOutput:
-            // We should only have set this if the blend was specified as (1, 0)
-            SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
-            break;
-        default:
-            SkFAIL("Unexpected coverage output");
-            break;
-    }
-}
-
 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 a520bc2..3238a75 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -52,11 +52,6 @@
      */
     void abandon();
 
-    /**
-     * The shader may modify the blend coefficients. Params are in/out.
-     */
-    void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const;
-
     const GrGLProgramDesc& getDesc() { return fDesc; }
 
     /**
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index c0a9e13..5339937 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -343,51 +343,14 @@
         header->fCoverageAttributeIndex = -1;
     }
 
-    // Here we deal with whether/how we handle color and coverage separately.
-
-    // Set this default and then possibly change our mind if there is coverage.
-    header->fCoverageOutput = kModulate_CoverageOutput;
-
-    // If we do have coverage determine whether it matters.
-    bool separateCoverageFromColor = optState.hasGeometryProcessor();
-    if (!optState.isCoverageDrawing() &&
-        (optState.numCoverageStages() > 0 ||
-         optState.hasGeometryProcessor() ||
-         requiresCoverageAttrib)) {
-
-        if (gpu->caps()->dualSourceBlendingSupport()) {
-            if (kZero_GrBlendCoeff == dstCoeff) {
-                // write the coverage value to second color
-                header->fCoverageOutput =  kSecondaryCoverage_CoverageOutput;
-                separateCoverageFromColor = true;
-            } else if (kSA_GrBlendCoeff == dstCoeff) {
-                // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
-                header->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput;
-                separateCoverageFromColor = true;
-            } else if (kSC_GrBlendCoeff == dstCoeff) {
-                // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
-                header->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput;
-                separateCoverageFromColor = true;
-            }
-        } else if (optState.readsDst() &&
-                   kOne_GrBlendCoeff == srcCoeff &&
-                   kZero_GrBlendCoeff == dstCoeff) {
-            header->fCoverageOutput = kCombineWithDst_CoverageOutput;
-            separateCoverageFromColor = true;
-        }
-    }
+    header->fPrimaryOutputType = optState.getPrimaryOutputType();
+    header->fSecondaryOutputType = optState.getSecondaryOutputType();
 
     for (int s = 0; s < optState.numColorStages(); ++s) {
         colorStages->push_back(&optState.getColorStage(s));
     }
-    SkTArray<const GrEffectStage*, true>* array;
-    if (separateCoverageFromColor) {
-        array = coverageStages;
-    } else {
-        array = colorStages;
-    }
     for (int s = 0; s < optState.numCoverageStages(); ++s) {
-        array->push_back(&optState.getCoverageStage(s));
+        coverageStages->push_back(&optState.getCoverageStage(s));
     }
 
     header->fColorEffectCnt = colorStages->count();
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index c9bdac5..172a202 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -11,6 +11,7 @@
 #include "GrGLEffect.h"
 #include "GrDrawState.h"
 #include "GrGpu.h"
+#include "GrOptDrawState.h"
 
 class GrGpuGL;
 
@@ -111,50 +112,24 @@
         kColorInputCnt
     };
 
-    enum CoverageOutput {
-        // modulate color and coverage, write result as the color output.
-        kModulate_CoverageOutput,
-        // Writes color*coverage as the primary color output and also writes coverage as the
-        // secondary output. Only set if dual source blending is supported.
-        kSecondaryCoverage_CoverageOutput,
-        // Writes color*coverage as the primary color output and also writes coverage * (1 - colorA)
-        // as the secondary output. Only set if dual source blending is supported.
-        kSecondaryCoverageISA_CoverageOutput,
-        // Writes color*coverage as the primary color output and also writes coverage *
-        // (1 - colorRGB) as the secondary output. Only set if dual source blending is supported.
-        kSecondaryCoverageISC_CoverageOutput,
-        // Combines the coverage, dst, and color as coverage * color + (1 - coverage) * dst. This
-        // can only be set if fDstReadKey is non-zero.
-        kCombineWithDst_CoverageOutput,
-
-        kCoverageOutputCnt
-    };
-
-    static bool CoverageOutputUsesSecondaryOutput(CoverageOutput co) {
-        switch (co) {
-            case kSecondaryCoverage_CoverageOutput: //  fallthru
-            case kSecondaryCoverageISA_CoverageOutput:
-            case kSecondaryCoverageISC_CoverageOutput:
-                return true;
-            default:
-                return false;
-        }
-    }
-
     struct KeyHeader {
-        uint8_t                     fDstReadKey;        // set by GrGLShaderBuilder if there
+        uint8_t                          fDstReadKey;   // set by GrGLShaderBuilder if there
                                                         // are effects that must read the dst.
                                                         // Otherwise, 0.
-        uint8_t                     fFragPosKey;        // set by GrGLShaderBuilder if there are
+        uint8_t                          fFragPosKey;   // set by GrGLShaderBuilder if there are
                                                         // effects that read the fragment position.
                                                         // Otherwise, 0.
-        ColorInput                  fColorInput : 8;
-        ColorInput                  fCoverageInput : 8;
-        CoverageOutput              fCoverageOutput : 8;
 
         SkBool8                     fUseFragShaderOnly;
         SkBool8                     fEmitsPointSize;
 
+        ColorInput                       fColorInput : 8;
+        ColorInput                       fCoverageInput : 8;
+
+        GrOptDrawState::PrimaryOutputType    fPrimaryOutputType : 8;
+        GrOptDrawState::SecondaryOutputType  fSecondaryOutputType : 8;
+
+
         // To enable experimental geometry shader code (not for use in
         // production)
 #if GR_GL_EXPERIMENTAL_GS
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 476f174..387741b 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -205,7 +205,7 @@
 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
 
 bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) {
-    SkAutoTUnref<GrOptDrawState> optState(this->getDrawState().createOptState());
+    SkAutoTUnref<GrOptDrawState> optState(this->getDrawState().createOptState(*this->caps()));
 
     // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true.
     SkASSERT(optState->getRenderTarget());
@@ -262,7 +262,6 @@
             fHWProgramID = programID;
         }
 
-        fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
         this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
 
         fCurrentProgram->setData(*optState.get(),
@@ -293,7 +292,7 @@
 }
 
 void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
-    SkAutoTUnref<GrOptDrawState> optState(this->getDrawState().createOptState());
+    SkAutoTUnref<GrOptDrawState> optState(this->getDrawState().createOptState(*this->caps()));
 
     GrGLsizei stride = static_cast<GrGLsizei>(optState->getVertexStride());
 
diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
index 730ce04..7279f1c 100644
--- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
@@ -304,18 +304,22 @@
 
     ///////////////////////////////////////////////////////////////////////////
     // write the secondary color output if necessary
-    if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
+    if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
         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) - inputColor.a());
-        } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput ==
-                   header.fCoverageOutput){
-            // Get (1-RGBA) into coeff
-            coeff = GrGLSLExpr4(1) - inputColor;
+        switch (header.fSecondaryOutputType) {
+            case GrOptDrawState::kCoverage_SecondaryOutputType:
+                break;
+            case GrOptDrawState::kCoverageISA_SecondaryOutputType:
+                // Get (1-A) into coeff
+                coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
+                break;
+            case GrOptDrawState::kCoverageISC_SecondaryOutputType:
+                // Get (1-RGBA) into coeff
+                coeff = GrGLSLExpr4(1) - inputColor;
+                break;
+            default:
+                SkFAIL("Unexpected Secondary Output");
         }
         // Get coeff * coverage into modulate and then write that to the dual source output.
         codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str());
@@ -326,13 +330,19 @@
 
     // Get "color * coverage" into fragColor
     GrGLSLExpr4 fragColor = inputColor * inputCoverage;
-    // 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) - inputCoverage;
-
-        GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor());
-
-        fragColor = fragColor + dstContribution;
+    switch (header.fPrimaryOutputType) {
+        case GrOptDrawState::kModulate_PrimaryOutputType:
+            break;
+        case GrOptDrawState::kCombineWithDst_PrimaryOutputType:
+            {
+                // Tack on "+(1-coverage)dst onto the frag color.
+                GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;
+                GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor());
+                fragColor = fragColor + dstContribution;
+            }
+            break;
+        default:
+            SkFAIL("Unknown Primary Output");
     }
     codeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str());
 }
diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
index ad61465..f99791e 100644
--- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
@@ -87,7 +87,9 @@
     // We pull the current state of attributes off of drawstate's optimized state and bind them in
     // order. This assumes that the drawState has not changed since we called flushGraphicsState()
     // higher up in the stack.
-    SkAutoTUnref<GrOptDrawState> optState(fProgramBuilder->gpu()->drawState()->createOptState());
+    const GrDrawTargetCaps* caps = fProgramBuilder->gpu()->caps();
+    const GrDrawState& drawState = *fProgramBuilder->gpu()->drawState();
+    SkAutoTUnref<GrOptDrawState> optState(drawState.createOptState(*caps));
     const GrVertexAttrib* vaPtr = optState->getVertexAttribs();
     const int vaCount = optState->getVertexAttribCount();