Revert of Attach GrOptDrawState into shader building pipeline (patchset #11 id:220001 of https://codereview.chromium.org/504203004/)

Reason for revert:
Failing some msaa gm's

Original issue's description:
> Attach GrOptDrawState into shader building pipeline
>
> The OptDrawState is now used for creating the actual gl shader. Current
> optimizations dones in GrOptDrawState include:
> All blend optimizations
> Constant color/coverage stage optimizations
>
> BUG=skia:
>
> Committed: https://skia.googlesource.com/skia/+/ee6206572b42fec11f83ad0c1e6d435903640518

R=bsalomon@google.com, joshualitt@google.com
TBR=bsalomon@google.com, joshualitt@google.com
NOTREECHECKS=true
NOTRY=true
BUG=skia:

Author: egdaniel@google.com

Review URL: https://codereview.chromium.org/560443004
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index f639744..642ec26 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -15,17 +15,9 @@
 
 GrOptDrawState* GrDrawState::createOptState() const {
     if (NULL == fCachedOptState) {
-        GrBlendCoeff srcCoeff;
-        GrBlendCoeff dstCoeff;
-        BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
-        fCachedOptState = SkNEW_ARGS(GrOptDrawState, (*this, blendFlags, srcCoeff, dstCoeff));
+        fCachedOptState = SkNEW_ARGS(GrOptDrawState, (*this));
     } else {
-#ifdef SK_DEBUG
-        GrBlendCoeff srcCoeff;
-        GrBlendCoeff dstCoeff;
-        BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
-        SkASSERT(GrOptDrawState(*this, blendFlags, srcCoeff, dstCoeff) == *fCachedOptState);
-#endif
+        SkASSERT(GrOptDrawState(*this) == *fCachedOptState);
     }
     fCachedOptState->ref();
     return fCachedOptState;
@@ -114,6 +106,9 @@
     }
     fColorStages = that.fColorStages;
     fCoverageStages = that.fCoverageStages;
+    fOptSrcBlend = that.fOptSrcBlend;
+    fOptDstBlend = that.fOptDstBlend;
+    fBlendOptFlags = that.fBlendOptFlags;
 
     fHints = that.fHints;
 
@@ -304,7 +299,7 @@
     // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
     GrBlendCoeff srcCoeff;
     GrBlendCoeff dstCoeff;
-    BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
+    GrRODrawState::BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
     return GrRODrawState::kNone_BlendOpt != flag ||
            (this->willEffectReadDstColor() &&
             kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
@@ -460,16 +455,3 @@
     }
 }
 
-////////////////////////////////////////////////////////////////////////////////
-
-void GrDrawState::invalidateOptState() const {
-    SkSafeSetNull(fCachedOptState);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-GrDrawState::~GrDrawState() {
-    SkSafeUnref(fCachedOptState);
-    SkASSERT(0 == fBlockEffectRemovalCnt);
-}
-
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 4869658..6a1e380 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -9,12 +9,11 @@
 #define GrDrawState_DEFINED
 
 #include "GrBlend.h"
+#include "GrOptDrawState.h"
 #include "GrProgramResource.h"
 #include "GrRODrawState.h"
 #include "effects/GrSimpleTextureEffect.h"
 
-class GrOptDrawState;
-
 /**
  * Modifiable subclass derived from GrRODrawState. The majority of the data that represents a draw
  * state is stored in the parent class. GrDrawState contains methods for setting, adding to, etc.
@@ -48,7 +47,10 @@
      **/
     GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix);
 
-    virtual ~GrDrawState();
+    virtual ~GrDrawState() {
+        SkSafeUnref(fCachedOptState);
+        SkASSERT(0 == fBlockEffectRemovalCnt);
+    }
 
     /**
      * Resets to the default state. GrEffects will be removed from all stages.
@@ -550,10 +552,17 @@
     GrOptDrawState* createOptState() const;
 
 private:
-    void invalidateOptState() const;
+    void invalidateOptState() const {
+        SkSafeSetNull(fCachedOptState);
+        fBlendOptFlags = kInvalid_BlendOptFlag;
+    }
 
     void onReset(const SkMatrix* initialViewMatrix);
 
+    void invalidateBlendOptFlags() {
+        fBlendOptFlags = kInvalid_BlendOptFlag;
+    }
+
     // Some of the auto restore objects assume that no effects are removed during their lifetime.
     // This is used to assert that this condition holds.
     SkDEBUGCODE(int fBlockEffectRemovalCnt;)
diff --git a/src/gpu/GrOptDrawState.cpp b/src/gpu/GrOptDrawState.cpp
index 5f35296..83546ba 100644
--- a/src/gpu/GrOptDrawState.cpp
+++ b/src/gpu/GrOptDrawState.cpp
@@ -9,10 +9,7 @@
 
 #include "GrDrawState.h"
 
-GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
-                               BlendOptFlags blendOptFlags,
-                               GrBlendCoeff optSrcCoeff,
-                               GrBlendCoeff optDstCoeff) : INHERITED(drawState) {
+GrOptDrawState::GrOptDrawState(const GrDrawState& drawState) : INHERITED(drawState) {
     fColor = drawState.getColor();
     fCoverage = drawState.getCoverage();
     fViewMatrix = drawState.getViewMatrix();
@@ -23,15 +20,13 @@
     fVAStride = drawState.getVertexStride();
     fStencilSettings = drawState.getStencil();
     fDrawFace = drawState.getDrawFace();
-    fBlendOptFlags = blendOptFlags;
-    fSrcBlend = optSrcCoeff;
-    fDstBlend = optDstCoeff;
+
+    fBlendOptFlags = drawState.getBlendOpts(false, &fSrcBlend, &fDstBlend);
 
     memcpy(fFixedFunctionVertexAttribIndices,
             drawState.getFixedFunctionVertexAttribIndices(),
             sizeof(fFixedFunctionVertexAttribIndices));
 
-
     fInputColorIsUsed = true;
     fInputCoverageIsUsed = true;
 
@@ -43,40 +38,8 @@
 
     this->copyEffectiveColorStages(drawState);
     this->copyEffectiveCoverageStages(drawState);
-    this->adjustFromBlendOpts();
 };
 
-void GrOptDrawState::adjustFromBlendOpts() {
-
-    switch (fBlendOptFlags) {
-        case kNone_BlendOpt:
-        case kSkipDraw_BlendOptFlag:
-            break;
-        case kCoverageAsAlpha_BlendOptFlag:
-            fFlagBits |= kCoverageDrawing_StateBit;
-            break;
-        case kEmitCoverage_BlendOptFlag:
-            fColor = 0xffffffff;
-            fInputColorIsUsed = true;
-            fColorStages.reset();
-            this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding);
-            break;
-        case kEmitTransBlack_BlendOptFlag:
-            fColor = 0;
-            fCoverage = 0xff;
-            fInputColorIsUsed = true;
-            fInputCoverageIsUsed = true;
-            fColorStages.reset();
-            fCoverageStages.reset();
-            this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding |
-                                                   0x1 << kCoverage_GrVertexAttribBinding);
-            break;
-        default:
-            SkFAIL("Unknown BlendOptFlag");
-
-    }
-}
-
 void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) {
     int numToRemove = 0;
     uint8_t maskCheck = 0x1;
@@ -87,7 +50,6 @@
         }
         maskCheck <<= 1;
     }
-
     fOptVA.reset(fVACount - numToRemove);
 
     GrVertexAttrib* dst = fOptVA.get();
@@ -102,9 +64,9 @@
                 fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1;
                 continue;
             }
-            fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
         }
         memcpy(dst, src, sizeof(GrVertexAttrib));
+        fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
         ++newIdx;
         ++dst;
     }
diff --git a/src/gpu/GrOptDrawState.h b/src/gpu/GrOptDrawState.h
index 457f035..a4edc01 100644
--- a/src/gpu/GrOptDrawState.h
+++ b/src/gpu/GrOptDrawState.h
@@ -8,9 +8,10 @@
 #ifndef GrOptDrawState_DEFINED
 #define GrOptDrawState_DEFINED
 
-#include "GrDrawState.h"
 #include "GrRODrawState.h"
 
+class GrDrawState;
+
 /**
  * Subclass of GrRODrawState that holds an optimized version of a GrDrawState. Like it's parent
  * it is meant to be an immutable class, and simply adds a few helpful data members not in the
@@ -18,19 +19,15 @@
  */
 class GrOptDrawState : public GrRODrawState {
 public:
-    bool operator== (const GrOptDrawState& that) const;
-
-    bool inputColorIsUsed() const { return fInputColorIsUsed; }
-    bool inputCoverageIsUsed() const { return fInputCoverageIsUsed; }
-
-private:
     /**
      * Constructs and optimized drawState out of a GrRODrawState.
      */
-    GrOptDrawState(const GrDrawState& drawState, BlendOptFlags blendOptFlags,
-                   GrBlendCoeff optSrcCoeff, GrBlendCoeff optDstCoeff);
+    explicit GrOptDrawState(const GrDrawState& drawState);
 
-    /**
+    bool operator== (const GrOptDrawState& that) const;
+
+private:
+    /*
      * Loops through all the color stage effects to check if the stage will ignore color input or
      * always output a constant color. In the ignore color input case we can ignore all previous
      * stages. In the constant color case, we can ignore all previous stages and
@@ -40,7 +37,7 @@
      */
     void copyEffectiveColorStages(const GrDrawState& ds);
 
-    /**
+    /*
      * Loops through all the coverage stage effects to check if the stage will ignore color input.
      * If a coverage stage will ignore input, then we can ignore all coverage stages before it. We
      * loop to determine the first effective coverage stage, and then copy all of our effective
@@ -48,18 +45,14 @@
      */
     void copyEffectiveCoverageStages(const GrDrawState& ds);
 
-    /**
+    /*
      * This function takes in a flag and removes the corresponding fixed function vertex attributes.
      * The flags are in the same order as GrVertexAttribBinding array. If bit i of removeVAFlags is
      * set, then vertex attributes with binding (GrVertexAttribute)i will be removed.
      */
     void removeFixedFunctionVertexAttribs(uint8_t removeVAFlags);
 
-    /**
-     * Alter the OptDrawState (adjusting stages, vertex attribs, flags, etc.) based on the
-     * BlendOptFlags.
-     */
-    void adjustFromBlendOpts();
+    void removeColorVertexAttrib();
 
     // These flags are needed to protect the code from creating an unused uniform color/coverage
     // which will cause shader compiler errors.
@@ -68,9 +61,6 @@
 
     SkAutoSTArray<4, GrVertexAttrib> fOptVA;
 
-    BlendOptFlags   fBlendOptFlags;
-
-    friend GrOptDrawState* GrDrawState::createOptState() const;
     typedef GrRODrawState INHERITED;
 };
 
diff --git a/src/gpu/GrRODrawState.cpp b/src/gpu/GrRODrawState.cpp
index e522008..f7e486f 100644
--- a/src/gpu/GrRODrawState.cpp
+++ b/src/gpu/GrRODrawState.cpp
@@ -184,6 +184,26 @@
         dstCoeff = &bogusDstCoeff;
     }
 
+    if (forceCoverage) {
+        return this->calcBlendOpts(true, srcCoeff, dstCoeff);
+    }
+
+    if (0 == (fBlendOptFlags & kInvalid_BlendOptFlag)) {
+        *srcCoeff = fOptSrcBlend;
+        *dstCoeff = fOptDstBlend;
+        return fBlendOptFlags;
+    }
+
+    fBlendOptFlags = this->calcBlendOpts(forceCoverage, srcCoeff, dstCoeff);
+    fOptSrcBlend = *srcCoeff;
+    fOptDstBlend = *dstCoeff;
+
+    return fBlendOptFlags;
+}
+
+GrRODrawState::BlendOptFlags GrRODrawState::calcBlendOpts(bool forceCoverage,
+                                                          GrBlendCoeff* srcCoeff,
+                                                          GrBlendCoeff* dstCoeff) const {
     *srcCoeff = this->getSrcBlendCoeff();
     *dstCoeff = this->getDstBlendCoeff();
 
@@ -352,3 +372,13 @@
     return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color);
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
+bool GrRODrawState::canIgnoreColorAttribute() const {
+    if (fBlendOptFlags & kInvalid_BlendOptFlag) {
+        this->getBlendOpts();
+    }
+    return SkToBool(fBlendOptFlags & (GrRODrawState::kEmitTransBlack_BlendOptFlag |
+                                      GrRODrawState::kEmitCoverage_BlendOptFlag));
+}
+
diff --git a/src/gpu/GrRODrawState.h b/src/gpu/GrRODrawState.h
index eea6f9b..d748e7d 100644
--- a/src/gpu/GrRODrawState.h
+++ b/src/gpu/GrRODrawState.h
@@ -167,12 +167,68 @@
     GrColor getBlendConstant() const { return fBlendConstant; }
 
     /**
+     * We don't use supplied vertex color attributes if our blend mode is EmitCoverage or
+     * EmitTransBlack
+     */
+    bool canIgnoreColorAttribute() const;
+
+    /**
      * Determines whether multiplying the computed per-pixel color by the pixel's fractional
      * coverage before the blend will give the correct final destination color. In general it
      * will not as coverage is applied after blending.
      */
     bool canTweakAlphaForCoverage() const;
 
+    /**
+     * Optimizations for blending / coverage to that can be applied based on the current state.
+     */
+    enum BlendOptFlags {
+        /**
+         * No optimization
+         */
+        kNone_BlendOpt                  = 0,
+        /**
+         * Don't draw at all
+         */
+        kSkipDraw_BlendOptFlag          = 0x1,
+        /**
+         * The coverage value does not have to be computed separately from alpha, the output
+         * color can be the modulation of the two.
+         */
+        kCoverageAsAlpha_BlendOptFlag   = 0x2,
+        /**
+         * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
+         * "don't cares".
+         */
+        kEmitCoverage_BlendOptFlag      = 0x4,
+        /**
+         * Emit transparent black instead of the src color, no need to compute coverage.
+         */
+        kEmitTransBlack_BlendOptFlag    = 0x8,
+        /**
+         * Flag used to invalidate the cached BlendOptFlags, OptSrcCoeff, and OptDstCoeff cached by
+         * the get BlendOpts function.
+         */
+        kInvalid_BlendOptFlag           = 1 << 31,
+    };
+    GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
+
+    /**
+     * Determines what optimizations can be applied based on the blend. The coefficients may have
+     * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
+     * params that receive the tweaked coefficients. Normally the function looks at the current
+     * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
+     * determine the blend optimizations that would be used if there was partial pixel coverage.
+     *
+     * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
+     * playback) must call this function and respect the flags that replace the output color.
+     *
+     * If the cached BlendOptFlags does not have the invalidate bit set, then getBlendOpts will
+     * simply returned the cached flags and coefficients. Otherwise it will calculate the values. 
+     */
+    BlendOptFlags getBlendOpts(bool forceCoverage = false,
+                               GrBlendCoeff* srcCoeff = NULL,
+                               GrBlendCoeff* dstCoeff = NULL) const;
     /// @}
 
     ///////////////////////////////////////////////////////////////////////////
@@ -351,52 +407,6 @@
 
     bool isEqual(const GrRODrawState& that) const;
 
-    /**
-     * Optimizations for blending / coverage to that can be applied based on the current state.
-     */
-    enum BlendOptFlags {
-        /**
-         * No optimization
-         */
-        kNone_BlendOpt                  = 0,
-        /**
-         * Don't draw at all
-         */
-        kSkipDraw_BlendOptFlag          = 0x1,
-        /**
-         * The coverage value does not have to be computed separately from alpha, the the output
-         * color can be the modulation of the two.
-         */
-        kCoverageAsAlpha_BlendOptFlag   = 0x2,
-        /**
-         * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
-         * "don't cares".
-         */
-        kEmitCoverage_BlendOptFlag      = 0x4,
-        /**
-         * Emit transparent black instead of the src color, no need to compute coverage.
-         */
-        kEmitTransBlack_BlendOptFlag    = 0x8,
-    };
-    GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
-
-    /**
-     * Determines what optimizations can be applied based on the blend. The coefficients may have
-     * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
-     * params that receive the tweaked coefficients. Normally the function looks at the current
-     * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
-     * determine the blend optimizations that would be used if there was partial pixel coverage.
-     *
-     * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
-     * playback) must call this function and respect the flags that replace the output color.
-     *
-     * If the cached BlendOptFlags does not have the invalidate bit set, then getBlendOpts will
-     * simply returned the cached flags and coefficients. Otherwise it will calculate the values. 
-     */
-    BlendOptFlags getBlendOpts(bool forceCoverage = false,
-                               GrBlendCoeff* srcCoeff = NULL,
-                               GrBlendCoeff* dstCoeff = NULL) const;
-
     // These fields are roughly sorted by decreasing likelihood of being different in op==
     GrProgramResource                   fRenderTarget;
     GrColor                             fColor;
@@ -419,6 +429,10 @@
 
     uint32_t                            fHints;
 
+    mutable GrBlendCoeff                fOptSrcBlend;
+    mutable GrBlendCoeff                fOptDstBlend;
+    mutable BlendOptFlags               fBlendOptFlags;
+
     // This is simply a different representation of info in fVertexAttribs and thus does
     // not need to be compared in op==.
     int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
@@ -429,6 +443,13 @@
      */
     bool srcAlphaWillBeOne() const;
 
+    /**
+     * Helper function for getBlendOpts.
+     */
+    BlendOptFlags calcBlendOpts(bool forceCoverage = false,
+                                GrBlendCoeff* srcCoeff = NULL,
+                                GrBlendCoeff* dstCoeff = NULL) const;
+
     typedef SkRefCnt INHERITED;
 };
 
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 96c5367..916c31c 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+
 #include "GrGLProgram.h"
 
 #include "GrAllocator.h"
@@ -15,7 +16,6 @@
 #include "GrGLPathRendering.h"
 #include "GrGLShaderVar.h"
 #include "GrGLSL.h"
-#include "GrOptDrawState.h"
 #include "SkXfermode.h"
 
 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
@@ -109,19 +109,31 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrGLProgram::setData(const GrOptDrawState& optState,
-                          GrGpu::DrawType drawType,
+void GrGLProgram::setData(GrGpu::DrawType drawType,
+                          GrDrawState::BlendOptFlags blendOpts,
                           const GrEffectStage* geometryProcessor,
                           const GrEffectStage* colorStages[],
                           const GrEffectStage* coverageStages[],
                           const GrDeviceCoordTexture* dstCopy,
                           SharedGLState* sharedState) {
-    GrColor color = optState.getColor();
-    GrColor coverage = optState.getCoverageColor();
+    const GrDrawState& drawState = fGpu->getDrawState();
 
-    this->setColor(optState, color, sharedState);
-    this->setCoverage(optState, coverage, sharedState);
-    this->setMatrixAndRenderTargetHeight(drawType, optState);
+    GrColor color;
+    GrColor coverage;
+    if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
+        color = 0;
+        coverage = 0;
+    } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
+        color = 0xffffffff;
+        coverage = drawState.getCoverageColor();
+    } else {
+        color = drawState.getColor();
+        coverage = drawState.getCoverageColor();
+    }
+
+    this->setColor(drawState, color, sharedState);
+    this->setCoverage(drawState, coverage, sharedState);
+    this->setMatrixAndRenderTargetHeight(drawType, drawState);
 
     if (dstCopy) {
         if (fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()) {
@@ -159,11 +171,11 @@
     }
 }
 
-void GrGLProgram::setColor(const GrOptDrawState& optState,
+void GrGLProgram::setColor(const GrDrawState& drawState,
                            GrColor color,
                            SharedGLState* sharedState) {
     const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
-    if (!optState.hasColorVertexAttribute()) {
+    if (!drawState.hasColorVertexAttribute() || drawState.canIgnoreColorAttribute()) {
         switch (header.fColorInput) {
             case GrGLProgramDesc::kAttribute_ColorInput:
                 SkASSERT(-1 != header.fColorAttributeIndex);
@@ -198,11 +210,11 @@
     }
 }
 
-void GrGLProgram::setCoverage(const GrOptDrawState& optState,
+void GrGLProgram::setCoverage(const GrDrawState& drawState,
                               GrColor coverage,
                               SharedGLState* sharedState) {
     const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
-    if (!optState.hasCoverageVertexAttribute()) {
+    if (!drawState.hasCoverageVertexAttribute()) {
         switch (header.fCoverageInput) {
             case GrGLProgramDesc::kAttribute_ColorInput:
                 if (sharedState->fConstAttribCoverage != coverage ||
@@ -237,8 +249,8 @@
 }
 
 void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
-                                                 const GrOptDrawState& optState) {
-    const GrRenderTarget* rt = optState.getRenderTarget();
+                                                 const GrDrawState& drawState) {
+    const GrRenderTarget* rt = drawState.getRenderTarget();
     SkISize size;
     size.set(rt->width(), rt->height());
 
@@ -250,13 +262,13 @@
     }
 
     if (GrGpu::IsPathRenderingDrawType(drawType)) {
-        fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
+        fGpu->glPathRendering()->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
     } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
                fMatrixState.fRenderTargetSize != size ||
-               !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
+               !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) {
         SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid());
 
-        fMatrixState.fViewMatrix = optState.getViewMatrix();
+        fMatrixState.fViewMatrix = drawState.getViewMatrix();
         fMatrixState.fRenderTargetSize = size;
         fMatrixState.fRenderTargetOrigin = rt->origin();
 
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index a520bc2..0f89e07 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -157,8 +157,8 @@
      * GrGpuGL object to bind the textures required by the GrGLEffects. The color and coverage
      * stages come from GrGLProgramDesc::Build().
      */
-    void setData(const GrOptDrawState&,
-                 GrGpu::DrawType,
+    void setData(GrGpu::DrawType,
+                 GrDrawState::BlendOptFlags,
                  const GrEffectStage* geometryProcessor,
                  const GrEffectStage* colorStages[],
                  const GrEffectStage* coverageStages[],
@@ -177,14 +177,14 @@
 
     // Helper for setData(). Makes GL calls to specify the initial color when there is not
     // per-vertex colors.
-    void setColor(const GrOptDrawState&, GrColor color, SharedGLState*);
+    void setColor(const GrDrawState&, GrColor color, SharedGLState*);
 
     // Helper for setData(). Makes GL calls to specify the initial coverage when there is not
     // per-vertex coverages.
-    void setCoverage(const GrOptDrawState&, GrColor coverage, SharedGLState*);
+    void setCoverage(const GrDrawState&, GrColor coverage, SharedGLState*);
 
     // Helper for setData() that sets the view matrix and loads the render target height uniform
-    void setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, const GrOptDrawState&);
+    void setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, const GrDrawState&);
 
     // these reflect the current values of uniforms (GL uniform values travel with program)
     MatrixState                         fMatrixState;
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index bde4072..d7ba287 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -11,7 +11,6 @@
 #include "GrDrawEffect.h"
 #include "GrEffect.h"
 #include "GrGpuGL.h"
-#include "GrOptDrawState.h"
 
 #include "SkChecksum.h"
 
@@ -47,8 +46,9 @@
     return true;
 }
 
-bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
+bool GrGLProgramDesc::Build(const GrDrawState& drawState,
                             GrGpu::DrawType drawType,
+                            GrDrawState::BlendOptFlags blendOpts,
                             GrBlendCoeff srcCoeff,
                             GrBlendCoeff dstCoeff,
                             const GrGpuGL* gpu,
@@ -60,19 +60,47 @@
     colorStages->reset();
     coverageStages->reset();
 
-    bool inputColorIsUsed = optState.inputColorIsUsed();
-    bool inputCoverageIsUsed = optState.inputColorIsUsed();
+    // 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();
+        }
+    }
 
     // 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 = optState.hasColorVertexAttribute();
-    bool requiresCoverageAttrib = optState.hasCoverageVertexAttribute();
+    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 = optState.numTotalStages() > 0 &&
-                                    optState.hasLocalCoordAttribute();
+    bool requiresLocalCoordAttrib = !(skipCoverage  && skipColor) &&
+                                    drawState.hasLocalCoordAttribute();
 
     bool readsDst = false;
     bool readFragPosition = false;
@@ -80,8 +108,16 @@
     // Provide option for shader programs without vertex shader only when drawing paths.
     bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType);
 
-    int numStages = optState.numTotalStages();
-
+    int numStages = 0;
+    if (drawState.hasGeometryProcessor()) {
+        numStages++;
+    }
+    if (!skipColor) {
+        numStages += drawState.numColorStages() - firstEffectiveColorStage;
+    }
+    if (!skipCoverage) {
+        numStages += drawState.numCoverageStages() - firstEffectiveCoverageStage;
+    }
     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();
@@ -95,7 +131,7 @@
     memset(desc->header(), 0, kHeaderSize);
 
     // We can only have one effect which touches the vertex shader
-    if (optState.hasGeometryProcessor()) {
+    if (drawState.hasGeometryProcessor()) {
         uint16_t* offsetAndSize =
                 reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
                                             offsetAndSizeIndex * 2 * sizeof(uint16_t));
@@ -104,7 +140,7 @@
             uint16_t effectKeySize;
             uint32_t effectOffset = desc->fKey.count();
             effectKeySuccess |= GetEffectKeyAndUpdateStats(
-                                    *optState.getGeometryProcessor(), gpu->glCaps(),
+                                    *drawState.getGeometryProcessor(), gpu->glCaps(),
                                     requiresLocalCoordAttrib, &b,
                                     &effectKeySize, &readsDst,
                                     &readFragPosition, &requiresVertexShader);
@@ -113,55 +149,57 @@
             offsetAndSize[0] = SkToU16(effectOffset);
             offsetAndSize[1] = effectKeySize;
             ++offsetAndSizeIndex;
-            *geometryProcessor = optState.getGeometryProcessor();
+            *geometryProcessor = drawState.getGeometryProcessor();
             SkASSERT(requiresVertexShader);
             header->fHasGeometryProcessor = true;
     }
 
-    for (int s = 0; s < optState.numColorStages(); ++s) {
-        uint16_t* offsetAndSize =
-            reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
-                                        offsetAndSizeIndex * 2 * sizeof(uint16_t));
+    if (!skipColor) {
+        for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
+            uint16_t* offsetAndSize =
+                reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
+                                            offsetAndSizeIndex * 2 * sizeof(uint16_t));
 
-        bool effectRequiresVertexShader = false;
-        GrEffectKeyBuilder b(&desc->fKey);
-        uint16_t effectKeySize;
-        uint32_t effectOffset = desc->fKey.count();
-        effectKeySuccess |= GetEffectKeyAndUpdateStats(
-            optState.getColorStage(s), gpu->glCaps(),
-            requiresLocalCoordAttrib, &b,
-            &effectKeySize, &readsDst,
-            &readFragPosition, &effectRequiresVertexShader);
-        effectKeySuccess |= (effectOffset <= SK_MaxU16);
+            bool effectRequiresVertexShader = false;
+            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, &effectRequiresVertexShader);
+            effectKeySuccess |= (effectOffset <= SK_MaxU16);
 
-        offsetAndSize[0] = SkToU16(effectOffset);
-        offsetAndSize[1] = effectKeySize;
-        ++offsetAndSizeIndex;
-        SkASSERT(!effectRequiresVertexShader);
+            offsetAndSize[0] = SkToU16(effectOffset);
+            offsetAndSize[1] = effectKeySize;
+            ++offsetAndSizeIndex;
+            SkASSERT(!effectRequiresVertexShader);
+        }
     }
+    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));
 
-    for (int s = 0; s < optState.numCoverageStages(); ++s) {
-        uint16_t* offsetAndSize =
-            reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
-                                        offsetAndSizeIndex * 2 * sizeof(uint16_t));
+            bool effectRequiresVertexShader = false;
+            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, &effectRequiresVertexShader);
+            effectKeySuccess |= (effectOffset <= SK_MaxU16);
 
-        bool effectRequiresVertexShader = false;
-        GrEffectKeyBuilder b(&desc->fKey);
-        uint16_t effectKeySize;
-        uint32_t effectOffset = desc->fKey.count();
-        effectKeySuccess |= GetEffectKeyAndUpdateStats(
-            optState.getCoverageStage(s), gpu->glCaps(),
-            requiresLocalCoordAttrib, &b,
-            &effectKeySize, &readsDst,
-            &readFragPosition, &effectRequiresVertexShader);
-        effectKeySuccess |= (effectOffset <= SK_MaxU16);
-
-        offsetAndSize[0] = SkToU16(effectOffset);
-        offsetAndSize[1] = effectKeySize;
-        ++offsetAndSizeIndex;
-        SkASSERT(!effectRequiresVertexShader);
+            offsetAndSize[0] = SkToU16(effectOffset);
+            offsetAndSize[1] = effectKeySize;
+            ++offsetAndSizeIndex;
+            SkASSERT(!effectRequiresVertexShader);
+        }
     }
-
     if (!effectKeySuccess) {
         desc->fKey.reset();
         return false;
@@ -184,20 +222,20 @@
 #endif
     bool defaultToUniformInputs = GR_GL_NO_CONSTANT_ATTRIBUTES || gpu->caps()->pathRenderingSupport();
 
-    if (!inputColorIsUsed) {
+    if (!inputColorIsUsed && !skipColor) {
         header->fColorInput = kAllOnes_ColorInput;
-    } else if (defaultToUniformInputs && !requiresColorAttrib) {
+    } else if (defaultToUniformInputs && !requiresColorAttrib && inputColorIsUsed) {
         header->fColorInput = kUniform_ColorInput;
     } else {
         header->fColorInput = kAttribute_ColorInput;
         header->fRequiresVertexShader = true;
     }
 
-    bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == optState.getCoverageColor();
+    bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor();
 
-    if (covIsSolidWhite || !inputCoverageIsUsed) {
+    if ((covIsSolidWhite || !inputCoverageIsUsed) && !skipCoverage) {
         header->fCoverageInput = kAllOnes_ColorInput;
-    } else if (defaultToUniformInputs && !requiresCoverageAttrib) {
+    } else if (defaultToUniformInputs && !requiresCoverageAttrib && inputCoverageIsUsed) {
         header->fCoverageInput = kUniform_ColorInput;
     } else {
         header->fCoverageInput = kAttribute_ColorInput;
@@ -219,19 +257,19 @@
 
     if (readFragPosition) {
         header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition(
-                optState.getRenderTarget(), gpu->glCaps());
+                drawState.getRenderTarget(), gpu->glCaps());
     } else {
         header->fFragPosKey = 0;
     }
 
     // Record attribute indices
-    header->fPositionAttributeIndex = optState.positionAttributeIndex();
-    header->fLocalCoordAttributeIndex = optState.localCoordAttributeIndex();
+    header->fPositionAttributeIndex = drawState.positionAttributeIndex();
+    header->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
 
     // For constant color and coverage we need an attribute with an index beyond those already set
-    int availableAttributeIndex = optState.getVertexAttribCount();
+    int availableAttributeIndex = drawState.getVertexAttribCount();
     if (requiresColorAttrib) {
-        header->fColorAttributeIndex = optState.colorVertexAttributeIndex();
+        header->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
     } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) {
         SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
         header->fColorAttributeIndex = availableAttributeIndex;
@@ -241,7 +279,7 @@
     }
 
     if (requiresCoverageAttrib) {
-        header->fCoverageAttributeIndex = optState.coverageVertexAttributeIndex();
+        header->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
     } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) {
         SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
         header->fCoverageAttributeIndex = availableAttributeIndex;
@@ -255,13 +293,15 @@
     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() ||
+    bool separateCoverageFromColor = drawState.hasGeometryProcessor();
+    if (!drawState.isCoverageDrawing() && !skipCoverage &&
+        (drawState.numCoverageStages() > 0 ||
+         drawState.hasGeometryProcessor() ||
          requiresCoverageAttrib)) {
 
-        if (gpu->caps()->dualSourceBlendingSupport()) {
+        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;
@@ -283,19 +323,22 @@
         }
     }
 
-    for (int s = 0; s < optState.numColorStages(); ++s) {
-        colorStages->push_back(&optState.getColorStage(s));
+    if (!skipColor) {
+        for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
+            colorStages->push_back(&drawState.getColorStage(s));
+        }
     }
-    SkTArray<const GrEffectStage*, true>* array;
-    if (separateCoverageFromColor) {
-        array = coverageStages;
-    } else {
-        array = colorStages;
+    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) {
-        array->push_back(&optState.getCoverageStage(s));
-    }
-
     header->fColorEffectCnt = colorStages->count();
     header->fCoverageEffectCnt = coverageStages->count();
 
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index e91dbe0..b1f54b7 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -55,13 +55,15 @@
                    int currAttribIndex);
 
     /**
-     * Builds a program descriptor from a GrOptDrawState. Whether the primitive type is points, and
-     * the caps of the GrGpuGL are also inputs. It also outputs the color and coverage stages
-     * referenced by the generated descriptor. Coverage stages from the drawState may be treated as
-     * color stages in the output.
+     * Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the
+     * output of GrDrawState::getBlendOpts, and the caps of the GrGpuGL are also inputs. It also
+     * outputs the color and coverage stages referenced by the generated descriptor. This may
+     * not contain all stages from the draw state and coverage stages from the drawState may
+     * be treated as color stages in the output.
      */
-    static bool Build(const GrOptDrawState&,
+    static bool Build(const GrDrawState&,
                       GrGpu::DrawType drawType,
+                      GrDrawState::BlendOptFlags,
                       GrBlendCoeff srcCoeff,
                       GrBlendCoeff dstCoeff,
                       const GrGpuGL* gpu,
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 5ff868c..c335e12 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -8,7 +8,6 @@
 
 #include "GrGpuGL.h"
 #include "GrGLStencilBuffer.h"
-#include "GrOptDrawState.h"
 #include "GrTemplates.h"
 #include "GrTypes.h"
 #include "SkStrokeRec.h"
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 476f174..be21abf 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -9,9 +9,8 @@
 
 #include "GrEffect.h"
 #include "GrGLEffect.h"
-#include "GrGLPathRendering.h"
-#include "GrOptDrawState.h"
 #include "SkRTConf.h"
+#include "GrGLPathRendering.h"
 #include "SkTSearch.h"
 
 #ifdef PROGRAM_CACHE_STATS
@@ -205,25 +204,23 @@
 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
 
 bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) {
-    SkAutoTUnref<GrOptDrawState> optState(this->getDrawState().createOptState());
+    const GrDrawState& drawState = this->getDrawState();
 
     // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true.
-    SkASSERT(optState->getRenderTarget());
+    SkASSERT(drawState.getRenderTarget());
 
     if (kStencilPath_DrawType == type) {
-        const GrRenderTarget* rt = optState->getRenderTarget();
+        const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
         SkISize size;
         size.set(rt->width(), rt->height());
-        this->glPathRendering()->setProjectionMatrix(optState->getViewMatrix(), size, rt->origin());
+        this->glPathRendering()->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
     } else {
         this->flushMiscFixedFunctionState();
 
-        GrBlendCoeff srcCoeff = optState->getSrcBlendCoeff();
-        GrBlendCoeff dstCoeff = optState->getDstBlendCoeff();
-
-        // In these blend coeff's we end up drawing nothing so we can skip draw all together
-        if (kZero_GrBlendCoeff == srcCoeff && kOne_GrBlendCoeff == dstCoeff &&
-            !optState->getStencil().doesWrite()) {
+        GrBlendCoeff srcCoeff;
+        GrBlendCoeff dstCoeff;
+        GrDrawState::BlendOptFlags blendOpts = drawState.getBlendOpts(false, &srcCoeff, &dstCoeff);
+        if (GrDrawState::kSkipDraw_BlendOptFlag & blendOpts) {
             return false;
         }
 
@@ -231,8 +228,9 @@
         SkSTArray<8, const GrEffectStage*, true> colorStages;
         SkSTArray<8, const GrEffectStage*, true> coverageStages;
         GrGLProgramDesc desc;
-        if (!GrGLProgramDesc::Build(*optState.get(),
+        if (!GrGLProgramDesc::Build(this->getDrawState(),
                                type,
+                               blendOpts,
                                srcCoeff,
                                dstCoeff,
                                this,
@@ -265,8 +263,8 @@
         fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
         this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
 
-        fCurrentProgram->setData(*optState.get(),
-                                 type,
+        fCurrentProgram->setData(type,
+                                 blendOpts,
                                  geometryProcessor,
                                  colorStages.begin(),
                                  coverageStages.begin(),
@@ -274,15 +272,15 @@
                                  &fSharedGLProgramState);
     }
 
-    GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(optState->getRenderTarget());
+    GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(drawState.getRenderTarget());
     this->flushStencil(type);
     this->flushScissor(glRT->getViewport(), glRT->origin());
     this->flushAAState(type);
 
     SkIRect* devRect = NULL;
     SkIRect devClipBounds;
-    if (optState->isClipState()) {
-        this->getClip()->getConservativeBounds(optState->getRenderTarget(), &devClipBounds);
+    if (drawState.isClipState()) {
+        this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds);
         devRect = &devClipBounds;
     }
     // This must come after textures are flushed because a texture may need
@@ -293,9 +291,8 @@
 }
 
 void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
-    SkAutoTUnref<GrOptDrawState> optState(this->getDrawState().createOptState());
 
-    GrGLsizei stride = static_cast<GrGLsizei>(optState->getVertexStride());
+    GrGLsizei stride = static_cast<GrGLsizei>(this->getDrawState().getVertexStride());
 
     size_t vertexOffsetInBytes = stride * info.startVertex();
 
@@ -349,12 +346,16 @@
         fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf);
 
     if (fCurrentProgram->hasVertexShader()) {
-        int vertexAttribCount = optState->getVertexAttribCount();
+        int vertexAttribCount = this->getDrawState().getVertexAttribCount();
         uint32_t usedAttribArraysMask = 0;
-        const GrVertexAttrib* vertexAttrib = optState->getVertexAttribs();
+        const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs();
+
+        bool canIgnoreColorAttrib = this->getDrawState().canIgnoreColorAttribute();
 
         for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount;
              ++vertexAttribIndex, ++vertexAttrib) {
+
+            if (kColor_GrVertexAttribBinding != vertexAttrib->fBinding || !canIgnoreColorAttrib) {
             usedAttribArraysMask |= (1 << vertexAttribIndex);
             GrVertexAttribType attribType = vertexAttrib->fType;
             attribState->set(this,
@@ -366,6 +367,7 @@
                              stride,
                              reinterpret_cast<GrGLvoid*>(
                                  vertexOffsetInBytes + vertexAttrib->fOffset));
+            }
         }
         attribState->disableUnusedArrays(this, usedAttribArraysMask);
     }
diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
index 5c074a2..f06c646 100644
--- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp
@@ -9,7 +9,6 @@
 #include "GrGLProgramBuilder.h"
 #include "GrGLShaderStringBuilder.h"
 #include "../GrGpuGL.h"
-#include "../../GrOptDrawState.h"
 
 #define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
@@ -84,12 +83,10 @@
                                    coverage_attribute_name()));
     }
 
-    // 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 GrVertexAttrib* vaPtr = optState->getVertexAttribs();
-    const int vaCount = optState->getVertexAttribCount();
+    // We pull the current state of attributes off of drawstate and bind them in order
+    const GrRODrawState* ds = fProgramBuilder->gpu()->drawState();
+    const GrVertexAttrib* vaPtr = ds->getVertexAttribs();
+    const int vaCount = ds->getVertexAttribCount();
 
     int i = fEffectAttribOffset;
     for (int index = 0; index < vaCount; index++) {