Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / gl / GrGLProgramDesc.cpp
index e1a3191..19a26c9 100644 (file)
  * found in the LICENSE file.
  */
 
+#include "gl/builders/GrGLProgramBuilder.h"
 #include "GrGLProgramDesc.h"
-#include "GrBackendEffectFactory.h"
-#include "GrDrawEffect.h"
-#include "GrEffect.h"
-#include "GrGLShaderBuilder.h"
+#include "GrBackendProcessorFactory.h"
+#include "GrProcessor.h"
 #include "GrGpuGL.h"
+#include "GrOptDrawState.h"
 
 #include "SkChecksum.h"
 
-bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
-                                                 const GrGLCaps& caps,
-                                                 bool useExplicitLocalCoords,
-                                                 GrEffectKeyBuilder* b,
-                                                 uint16_t* effectKeySize,
-                                                 bool* setTrueIfReadsDst,
-                                                 bool* setTrueIfReadsPos,
-                                                 bool* setTrueIfHasVertexCode) {
-    const GrBackendEffectFactory& factory = stage.getEffect()->getFactory();
-    GrDrawEffect drawEffect(stage, useExplicitLocalCoords);
-    if (stage.getEffect()->willReadDstColor()) {
-        *setTrueIfReadsDst = true;
+/**
+ * The key for an individual coord transform is made up of a matrix type and a bit that
+ * indicates the source of the input coords.
+ */
+enum {
+    kMatrixTypeKeyBits   = 1,
+    kMatrixTypeKeyMask   = (1 << kMatrixTypeKeyBits) - 1,
+    kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
+    kTransformKeyBits    = kMatrixTypeKeyBits + 1,
+};
+
+/**
+ * We specialize the vertex code for each of these matrix types.
+ */
+enum MatrixType {
+    kNoPersp_MatrixType  = 0,
+    kGeneral_MatrixType  = 1,
+};
+
+/**
+ * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
+ * present in the texture's config. swizzleComponentMask indicates the channels present in the
+ * shader swizzle.
+ */
+static bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
+                                             uint32_t configComponentMask,
+                                             uint32_t swizzleComponentMask) {
+    if (caps.textureSwizzleSupport()) {
+        // Any remapping is handled using texture swizzling not shader modifications.
+        return false;
+    }
+    // check if the texture is alpha-only
+    if (kA_GrColorComponentFlag == configComponentMask) {
+        if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
+            // we must map the swizzle 'a's to 'r'.
+            return true;
+        }
+        if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
+            // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
+            // alpha-only textures smear alpha across all four channels when read.
+            return true;
+        }
+    }
+    return false;
+}
+
+static uint32_t gen_attrib_key(const GrGeometryProcessor* effect) {
+    uint32_t key = 0;
+
+    const GrGeometryProcessor::VertexAttribArray& vars = effect->getVertexAttribs();
+    int numAttributes = vars.count();
+    SkASSERT(numAttributes <= 2);
+    for (int a = 0; a < numAttributes; ++a) {
+        uint32_t value = 1 << a;
+        key |= value;
+    }
+    return key;
+}
+
+static uint32_t gen_transform_key(const GrProcessorStage& effectStage,
+                                  bool useExplicitLocalCoords) {
+    uint32_t totalKey = 0;
+    int numTransforms = effectStage.getProcessor()->numTransforms();
+    for (int t = 0; t < numTransforms; ++t) {
+        uint32_t key = 0;
+        if (effectStage.isPerspectiveCoordTransform(t, useExplicitLocalCoords)) {
+            key |= kGeneral_MatrixType;
+        } else {
+            key |= kNoPersp_MatrixType;
+        }
+
+        const GrCoordTransform& coordTransform = effectStage.getProcessor()->coordTransform(t);
+        if (kLocal_GrCoordSet != coordTransform.sourceCoords() && useExplicitLocalCoords) {
+            key |= kPositionCoords_Flag;
+        }
+        key <<= kTransformKeyBits * t;
+        SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
+        totalKey |= key;
+    }
+    return totalKey;
+}
+
+static uint32_t gen_texture_key(const GrProcessor* effect, const GrGLCaps& caps) {
+    uint32_t key = 0;
+    int numTextures = effect->numTextures();
+    for (int t = 0; t < numTextures; ++t) {
+        const GrTextureAccess& access = effect->textureAccess(t);
+        uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
+        if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
+            key |= 1 << t;
+        }
     }
-    if (stage.getEffect()->willReadFragmentPosition()) {
-        *setTrueIfReadsPos = true;
+    return key;
+}
+
+/**
+ * A function which emits a meta key into the key builder.  This is required because shader code may
+ * be dependent on properties of the effect that the effect itself doesn't use
+ * in its key (e.g. the pixel format of textures used). So we create a meta-key for
+ * every effect using this function. It is also responsible for inserting the effect's class ID
+ * which must be different for every GrProcessor subclass. It can fail if an effect uses too many
+ * textures, transforms, etc, for the space allotted in the meta-key.
+ */
+
+static uint32_t* get_processor_meta_key(const GrProcessorStage& processorStage,
+                                        bool useExplicitLocalCoords,
+                                        const GrGLCaps& caps,
+                                        GrProcessorKeyBuilder* b) {
+
+    uint32_t textureKey = gen_texture_key(processorStage.getProcessor(), caps);
+    uint32_t transformKey = gen_transform_key(processorStage,useExplicitLocalCoords);
+    uint32_t classID = processorStage.getProcessor()->getFactory().effectClassID();
+
+    // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
+    // don't fit.
+    static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
+    if ((textureKey | transformKey | classID) & kMetaKeyInvalidMask) {
+        return NULL;
     }
-    if (stage.getEffect()->hasVertexCode()) {
-        *setTrueIfHasVertexCode = true;
+
+    uint32_t* key = b->add32n(2);
+    key[0] = (textureKey << 16 | transformKey);
+    key[1] = (classID << 16);
+    return key;
+}
+
+bool GrGLProgramDesc::GetProcessorKey(const GrProcessorStage& stage,
+                                      const GrGLCaps& caps,
+                                      bool useExplicitLocalCoords,
+                                      GrProcessorKeyBuilder* b,
+                                      uint16_t* processorKeySize) {
+    const GrProcessor& effect = *stage.getProcessor();
+    const GrBackendProcessorFactory& factory = effect.getFactory();
+    factory.getGLProcessorKey(effect, caps, b);
+    size_t size = b->size();
+    if (size > SK_MaxU16) {
+        *processorKeySize = 0; // suppresses a warning.
+        return false;
     }
-    factory.getGLEffectKey(drawEffect, caps, b);
+    *processorKeySize = SkToU16(size);
+    if (NULL == get_processor_meta_key(stage, useExplicitLocalCoords, caps, b)) {
+        return false;
+    }
+    return true;
+}
+
+bool GrGLProgramDesc::GetGeometryProcessorKey(const GrGeometryStage& stage,
+                                              const GrGLCaps& caps,
+                                              bool useExplicitLocalCoords,
+                                              GrProcessorKeyBuilder* b,
+                                              uint16_t* processorKeySize) {
+    const GrProcessor& effect = *stage.getProcessor();
+    const GrBackendProcessorFactory& factory = effect.getFactory();
+    factory.getGLProcessorKey(effect, caps, b);
     size_t size = b->size();
     if (size > SK_MaxU16) {
-        *effectKeySize = 0; // suppresses a warning.
+        *processorKeySize = 0; // suppresses a warning.
         return false;
     }
-    *effectKeySize = SkToU16(size);
-    if (!GrGLProgramEffects::GenEffectMetaKey(drawEffect, caps, b)) {
+    *processorKeySize = SkToU16(size);
+    uint32_t* key = get_processor_meta_key(stage, useExplicitLocalCoords, caps, b);
+    if (NULL == key) {
         return false;
     }
+    uint32_t attribKey = gen_attrib_key(stage.getGeometryProcessor());
+
+    // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
+    // don't fit.
+    static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
+    if ((attribKey) & kMetaKeyInvalidMask) {
+       return false;
+    }
+
+    key[1] |= attribKey;
     return true;
 }
 
-bool GrGLProgramDesc::Build(const GrDrawState& drawState,
+
+bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
                             GrGpu::DrawType drawType,
-                            GrDrawState::BlendOptFlags blendOpts,
                             GrBlendCoeff srcCoeff,
                             GrBlendCoeff dstCoeff,
-                            const GrGpuGL* gpu,
+                            GrGpuGL* gpu,
                             const GrDeviceCoordTexture* dstCopy,
-                            SkTArray<const GrEffectStage*, true>* colorStages,
-                            SkTArray<const GrEffectStage*, true>* coverageStages,
+                            const GrGeometryStage** geometryProcessor,
+                            SkTArray<const GrFragmentStage*, true>* colorStages,
+                            SkTArray<const GrFragmentStage*, true>* coverageStages,
                             GrGLProgramDesc* desc) {
     colorStages->reset();
     coverageStages->reset();
 
-    // This should already have been caught
-    SkASSERT(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts));
-
-    bool skipCoverage = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
-
-    bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag |
-                                           GrDrawState::kEmitCoverage_BlendOptFlag));
-
-    int firstEffectiveColorStage = 0;
-    bool inputColorIsUsed = true;
-    if (!skipColor) {
-        firstEffectiveColorStage = drawState.numColorStages();
-        while (firstEffectiveColorStage > 0 && inputColorIsUsed) {
-            --firstEffectiveColorStage;
-            const GrEffect* effect = drawState.getColorStage(firstEffectiveColorStage).getEffect();
-            inputColorIsUsed = effect->willUseInputColor();
-        }
-    }
-
-    int firstEffectiveCoverageStage = 0;
-    bool inputCoverageIsUsed = true;
-    if (!skipCoverage) {
-        firstEffectiveCoverageStage = drawState.numCoverageStages();
-        while (firstEffectiveCoverageStage > 0 && inputCoverageIsUsed) {
-            --firstEffectiveCoverageStage;
-            const GrEffect* effect = drawState.getCoverageStage(firstEffectiveCoverageStage).getEffect();
-            inputCoverageIsUsed = effect->willUseInputColor();
-        }
-    }
+    bool inputColorIsUsed = optState.inputColorIsUsed();
+    bool inputCoverageIsUsed = optState.inputCoverageIsUsed();
 
     // The descriptor is used as a cache key. Thus when a field of the
     // descriptor will not affect program generation (because of the attribute
     // bindings in use or other descriptor field settings) it should be set
     // to a canonical value to avoid duplicate programs with different keys.
 
-    bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute();
-    bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute();
-    // we only need the local coords if we're actually going to generate effect code
-    bool requiresLocalCoordAttrib = !(skipCoverage  && skipColor) &&
-                                    drawState.hasLocalCoordAttribute();
-
-    bool readsDst = false;
-    bool readFragPosition = false;
-    // We use vertexshader-less shader programs only when drawing paths.
-    bool hasVertexCode = !(GrGpu::kDrawPath_DrawType == drawType ||
-                           GrGpu::kDrawPaths_DrawType == drawType);
-    int numStages = 0;
-    if (!skipColor) {
-        numStages += drawState.numColorStages() - firstEffectiveColorStage;
-    }
-    if (!skipCoverage) {
-        numStages += drawState.numCoverageStages() - firstEffectiveCoverageStage;
-    }
+    bool requiresLocalCoordAttrib = optState.requiresLocalCoordAttrib();
+
+    int numStages = optState.numTotalStages();
+
     GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t));
     // Make room for everything up to and including the array of offsets to effect keys.
     desc->fKey.reset();
@@ -119,62 +224,78 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
 
     int offsetAndSizeIndex = 0;
 
-    bool effectKeySuccess = true;
-    if (!skipColor) {
-        for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
-            uint16_t* offsetAndSize =
+    KeyHeader* header = desc->header();
+    // make sure any padding in the header is zeroed.
+    memset(desc->header(), 0, kHeaderSize);
+
+    // We can only have one effect which touches the vertex shader
+    if (optState.hasGeometryProcessor()) {
+        uint16_t* offsetAndSize =
                 reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
                                             offsetAndSizeIndex * 2 * sizeof(uint16_t));
 
-            GrEffectKeyBuilder b(&desc->fKey);
-            uint16_t effectKeySize;
-            uint32_t effectOffset = desc->fKey.count();
-            effectKeySuccess |= GetEffectKeyAndUpdateStats(
-                                    drawState.getColorStage(s), gpu->glCaps(),
-                                    requiresLocalCoordAttrib, &b,
-                                    &effectKeySize, &readsDst,
-                                    &readFragPosition, &hasVertexCode);
-            effectKeySuccess |= (effectOffset <= SK_MaxU16);
-
-            offsetAndSize[0] = SkToU16(effectOffset);
-            offsetAndSize[1] = effectKeySize;
-            ++offsetAndSizeIndex;
+        GrProcessorKeyBuilder b(&desc->fKey);
+        uint16_t processorKeySize;
+        uint32_t processorOffset = desc->fKey.count();
+        const GrGeometryStage& gpStage = *optState.getGeometryProcessor();
+        if (processorOffset > SK_MaxU16 ||
+                !GetGeometryProcessorKey(gpStage, gpu->glCaps(), requiresLocalCoordAttrib, &b,
+                                         &processorKeySize)) {
+            desc->fKey.reset();
+            return false;
         }
+
+        offsetAndSize[0] = SkToU16(processorOffset);
+        offsetAndSize[1] = processorKeySize;
+        ++offsetAndSizeIndex;
+        *geometryProcessor = &gpStage;
+        header->fHasGeometryProcessor = true;
     }
-    if (!skipCoverage) {
-        for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
-            uint16_t* offsetAndSize =
-                reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
-                                            offsetAndSizeIndex * 2 * sizeof(uint16_t));
 
-            GrEffectKeyBuilder b(&desc->fKey);
-            uint16_t effectKeySize;
-            uint32_t effectOffset = desc->fKey.count();
-            effectKeySuccess |= GetEffectKeyAndUpdateStats(
-                                    drawState.getCoverageStage(s), gpu->glCaps(),
-                                    requiresLocalCoordAttrib, &b,
-                                    &effectKeySize, &readsDst,
-                                    &readFragPosition, &hasVertexCode);
-            effectKeySuccess |= (effectOffset <= SK_MaxU16);
-
-            offsetAndSize[0] = SkToU16(effectOffset);
-            offsetAndSize[1] = effectKeySize;
-            ++offsetAndSizeIndex;
+    for (int s = 0; s < optState.numColorStages(); ++s) {
+        uint16_t* offsetAndSize =
+            reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
+                                        offsetAndSizeIndex * 2 * sizeof(uint16_t));
+
+        GrProcessorKeyBuilder b(&desc->fKey);
+        uint16_t processorKeySize;
+        uint32_t processorOffset = desc->fKey.count();
+        if (processorOffset > SK_MaxU16 ||
+                !GetProcessorKey(optState.getColorStage(s), gpu->glCaps(),
+                                 requiresLocalCoordAttrib, &b, &processorKeySize)) {
+            desc->fKey.reset();
+            return false;
         }
-    }
-    if (!effectKeySuccess) {
-        desc->fKey.reset();
-        return false;
+
+        offsetAndSize[0] = SkToU16(processorOffset);
+        offsetAndSize[1] = processorKeySize;
+        ++offsetAndSizeIndex;
     }
 
-    KeyHeader* header = desc->header();
-    // make sure any padding in the header is zeroed.
-    memset(desc->header(), 0, kHeaderSize);
+    for (int s = 0; s < optState.numCoverageStages(); ++s) {
+        uint16_t* offsetAndSize =
+            reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
+                                        offsetAndSizeIndex * 2 * sizeof(uint16_t));
+
+        GrProcessorKeyBuilder b(&desc->fKey);
+        uint16_t processorKeySize;
+        uint32_t processorOffset = desc->fKey.count();
+        if (processorOffset > SK_MaxU16 ||
+                !GetProcessorKey(optState.getCoverageStage(s), gpu->glCaps(),
+                                 requiresLocalCoordAttrib, &b, &processorKeySize)) {
+            desc->fKey.reset();
+            return false;
+        }
+
+        offsetAndSize[0] = SkToU16(processorOffset);
+        offsetAndSize[1] = processorKeySize;
+        ++offsetAndSizeIndex;
+    }
 
     // Because header is a pointer into the dynamic array, we can't push any new data into the key
     // below here.
 
-    header->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib;
+
     header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType;
 
     // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
@@ -186,53 +307,68 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
     header->fExperimentalGS = false;
 #endif
 #endif
-    bool defaultToUniformInputs = GR_GL_NO_CONSTANT_ATTRIBUTES || gpu->caps()->pathRenderingSupport();
 
-    if (defaultToUniformInputs && !requiresColorAttrib && inputColorIsUsed) {
+    if (gpu->caps()->pathRenderingSupport() &&
+        GrGpu::IsPathRenderingDrawType(drawType) &&
+        gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode) {
+        header->fUseFragShaderOnly = true;
+        SkASSERT(!optState.hasGeometryProcessor());
+    } else {
+        header->fUseFragShaderOnly = false;
+    }
+
+    bool defaultToUniformInputs = GrGpu::IsPathRenderingDrawType(drawType) ||
+                                  GR_GL_NO_CONSTANT_ATTRIBUTES;
+
+    if (!inputColorIsUsed) {
+        header->fColorInput = kAllOnes_ColorInput;
+    } else if (defaultToUniformInputs && !optState.hasColorVertexAttribute()) {
         header->fColorInput = kUniform_ColorInput;
     } else {
         header->fColorInput = kAttribute_ColorInput;
-        header->fHasVertexCode = true;
+        SkASSERT(!header->fUseFragShaderOnly);
     }
 
-    bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor();
+    bool covIsSolidWhite = !optState.hasCoverageVertexAttribute() &&
+                           0xffffffff == optState.getCoverageColor();
 
-    if ((covIsSolidWhite || !inputCoverageIsUsed) && !skipCoverage) {
-        header->fCoverageInput = kSolidWhite_ColorInput;
-    } else if (defaultToUniformInputs && !requiresCoverageAttrib && inputCoverageIsUsed) {
+    if (covIsSolidWhite || !inputCoverageIsUsed) {
+        header->fCoverageInput = kAllOnes_ColorInput;
+    } else if (defaultToUniformInputs && !optState.hasCoverageVertexAttribute()) {
         header->fCoverageInput = kUniform_ColorInput;
     } else {
         header->fCoverageInput = kAttribute_ColorInput;
-        header->fHasVertexCode = true;
+        SkASSERT(!header->fUseFragShaderOnly);
     }
 
-    if (readsDst) {
-        SkASSERT(NULL != dstCopy || gpu->caps()->dstReadInShaderSupport());
+    if (optState.readsDst()) {
+        SkASSERT(dstCopy || gpu->caps()->dstReadInShaderSupport());
         const GrTexture* dstCopyTexture = NULL;
-        if (NULL != dstCopy) {
+        if (dstCopy) {
             dstCopyTexture = dstCopy->texture();
         }
-        header->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps());
+        header->fDstReadKey = GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture,
+                gpu->glCaps());
         SkASSERT(0 != header->fDstReadKey);
     } else {
         header->fDstReadKey = 0;
     }
 
-    if (readFragPosition) {
-        header->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(drawState.getRenderTarget(),
-                                                                      gpu->glCaps());
+    if (optState.readsFragPosition()) {
+        header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition(
+                optState.getRenderTarget(), gpu->glCaps());
     } else {
         header->fFragPosKey = 0;
     }
 
     // Record attribute indices
-    header->fPositionAttributeIndex = drawState.positionAttributeIndex();
-    header->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
+    header->fPositionAttributeIndex = optState.positionAttributeIndex();
+    header->fLocalCoordAttributeIndex = optState.localCoordAttributeIndex();
 
     // For constant color and coverage we need an attribute with an index beyond those already set
-    int availableAttributeIndex = drawState.getVertexAttribCount();
-    if (requiresColorAttrib) {
-        header->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
+    int availableAttributeIndex = optState.getVertexAttribCount();
+    if (optState.hasColorVertexAttribute()) {
+        header->fColorAttributeIndex = optState.colorVertexAttributeIndex();
     } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) {
         SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
         header->fColorAttributeIndex = availableAttributeIndex;
@@ -241,8 +377,8 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
         header->fColorAttributeIndex = -1;
     }
 
-    if (requiresCoverageAttrib) {
-        header->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
+    if (optState.hasCoverageVertexAttribute()) {
+        header->fCoverageAttributeIndex = optState.coverageVertexAttributeIndex();
     } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) {
         SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
         header->fCoverageAttributeIndex = availableAttributeIndex;
@@ -250,55 +386,16 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
         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 = false;
-    if (!drawState.isCoverageDrawing() && !skipCoverage &&
-        (drawState.numCoverageStages() > 0 || requiresCoverageAttrib)) {
-
-        if (gpu->caps()->dualSourceBlendingSupport() &&
-            !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
-                           GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
-            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 (readsDst &&
-                   kOne_GrBlendCoeff == srcCoeff &&
-                   kZero_GrBlendCoeff == dstCoeff) {
-            header->fCoverageOutput = kCombineWithDst_CoverageOutput;
-            separateCoverageFromColor = true;
-        }
-    }
-    if (!skipColor) {
-        for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
-            colorStages->push_back(&drawState.getColorStage(s));
-        }
+    header->fPrimaryOutputType = optState.getPrimaryOutputType();
+    header->fSecondaryOutputType = optState.getSecondaryOutputType();
+
+    for (int s = 0; s < optState.numColorStages(); ++s) {
+        colorStages->push_back(&optState.getColorStage(s));
     }
-    if (!skipCoverage) {
-        SkTArray<const GrEffectStage*, true>* array;
-        if (separateCoverageFromColor) {
-            array = coverageStages;
-        } else {
-            array = colorStages;
-        }
-        for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
-            array->push_back(&drawState.getCoverageStage(s));
-        }
+    for (int s = 0; s < optState.numCoverageStages(); ++s) {
+        coverageStages->push_back(&optState.getCoverageStage(s));
     }
+
     header->fColorEffectCnt = colorStages->count();
     header->fCoverageEffectCnt = coverageStages->count();