Split GrDrawState and GrOptDrawState into separate classes and remove base class.

Besides splitting the two classes, there are no logical changes here and mostly moving code around.

BUG=skia:
R=bsalomon@google.com

Author: egdaniel@google.com

Review URL: https://codereview.chromium.org/597323002
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index 168cf0b..872d20a 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -16,14 +16,16 @@
     if (NULL == fCachedOptState || caps.getUniqueID() != fCachedCapsID) {
         GrBlendCoeff srcCoeff;
         GrBlendCoeff dstCoeff;
-        BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
+        GrOptDrawState::BlendOptFlags blendFlags =
+            (GrOptDrawState::BlendOptFlags) this->getBlendOpts(false, &srcCoeff, &dstCoeff);
         fCachedOptState = SkNEW_ARGS(GrOptDrawState, (*this, blendFlags, srcCoeff, dstCoeff, caps));
         fCachedCapsID = caps.getUniqueID();
     } else {
 #ifdef SK_DEBUG
         GrBlendCoeff srcCoeff;
         GrBlendCoeff dstCoeff;
-        BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
+        GrOptDrawState::BlendOptFlags blendFlags =
+            (GrOptDrawState::BlendOptFlags) this->getBlendOpts(false, &srcCoeff, &dstCoeff);
         SkASSERT(GrOptDrawState(*this, blendFlags, srcCoeff, dstCoeff, caps) == *fCachedOptState);
 #endif
     }
@@ -33,6 +35,66 @@
 
 //////////////////////////////////////////////////////////////////////////////s
 
+bool GrDrawState::isEqual(const GrDrawState& that) const {
+    bool usingVertexColors = this->hasColorVertexAttribute();
+    if (!usingVertexColors && this->fColor != that.fColor) {
+        return false;
+    }
+
+    if (this->getRenderTarget() != that.getRenderTarget() ||
+        this->fColorStages.count() != that.fColorStages.count() ||
+        this->fCoverageStages.count() != that.fCoverageStages.count() ||
+        !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
+        this->fSrcBlend != that.fSrcBlend ||
+        this->fDstBlend != that.fDstBlend ||
+        this->fBlendConstant != that.fBlendConstant ||
+        this->fFlagBits != that.fFlagBits ||
+        this->fVACount != that.fVACount ||
+        this->fVAStride != that.fVAStride ||
+        memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
+        this->fStencilSettings != that.fStencilSettings ||
+        this->fDrawFace != that.fDrawFace) {
+        return false;
+    }
+
+    bool usingVertexCoverage = this->hasCoverageVertexAttribute();
+    if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
+        return false;
+    }
+
+    bool explicitLocalCoords = this->hasLocalCoordAttribute();
+    if (this->hasGeometryProcessor()) {
+        if (!that.hasGeometryProcessor()) {
+            return false;
+        } else if (!GrProcessorStage::AreCompatible(*this->getGeometryProcessor(),
+                                                    *that.getGeometryProcessor(),
+                                                    explicitLocalCoords)) {
+            return false;
+        }
+    } else if (that.hasGeometryProcessor()) {
+        return false;
+    }
+
+    for (int i = 0; i < this->numColorStages(); i++) {
+        if (!GrProcessorStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
+                                             explicitLocalCoords)) {
+            return false;
+        }
+    }
+    for (int i = 0; i < this->numCoverageStages(); i++) {
+        if (!GrProcessorStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
+                                             explicitLocalCoords)) {
+            return false;
+        }
+    }
+
+    SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices,
+                         that.fFixedFunctionVertexAttribIndices,
+                         sizeof(this->fFixedFunctionVertexAttribIndices)));
+
+    return true;
+}
+
 GrDrawState::CombinedState GrDrawState::CombineIfPossible(
     const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
 
@@ -218,11 +280,54 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+bool GrDrawState::validateVertexAttribs() const {
+    // check consistency of effects and attributes
+    GrSLType slTypes[kMaxVertexAttribCnt];
+    for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
+        slTypes[i] = static_cast<GrSLType>(-1);
+    }
+
+    if (this->hasGeometryProcessor()) {
+        const GrGeometryStage& stage = *this->getGeometryProcessor();
+        const GrGeometryProcessor* gp = stage.getGeometryProcessor();
+        SkASSERT(gp);
+        // make sure that any attribute indices have the correct binding type, that the attrib
+        // type and effect's shader lang type are compatible, and that attributes shared by
+        // multiple effects use the same shader lang type.
+        const GrGeometryProcessor::VertexAttribArray& s = gp->getVertexAttribs();
+
+        int effectIndex = 0;
+        for (int index = 0; index < fVACount; index++) {
+            if (kGeometryProcessor_GrVertexAttribBinding != fVAPtr[index].fBinding) {
+                // we only care about effect bindings
+                continue;
+            }
+            SkASSERT(effectIndex < s.count());
+            GrSLType effectSLType = s[effectIndex].getType();
+            GrVertexAttribType attribType = fVAPtr[index].fType;
+            int slVecCount = GrSLTypeVectorCount(effectSLType);
+            int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
+            if (slVecCount != attribVecCount ||
+                (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) {
+                return false;
+            }
+            slTypes[index] = effectSLType;
+            effectIndex++;
+        }
+        // Make sure all attributes are consumed and we were able to find everything
+        SkASSERT(s.count() == effectIndex);
+    }
+
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) {
     // this works as long as we're 4 byte-aligned
 #ifdef SK_DEBUG
     uint32_t overlapCheck = 0;
-    SkASSERT(count <= GrRODrawState::kMaxVertexAttribCnt);
+    SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
     for (int index = 0; index < count; ++index) {
         size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
         size_t attribOffset = attribs[index].fOffset;
@@ -305,11 +410,39 @@
     GrBlendCoeff srcCoeff;
     GrBlendCoeff dstCoeff;
     BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
-    return GrRODrawState::kNone_BlendOpt != flag ||
+    return GrDrawState::kNone_BlendOpt != flag ||
            (this->willEffectReadDstColor() &&
             kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
 }
 
+bool GrDrawState::hasSolidCoverage() const {
+    // If we're drawing coverage directly then coverage is effectively treated as color.
+    if (this->isCoverageDrawing()) {
+        return true;
+    }
+
+    GrColor coverage;
+    uint32_t validComponentFlags;
+    // Initialize to an unknown starting coverage if per-vertex coverage is specified.
+    if (this->hasCoverageVertexAttribute()) {
+        validComponentFlags = 0;
+    } else {
+        coverage = fCoverage;
+        validComponentFlags = kRGBA_GrColorComponentFlags;
+    }
+
+    // Run through the coverage stages and see if the coverage will be all ones at the end.
+    if (this->hasGeometryProcessor()) {
+        const GrGeometryProcessor* gp = fGeometryProcessor->getGeometryProcessor();
+        gp->getConstantColorComponents(&coverage, &validComponentFlags);
+    }
+    for (int s = 0; s < this->numCoverageStages(); ++s) {
+        const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
+        processor->getConstantColorComponents(&coverage, &validComponentFlags);
+    }
+    return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) {
@@ -323,6 +456,22 @@
 
 //////////////////////////////////////////////////////////////////////////////s
 
+bool GrDrawState::willEffectReadDstColor() const {
+    if (!this->isColorWriteDisabled()) {
+        for (int s = 0; s < this->numColorStages(); ++s) {
+            if (this->getColorStage(s).getFragmentProcessor()->willReadDstColor()) {
+                return true;
+            }
+        }
+    }
+    for (int s = 0; s < this->numCoverageStages(); ++s) {
+        if (this->getCoverageStage(s).getFragmentProcessor()->willReadDstColor()) {
+            return true;
+        }
+    }
+    return false;
+}
+
 void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
     if (fDrawState) {
         // See the big comment on the class definition about GPs.
@@ -360,6 +509,28 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
+// others will blend incorrectly.
+bool GrDrawState::canTweakAlphaForCoverage() const {
+    /*
+     The fractional coverage is f.
+     The src and dst coeffs are Cs and Cd.
+     The dst and src colors are S and D.
+     We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
+     we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
+     term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
+     find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
+     Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
+     color by definition.
+     */
+    return kOne_GrBlendCoeff == fDstBlend ||
+           kISA_GrBlendCoeff == fDstBlend ||
+           kISC_GrBlendCoeff == fDstBlend ||
+           this->isCoverageDrawing();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 void GrDrawState::AutoViewMatrixRestore::restore() {
     if (fDrawState) {
         SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
@@ -462,6 +633,22 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+void GrDrawState::convertToPendingExec() {
+    fRenderTarget.markPendingIO();
+    fRenderTarget.removeRef();
+    for (int i = 0; i < fColorStages.count(); ++i) {
+        fColorStages[i].convertToPendingExec();
+    }
+    if (fGeometryProcessor) {
+        fGeometryProcessor->convertToPendingExec();
+    }
+    for (int i = 0; i < fCoverageStages.count(); ++i) {
+        fCoverageStages[i].convertToPendingExec();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 void GrDrawState::invalidateOptState() const {
     SkSafeSetNull(fCachedOptState);
 }
@@ -473,3 +660,150 @@
     SkASSERT(0 == fBlockEffectRemovalCnt);
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
+GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
+                                                         GrBlendCoeff* srcCoeff,
+                                                         GrBlendCoeff* dstCoeff) const {
+    GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
+    if (NULL == srcCoeff) {
+        srcCoeff = &bogusSrcCoeff;
+    }
+    if (NULL == dstCoeff) {
+        dstCoeff = &bogusDstCoeff;
+    }
+
+    *srcCoeff = this->getSrcBlendCoeff();
+    *dstCoeff = this->getDstBlendCoeff();
+
+    if (this->isColorWriteDisabled()) {
+        *srcCoeff = kZero_GrBlendCoeff;
+        *dstCoeff = kOne_GrBlendCoeff;
+    }
+
+    bool srcAIsOne = this->srcAlphaWillBeOne();
+    bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
+                         (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
+    bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
+                         (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
+
+    // When coeffs are (0,1) there is no reason to draw at all, unless
+    // stenciling is enabled. Having color writes disabled is effectively
+    // (0,1).
+    if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
+        if (this->getStencil().doesWrite()) {
+            return kEmitCoverage_BlendOptFlag;
+        } else {
+            *dstCoeff = kOne_GrBlendCoeff;
+            return kSkipDraw_BlendOptFlag;
+        }
+    }
+
+    bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
+
+    // if we don't have coverage we can check whether the dst
+    // has to read at all. If not, we'll disable blending.
+    if (!hasCoverage) {
+        if (dstCoeffIsZero) {
+            if (kOne_GrBlendCoeff == *srcCoeff) {
+                // if there is no coverage and coeffs are (1,0) then we
+                // won't need to read the dst at all, it gets replaced by src
+                *dstCoeff = kZero_GrBlendCoeff;
+                return kNone_BlendOpt;
+            } else if (kZero_GrBlendCoeff == *srcCoeff) {
+                // if the op is "clear" then we don't need to emit a color
+                // or blend, just write transparent black into the dst.
+                *srcCoeff = kOne_GrBlendCoeff;
+                *dstCoeff = kZero_GrBlendCoeff;
+                return kEmitTransBlack_BlendOptFlag;
+            }
+        }
+    } else if (this->isCoverageDrawing()) {
+        // we have coverage but we aren't distinguishing it from alpha by request.
+        return kCoverageAsAlpha_BlendOptFlag;
+    } else {
+        // check whether coverage can be safely rolled into alpha
+        // of if we can skip color computation and just emit coverage
+        if (this->canTweakAlphaForCoverage()) {
+            return kCoverageAsAlpha_BlendOptFlag;
+        }
+        if (dstCoeffIsZero) {
+            if (kZero_GrBlendCoeff == *srcCoeff) {
+                // the source color is not included in the blend
+                // the dst coeff is effectively zero so blend works out to:
+                // (c)(0)D + (1-c)D = (1-c)D.
+                *dstCoeff = kISA_GrBlendCoeff;
+                return  kEmitCoverage_BlendOptFlag;
+            } else if (srcAIsOne) {
+                // the dst coeff is effectively zero so blend works out to:
+                // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
+                // If Sa is 1 then we can replace Sa with c
+                // and set dst coeff to 1-Sa.
+                *dstCoeff = kISA_GrBlendCoeff;
+                return  kCoverageAsAlpha_BlendOptFlag;
+            }
+        } else if (dstCoeffIsOne) {
+            // the dst coeff is effectively one so blend works out to:
+            // cS + (c)(1)D + (1-c)D = cS + D.
+            *dstCoeff = kOne_GrBlendCoeff;
+            return  kCoverageAsAlpha_BlendOptFlag;
+        }
+    }
+
+    return kNone_BlendOpt;
+}
+
+
+bool GrDrawState::srcAlphaWillBeOne() const {
+    uint32_t validComponentFlags;
+    GrColor color;
+    // Check if per-vertex or constant color may have partial alpha
+    if (this->hasColorVertexAttribute()) {
+        if (fHints & kVertexColorsAreOpaque_Hint) {
+            validComponentFlags = kA_GrColorComponentFlag;
+            color = 0xFF << GrColor_SHIFT_A;
+        } else {
+            validComponentFlags = 0;
+            color = 0; // not strictly necessary but we get false alarms from tools about uninit.
+        }
+    } else {
+        validComponentFlags = kRGBA_GrColorComponentFlags;
+        color = this->getColor();
+    }
+
+    // Run through the color stages
+    for (int s = 0; s < this->numColorStages(); ++s) {
+        const GrProcessor* processor = this->getColorStage(s).getProcessor();
+        processor->getConstantColorComponents(&color, &validComponentFlags);
+    }
+
+    // Check whether coverage is treated as color. If so we run through the coverage computation.
+    if (this->isCoverageDrawing()) {
+        // The shader generated for coverage drawing runs the full coverage computation and then
+        // makes the shader output be the multiplication of color and coverage. We mirror that here.
+        GrColor coverage;
+        uint32_t coverageComponentFlags;
+        if (this->hasCoverageVertexAttribute()) {
+            coverageComponentFlags = 0;
+            coverage = 0; // suppresses any warnings.
+        } else {
+            coverageComponentFlags = kRGBA_GrColorComponentFlags;
+            coverage = this->getCoverageColor();
+        }
+
+        // Run through the coverage stages
+        for (int s = 0; s < this->numCoverageStages(); ++s) {
+            const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
+            processor->getConstantColorComponents(&coverage, &coverageComponentFlags);
+        }
+
+        // Since the shader will multiply coverage and color, the only way the final A==1 is if
+        // coverage and color both have A==1.
+        return (kA_GrColorComponentFlag & validComponentFlags & coverageComponentFlags) &&
+                0xFF == GrColorUnpackA(color) && 0xFF == GrColorUnpackA(coverage);
+
+    }
+
+    return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color);
+}
+
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 19ea4df..b855c87 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -8,21 +8,22 @@
 #ifndef GrDrawState_DEFINED
 #define GrDrawState_DEFINED
 
+
 #include "GrBlend.h"
 #include "GrDrawTargetCaps.h"
 #include "GrGpuResourceRef.h"
-#include "GrRODrawState.h"
+#include "GrProcessorStage.h"
+#include "GrRenderTarget.h"
+#include "GrStencil.h"
+#include "SkMatrix.h"
 #include "effects/GrSimpleTextureEffect.h"
 
+class GrDrawTargetCaps;
 class GrOptDrawState;
+class GrPaint;
+class GrTexture;
 
-/**
- * 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.
- * various data members of the draw state. This class is used to configure the state used when
- * issuing draws via GrDrawTarget.
- */
-class GrDrawState : public GrRODrawState {
+class GrDrawState : public SkRefCnt {
 public:
     SK_DECLARE_INST_COUNT(GrDrawState)
 
@@ -70,6 +71,31 @@
     /// @name Vertex Attributes
     ////
 
+    enum {
+        kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
+    };
+
+    const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; }
+    int getVertexAttribCount() const { return fVACount; }
+
+    size_t getVertexStride() const { return fVAStride; }
+
+    bool hasLocalCoordAttribute() const {
+        return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
+    }
+    bool hasColorVertexAttribute() const {
+        return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
+    }
+    bool hasCoverageVertexAttribute() const {
+        return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
+    }
+
+    const int* getFixedFunctionVertexAttribIndices() const {
+        return fFixedFunctionVertexAttribIndices;
+    }
+
+    bool validateVertexAttribs() const;
+
    /**
      * The format of vertices is represented as an array of GrVertexAttribs, with each representing
      * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in
@@ -127,12 +153,19 @@
      */
     bool couldApplyCoverage(const GrDrawTargetCaps& caps) const;
 
+    /**
+     * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
+     */
+    bool hasSolidCoverage() const;
+
     /// @}
 
     ///////////////////////////////////////////////////////////////////////////
     /// @name Color
     ////
 
+    GrColor getColor() const { return fColor; }
+
     /**
      *  Sets color for next draw to a premultiplied-alpha color.
      *
@@ -159,6 +192,12 @@
     /// @name Coverage
     ////
 
+    uint8_t getCoverage() const { return fCoverage; }
+
+    GrColor getCoverageColor() const {
+        return GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
+    }
+
     /**
      * Sets a constant fractional coverage to be applied to the draw. The
      * initial value (after construction or reset()) is 0xff. The constant
@@ -207,6 +246,23 @@
     /// the color / coverage distinction.
     ////
 
+    int numColorStages() const { return fColorStages.count(); }
+    int numCoverageStages() const { return fCoverageStages.count(); }
+    int numTotalStages() const {
+         return this->numColorStages() + this->numCoverageStages() +
+                 (this->hasGeometryProcessor() ? 1 : 0);
+    }
+
+    bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
+    const GrGeometryStage* getGeometryProcessor() const { return fGeometryProcessor.get(); }
+    const GrFragmentStage& getColorStage(int idx) const { return fColorStages[idx]; }
+    const GrFragmentStage& getCoverageStage(int idx) const { return fCoverageStages[idx]; }
+
+    /**
+     * Checks whether any of the effects will read the dst pixel color.
+     */
+    bool willEffectReadDstColor() const;
+
     const GrFragmentProcessor* addColorProcessor(const GrFragmentProcessor* effect) {
         SkASSERT(effect);
         SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (effect));
@@ -295,6 +351,22 @@
     /// @name Blending
     ////
 
+    GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
+    GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
+
+    /**
+     * Retrieves the last value set by setBlendConstant()
+     * @return the blending constant value
+     */
+    GrColor getBlendConstant() const { return fBlendConstant; }
+
+    /**
+     * 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;
+
     /**
      * Sets the blending function coefficients.
      *
@@ -348,6 +420,32 @@
     ////
 
     /**
+     * Retrieves the current view matrix
+     * @return the current view matrix.
+     */
+    const SkMatrix& getViewMatrix() const { return fViewMatrix; }
+
+    /**
+     *  Retrieves the inverse of the current view matrix.
+     *
+     *  If the current view matrix is invertible, return true, and if matrix
+     *  is non-null, copy the inverse into it. If the current view matrix is
+     *  non-invertible, return false and ignore the matrix parameter.
+     *
+     * @param matrix if not null, will receive a copy of the current inverse.
+     */
+    bool getViewInverse(SkMatrix* matrix) const {
+        SkMatrix inverse;
+        if (fViewMatrix.invert(&inverse)) {
+            if (matrix) {
+                *matrix = inverse;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Sets the view matrix to identity and updates any installed effects to compensate for the
      * coord system change.
      */
@@ -398,6 +496,15 @@
     ////
 
     /**
+     * Retrieves the currently set render-target.
+     *
+     * @return    The currently set render target.
+     */
+    GrRenderTarget* getRenderTarget() const {
+        return static_cast<GrRenderTarget*>(fRenderTarget.getResource());
+    }
+
+    /**
      * Sets the render-target used at the next drawing call
      *
      * @param target  The render target to set.
@@ -413,6 +520,8 @@
     /// @name Stencil
     ////
 
+    const GrStencilSettings& getStencil() const { return fStencilSettings; }
+
     /**
      * Sets the stencil settings to use for the next draw.
      * Changing the clip has the side-effect of possibly zeroing
@@ -445,6 +554,54 @@
     /// @name State Flags
     ////
 
+    /**
+     *  Flags that affect rendering. Controlled using enable/disableState(). All
+     *  default to disabled.
+     */
+    enum StateBits {
+        /**
+         * Perform dithering. TODO: Re-evaluate whether we need this bit
+         */
+        kDither_StateBit        = 0x01,
+        /**
+         * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
+         * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
+         * the 3D API.
+         */
+        kHWAntialias_StateBit   = 0x02,
+        /**
+         * Draws will respect the clip, otherwise the clip is ignored.
+         */
+        kClip_StateBit          = 0x04,
+        /**
+         * Disables writing to the color buffer. Useful when performing stencil
+         * operations.
+         */
+        kNoColorWrites_StateBit = 0x08,
+
+        /**
+         * Usually coverage is applied after color blending. The color is blended using the coeffs
+         * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
+         * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
+         * this case there is no distinction between coverage and color and the caller needs direct
+         * control over the blend coeffs. When set, there will be a single blend step controlled by
+         * setBlendFunc() which will use coverage*color as the src color.
+         */
+         kCoverageDrawing_StateBit = 0x10,
+
+        // Users of the class may add additional bits to the vector
+        kDummyStateBit,
+        kLastPublicStateBit = kDummyStateBit-1,
+    };
+
+    uint32_t getFlagBits() const { return fFlagBits; }
+
+    bool isStateFlagEnabled(uint32_t stateBit) const { return 0 != (stateBit & fFlagBits); }
+
+    bool isClipState() const { return 0 != (fFlagBits & kClip_StateBit); }
+    bool isColorWriteDisabled() const { return 0 != (fFlagBits & kNoColorWrites_StateBit); }
+    bool isCoverageDrawing() const { return 0 != (fFlagBits & kCoverageDrawing_StateBit); }
+
     void resetStateFlags() {
         if (0 != fFlagBits) {
             fFlagBits = 0;
@@ -496,6 +653,21 @@
     /// @name Face Culling
     ////
 
+    enum DrawFace {
+        kInvalid_DrawFace = -1,
+
+        kBoth_DrawFace,
+        kCCW_DrawFace,
+        kCW_DrawFace,
+    };
+
+    /**
+     * Gets whether the target is drawing clockwise, counterclockwise,
+     * or both faces.
+     * @return the current draw face(s).
+     */
+    DrawFace getDrawFace() const { return fDrawFace; }
+
     /**
      * Controls whether clockwise, counterclockwise, or both faces are drawn.
      * @param face  the face(s) to draw.
@@ -512,8 +684,12 @@
     /// Hints that when provided can enable optimizations.
     ////
 
+    enum Hints { kVertexColorsAreOpaque_Hint = 0x1, };
+
     void setHint(Hints hint, bool value) { fHints = value ? (fHints | hint) : (fHints & ~hint); }
 
+    bool vertexColorsAreOpaque() const { return kVertexColorsAreOpaque_Hint & fHints; }
+
     /// @}
 
     ///////////////////////////////////////////////////////////////////////////
@@ -548,6 +724,71 @@
     GrOptDrawState* createOptState(const GrDrawTargetCaps&) const;
 
 private:
+    /**
+     * Converts refs on GrGpuResources owned directly or indirectly by this GrDrawState into
+     * pending reads and writes. This should be called when a GrDrawState is recorded into
+     * a GrDrawTarget for later execution. Subclasses of GrDrawState may add setters. However,
+     * once this call has been made the GrDrawState is immutable. It is also no longer copyable.
+     * In the future this conversion will automatically happen when converting a GrDrawState into
+     * an optimized draw state.
+     */
+    void convertToPendingExec();
+
+    friend class GrDrawTarget;
+
+    bool isEqual(const GrDrawState& 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;
+
+    /**
+     * Determines whether src alpha is guaranteed to be one for all src pixels
+     */
+    bool srcAlphaWillBeOne() const;
+
     void invalidateOptState() const;
 
     void onReset(const SkMatrix* initialViewMatrix);
@@ -558,10 +799,39 @@
 
     void internalSetVertexAttribs(const GrVertexAttrib attribs[], int count, size_t stride);
 
+    typedef GrTGpuResourceRef<GrRenderTarget> ProgramRenderTarget;
+    // These fields are roughly sorted by decreasing likelihood of being different in op==
+    ProgramRenderTarget                 fRenderTarget;
+    GrColor                             fColor;
+    SkMatrix                            fViewMatrix;
+    GrColor                             fBlendConstant;
+    uint32_t                            fFlagBits;
+    const GrVertexAttrib*               fVAPtr;
+    int                                 fVACount;
+    size_t                              fVAStride;
+    GrStencilSettings                   fStencilSettings;
+    uint8_t                             fCoverage;
+    DrawFace                            fDrawFace;
+    GrBlendCoeff                        fSrcBlend;
+    GrBlendCoeff                        fDstBlend;
+
+    typedef SkSTArray<4, GrFragmentStage>   FragmentStageArray;
+    SkAutoTDelete<GrGeometryStage>          fGeometryProcessor;
+    FragmentStageArray                      fColorStages;
+    FragmentStageArray                      fCoverageStages;
+
+    uint32_t                            fHints;
+
+    // This is simply a different representation of info in fVertexAttribs and thus does
+    // not need to be compared in op==.
+    int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
+
     mutable GrOptDrawState* fCachedOptState;
     mutable uint32_t fCachedCapsID;
 
-    typedef GrRODrawState INHERITED;
+    typedef SkRefCnt INHERITED;
 };
 
+//GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
+
 #endif
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 8ffc681..dd2224b 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -694,8 +694,8 @@
     virtual DrawToken getCurrentDrawToken() { return DrawToken(this, 0); }
 
 protected:
-    // Extend access to GrRODrawState::convertToPEndeingExec to subclasses.
-    void convertDrawStateToPendingExec(GrRODrawState* ds) {
+    // Extend access to GrDrawState::convertToPEndeingExec to subclasses.
+    void convertDrawStateToPendingExec(GrDrawState* ds) {
         ds->convertToPendingExec();
     }
 
diff --git a/src/gpu/GrOptDrawState.cpp b/src/gpu/GrOptDrawState.cpp
index 8653a8b..98a5689 100644
--- a/src/gpu/GrOptDrawState.cpp
+++ b/src/gpu/GrOptDrawState.cpp
@@ -15,7 +15,9 @@
                                BlendOptFlags blendOptFlags,
                                GrBlendCoeff optSrcCoeff,
                                GrBlendCoeff optDstCoeff,
-                               const GrDrawTargetCaps& caps) : INHERITED(drawState) {
+                               const GrDrawTargetCaps& caps) {
+    fRenderTarget.set(SkSafeRef(drawState.getRenderTarget()),
+                              GrIORef::kWrite_IOType);
     fColor = drawState.getColor();
     fCoverage = drawState.getCoverage();
     fViewMatrix = drawState.getViewMatrix();
@@ -25,14 +27,14 @@
     fVACount = drawState.getVertexAttribCount();
     fVAStride = drawState.getVertexStride();
     fStencilSettings = drawState.getStencil();
-    fDrawFace = drawState.getDrawFace();
+    fDrawFace = (DrawFace)drawState.getDrawFace();
     fBlendOptFlags = blendOptFlags;
     fSrcBlend = optSrcCoeff;
     fDstBlend = optDstCoeff;
 
     memcpy(fFixedFunctionVertexAttribIndices,
-            drawState.getFixedFunctionVertexAttribIndices(),
-            sizeof(fFixedFunctionVertexAttribIndices));
+           drawState.getFixedFunctionVertexAttribIndices(),
+           sizeof(fFixedFunctionVertexAttribIndices));
 
 
     fInputColorIsUsed = true;
@@ -262,7 +264,76 @@
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
 bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
     return this->isEqual(that);
 }
 
+bool GrOptDrawState::isEqual(const GrOptDrawState& that) const {
+    bool usingVertexColors = this->hasColorVertexAttribute();
+    if (!usingVertexColors && this->fColor != that.fColor) {
+        return false;
+    }
+
+    if (this->getRenderTarget() != that.getRenderTarget() ||
+        this->fColorStages.count() != that.fColorStages.count() ||
+        this->fCoverageStages.count() != that.fCoverageStages.count() ||
+        !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
+        this->fSrcBlend != that.fSrcBlend ||
+        this->fDstBlend != that.fDstBlend ||
+        this->fBlendConstant != that.fBlendConstant ||
+        this->fFlagBits != that.fFlagBits ||
+        this->fVACount != that.fVACount ||
+        this->fVAStride != that.fVAStride ||
+        memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
+        this->fStencilSettings != that.fStencilSettings ||
+        this->fDrawFace != that.fDrawFace ||
+        this->fInputColorIsUsed != that.fInputColorIsUsed ||
+        this->fInputCoverageIsUsed != that.fInputCoverageIsUsed ||
+        this->fReadsDst != that.fReadsDst ||
+        this->fReadsFragPosition != that.fReadsFragPosition ||
+        this->fRequiresLocalCoordAttrib != that.fRequiresLocalCoordAttrib ||
+        this->fPrimaryOutputType != that.fPrimaryOutputType ||
+        this->fSecondaryOutputType != that.fSecondaryOutputType) {
+        return false;
+    }
+
+    bool usingVertexCoverage = this->hasCoverageVertexAttribute();
+    if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
+        return false;
+    }
+
+    bool explicitLocalCoords = this->hasLocalCoordAttribute();
+    if (this->hasGeometryProcessor()) {
+        if (!that.hasGeometryProcessor()) {
+            return false;
+        } else if (!GrProcessorStage::AreCompatible(*this->getGeometryProcessor(),
+                                                    *that.getGeometryProcessor(),
+                                                    explicitLocalCoords)) {
+            return false;
+        }
+    } else if (that.hasGeometryProcessor()) {
+        return false;
+    }
+
+    for (int i = 0; i < this->numColorStages(); i++) {
+        if (!GrProcessorStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
+                                             explicitLocalCoords)) {
+            return false;
+        }
+    }
+    for (int i = 0; i < this->numCoverageStages(); i++) {
+        if (!GrProcessorStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
+                                             explicitLocalCoords)) {
+            return false;
+        }
+    }
+
+    SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices,
+                         that.fFixedFunctionVertexAttribIndices,
+                         sizeof(this->fFixedFunctionVertexAttribIndices)));
+
+    return true;
+}
+
diff --git a/src/gpu/GrOptDrawState.h b/src/gpu/GrOptDrawState.h
index b4f59d3..f0a726e 100644
--- a/src/gpu/GrOptDrawState.h
+++ b/src/gpu/GrOptDrawState.h
@@ -9,17 +9,272 @@
 #define GrOptDrawState_DEFINED
 
 #include "GrDrawState.h"
-#include "GrRODrawState.h"
 
 /**
- * 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
- * base class.
+ * Class that holds an optimized version of a GrDrawState. It is meant to be an immutable class,
+ * and contains all data needed to set the state for a gpu draw.
  */
-class GrOptDrawState : public GrRODrawState {
+class GrOptDrawState : public SkRefCnt {
 public:
     bool operator== (const GrOptDrawState& that) const;
 
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Vertex Attributes
+    ////
+
+    enum {
+        kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
+    };
+
+    const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; }
+    int getVertexAttribCount() const { return fVACount; }
+
+    size_t getVertexStride() const { return fVAStride; }
+
+    /**
+     * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the
+     * binding does not appear in the current attribs. These bindings should appear only once in
+     * the attrib array.
+     */
+
+    int positionAttributeIndex() const {
+        return fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
+    }
+    int localCoordAttributeIndex() const {
+        return fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
+    }
+    int colorVertexAttributeIndex() const {
+        return fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
+    }
+    int coverageVertexAttributeIndex() const {
+        return fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
+    }
+
+    bool hasLocalCoordAttribute() const {
+        return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
+    }
+    bool hasColorVertexAttribute() const {
+        return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
+    }
+    bool hasCoverageVertexAttribute() const {
+        return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
+    }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Color
+    ////
+
+    GrColor getColor() const { return fColor; }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Coverage
+    ////
+
+    uint8_t getCoverage() const { return fCoverage; }
+
+    GrColor getCoverageColor() const {
+        return GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
+    }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Effect Stages
+    /// Each stage hosts a GrProcessor. The effect produces an output color or coverage in the
+    /// fragment shader. Its inputs are the output from the previous stage as well as some variables
+    /// available to it in the fragment and vertex shader (e.g. the vertex position, the dst color,
+    /// the fragment position, local coordinates).
+    ///
+    /// The stages are divided into two sets, color-computing and coverage-computing. The final
+    /// color stage produces the final pixel color. The coverage-computing stages function exactly
+    /// as the color-computing but the output of the final coverage stage is treated as a fractional
+    /// pixel coverage rather than as input to the src/dst color blend step.
+    ///
+    /// The input color to the first color-stage is either the constant color or interpolated
+    /// per-vertex colors. The input to the first coverage stage is either a constant coverage
+    /// (usually full-coverage) or interpolated per-vertex coverage.
+    ///
+    /// See the documentation of kCoverageDrawing_StateBit for information about disabling the
+    /// the color / coverage distinction.
+    ////
+
+    int numColorStages() const { return fColorStages.count(); }
+    int numCoverageStages() const { return fCoverageStages.count(); }
+    int numTotalStages() const {
+         return this->numColorStages() + this->numCoverageStages() +
+                 (this->hasGeometryProcessor() ? 1 : 0);
+    }
+
+    bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
+    const GrGeometryStage* getGeometryProcessor() const { return fGeometryProcessor.get(); }
+    const GrFragmentStage& getColorStage(int idx) const { return fColorStages[idx]; }
+    const GrFragmentStage& getCoverageStage(int idx) const { return fCoverageStages[idx]; }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Blending
+    ////
+
+    GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
+    GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
+
+    /**
+     * Retrieves the last value set by setBlendConstant()
+     * @return the blending constant value
+     */
+    GrColor getBlendConstant() const { return fBlendConstant; }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name View Matrix
+    ////
+
+    /**
+     * Retrieves the current view matrix
+     * @return the current view matrix.
+     */
+    const SkMatrix& getViewMatrix() const { return fViewMatrix; }
+
+    /**
+     *  Retrieves the inverse of the current view matrix.
+     *
+     *  If the current view matrix is invertible, return true, and if matrix
+     *  is non-null, copy the inverse into it. If the current view matrix is
+     *  non-invertible, return false and ignore the matrix parameter.
+     *
+     * @param matrix if not null, will receive a copy of the current inverse.
+     */
+    bool getViewInverse(SkMatrix* matrix) const {
+        SkMatrix inverse;
+        if (fViewMatrix.invert(&inverse)) {
+            if (matrix) {
+                *matrix = inverse;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Render Target
+    ////
+
+    /**
+     * Retrieves the currently set render-target.
+     *
+     * @return    The currently set render target.
+     */
+    GrRenderTarget* getRenderTarget() const {
+        return static_cast<GrRenderTarget*>(fRenderTarget.getResource());
+    }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Stencil
+    ////
+
+    const GrStencilSettings& getStencil() const { return fStencilSettings; }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name State Flags
+    ////
+
+    /**
+     *  Flags that affect rendering. Controlled using enable/disableState(). All
+     *  default to disabled.
+     */
+    enum StateBits {
+        /**
+         * Perform dithering. TODO: Re-evaluate whether we need this bit
+         */
+        kDither_StateBit        = 0x01,
+        /**
+         * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
+         * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
+         * the 3D API.
+         */
+        kHWAntialias_StateBit   = 0x02,
+        /**
+         * Draws will respect the clip, otherwise the clip is ignored.
+         */
+        kClip_StateBit          = 0x04,
+        /**
+         * Disables writing to the color buffer. Useful when performing stencil
+         * operations.
+         */
+        kNoColorWrites_StateBit = 0x08,
+
+        /**
+         * Usually coverage is applied after color blending. The color is blended using the coeffs
+         * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
+         * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
+         * this case there is no distinction between coverage and color and the caller needs direct
+         * control over the blend coeffs. When set, there will be a single blend step controlled by
+         * setBlendFunc() which will use coverage*color as the src color.
+         */
+         kCoverageDrawing_StateBit = 0x10,
+
+        // Users of the class may add additional bits to the vector
+        kDummyStateBit,
+        kLastPublicStateBit = kDummyStateBit-1,
+    };
+
+    bool isStateFlagEnabled(uint32_t stateBit) const { return 0 != (stateBit & fFlagBits); }
+
+    bool isDitherState() const { return 0 != (fFlagBits & kDither_StateBit); }
+    bool isHWAntialiasState() const { return 0 != (fFlagBits & kHWAntialias_StateBit); }
+    bool isClipState() const { return 0 != (fFlagBits & kClip_StateBit); }
+    bool isColorWriteDisabled() const { return 0 != (fFlagBits & kNoColorWrites_StateBit); }
+    bool isCoverageDrawing() const { return 0 != (fFlagBits & kCoverageDrawing_StateBit); }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Face Culling
+    ////
+
+    enum DrawFace {
+        kInvalid_DrawFace = -1,
+
+        kBoth_DrawFace,
+        kCCW_DrawFace,
+        kCW_DrawFace,
+    };
+
+    /**
+     * Gets whether the target is drawing clockwise, counterclockwise,
+     * or both faces.
+     * @return the current draw face(s).
+     */
+    DrawFace getDrawFace() const { return fDrawFace; }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    /** Return type for CombineIfPossible. */
+    enum CombinedState {
+        /** The GrDrawStates cannot be combined. */
+        kIncompatible_CombinedState,
+        /** Either draw state can be used in place of the other. */
+        kAOrB_CombinedState,
+        /** Use the first draw state. */
+        kA_CombinedState,
+        /** Use the second draw state. */
+        kB_CombinedState,
+    };
+
     bool inputColorIsUsed() const { return fInputColorIsUsed; }
     bool inputCoverageIsUsed() const { return fInputCoverageIsUsed; }
 
@@ -64,6 +319,35 @@
 
 private:
     /**
+     * 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);
+
+    /**
      * Constructs and optimized drawState out of a GrRODrawState.
      */
     GrOptDrawState(const GrDrawState& drawState, BlendOptFlags blendOptFlags,
@@ -114,6 +398,33 @@
      */
     void setOutputStateInfo(const GrDrawTargetCaps&);
 
+    bool isEqual(const GrOptDrawState& that) const;
+
+    // These fields are roughly sorted by decreasing likelihood of being different in op==
+    typedef GrTGpuResourceRef<GrRenderTarget> ProgramRenderTarget;
+    ProgramRenderTarget                 fRenderTarget;
+    GrColor                             fColor;
+    SkMatrix                            fViewMatrix;
+    GrColor                             fBlendConstant;
+    uint32_t                            fFlagBits;
+    const GrVertexAttrib*               fVAPtr;
+    int                                 fVACount;
+    size_t                              fVAStride;
+    GrStencilSettings                   fStencilSettings;
+    uint8_t                             fCoverage;
+    DrawFace                            fDrawFace;
+    GrBlendCoeff                        fSrcBlend;
+    GrBlendCoeff                        fDstBlend;
+
+    typedef SkSTArray<4, GrFragmentStage> FragmentStageArray;
+    SkAutoTDelete<GrGeometryStage>        fGeometryProcessor;
+    FragmentStageArray                    fColorStages;
+    FragmentStageArray                    fCoverageStages;
+
+    // This is simply a different representation of info in fVertexAttribs and thus does
+    // not need to be compared in op==.
+    int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
+
     // These flags are needed to protect the code from creating an unused uniform color/coverage
     // which will cause shader compiler errors.
     bool            fInputColorIsUsed;
@@ -133,7 +444,10 @@
     SecondaryOutputType  fSecondaryOutputType : 8;
 
     friend GrOptDrawState* GrDrawState::createOptState(const GrDrawTargetCaps&) const;
-    typedef GrRODrawState INHERITED;
+    typedef SkRefCnt INHERITED;
 };
 
+GR_MAKE_BITFIELD_OPS(GrOptDrawState::BlendOptFlags);
+
 #endif
+
diff --git a/src/gpu/GrRODrawState.cpp b/src/gpu/GrRODrawState.cpp
deleted file mode 100644
index 2a673f3..0000000
--- a/src/gpu/GrRODrawState.cpp
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrRODrawState.h"
-
-#include "GrDrawTargetCaps.h"
-#include "GrRenderTarget.h"
-
-////////////////////////////////////////////////////////////////////////////////
-
-GrRODrawState::GrRODrawState(const GrRODrawState& drawState) : INHERITED() {
-    fRenderTarget.setResource(SkSafeRef(drawState.fRenderTarget.getResource()),
-                              GrIORef::kWrite_IOType);
-}
-
-bool GrRODrawState::isEqual(const GrRODrawState& that) const {
-    bool usingVertexColors = this->hasColorVertexAttribute();
-    if (!usingVertexColors && this->fColor != that.fColor) {
-        return false;
-    }
-
-    if (this->getRenderTarget() != that.getRenderTarget() ||
-        this->fColorStages.count() != that.fColorStages.count() ||
-        this->fCoverageStages.count() != that.fCoverageStages.count() ||
-        !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
-        this->fSrcBlend != that.fSrcBlend ||
-        this->fDstBlend != that.fDstBlend ||
-        this->fBlendConstant != that.fBlendConstant ||
-        this->fFlagBits != that.fFlagBits ||
-        this->fVACount != that.fVACount ||
-        this->fVAStride != that.fVAStride ||
-        memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
-        this->fStencilSettings != that.fStencilSettings ||
-        this->fDrawFace != that.fDrawFace) {
-        return false;
-    }
-
-    bool usingVertexCoverage = this->hasCoverageVertexAttribute();
-    if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
-        return false;
-    }
-
-    bool explicitLocalCoords = this->hasLocalCoordAttribute();
-    if (this->hasGeometryProcessor()) {
-        if (!that.hasGeometryProcessor()) {
-            return false;
-        } else if (!GrProcessorStage::AreCompatible(*this->getGeometryProcessor(),
-                                                    *that.getGeometryProcessor(),
-                                                    explicitLocalCoords)) {
-            return false;
-        }
-    } else if (that.hasGeometryProcessor()) {
-        return false;
-    }
-
-    for (int i = 0; i < this->numColorStages(); i++) {
-        if (!GrProcessorStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
-                                             explicitLocalCoords)) {
-            return false;
-        }
-    }
-    for (int i = 0; i < this->numCoverageStages(); i++) {
-        if (!GrProcessorStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
-                                             explicitLocalCoords)) {
-            return false;
-        }
-    }
-
-    SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices,
-                            that.fFixedFunctionVertexAttribIndices,
-                            sizeof(this->fFixedFunctionVertexAttribIndices)));
-
-    return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-bool GrRODrawState::validateVertexAttribs() const {
-    // check consistency of effects and attributes
-    GrSLType slTypes[kMaxVertexAttribCnt];
-    for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
-        slTypes[i] = static_cast<GrSLType>(-1);
-    }
-
-    if (this->hasGeometryProcessor()) {
-        const GrGeometryStage& stage = *this->getGeometryProcessor();
-        const GrGeometryProcessor* gp = stage.getGeometryProcessor();
-        SkASSERT(gp);
-        // make sure that any attribute indices have the correct binding type, that the attrib
-        // type and effect's shader lang type are compatible, and that attributes shared by
-        // multiple effects use the same shader lang type.
-        const GrGeometryProcessor::VertexAttribArray& s = gp->getVertexAttribs();
-
-        int effectIndex = 0;
-        for (int index = 0; index < fVACount; index++) {
-            if (kGeometryProcessor_GrVertexAttribBinding != fVAPtr[index].fBinding) {
-                // we only care about effect bindings
-                continue;
-            }
-            SkASSERT(effectIndex < s.count());
-            GrSLType effectSLType = s[effectIndex].getType();
-            GrVertexAttribType attribType = fVAPtr[index].fType;
-            int slVecCount = GrSLTypeVectorCount(effectSLType);
-            int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
-            if (slVecCount != attribVecCount ||
-                (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) {
-                return false;
-            }
-            slTypes[index] = effectSLType;
-            effectIndex++;
-        }
-        // Make sure all attributes are consumed and we were able to find everything
-        SkASSERT(s.count() == effectIndex);
-    }
-
-    return true;
-}
-
-bool GrRODrawState::hasSolidCoverage() const {
-    // If we're drawing coverage directly then coverage is effectively treated as color.
-    if (this->isCoverageDrawing()) {
-        return true;
-    }
-
-    GrColor coverage;
-    uint32_t validComponentFlags;
-    // Initialize to an unknown starting coverage if per-vertex coverage is specified.
-    if (this->hasCoverageVertexAttribute()) {
-        validComponentFlags = 0;
-    } else {
-        coverage = fCoverage;
-        validComponentFlags = kRGBA_GrColorComponentFlags;
-    }
-
-    // Run through the coverage stages and see if the coverage will be all ones at the end.
-    if (this->hasGeometryProcessor()) {
-        const GrGeometryProcessor* gp = fGeometryProcessor->getGeometryProcessor();
-        gp->getConstantColorComponents(&coverage, &validComponentFlags);
-    }
-    for (int s = 0; s < this->numCoverageStages(); ++s) {
-        const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
-        processor->getConstantColorComponents(&coverage, &validComponentFlags);
-    }
-    return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-bool GrRODrawState::willEffectReadDstColor() const {
-    if (!this->isColorWriteDisabled()) {
-        for (int s = 0; s < this->numColorStages(); ++s) {
-            if (this->getColorStage(s).getFragmentProcessor()->willReadDstColor()) {
-                return true;
-            }
-        }
-    }
-    for (int s = 0; s < this->numCoverageStages(); ++s) {
-        if (this->getCoverageStage(s).getFragmentProcessor()->willReadDstColor()) {
-            return true;
-        }
-    }
-    return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-GrRODrawState::BlendOptFlags GrRODrawState::getBlendOpts(bool forceCoverage,
-                                                         GrBlendCoeff* srcCoeff,
-                                                         GrBlendCoeff* dstCoeff) const {
-    GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
-    if (NULL == srcCoeff) {
-        srcCoeff = &bogusSrcCoeff;
-    }
-    if (NULL == dstCoeff) {
-        dstCoeff = &bogusDstCoeff;
-    }
-
-    *srcCoeff = this->getSrcBlendCoeff();
-    *dstCoeff = this->getDstBlendCoeff();
-
-    if (this->isColorWriteDisabled()) {
-        *srcCoeff = kZero_GrBlendCoeff;
-        *dstCoeff = kOne_GrBlendCoeff;
-    }
-
-    bool srcAIsOne = this->srcAlphaWillBeOne();
-    bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
-                         (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
-    bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
-                         (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
-
-    // When coeffs are (0,1) there is no reason to draw at all, unless
-    // stenciling is enabled. Having color writes disabled is effectively
-    // (0,1).
-    if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
-        if (this->getStencil().doesWrite()) {
-            return kEmitCoverage_BlendOptFlag;
-        } else {
-            *dstCoeff = kOne_GrBlendCoeff;
-            return kSkipDraw_BlendOptFlag;
-        }
-    }
-
-    bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
-
-    // if we don't have coverage we can check whether the dst
-    // has to read at all. If not, we'll disable blending.
-    if (!hasCoverage) {
-        if (dstCoeffIsZero) {
-            if (kOne_GrBlendCoeff == *srcCoeff) {
-                // if there is no coverage and coeffs are (1,0) then we
-                // won't need to read the dst at all, it gets replaced by src
-                *dstCoeff = kZero_GrBlendCoeff;
-                return kNone_BlendOpt;
-            } else if (kZero_GrBlendCoeff == *srcCoeff) {
-                // if the op is "clear" then we don't need to emit a color
-                // or blend, just write transparent black into the dst.
-                *srcCoeff = kOne_GrBlendCoeff;
-                *dstCoeff = kZero_GrBlendCoeff;
-                return kEmitTransBlack_BlendOptFlag;
-            }
-        }
-    } else if (this->isCoverageDrawing()) {
-        // we have coverage but we aren't distinguishing it from alpha by request.
-        return kCoverageAsAlpha_BlendOptFlag;
-    } else {
-        // check whether coverage can be safely rolled into alpha
-        // of if we can skip color computation and just emit coverage
-        if (this->canTweakAlphaForCoverage()) {
-            return kCoverageAsAlpha_BlendOptFlag;
-        }
-        if (dstCoeffIsZero) {
-            if (kZero_GrBlendCoeff == *srcCoeff) {
-                // the source color is not included in the blend
-                // the dst coeff is effectively zero so blend works out to:
-                // (c)(0)D + (1-c)D = (1-c)D.
-                *dstCoeff = kISA_GrBlendCoeff;
-                return  kEmitCoverage_BlendOptFlag;
-            } else if (srcAIsOne) {
-                // the dst coeff is effectively zero so blend works out to:
-                // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
-                // If Sa is 1 then we can replace Sa with c
-                // and set dst coeff to 1-Sa.
-                *dstCoeff = kISA_GrBlendCoeff;
-                return  kCoverageAsAlpha_BlendOptFlag;
-            }
-        } else if (dstCoeffIsOne) {
-            // the dst coeff is effectively one so blend works out to:
-            // cS + (c)(1)D + (1-c)D = cS + D.
-            *dstCoeff = kOne_GrBlendCoeff;
-            return  kCoverageAsAlpha_BlendOptFlag;
-        }
-    }
-
-    return kNone_BlendOpt;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
-// others will blend incorrectly.
-bool GrRODrawState::canTweakAlphaForCoverage() const {
-    /*
-     The fractional coverage is f.
-     The src and dst coeffs are Cs and Cd.
-     The dst and src colors are S and D.
-     We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
-     we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
-     term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
-     find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
-     Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
-     color by definition.
-     */
-    return kOne_GrBlendCoeff == fDstBlend ||
-           kISA_GrBlendCoeff == fDstBlend ||
-           kISC_GrBlendCoeff == fDstBlend ||
-           this->isCoverageDrawing();
-}
-
-void GrRODrawState::convertToPendingExec() {
-    fRenderTarget.markPendingIO();
-    fRenderTarget.removeRef();
-    for (int i = 0; i < fColorStages.count(); ++i) {
-        fColorStages[i].convertToPendingExec();
-    }
-    if (fGeometryProcessor) {
-        fGeometryProcessor->convertToPendingExec();
-    }
-    for (int i = 0; i < fCoverageStages.count(); ++i) {
-        fCoverageStages[i].convertToPendingExec();
-    }
-}
-
-bool GrRODrawState::srcAlphaWillBeOne() const {
-    uint32_t validComponentFlags;
-    GrColor color;
-    // Check if per-vertex or constant color may have partial alpha
-    if (this->hasColorVertexAttribute()) {
-        if (fHints & kVertexColorsAreOpaque_Hint) {
-            validComponentFlags = kA_GrColorComponentFlag;
-            color = 0xFF << GrColor_SHIFT_A;
-        } else {
-            validComponentFlags = 0;
-            color = 0; // not strictly necessary but we get false alarms from tools about uninit.
-        }
-    } else {
-        validComponentFlags = kRGBA_GrColorComponentFlags;
-        color = this->getColor();
-    }
-
-    // Run through the color stages
-    for (int s = 0; s < this->numColorStages(); ++s) {
-        const GrProcessor* processor = this->getColorStage(s).getProcessor();
-        processor->getConstantColorComponents(&color, &validComponentFlags);
-    }
-
-    // Check whether coverage is treated as color. If so we run through the coverage computation.
-    if (this->isCoverageDrawing()) {
-        // The shader generated for coverage drawing runs the full coverage computation and then
-        // makes the shader output be the multiplication of color and coverage. We mirror that here.
-        GrColor coverage;
-        uint32_t coverageComponentFlags;
-        if (this->hasCoverageVertexAttribute()) {
-            coverageComponentFlags = 0;
-            coverage = 0; // suppresses any warnings.
-        } else {
-            coverageComponentFlags = kRGBA_GrColorComponentFlags;
-            coverage = this->getCoverageColor();
-        }
-
-        // Run through the coverage stages
-        for (int s = 0; s < this->numCoverageStages(); ++s) {
-            const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
-            processor->getConstantColorComponents(&coverage, &coverageComponentFlags);
-        }
-
-        // Since the shader will multiply coverage and color, the only way the final A==1 is if
-        // coverage and color both have A==1.
-        return (kA_GrColorComponentFlag & validComponentFlags & coverageComponentFlags) &&
-                0xFF == GrColorUnpackA(color) && 0xFF == GrColorUnpackA(coverage);
-
-    }
-
-    return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color);
-}
-
diff --git a/src/gpu/GrRODrawState.h b/src/gpu/GrRODrawState.h
deleted file mode 100644
index ac263ff..0000000
--- a/src/gpu/GrRODrawState.h
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrRODrawState_DEFINED
-#define GrRODrawState_DEFINED
-
-#include "GrProcessorStage.h"
-#include "GrRenderTarget.h"
-#include "GrStencil.h"
-#include "SkMatrix.h"
-
-class GrDrawState;
-class GrDrawTargetCaps;
-class GrPaint;
-class GrTexture;
-
-/**
- * Read-only base class for GrDrawState. This class contains all the necessary data to represent a
- * canonical DrawState. All methods in the class are const, thus once created the data in the class
- * cannot be changed.
- */
-class GrRODrawState : public SkRefCnt {
-public:
-    SK_DECLARE_INST_COUNT(GrRODrawState)
-
-    GrRODrawState() {}
-
-    GrRODrawState& operator= (const GrRODrawState& that);
-
-    ///////////////////////////////////////////////////////////////////////////
-    /// @name Vertex Attributes
-    ////
-
-    enum {
-        kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
-    };
-
-    const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; }
-    int getVertexAttribCount() const { return fVACount; }
-
-    size_t getVertexStride() const { return fVAStride; }
-
-    /**
-     * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the
-     * binding does not appear in the current attribs. These bindings should appear only once in
-     * the attrib array.
-     */
-
-    int positionAttributeIndex() const {
-        return fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
-    }
-    int localCoordAttributeIndex() const {
-        return fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
-    }
-    int colorVertexAttributeIndex() const {
-        return fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
-    }
-    int coverageVertexAttributeIndex() const {
-        return fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
-    }
-
-    bool hasLocalCoordAttribute() const {
-        return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
-    }
-    bool hasColorVertexAttribute() const {
-        return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
-    }
-    bool hasCoverageVertexAttribute() const {
-        return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
-    }
-
-    const int* getFixedFunctionVertexAttribIndices() const {
-        return fFixedFunctionVertexAttribIndices;
-    }
-
-    bool validateVertexAttribs() const;
-
-    /// @}
-
-    /**
-     * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
-     */
-    bool hasSolidCoverage() const;
-
-    /// @}
-
-    ///////////////////////////////////////////////////////////////////////////
-    /// @name Color
-    ////
-
-    GrColor getColor() const { return fColor; }
-
-    /// @}
-
-    ///////////////////////////////////////////////////////////////////////////
-    /// @name Coverage
-    ////
-
-    uint8_t getCoverage() const { return fCoverage; }
-
-    GrColor getCoverageColor() const {
-        return GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
-    }
-
-    /// @}
-
-    ///////////////////////////////////////////////////////////////////////////
-    /// @name Effect Stages
-    /// Each stage hosts a GrProcessor. The effect produces an output color or coverage in the
-    /// fragment shader. Its inputs are the output from the previous stage as well as some variables
-    /// available to it in the fragment and vertex shader (e.g. the vertex position, the dst color,
-    /// the fragment position, local coordinates).
-    ///
-    /// The stages are divided into two sets, color-computing and coverage-computing. The final
-    /// color stage produces the final pixel color. The coverage-computing stages function exactly
-    /// as the color-computing but the output of the final coverage stage is treated as a fractional
-    /// pixel coverage rather than as input to the src/dst color blend step.
-    ///
-    /// The input color to the first color-stage is either the constant color or interpolated
-    /// per-vertex colors. The input to the first coverage stage is either a constant coverage
-    /// (usually full-coverage) or interpolated per-vertex coverage.
-    ///
-    /// See the documentation of kCoverageDrawing_StateBit for information about disabling the
-    /// the color / coverage distinction.
-    ////
-
-    int numColorStages() const { return fColorStages.count(); }
-    int numCoverageStages() const { return fCoverageStages.count(); }
-    int numTotalStages() const {
-         return this->numColorStages() + this->numCoverageStages() +
-                 (this->hasGeometryProcessor() ? 1 : 0);
-    }
-
-    bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
-    const GrGeometryStage* getGeometryProcessor() const { return fGeometryProcessor.get(); }
-    const GrFragmentStage& getColorStage(int stageIdx) const { return fColorStages[stageIdx]; }
-    const GrFragmentStage& getCoverageStage(int stageIdx) const { return fCoverageStages[stageIdx]; }
-
-    /**
-     * Checks whether any of the effects will read the dst pixel color.
-     */
-    bool willEffectReadDstColor() const;
-
-    /// @}
-
-    ///////////////////////////////////////////////////////////////////////////
-    /// @name Blending
-    ////
-
-    GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
-    GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
-
-    void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
-                          GrBlendCoeff* dstBlendCoeff) const {
-        *srcBlendCoeff = fSrcBlend;
-        *dstBlendCoeff = fDstBlend;
-    }
-
-    /**
-     * Retrieves the last value set by setBlendConstant()
-     * @return the blending constant value
-     */
-    GrColor getBlendConstant() const { return fBlendConstant; }
-
-    /**
-     * 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;
-
-    /// @}
-
-    ///////////////////////////////////////////////////////////////////////////
-    /// @name View Matrix
-    ////
-
-    /**
-     * Retrieves the current view matrix
-     * @return the current view matrix.
-     */
-    const SkMatrix& getViewMatrix() const { return fViewMatrix; }
-
-    /**
-     *  Retrieves the inverse of the current view matrix.
-     *
-     *  If the current view matrix is invertible, return true, and if matrix
-     *  is non-null, copy the inverse into it. If the current view matrix is
-     *  non-invertible, return false and ignore the matrix parameter.
-     *
-     * @param matrix if not null, will receive a copy of the current inverse.
-     */
-    bool getViewInverse(SkMatrix* matrix) const {
-        // TODO: determine whether we really need to leave matrix unmodified
-        // at call sites when inversion fails.
-        SkMatrix inverse;
-        if (fViewMatrix.invert(&inverse)) {
-            if (matrix) {
-                *matrix = inverse;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /// @}
-
-    ///////////////////////////////////////////////////////////////////////////
-    /// @name Render Target
-    ////
-
-    /**
-     * Retrieves the currently set render-target.
-     *
-     * @return    The currently set render target.
-     */
-    GrRenderTarget* getRenderTarget() const {
-        return static_cast<GrRenderTarget*>(fRenderTarget.getResource());
-    }
-
-    /// @}
-
-    ///////////////////////////////////////////////////////////////////////////
-    /// @name Stencil
-    ////
-
-    const GrStencilSettings& getStencil() const { return fStencilSettings; }
-
-    /// @}
-
-    ///////////////////////////////////////////////////////////////////////////
-    /// @name State Flags
-    ////
-
-    /**
-     *  Flags that affect rendering. Controlled using enable/disableState(). All
-     *  default to disabled.
-     */
-    enum StateBits {
-        /**
-         * Perform dithering. TODO: Re-evaluate whether we need this bit
-         */
-        kDither_StateBit        = 0x01,
-        /**
-         * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
-         * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
-         * the 3D API.
-         */
-        kHWAntialias_StateBit   = 0x02,
-        /**
-         * Draws will respect the clip, otherwise the clip is ignored.
-         */
-        kClip_StateBit          = 0x04,
-        /**
-         * Disables writing to the color buffer. Useful when performing stencil
-         * operations.
-         */
-        kNoColorWrites_StateBit = 0x08,
-
-        /**
-         * Usually coverage is applied after color blending. The color is blended using the coeffs
-         * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
-         * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
-         * this case there is no distinction between coverage and color and the caller needs direct
-         * control over the blend coeffs. When set, there will be a single blend step controlled by
-         * setBlendFunc() which will use coverage*color as the src color.
-         */
-         kCoverageDrawing_StateBit = 0x10,
-
-        // Users of the class may add additional bits to the vector
-        kDummyStateBit,
-        kLastPublicStateBit = kDummyStateBit-1,
-    };
-
-    uint32_t getFlagBits() const { return fFlagBits; }
-
-    bool isStateFlagEnabled(uint32_t stateBit) const { return 0 != (stateBit & fFlagBits); }
-
-    bool isDitherState() const { return 0 != (fFlagBits & kDither_StateBit); }
-    bool isHWAntialiasState() const { return 0 != (fFlagBits & kHWAntialias_StateBit); }
-    bool isClipState() const { return 0 != (fFlagBits & kClip_StateBit); }
-    bool isColorWriteDisabled() const { return 0 != (fFlagBits & kNoColorWrites_StateBit); }
-    bool isCoverageDrawing() const { return 0 != (fFlagBits & kCoverageDrawing_StateBit); }
-
-    /// @}
-
-    ///////////////////////////////////////////////////////////////////////////
-    /// @name Face Culling
-    ////
-
-    enum DrawFace {
-        kInvalid_DrawFace = -1,
-
-        kBoth_DrawFace,
-        kCCW_DrawFace,
-        kCW_DrawFace,
-    };
-
-    /**
-     * Gets whether the target is drawing clockwise, counterclockwise,
-     * or both faces.
-     * @return the current draw face(s).
-     */
-    DrawFace getDrawFace() const { return fDrawFace; }
-
-    /// @}
-
-    ///////////////////////////////////////////////////////////////////////////
-    /// @name Hints
-    /// Hints that when provided can enable optimizations.
-    ////
-
-    enum Hints { kVertexColorsAreOpaque_Hint = 0x1, };
-
-    bool vertexColorsAreOpaque() const { return kVertexColorsAreOpaque_Hint & fHints; }
-
-    /// @}
-
-    ///////////////////////////////////////////////////////////////////////////
-
-    /** Return type for CombineIfPossible. */
-    enum CombinedState {
-        /** The GrDrawStates cannot be combined. */
-        kIncompatible_CombinedState,
-        /** Either draw state can be used in place of the other. */
-        kAOrB_CombinedState,
-        /** Use the first draw state. */
-        kA_CombinedState,
-        /** Use the second draw state. */
-        kB_CombinedState,
-    };
-
-protected:
-    /**
-     * Converts refs on GrGpuResources owned directly or indirectly by this GrRODrawState into
-     * pending reads and writes. This should be called when a GrDrawState is recorded into
-     * a GrDrawTarget for later execution. Subclasses of GrRODrawState may add setters. However,
-     * once this call has been made the GrRODrawState is immutable. It is also no longer copyable.
-     * In the future this conversion will automatically happen when converting a GrDrawState into
-     * an optimized draw state.
-     */
-    void convertToPendingExec();
-
-    friend class GrDrawTarget;
-
-    explicit GrRODrawState(const GrRODrawState& drawState);
-
-    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;
-
-    typedef GrTGpuResourceRef<GrRenderTarget> ProgramRenderTarget;
-    // These fields are roughly sorted by decreasing likelihood of being different in op==
-    ProgramRenderTarget                 fRenderTarget;
-    GrColor                             fColor;
-    SkMatrix                            fViewMatrix;
-    GrColor                             fBlendConstant;
-    uint32_t                            fFlagBits;
-    const GrVertexAttrib*               fVAPtr;
-    int                                 fVACount;
-    size_t                              fVAStride;
-    GrStencilSettings                   fStencilSettings;
-    uint8_t                             fCoverage;
-    DrawFace                            fDrawFace;
-    GrBlendCoeff                        fSrcBlend;
-    GrBlendCoeff                        fDstBlend;
-
-    typedef SkSTArray<4, GrFragmentStage>   FragmentStageArray;
-    SkAutoTDelete<GrGeometryStage>          fGeometryProcessor;
-    FragmentStageArray                      fColorStages;
-    FragmentStageArray                      fCoverageStages;
-
-    uint32_t                            fHints;
-
-    // This is simply a different representation of info in fVertexAttribs and thus does
-    // not need to be compared in op==.
-    int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
-
-private:
-    /**
-     * Determines whether src alpha is guaranteed to be one for all src pixels
-     */
-    bool srcAlphaWillBeOne() const;
-
-    typedef SkRefCnt INHERITED;
-};
-
-GR_MAKE_BITFIELD_OPS(GrRODrawState::BlendOptFlags);
-
-#endif
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index a01f7b7..be38511 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -239,7 +239,7 @@
         GL_CALL(Disable(GR_GL_DEPTH_TEST));
         GL_CALL(DepthMask(GR_GL_FALSE));
 
-        fHWDrawFace = GrDrawState::kInvalid_DrawFace;
+        fHWDrawFace = GrOptDrawState::kInvalid_DrawFace;
         fHWDitherEnabled = kUnknown_TriState;
 
         if (kGL_GrGLStandard == this->glStandard()) {
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 65816b5..e5f2915 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -431,7 +431,7 @@
     TriState                    fHWStencilTestEnabled;
 
 
-    GrDrawState::DrawFace       fHWDrawFace;
+    GrOptDrawState::DrawFace    fHWDrawFace;
     TriState                    fHWWriteToColor;
     TriState                    fHWDitherEnabled;
     uint32_t                    fHWBoundRenderTargetUniqueID;