Drawstate on stack

BUG=skia:

Review URL: https://codereview.chromium.org/732693002
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index c3275c8..934eb04 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -610,9 +610,10 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-bool GrAAConvexPathRenderer::canDrawPath(const SkPath& path,
+bool GrAAConvexPathRenderer::canDrawPath(const GrDrawTarget* target,
+                                         const GrDrawState*,
+                                         const SkPath& path,
                                          const SkStrokeRec& stroke,
-                                         const GrDrawTarget* target,
                                          bool antiAlias) const {
     return (target->caps()->shaderDerivativeSupport() && antiAlias &&
             stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex());
@@ -628,9 +629,10 @@
 
 };
 
-bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
+bool GrAAConvexPathRenderer::onDrawPath(GrDrawTarget* target,
+                                        GrDrawState* drawState,
+                                        const SkPath& origPath,
                                         const SkStrokeRec&,
-                                        GrDrawTarget* target,
                                         bool antiAlias) {
 
     const SkPath* path = &origPath;
@@ -638,12 +640,11 @@
         return true;
     }
 
-    SkMatrix viewMatrix = target->getDrawState().getViewMatrix();
-    GrDrawTarget::AutoStateRestore asr;
-    if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
+    SkMatrix viewMatrix = drawState->getViewMatrix();
+    GrDrawState::AutoViewMatrixRestore avmr;
+    if (!avmr.setIdentity(drawState)) {
         return false;
     }
-    GrDrawState* drawState = target->drawState();
 
     // We use the fact that SkPath::transform path does subdivision based on
     // perspective. Otherwise, we apply the view matrix when copying to the
@@ -682,7 +683,7 @@
     GrGeometryProcessor* quadProcessor = QuadEdgeEffect::Create();
     drawState->setGeometryProcessor(quadProcessor)->unref();
 
-    GrDrawTarget::AutoReleaseGeometry arg(target, vCount, iCount);
+    GrDrawTarget::AutoReleaseGeometry arg(target, vCount, drawState->getVertexStride(), iCount);
     if (!arg.succeeded()) {
         return false;
     }
@@ -707,7 +708,8 @@
     int vOffset = 0;
     for (int i = 0; i < draws.count(); ++i) {
         const Draw& draw = draws[i];
-        target->drawIndexed(kTriangles_GrPrimitiveType,
+        target->drawIndexed(drawState,
+                            kTriangles_GrPrimitiveType,
                             vOffset,  // start vertex
                             0,        // start index
                             draw.fVertexCnt,
diff --git a/src/gpu/GrAAConvexPathRenderer.h b/src/gpu/GrAAConvexPathRenderer.h
index 4dd8585..bb40e19 100644
--- a/src/gpu/GrAAConvexPathRenderer.h
+++ b/src/gpu/GrAAConvexPathRenderer.h
@@ -15,15 +15,17 @@
 public:
     GrAAConvexPathRenderer();
 
-    virtual bool canDrawPath(const SkPath& path,
-                             const SkStrokeRec& stroke,
-                             const GrDrawTarget* target,
+    virtual bool canDrawPath(const GrDrawTarget*,
+                             const GrDrawState*,
+                             const SkPath&,
+                             const SkStrokeRec&,
                              bool antiAlias) const SK_OVERRIDE;
 
 protected:
-    virtual bool onDrawPath(const SkPath& path,
-                            const SkStrokeRec& stroke,
-                            GrDrawTarget* target,
+    virtual bool onDrawPath(GrDrawTarget*,
+                            GrDrawState*,
+                            const SkPath&,
+                            const SkStrokeRec&,
                             bool antiAlias) SK_OVERRIDE;
 };
 
diff --git a/src/gpu/GrAADistanceFieldPathRenderer.cpp b/src/gpu/GrAADistanceFieldPathRenderer.cpp
index cb0c892..5e0410f 100755
--- a/src/gpu/GrAADistanceFieldPathRenderer.cpp
+++ b/src/gpu/GrAADistanceFieldPathRenderer.cpp
@@ -65,9 +65,10 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-bool GrAADistanceFieldPathRenderer::canDrawPath(const SkPath& path,
+bool GrAADistanceFieldPathRenderer::canDrawPath(const GrDrawTarget* target,
+                                                const GrDrawState* drawState,
+                                                const SkPath& path,
                                                 const SkStrokeRec& stroke,
-                                                const GrDrawTarget* target,
                                                 bool antiAlias) const {
     
     // TODO: Support inverse fill
@@ -78,8 +79,7 @@
     }
 
     // currently don't support perspective
-    const GrDrawState& drawState = target->getDrawState();
-    const SkMatrix& vm = drawState.getViewMatrix();
+    const SkMatrix& vm = drawState->getViewMatrix();
     if (vm.hasPerspective()) {
         return false;
     }
@@ -93,10 +93,11 @@
 }
 
 
-GrPathRenderer::StencilSupport GrAADistanceFieldPathRenderer::onGetStencilSupport(
-                                                                       const SkPath&,
-                                                                       const SkStrokeRec&,
-                                                                       const GrDrawTarget*) const {
+GrPathRenderer::StencilSupport
+GrAADistanceFieldPathRenderer::onGetStencilSupport(const GrDrawTarget*,
+                                                   const GrDrawState*,
+                                                   const SkPath&,
+                                                   const SkStrokeRec&) const {
     return GrPathRenderer::kNoSupport_StencilSupport;
 }
 
@@ -109,9 +110,10 @@
 };
 static const size_t kSDFPathVASize = 2 * sizeof(SkPoint);
 
-bool GrAADistanceFieldPathRenderer::onDrawPath(const SkPath& path,
+bool GrAADistanceFieldPathRenderer::onDrawPath(GrDrawTarget* target,
+                                               GrDrawState* drawState,
+                                               const SkPath& path,
                                                const SkStrokeRec& stroke,
-                                               GrDrawTarget* target,
                                                bool antiAlias) {
     // we've already bailed on inverse filled paths, so this is safe
     if (path.isEmpty()) {
@@ -121,8 +123,7 @@
     SkASSERT(fContext);
 
     // get mip level
-    const GrDrawState& drawState = target->getDrawState();
-    const SkMatrix& vm = drawState.getViewMatrix();
+    const SkMatrix& vm = drawState->getViewMatrix();
     SkScalar maxScale = vm.getMaxScale();
     const SkRect& bounds = path.getBounds();
     SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
@@ -149,7 +150,7 @@
     }
 
     // use signed distance field to render
-    return this->internalDrawPath(path, pathData, target);
+    return this->internalDrawPath(target, drawState, path, pathData);
 }
 
 // padding around path bounds to allow for antialiased pixels
@@ -310,11 +311,11 @@
     return true;
 }
 
-bool GrAADistanceFieldPathRenderer::internalDrawPath(const SkPath& path,
-                                                     const PathData* pathData,
-                                                     GrDrawTarget* target) {
+bool GrAADistanceFieldPathRenderer::internalDrawPath(GrDrawTarget* target,
+                                                     GrDrawState* drawState,
+                                                     const SkPath& path,
+                                                     const PathData* pathData) {
     GrTexture* texture = fAtlas->getTexture();
-    GrDrawState* drawState = target->drawState();
     GrDrawState::AutoRestoreEffects are(drawState);
     
     SkASSERT(pathData->fPlot);
@@ -325,7 +326,8 @@
     drawState->setVertexAttribs<gSDFPathVertexAttribs>(SK_ARRAY_COUNT(gSDFPathVertexAttribs),
                                                        kSDFPathVASize);
     void* vertices = NULL;
-    bool success = target->reserveVertexAndIndexSpace(4, 0, &vertices, NULL);
+    bool success = target->reserveVertexAndIndexSpace(4, drawState->getVertexStride(), 0, &vertices,
+                                                      NULL);
     GrAlwaysAssert(success);
     
     SkScalar dx = pathData->fBounds.fLeft;
@@ -375,7 +377,7 @@
 
     vm.mapRect(&r);
     target->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
-    target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &r);
+    target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 4, 6, &r);
     target->resetVertexSource();
     
     return true;
diff --git a/src/gpu/GrAADistanceFieldPathRenderer.h b/src/gpu/GrAADistanceFieldPathRenderer.h
index c337016..e9a32dc 100755
--- a/src/gpu/GrAADistanceFieldPathRenderer.h
+++ b/src/gpu/GrAADistanceFieldPathRenderer.h
@@ -25,19 +25,22 @@
     GrAADistanceFieldPathRenderer(GrContext* context);
     virtual ~GrAADistanceFieldPathRenderer();
     
-    virtual bool canDrawPath(const SkPath& path,
-                             const SkStrokeRec& stroke,
-                             const GrDrawTarget* target,
+    virtual bool canDrawPath(const GrDrawTarget*,
+                             const GrDrawState*,
+                             const SkPath&,
+                             const SkStrokeRec&,
                              bool antiAlias) const SK_OVERRIDE;
 
 protected:
-    virtual StencilSupport onGetStencilSupport(const SkPath&,
-                                               const SkStrokeRec&,
-                                               const GrDrawTarget*) const SK_OVERRIDE;
+    virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
+                                               const GrDrawState*,
+                                               const SkPath&,
+                                               const SkStrokeRec&) const SK_OVERRIDE;
     
-    virtual bool onDrawPath(const SkPath& path,
-                            const SkStrokeRec& stroke,
-                            GrDrawTarget* target,
+    virtual bool onDrawPath(GrDrawTarget*,
+                            GrDrawState*,
+                            const SkPath&,
+                            const SkStrokeRec&,
                             bool antiAlias) SK_OVERRIDE;
 
 private:
@@ -76,7 +79,8 @@
     SkTDynamicHash<PathData, PathData::Key> fPathCache;
     PathDataList                       fPathList;
     
-    bool internalDrawPath(const SkPath& path, const PathData* pathData, GrDrawTarget* target);
+    bool internalDrawPath(GrDrawTarget*, GrDrawState*, const SkPath& path,
+                          const PathData* pathData);
     PathData* addPathToAtlas(const SkPath& path, const SkStrokeRec& stroke, bool antiAlias,
                              uint32_t dimension, SkScalar scale);
     bool freeUnusedPlot();
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index 74d19bd..0d16cf8 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -650,14 +650,13 @@
 };
 };
 
-bool GrAAHairLinePathRenderer::createLineGeom(const SkPath& path,
-                                              GrDrawTarget* target,
-                                              const PtArray& lines,
-                                              int lineCnt,
+bool GrAAHairLinePathRenderer::createLineGeom(GrDrawTarget* target,
+                                              GrDrawState* drawState,
                                               GrDrawTarget::AutoReleaseGeometry* arg,
-                                              SkRect* devBounds) {
-    GrDrawState* drawState = target->drawState();
-
+                                              SkRect* devBounds,
+                                              const SkPath& path,
+                                              const PtArray& lines,
+                                              int lineCnt) {
     const SkMatrix& viewM = drawState->getViewMatrix();
 
     int vertCnt = kLineSegNumVertices * lineCnt;
@@ -665,7 +664,7 @@
     GrDefaultGeoProcFactory::SetAttribs(drawState, GrDefaultGeoProcFactory::kPosition_GPType |
                                                    GrDefaultGeoProcFactory::kCoverage_GPType);
 
-    if (!arg->set(target, vertCnt, 0)) {
+    if (!arg->set(target, vertCnt, drawState->getVertexStride(),  0)) {
         return false;
     }
 
@@ -692,27 +691,25 @@
     return true;
 }
 
-bool GrAAHairLinePathRenderer::createBezierGeom(
-                                          const SkPath& path,
-                                          GrDrawTarget* target,
-                                          const PtArray& quads,
-                                          int quadCnt,
-                                          const PtArray& conics,
-                                          int conicCnt,
-                                          const IntArray& qSubdivs,
-                                          const FloatArray& cWeights,
-                                          GrDrawTarget::AutoReleaseGeometry* arg,
-                                          SkRect* devBounds) {
-    GrDrawState* drawState = target->drawState();
-
+bool GrAAHairLinePathRenderer::createBezierGeom(GrDrawTarget* target,
+                                                GrDrawState* drawState,
+                                                GrDrawTarget::AutoReleaseGeometry* arg,
+                                                SkRect* devBounds,
+                                                const SkPath& path,
+                                                const PtArray& quads,
+                                                int quadCnt,
+                                                const PtArray& conics,
+                                                int conicCnt,
+                                                const IntArray& qSubdivs,
+                                                const FloatArray& cWeights) {
     const SkMatrix& viewM = drawState->getViewMatrix();
 
     int vertCnt = kQuadNumVertices * quadCnt + kQuadNumVertices * conicCnt;
 
     int vAttribCnt = SK_ARRAY_COUNT(gHairlineBezierAttribs);
-    target->drawState()->setVertexAttribs<gHairlineBezierAttribs>(vAttribCnt, sizeof(BezierVertex));
+    drawState->setVertexAttribs<gHairlineBezierAttribs>(vAttribCnt, sizeof(BezierVertex));
 
-    if (!arg->set(target, vertCnt, 0)) {
+    if (!arg->set(target, vertCnt, drawState->getVertexStride(), 0)) {
         return false;
     }
 
@@ -757,16 +754,17 @@
     return true;
 }
 
-bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path,
+bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target,
+                                           const GrDrawState* drawState,
+                                           const SkPath& path,
                                            const SkStrokeRec& stroke,
-                                           const GrDrawTarget* target,
                                            bool antiAlias) const {
     if (!antiAlias) {
         return false;
     }
 
     if (!IsStrokeHairlineOrEquivalent(stroke,
-                                      target->getDrawState().getViewMatrix(),
+                                      drawState->getViewMatrix(),
                                       NULL)) {
         return false;
     }
@@ -815,19 +813,16 @@
     return true;
 }
 
-bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
+bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target,
+                                          GrDrawState* drawState,
+                                          const SkPath& path,
                                           const SkStrokeRec& stroke,
-                                          GrDrawTarget* target,
                                           bool antiAlias) {
-    GrDrawState* drawState = target->drawState();
-
     SkScalar hairlineCoverage;
-    if (IsStrokeHairlineOrEquivalent(stroke,
-                                     target->getDrawState().getViewMatrix(),
+    if (IsStrokeHairlineOrEquivalent(stroke, drawState->getViewMatrix(),
                                      &hairlineCoverage)) {
-        uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage *
-                                                 target->getDrawState().getCoverage());
-        target->drawState()->setCoverage(newCoverage);
+        uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage * drawState->getCoverage());
+        drawState->setCoverage(newCoverage);
     }
 
     SkIRect devClipBounds;
@@ -851,25 +846,22 @@
         GrDrawTarget::AutoReleaseGeometry arg;
         SkRect devBounds;
 
-        if (!this->createLineGeom(path,
-                                  target,
-                                  lines,
-                                  lineCnt,
+        if (!this->createLineGeom(target,
+                                  drawState,
                                   &arg,
-                                  &devBounds)) {
+                                  &devBounds,
+                                  path,
+                                  lines,
+                                  lineCnt)) {
             return false;
         }
 
-        GrDrawTarget::AutoStateRestore asr;
-
         // createLineGeom transforms the geometry to device space when the matrix does not have
         // perspective.
-        if (target->getDrawState().getViewMatrix().hasPerspective()) {
-            asr.set(target, GrDrawTarget::kPreserve_ASRInit);
-        } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
+        GrDrawState::AutoViewMatrixRestore avmr;
+        if (!drawState->getViewMatrix().hasPerspective() && !avmr.setIdentity(drawState)) {
             return false;
         }
-        GrDrawState* drawState = target->drawState();
 
         // Check devBounds
         SkASSERT(check_bounds<LineVertex>(drawState, devBounds, arg.vertices(),
@@ -882,7 +874,8 @@
             int lines = 0;
             while (lines < lineCnt) {
                 int n = SkTMin(lineCnt - lines, kLineSegsNumInIdxBuffer);
-                target->drawIndexed(kTriangles_GrPrimitiveType,
+                target->drawIndexed(drawState,
+                                    kTriangles_GrPrimitiveType,
                                     kLineSegNumVertices*lines,     // startV
                                     0,                             // startI
                                     kLineSegNumVertices*n,         // vCount
@@ -898,29 +891,27 @@
         GrDrawTarget::AutoReleaseGeometry arg;
         SkRect devBounds;
 
-        if (!this->createBezierGeom(path,
-                                    target,
+        if (!this->createBezierGeom(target,
+                                    drawState,
+                                    &arg,
+                                    &devBounds,
+                                    path,
                                     quads,
                                     quadCnt,
                                     conics,
                                     conicCnt,
                                     qSubdivs,
-                                    cWeights,
-                                    &arg,
-                                    &devBounds)) {
+                                    cWeights)) {
             return false;
         }
 
-        GrDrawTarget::AutoStateRestore asr;
-
         // createGeom transforms the geometry to device space when the matrix does not have
         // perspective.
-        if (target->getDrawState().getViewMatrix().hasPerspective()) {
-            asr.set(target, GrDrawTarget::kPreserve_ASRInit);
-        } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
+        GrDrawState::AutoViewMatrixRestore avmr;
+        if (!drawState->getViewMatrix().hasPerspective() && !avmr.setIdentity(drawState)) {
             return false;
         }
-        GrDrawState* drawState = target->drawState();
+
 
         // Check devBounds
         SkASSERT(check_bounds<BezierVertex>(drawState, devBounds, arg.vertices(),
@@ -936,7 +927,8 @@
             int quads = 0;
             while (quads < quadCnt) {
                 int n = SkTMin(quadCnt - quads, kQuadsNumInIdxBuffer);
-                target->drawIndexed(kTriangles_GrPrimitiveType,
+                target->drawIndexed(drawState,
+                                    kTriangles_GrPrimitiveType,
                                     kQuadNumVertices*quads,               // startV
                                     0,                                    // startI
                                     kQuadNumVertices*n,                   // vCount
@@ -955,7 +947,8 @@
             int conics = 0;
             while (conics < conicCnt) {
                 int n = SkTMin(conicCnt - conics, kQuadsNumInIdxBuffer);
-                target->drawIndexed(kTriangles_GrPrimitiveType,
+                target->drawIndexed(drawState,
+                                    kTriangles_GrPrimitiveType,
                                     kQuadNumVertices*(quadCnt + conics),  // startV
                                     0,                                    // startI
                                     kQuadNumVertices*n,                   // vCount
diff --git a/src/gpu/GrAAHairLinePathRenderer.h b/src/gpu/GrAAHairLinePathRenderer.h
index 22cc876e..c5f64f5 100644
--- a/src/gpu/GrAAHairLinePathRenderer.h
+++ b/src/gpu/GrAAHairLinePathRenderer.h
@@ -17,9 +17,10 @@
 
     static GrPathRenderer* Create(GrContext* context);
 
-    virtual bool canDrawPath(const SkPath& path,
-                             const SkStrokeRec& stroke,
-                             const GrDrawTarget* target,
+    virtual bool canDrawPath(const GrDrawTarget*,
+                             const GrDrawState*,
+                             const SkPath&,
+                             const SkStrokeRec&,
                              bool antiAlias) const SK_OVERRIDE;
 
     typedef SkTArray<SkPoint, true> PtArray;
@@ -27,9 +28,10 @@
     typedef SkTArray<float, true> FloatArray;
 
 protected:
-    virtual bool onDrawPath(const SkPath& path,
-                            const SkStrokeRec& stroke,
-                            GrDrawTarget* target,
+    virtual bool onDrawPath(GrDrawTarget*,
+                            GrDrawState*,
+                            const SkPath&,
+                            const SkStrokeRec&,
                             bool antiAlias) SK_OVERRIDE;
 
 private:
@@ -37,23 +39,25 @@
                              const GrIndexBuffer* fLinesIndexBuffer,
                              const GrIndexBuffer* fQuadsIndexBuffer);
 
-    bool createLineGeom(const SkPath& path,
-                        GrDrawTarget* target,
-                        const PtArray& lines,
-                        int lineCnt,
+    bool createLineGeom(GrDrawTarget* target,
+                        GrDrawState*,
                         GrDrawTarget::AutoReleaseGeometry* arg,
-                        SkRect* devBounds);
+                        SkRect* devBounds,
+                        const SkPath& path,
+                        const PtArray& lines,
+                        int lineCnt);
 
-    bool createBezierGeom(const SkPath& path,
-                          GrDrawTarget* target,
+    bool createBezierGeom(GrDrawTarget* target,
+                          GrDrawState*,
+                          GrDrawTarget::AutoReleaseGeometry* arg,
+                          SkRect* devBounds,
+                          const SkPath& path,
                           const PtArray& quads,
                           int quadCnt,
                           const PtArray& conics,
                           int conicCnt,
                           const IntArray& qSubdivs,
-                          const FloatArray& cWeights,
-                          GrDrawTarget::AutoReleaseGeometry* arg,
-                          SkRect* devBounds);
+                          const FloatArray& cWeights);
 
     const GrIndexBuffer*        fLinesIndexBuffer;
     const GrIndexBuffer*        fQuadsIndexBuffer;
diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp
index f748895..edb59d0 100644
--- a/src/gpu/GrAARectRenderer.cpp
+++ b/src/gpu/GrAARectRenderer.cpp
@@ -177,10 +177,10 @@
 }
 
 void GrAARectRenderer::geometryFillAARect(GrDrawTarget* target,
+                                          GrDrawState* drawState,
                                           const SkRect& rect,
                                           const SkMatrix& combinedMatrix,
                                           const SkRect& devRect) {
-    GrDrawState* drawState = target->drawState();
     GrDrawState::AutoRestoreEffects are(drawState);
 
     GrColor color = drawState->getColor();
@@ -190,7 +190,7 @@
         drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
     }
 
-    GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0);
+    GrDrawTarget::AutoReleaseGeometry geo(target, 8, drawState->getVertexStride(),  0);
     if (!geo.succeeded()) {
         SkDebugf("Failed to get space for vertices!\n");
         return;
@@ -300,13 +300,16 @@
     }
 
     target->setIndexSourceToBuffer(indexBuffer);
-    target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1,
+    target->drawIndexedInstances(drawState,
+                                 kTriangles_GrPrimitiveType,
+                                 1,
                                  kVertsPerAAFillRect,
                                  kIndicesPerAAFillRect);
     target->resetIndexSource();
 }
 
 void GrAARectRenderer::strokeAARect(GrDrawTarget* target,
+                                    GrDrawState* drawState,
                                     const SkRect& rect,
                                     const SkMatrix& combinedMatrix,
                                     const SkRect& devRect,
@@ -353,7 +356,7 @@
     }
 
     if (spare <= 0 && miterStroke) {
-        this->fillAARect(target, devOutside, SkMatrix::I(), devOutside);
+        this->fillAARect(target, drawState, devOutside, SkMatrix::I(), devOutside);
         return;
     }
 
@@ -370,17 +373,17 @@
         devOutsideAssist.outset(0, ry);
     }
 
-    this->geometryStrokeAARect(target, devOutside, devOutsideAssist, devInside, miterStroke);
+    this->geometryStrokeAARect(target, drawState, devOutside, devOutsideAssist, devInside,
+                               miterStroke);
 }
 
 void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target,
+                                            GrDrawState* drawState,
                                             const SkRect& devOutside,
                                             const SkRect& devOutsideAssist,
                                             const SkRect& devInside,
                                             bool miterStroke) {
-    GrDrawState* drawState = target->drawState();
     GrDrawState::AutoRestoreEffects are(drawState);
-
     CoverageAttribType covAttribType = set_rect_attribs(drawState);
 
     GrColor color = drawState->getColor();
@@ -392,7 +395,7 @@
     int outerVertexNum = miterStroke ? 4 : 8;
     int totalVertexNum = (outerVertexNum + innerVertexNum) * 2;
 
-    GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum, 0);
+    GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum,  drawState->getVertexStride(), 0);
     if (!geo.succeeded()) {
         SkDebugf("Failed to get space for vertices!\n");
         return;
@@ -499,12 +502,16 @@
     }
 
     target->setIndexSourceToBuffer(indexBuffer);
-    target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1,
-                                 totalVertexNum, aa_stroke_rect_index_count(miterStroke));
+    target->drawIndexedInstances(drawState,
+                                 kTriangles_GrPrimitiveType,
+                                 1,
+                                 totalVertexNum,
+                                 aa_stroke_rect_index_count(miterStroke));
     target->resetIndexSource();
 }
 
 void GrAARectRenderer::fillAANestedRects(GrDrawTarget* target,
+                                         GrDrawState* drawState,
                                          const SkRect rects[2],
                                          const SkMatrix& combinedMatrix) {
     SkASSERT(combinedMatrix.rectStaysRect());
@@ -516,9 +523,9 @@
     combinedMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2);
 
     if (devInside.isEmpty()) {
-        this->fillAARect(target, devOutside, SkMatrix::I(), devOutside);
+        this->fillAARect(target, drawState, devOutside, SkMatrix::I(), devOutside);
         return;
     }
 
-    this->geometryStrokeAARect(target, devOutside, devOutsideAssist, devInside, true);
+    this->geometryStrokeAARect(target, drawState, devOutside, devOutsideAssist, devInside, true);
 }
diff --git a/src/gpu/GrAARectRenderer.h b/src/gpu/GrAARectRenderer.h
index e39b87a..a8ba085 100644
--- a/src/gpu/GrAARectRenderer.h
+++ b/src/gpu/GrAARectRenderer.h
@@ -14,6 +14,7 @@
 #include "SkStrokeRec.h"
 
 class GrGpu;
+class GrDrawState;
 class GrDrawTarget;
 class GrIndexBuffer;
 
@@ -41,32 +42,37 @@
     // between them by passing in stroke (==NULL means fill).
 
     void fillAARect(GrDrawTarget* target,
+                    GrDrawState* ds,
                     const SkRect& rect,
                     const SkMatrix& combinedMatrix,
                     const SkRect& devRect) {
-        this->geometryFillAARect(target, rect, combinedMatrix, devRect);
+        this->geometryFillAARect(target, ds, rect, combinedMatrix, devRect);
     }
 
-    void strokeAARect(GrDrawTarget* target,
+    void strokeAARect(GrDrawTarget*,
+                      GrDrawState*,
                       const SkRect& rect,
                       const SkMatrix& combinedMatrix,
                       const SkRect& devRect,
                       const SkStrokeRec& stroke);
 
     // First rect is outer; second rect is inner
-    void fillAANestedRects(GrDrawTarget* target,
+    void fillAANestedRects(GrDrawTarget*,
+                           GrDrawState*,
                            const SkRect rects[2],
                            const SkMatrix& combinedMatrix);
 
 private:
     GrIndexBuffer* aaStrokeRectIndexBuffer(bool miterStroke);
 
-    void geometryFillAARect(GrDrawTarget* target,
+    void geometryFillAARect(GrDrawTarget*,
+                            GrDrawState*,
                             const SkRect& rect,
                             const SkMatrix& combinedMatrix,
                             const SkRect& devRect);
 
-    void geometryStrokeAARect(GrDrawTarget* target,
+    void geometryStrokeAARect(GrDrawTarget*,
+                              GrDrawState*,
                               const SkRect& devOutside,
                               const SkRect& devOutsideAssist,
                               const SkRect& devInside,
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp
index 50fe9ca..f22b760 100755
--- a/src/gpu/GrBitmapTextContext.cpp
+++ b/src/gpu/GrBitmapTextContext.cpp
@@ -80,10 +80,6 @@
     return SkNEW_ARGS(GrBitmapTextContext, (context, props));
 }
 
-GrBitmapTextContext::~GrBitmapTextContext() {
-    this->finish();
-}
-
 bool GrBitmapTextContext::canDraw(const SkPaint& paint) {
     return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix());
 }
@@ -102,8 +98,8 @@
 }
 
 void GrBitmapTextContext::onDrawText(const GrPaint& paint, const SkPaint& skPaint,
-                                   const char text[], size_t byteLength,
-                                   SkScalar x, SkScalar y) {
+                                     const char text[], size_t byteLength,
+                                     SkScalar x, SkScalar y) {
     SkASSERT(byteLength == 0 || text != NULL);
 
     // nothing to draw
@@ -196,9 +192,9 @@
 }
 
 void GrBitmapTextContext::onDrawPosText(const GrPaint& paint, const SkPaint& skPaint,
-                                      const char text[], size_t byteLength,
-                                      const SkScalar pos[], int scalarsPerPosition,
-                                      const SkPoint& offset) {
+                                        const char text[], size_t byteLength,
+                                        const SkScalar pos[], int scalarsPerPosition,
+                                        const SkPoint& offset) {
     SkASSERT(byteLength == 0 || text != NULL);
     SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
 
@@ -347,24 +343,41 @@
     this->finish();
 }
 
-static void* alloc_vertices(GrDrawTarget* drawTarget, int numVertices, GrMaskFormat maskFormat) {
+static size_t get_vertex_stride(GrMaskFormat maskFormat) {
+    switch (maskFormat) {
+        case kA8_GrMaskFormat:
+            return kGrayTextVASize;
+        case kARGB_GrMaskFormat:
+            return kColorTextVASize;
+        default:
+            return kLCDTextVASize;
+    }
+}
+
+static void set_vertex_attributes(GrDrawState* drawState, GrMaskFormat maskFormat) {
+    if (kA8_GrMaskFormat == maskFormat) {
+        drawState->setVertexAttribs<gGrayVertexAttribs>(
+                                    SK_ARRAY_COUNT(gGrayVertexAttribs), kGrayTextVASize);
+    } else if (kARGB_GrMaskFormat == maskFormat) {
+        GrDefaultGeoProcFactory::SetAttribs(drawState,
+                                            GrDefaultGeoProcFactory::kLocalCoord_GPType);
+    } else {
+        drawState->setVertexAttribs<gLCDVertexAttribs>(
+                                    SK_ARRAY_COUNT(gLCDVertexAttribs), kLCDTextVASize);
+    }
+}
+
+static void* alloc_vertices(GrDrawTarget* drawTarget,
+                            int numVertices,
+                            GrMaskFormat maskFormat) {
     if (numVertices <= 0) {
         return NULL;
     }
 
     // set up attributes
-    if (kA8_GrMaskFormat == maskFormat) {
-        drawTarget->drawState()->setVertexAttribs<gGrayVertexAttribs>(
-                                    SK_ARRAY_COUNT(gGrayVertexAttribs), kGrayTextVASize);
-    } else if (kARGB_GrMaskFormat == maskFormat) {
-        GrDefaultGeoProcFactory::SetAttribs(drawTarget->drawState(),
-                                            GrDefaultGeoProcFactory::kLocalCoord_GPType);
-    } else {
-        drawTarget->drawState()->setVertexAttribs<gLCDVertexAttribs>(
-                                    SK_ARRAY_COUNT(gLCDVertexAttribs), kLCDTextVASize);
-    }
     void* vertices = NULL;
     bool success = drawTarget->reserveVertexAndIndexSpace(numVertices,
+                                                          get_vertex_stride(maskFormat),
                                                           0,
                                                           &vertices,
                                                           NULL);
@@ -498,18 +511,7 @@
 
     fVertexBounds.joinNonEmptyArg(r);
 
-    size_t vertSize;
-    switch (fCurrMaskFormat) {
-        case kA8_GrMaskFormat:
-            vertSize = kGrayTextVASize;
-            break;
-        case kARGB_GrMaskFormat:
-            vertSize = kColorTextVASize;
-        default:
-            vertSize = kLCDTextVASize;
-    }
-
-    SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexStride());
+    size_t vertSize = get_vertex_stride(fCurrMaskFormat);
 
     SkPoint* positions = reinterpret_cast<SkPoint*>(
         reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex);
@@ -524,9 +526,6 @@
                               SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + height)),
                               vertSize);
     if (kA8_GrMaskFormat == fCurrMaskFormat) {
-        if (0xFF == GrColorUnpackA(fPaint.getColor())) {
-            fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
-        }
         // color comes after position.
         GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
         for (int i = 0; i < 4; ++i) {
@@ -549,9 +548,10 @@
         return;
     }
 
-    GrDrawState* drawState = fDrawTarget->drawState();
-    GrDrawState::AutoRestoreEffects are(drawState);
-    drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget());
+    GrDrawState drawState;
+    drawState.setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget());
+
+    set_vertex_attributes(&drawState, fCurrMaskFormat);
 
     if (fCurrVertex > 0) {
         // setup our sampler state for our text texture/atlas
@@ -561,11 +561,11 @@
 
         // This effect could be stored with one of the cache objects (atlas?)
         if (kARGB_GrMaskFormat == fCurrMaskFormat) {
-            drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(true))->unref();
+            drawState.setGeometryProcessor(GrDefaultGeoProcFactory::Create(true))->unref();
             GrFragmentProcessor* fragProcessor = GrSimpleTextureEffect::Create(fCurrTexture,
                                                                                SkMatrix::I(),
                                                                                params);
-            drawState->addColorProcessor(fragProcessor)->unref();
+            drawState.addColorProcessor(fragProcessor)->unref();
         } else {
             uint32_t textureUniqueID = fCurrTexture->getUniqueID();
             if (textureUniqueID != fEffectTextureUniqueID) {
@@ -574,16 +574,16 @@
                 fEffectTextureUniqueID = textureUniqueID;
             }
 
-            drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
+            drawState.setGeometryProcessor(fCachedGeometryProcessor.get());
         }
 
         SkASSERT(fStrike);
         switch (fCurrMaskFormat) {
                 // Color bitmap text
             case kARGB_GrMaskFormat:
-                SkASSERT(!drawState->hasColorVertexAttribute());
-                drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
-                drawState->setAlpha(fSkPaint.getAlpha());
+                SkASSERT(!drawState.hasColorVertexAttribute());
+                drawState.setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+                drawState.setAlpha(fSkPaint.getAlpha());
                 break;
                 // LCD text
             case kA565_GrMaskFormat: {
@@ -592,34 +592,39 @@
                     fPaint.numColorStages()) {
                     SkDebugf("LCD Text will not draw correctly.\n");
                 }
-                SkASSERT(!drawState->hasColorVertexAttribute());
+                SkASSERT(!drawState.hasColorVertexAttribute());
                 // We don't use the GrPaint's color in this case because it's been premultiplied by
                 // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
                 // the mask texture color. The end result is that we get
                 //            mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
                 int a = SkColorGetA(fSkPaint.getColor());
                 // paintAlpha
-                drawState->setColor(SkColorSetARGB(a, a, a, a));
+                drawState.setColor(SkColorSetARGB(a, a, a, a));
                 // paintColor
-                drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
-                drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
+                drawState.setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
+                drawState.setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
                 break;
             }
                 // Grayscale/BW text
             case kA8_GrMaskFormat:
+                drawState.setHint(GrDrawState::kVertexColorsAreOpaque_Hint,
+                                   0xFF == GrColorUnpackA(fPaint.getColor()));
                 // set back to normal in case we took LCD path previously.
-                drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+                drawState.setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
                 // We're using per-vertex color.
-                SkASSERT(drawState->hasColorVertexAttribute());
+                SkASSERT(drawState.hasColorVertexAttribute());
                 break;
             default:
                 SkFAIL("Unexpected mask format.");
         }
         int nGlyphs = fCurrVertex / kVerticesPerGlyph;
         fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
-        fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
+        fDrawTarget->drawIndexedInstances(&drawState,
+                                          kTriangles_GrPrimitiveType,
                                           nGlyphs,
-                                          kVerticesPerGlyph, kIndicesPerGlyph, &fVertexBounds);
+                                          kVerticesPerGlyph,
+                                          kIndicesPerGlyph,
+                                          &fVertexBounds);
 
         fDrawTarget->resetVertexSource();
         fVertices = NULL;
diff --git a/src/gpu/GrBitmapTextContext.h b/src/gpu/GrBitmapTextContext.h
index d98a9f4..a3d0eb2 100644
--- a/src/gpu/GrBitmapTextContext.h
+++ b/src/gpu/GrBitmapTextContext.h
@@ -20,7 +20,7 @@
 public:
     static GrBitmapTextContext* Create(GrContext*, const SkDeviceProperties&);
 
-    virtual ~GrBitmapTextContext();
+    virtual ~GrBitmapTextContext() {}
 
 private:
     GrTextStrike*                     fStrike;
@@ -50,7 +50,6 @@
     void appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
     void flush();                 // automatically called by destructor
     void finish();
-
 };
 
 #endif
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index e04d444..f86aa9d 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2012 Google Inc.
  *
@@ -24,17 +23,15 @@
 #include "effects/GrRRectEffect.h"
 
 #define GR_AA_CLIP 1
-
 typedef SkClipStack::Element Element;
 
 ////////////////////////////////////////////////////////////////////////////////
 namespace {
 // set up the draw state to enable the aa clipping mask. Besides setting up the
 // stage matrix this also alters the vertex layout
-void setup_drawstate_aaclip(GrDrawTarget* gpu,
-                            GrTexture* result,
-                            const SkIRect &devBound) {
-    GrDrawState* drawState = gpu->drawState();
+void setup_drawstate_aaclip(const SkIRect &devBound,
+                            GrDrawState* drawState,
+                            GrTexture* result) {
     SkASSERT(drawState);
 
     SkMatrix mat;
@@ -58,7 +55,8 @@
 }
 
 bool path_needs_SW_renderer(GrContext* context,
-                            GrDrawTarget* gpu,
+                            const GrDrawTarget* gpu,
+                            const GrDrawState* drawState,
                             const SkPath& origPath,
                             const SkStrokeRec& stroke,
                             bool doAA) {
@@ -72,9 +70,8 @@
                                          GrPathRendererChain::kColorAntiAlias_DrawType :
                                          GrPathRendererChain::kColor_DrawType;
 
-    return NULL == context->getPathRenderer(*path, stroke, gpu, false, type);
+    return NULL == context->getPathRenderer(gpu, drawState, *path, stroke, false, type);
 }
-
 }
 
 /*
@@ -82,8 +79,8 @@
  * will be used on any element. If so, it returns true to indicate that the
  * entire clip should be rendered in SW and then uploaded en masse to the gpu.
  */
-bool GrClipMaskManager::useSWOnlyPath(const GrReducedClip::ElementList& elements) {
-
+bool GrClipMaskManager::useSWOnlyPath(const GrDrawState* drawState,
+                                      const GrReducedClip::ElementList& elements) {
     // TODO: generalize this function so that when
     // a clip gets complex enough it can just be done in SW regardless
     // of whether it would invoke the GrSoftwarePathRenderer.
@@ -96,7 +93,7 @@
         if (Element::kRect_Type != element->getType()) {
             SkPath path;
             element->asPath(&path);
-            if (path_needs_SW_renderer(this->getContext(), fClipTarget, path, stroke,
+            if (path_needs_SW_renderer(this->getContext(), fClipTarget, drawState, path, stroke,
                                        element->isAA())) {
                 return true;
             }
@@ -105,12 +102,11 @@
     return false;
 }
 
-bool GrClipMaskManager::installClipEffects(const GrReducedClip::ElementList& elements,
+bool GrClipMaskManager::installClipEffects(GrDrawState* drawState,
                                            GrDrawState::AutoRestoreEffects* are,
+                                           const GrReducedClip::ElementList& elements,
                                            const SkVector& clipToRTOffset,
                                            const SkRect* drawBounds) {
-
-    GrDrawState* drawState = fClipTarget->drawState();
     SkRect boundsInClipSpace;
     if (drawBounds) {
         boundsInClipSpace = *drawBounds;
@@ -120,10 +116,7 @@
     are->set(drawState);
     GrRenderTarget* rt = drawState->getRenderTarget();
     GrReducedClip::ElementList::Iter iter(elements);
-
-    bool setARE = false;
     bool failed = false;
-
     while (iter.get()) {
         SkRegion::Op op = iter.get()->getOp();
         bool invert;
@@ -187,11 +180,7 @@
                     break;
             }
             if (fp) {
-                if (!setARE) {
-                    are->set(fClipTarget->drawState());
-                    setARE = true;
-                }
-                fClipTarget->drawState()->addCoverageProcessor(fp);
+                drawState->addCoverageProcessor(fp);
             } else {
                 failed = true;
                 break;
@@ -203,18 +192,18 @@
     if (failed) {
         are->set(NULL);
     }
-
     return !failed;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // sort out what kind of clip mask needs to be created: alpha, stencil,
 // scissor, or entirely software
-bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn,
-                                      const SkRect* devBounds,
+bool GrClipMaskManager::setupClipping(GrDrawState* drawState,
                                       GrDrawState::AutoRestoreEffects* are,
                                       GrDrawState::AutoRestoreStencil* ars,
-                                      ScissorState* scissorState) {
+                                      ScissorState* scissorState,
+                                      const GrClipData* clipDataIn,
+                                      const SkRect* devBounds) {
     fCurrClipMaskType = kNone_ClipMaskType;
     if (kRespectClip_StencilClipMode == fClipMode) {
         fClipMode = kIgnoreClip_StencilClipMode;
@@ -225,10 +214,8 @@
     GrReducedClip::InitialState initialState;
     SkIRect clipSpaceIBounds;
     bool requiresAA;
+    GrRenderTarget* rt = drawState->getRenderTarget();
 
-    GrDrawState* drawState = fClipTarget->drawState();
-
-    const GrRenderTarget* rt = drawState->getRenderTarget();
     // GrDrawTarget should have filtered this for us
     SkASSERT(rt);
 
@@ -253,7 +240,7 @@
     }
 
     if (ignoreClip) {
-        this->setDrawStateStencil(ars);
+        this->setDrawStateStencil(drawState, ars);
         return true;
     }
 
@@ -269,14 +256,15 @@
         SkVector clipToRTOffset = { SkIntToScalar(-clipDataIn->fOrigin.fX),
                                     SkIntToScalar(-clipDataIn->fOrigin.fY) };
         if (elements.isEmpty() ||
-            (requiresAA && this->installClipEffects(elements, are, clipToRTOffset, devBounds))) {
+            (requiresAA && this->installClipEffects(drawState, are, elements, clipToRTOffset,
+                                                    devBounds))) {
             SkIRect scissorSpaceIBounds(clipSpaceIBounds);
             scissorSpaceIBounds.offset(-clipDataIn->fOrigin);
             if (NULL == devBounds ||
                 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) {
                 scissorState->set(scissorSpaceIBounds);
             }
-            this->setDrawStateStencil(ars);
+            this->setDrawStateStencil(drawState, ars);
             return true;
         }
     }
@@ -286,7 +274,7 @@
     if (0 == rt->numSamples() && requiresAA) {
         GrTexture* result = NULL;
 
-        if (this->useSWOnlyPath(elements)) {
+        if (this->useSWOnlyPath(drawState, elements)) {
             // The clip geometry is complex enough that it will be more efficient to create it
             // entirely in software
             result = this->createSoftwareClipMask(genID,
@@ -305,9 +293,8 @@
             // clipSpace bounds. We determine the mask's position WRT to the render target here.
             SkIRect rtSpaceMaskBounds = clipSpaceIBounds;
             rtSpaceMaskBounds.offset(-clipDataIn->fOrigin);
-            are->set(fClipTarget->drawState());
-            setup_drawstate_aaclip(fClipTarget, result, rtSpaceMaskBounds);
-            this->setDrawStateStencil(ars);
+            setup_drawstate_aaclip(rtSpaceMaskBounds, drawState, result);
+            this->setDrawStateStencil(drawState, ars);
             return true;
         }
         // if alpha clip mask creation fails fall through to the non-AA code paths
@@ -323,7 +310,8 @@
 
     // use the stencil clip if we can't represent the clip as a rectangle.
     SkIPoint clipSpaceToStencilSpaceOffset = -clipDataIn->fOrigin;
-    this->createStencilClipMask(genID,
+    this->createStencilClipMask(rt,
+                                genID,
                                 initialState,
                                 elements,
                                 clipSpaceIBounds,
@@ -335,27 +323,15 @@
     SkIRect scissorSpaceIBounds(clipSpaceIBounds);
     scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset);
     scissorState->set(scissorSpaceIBounds);
-    this->setDrawStateStencil(ars);
+    this->setDrawStateStencil(drawState, ars);
     return true;
 }
 
-#define VISUALIZE_COMPLEX_CLIP 0
-
-#if VISUALIZE_COMPLEX_CLIP
-    #include "SkRandom.h"
-    SkRandom gRandom;
-    #define SET_RANDOM_COLOR drawState->setColor(0xff000000 | gRandom.nextU());
-#else
-    #define SET_RANDOM_COLOR
-#endif
-
 namespace {
-
 ////////////////////////////////////////////////////////////////////////////////
 // set up the OpenGL blend function to perform the specified
 // boolean operation for alpha clip mask creation
-void setup_boolean_blendcoeffs(GrDrawState* drawState, SkRegion::Op op) {
-
+void setup_boolean_blendcoeffs(SkRegion::Op op, GrDrawState* drawState) {
     switch (op) {
         case SkRegion::kReplace_Op:
             drawState->setBlendFunc(kOne_GrBlendCoeff, kZero_GrBlendCoeff);
@@ -380,14 +356,14 @@
             break;
     }
 }
-
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-bool GrClipMaskManager::drawElement(GrTexture* target,
+bool GrClipMaskManager::drawElement(GrDrawState* drawState,
+                                    GrTexture* target,
                                     const SkClipStack::Element* element,
                                     GrPathRenderer* pr) {
-    GrDrawState* drawState = fClipTarget->drawState();
+    GrDrawTarget::AutoGeometryPush agp(fClipTarget);
 
     drawState->setRenderTarget(target->asRenderTarget());
 
@@ -401,11 +377,12 @@
             // the entire mask bounds and writes 0 outside the rect.
             if (element->isAA()) {
                 this->getContext()->getAARectRenderer()->fillAARect(fClipTarget,
+                                                                    drawState,
                                                                     element->getRect(),
                                                                     SkMatrix::I(),
                                                                     element->getRect());
             } else {
-                fClipTarget->drawSimpleRect(element->getRect());
+                fClipTarget->drawSimpleRect(drawState, element->getRect());
             }
             return true;
         default: {
@@ -420,22 +397,24 @@
                 GrPathRendererChain::DrawType type;
                 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType :
                                          GrPathRendererChain::kColor_DrawType;
-                pr = this->getContext()->getPathRenderer(path, stroke, fClipTarget, false, type);
+                pr = this->getContext()->getPathRenderer(fClipTarget, drawState, path, stroke,
+                                                         false, type);
             }
             if (NULL == pr) {
                 return false;
             }
-            pr->drawPath(path, stroke, fClipTarget, element->isAA());
+
+            pr->drawPath(fClipTarget, drawState, path, stroke, element->isAA());
             break;
         }
     }
     return true;
 }
 
-bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target,
-                                                 const SkClipStack::Element* element,
-                                                 GrPathRenderer** pr) {
-    GrDrawState* drawState = fClipTarget->drawState();
+bool GrClipMaskManager::canStencilAndDrawElement(GrDrawState* drawState,
+                                                 GrTexture* target,
+                                                 GrPathRenderer** pr,
+                                                 const SkClipStack::Element* element) {
     drawState->setRenderTarget(target->asRenderTarget());
 
     if (Element::kRect_Type == element->getType()) {
@@ -452,24 +431,23 @@
         GrPathRendererChain::DrawType type = element->isAA() ?
             GrPathRendererChain::kStencilAndColorAntiAlias_DrawType :
             GrPathRendererChain::kStencilAndColor_DrawType;
-        *pr = this->getContext()->getPathRenderer(path, stroke, fClipTarget, false, type);
+        *pr = this->getContext()->getPathRenderer(fClipTarget, drawState, path, stroke, false,
+                                                  type);
         return SkToBool(*pr);
     }
 }
 
-void GrClipMaskManager::mergeMask(GrTexture* dstMask,
+void GrClipMaskManager::mergeMask(GrDrawState* drawState,
+                                  GrTexture* dstMask,
                                   GrTexture* srcMask,
                                   SkRegion::Op op,
                                   const SkIRect& dstBound,
                                   const SkIRect& srcBound) {
-    GrDrawState::AutoViewMatrixRestore avmr;
-    GrDrawState* drawState = fClipTarget->drawState();
-    SkAssertResult(avmr.setIdentity(drawState));
-    GrDrawState::AutoRestoreEffects are(drawState);
+    SkAssertResult(drawState->setIdentityViewMatrix());
 
     drawState->setRenderTarget(dstMask->asRenderTarget());
 
-    setup_boolean_blendcoeffs(drawState, op);
+    setup_boolean_blendcoeffs(op, drawState);
 
     SkMatrix sampleM;
     sampleM.setIDiv(srcMask->width(), srcMask->height());
@@ -480,7 +458,7 @@
                                       GrTextureDomain::MakeTexelDomain(srcMask, srcBound),
                                       GrTextureDomain::kDecal_Mode,
                                       GrTextureParams::kNone_FilterMode))->unref();
-    fClipTarget->drawSimpleRect(SkRect::Make(dstBound));
+    fClipTarget->drawSimpleRect(drawState, SkRect::Make(dstBound));
 }
 
 GrTexture* GrClipMaskManager::createTempMask(int width, int height) {
@@ -563,13 +541,6 @@
     // Set the matrix so that rendered clip elements are transformed to mask space from clip space.
     SkMatrix translate;
     translate.setTranslate(clipToMaskOffset);
-    GrDrawTarget::AutoGeometryAndStatePush agasp(fClipTarget, GrDrawTarget::kReset_ASRInit,
-                                                 &translate);
-
-    GrDrawState* drawState = fClipTarget->drawState();
-
-    // We're drawing a coverage mask and want coverage to be run through the blend function.
-    drawState->enableState(GrDrawState::kCoverageDrawing_StateBit);
 
     // The scratch texture that we are drawing into can be substantially larger than the mask. Only
     // clear the part that we care about.
@@ -583,18 +554,21 @@
     // pass must not set values outside of this bounds or stencil values outside the rect won't be
     // cleared.
     GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds);
-    drawState->enableState(GrDrawState::kClip_StateBit);
-
     SkAutoTUnref<GrTexture> temp;
+
     // walk through each clip element and perform its set op
     for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) {
         const Element* element = iter.get();
         SkRegion::Op op = element->getOp();
         bool invert = element->isInverseFilled();
-
         if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
+            GrDrawState drawState(translate);
+            // We're drawing a coverage mask and want coverage to be run through the blend function.
+            drawState.enableState(GrDrawState::kCoverageDrawing_StateBit |
+                                  GrDrawState::kClip_StateBit);
+
             GrPathRenderer* pr = NULL;
-            bool useTemp = !this->canStencilAndDrawElement(result, element, &pr);
+            bool useTemp = !this->canStencilAndDrawElement(&drawState, result, &pr, element);
             GrTexture* dst;
             // This is the bounds of the clip element in the space of the alpha-mask. The temporary
             // mask buffer can be substantially larger than the actually clip stack element. We
@@ -622,11 +596,10 @@
                 dst = temp;
                 // clear the temp target and set blend to replace
                 fClipTarget->clear(&maskSpaceElementIBounds,
-                            invert ? 0xffffffff : 0x00000000,
-                            true,
-                            dst->asRenderTarget());
-                setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op);
-
+                                   invert ? 0xffffffff : 0x00000000,
+                                   true,
+                                   dst->asRenderTarget());
+                setup_boolean_blendcoeffs(SkRegion::kReplace_Op, &drawState);
             } else {
                 // draw directly into the result with the stencil set to make the pixels affected
                 // by the clip shape be non-zero.
@@ -638,13 +611,17 @@
                                              0xffff,
                                              0xffff,
                                              0xffff);
-                drawState->setStencil(kStencilInElement);
-                setup_boolean_blendcoeffs(drawState, op);
+                drawState.setStencil(kStencilInElement);
+                setup_boolean_blendcoeffs(op, &drawState);
             }
 
-            drawState->setAlpha(invert ? 0x00 : 0xff);
+            drawState.setAlpha(invert ? 0x00 : 0xff);
 
-            if (!this->drawElement(dst, element, pr)) {
+            // We have to backup the drawstate because the drawElement call may call into
+            // renderers which consume it.
+            GrDrawState backupDrawState(drawState);
+
+            if (!this->drawElement(&drawState, dst, element, pr)) {
                 fAACache.reset();
                 return NULL;
             }
@@ -652,14 +629,15 @@
             if (useTemp) {
                 // Now draw into the accumulator using the real operation and the temp buffer as a
                 // texture
-                this->mergeMask(result,
+                this->mergeMask(&backupDrawState,
+                                result,
                                 temp,
                                 op,
                                 maskSpaceIBounds,
                                 maskSpaceElementIBounds);
             } else {
                 // Draw to the exterior pixels (those with a zero stencil value).
-                drawState->setAlpha(invert ? 0xff : 0x00);
+                backupDrawState.setAlpha(invert ? 0xff : 0x00);
                 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement,
                                              kZero_StencilOp,
                                              kZero_StencilOp,
@@ -667,15 +645,18 @@
                                              0xffff,
                                              0x0000,
                                              0xffff);
-                drawState->setStencil(kDrawOutsideElement);
-                fClipTarget->drawSimpleRect(clipSpaceIBounds);
-                drawState->disableStencil();
+                backupDrawState.setStencil(kDrawOutsideElement);
+                fClipTarget->drawSimpleRect(&backupDrawState, clipSpaceIBounds);
             }
         } else {
+            GrDrawState drawState(translate);
+            drawState.enableState(GrDrawState::kCoverageDrawing_StateBit |
+                                  GrDrawState::kClip_StateBit);
+
             // all the remaining ops can just be directly draw into the accumulation buffer
-            drawState->setAlpha(0xff);
-            setup_boolean_blendcoeffs(drawState, op);
-            this->drawElement(result, element);
+            drawState.setAlpha(0xff);
+            setup_boolean_blendcoeffs(op, &drawState);
+            this->drawElement(&drawState, result, element);
         }
     }
 
@@ -686,18 +667,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device
 // (as opposed to canvas) coordinates
-bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID,
+bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
+                                              int32_t elementsGenID,
                                               GrReducedClip::InitialState initialState,
                                               const GrReducedClip::ElementList& elements,
                                               const SkIRect& clipSpaceIBounds,
                                               const SkIPoint& clipSpaceToStencilOffset) {
-
     SkASSERT(kNone_ClipMaskType == fCurrClipMaskType);
-
-    GrDrawState* drawState = fClipTarget->drawState();
-    SkASSERT(drawState->isClipState());
-
-    GrRenderTarget* rt = drawState->getRenderTarget();
     SkASSERT(rt);
 
     // TODO: dynamically attach a SB when needed.
@@ -708,7 +684,6 @@
 
     if (stencilBuffer->mustRenderClip(elementsGenID, clipSpaceIBounds, clipSpaceToStencilOffset)) {
         stencilBuffer->setLastClip(elementsGenID, clipSpaceIBounds, clipSpaceToStencilOffset);
-
         // Set the matrix so that rendered clip elements are transformed from clip to stencil space.
         SkVector translate = {
             SkIntToScalar(clipSpaceToStencilOffset.fX),
@@ -716,21 +691,11 @@
         };
         SkMatrix matrix;
         matrix.setTranslate(translate);
-        GrDrawTarget::AutoGeometryAndStatePush agasp(fClipTarget, GrDrawTarget::kReset_ASRInit,
-                                                     &matrix);
-        drawState = fClipTarget->drawState();
-
-        drawState->setRenderTarget(rt);
 
         // We set the current clip to the bounds so that our recursive draws are scissored to them.
         SkIRect stencilSpaceIBounds(clipSpaceIBounds);
         stencilSpaceIBounds.offset(clipSpaceToStencilOffset);
         GrDrawTarget::AutoClipRestore acr(fClipTarget, stencilSpaceIBounds);
-        drawState->enableState(GrDrawState::kClip_StateBit);
-
-#if !VISUALIZE_COMPLEX_CLIP
-        drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
-#endif
 
         int clipBit = stencilBuffer->bits();
         SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil buffers");
@@ -744,20 +709,26 @@
         // with the existing clip.
         for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
             const Element* element = iter.get();
+
+            GrDrawState drawState(matrix);
+            drawState.setRenderTarget(rt);
+            drawState.enableState(GrDrawState::kClip_StateBit);
+            drawState.enableState(GrDrawState::kNoColorWrites_StateBit);
+
+            // if the target is MSAA then we want MSAA enabled when the clip is soft
+            if (rt->isMultisampled()) {
+                drawState.setState(GrDrawState::kHWAntialias_StateBit, element->isAA());
+            }
+
             bool fillInverted = false;
             // enabled at bottom of loop
             fClipMode = kIgnoreClip_StencilClipMode;
-            // if the target is MSAA then we want MSAA enabled when the clip is soft
-            if (rt->isMultisampled()) {
-                drawState->setState(GrDrawState::kHWAntialias_StateBit, element->isAA());
-            }
 
             // This will be used to determine whether the clip shape can be rendered into the
             // stencil with arbitrary stencil settings.
             GrPathRenderer::StencilSupport stencilSupport;
 
             SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
-
             SkRegion::Op op = element->getOp();
 
             GrPathRenderer* pr = NULL;
@@ -771,9 +742,10 @@
                 if (fillInverted) {
                     clipPath.toggleInverseFillType();
                 }
-                pr = this->getContext()->getPathRenderer(clipPath,
+                pr = this->getContext()->getPathRenderer(fClipTarget,
+                                                         &drawState,
+                                                         clipPath,
                                                          stroke,
-                                                         fClipTarget,
                                                          false,
                                                          GrPathRendererChain::kStencilOnly_DrawType,
                                                          &stencilSupport);
@@ -807,17 +779,17 @@
                                              0xffff,
                                              0x0000,
                                              0xffff);
-                SET_RANDOM_COLOR
                 if (Element::kRect_Type == element->getType()) {
-                    *drawState->stencil() = gDrawToStencil;
-                    fClipTarget->drawSimpleRect(element->getRect());
+                    *drawState.stencil() = gDrawToStencil;
+                    fClipTarget->drawSimpleRect(&drawState, element->getRect());
                 } else {
                     if (!clipPath.isEmpty()) {
+                        GrDrawTarget::AutoGeometryPush agp(fClipTarget);
                         if (canRenderDirectToStencil) {
-                            *drawState->stencil() = gDrawToStencil;
-                            pr->drawPath(clipPath, stroke, fClipTarget, false);
+                            *drawState.stencil() = gDrawToStencil;
+                            pr->drawPath(fClipTarget, &drawState, clipPath, stroke, false);
                         } else {
-                            pr->stencilPath(clipPath, stroke, fClipTarget);
+                            pr->stencilPath(fClipTarget, &drawState, clipPath, stroke);
                         }
                     }
                 }
@@ -827,20 +799,20 @@
             // element directly or a bounding rect of the entire clip.
             fClipMode = kModifyClip_StencilClipMode;
             for (int p = 0; p < passes; ++p) {
-                *drawState->stencil() = stencilSettings[p];
+                GrDrawState drawStateCopy(drawState);
+                *drawStateCopy.stencil() = stencilSettings[p];
+
                 if (canDrawDirectToClip) {
                     if (Element::kRect_Type == element->getType()) {
-                        SET_RANDOM_COLOR
-                        fClipTarget->drawSimpleRect(element->getRect());
+                        fClipTarget->drawSimpleRect(&drawStateCopy, element->getRect());
                     } else {
-                        SET_RANDOM_COLOR
-                        pr->drawPath(clipPath, stroke, fClipTarget, false);
+                        GrDrawTarget::AutoGeometryPush agp(fClipTarget);
+                        pr->drawPath(fClipTarget, &drawStateCopy, clipPath, stroke, false);
                     }
                 } else {
-                    SET_RANDOM_COLOR
                     // The view matrix is setup to do clip space -> stencil space translation, so
                     // draw rect in clip space.
-                    fClipTarget->drawSimpleRect(SkRect::Make(clipSpaceIBounds));
+                    fClipTarget->drawSimpleRect(&drawStateCopy, SkRect::Make(clipSpaceIBounds));
                 }
             }
         }
@@ -852,7 +824,6 @@
     return true;
 }
 
-
 // mapping of clip-respecting stencil funcs to normal stencil funcs
 // mapping depends on whether stencil-clipping is in effect.
 static const GrStencilFunc
@@ -905,33 +876,32 @@
 }
 }
 
-void GrClipMaskManager::setDrawStateStencil(GrDrawState::AutoRestoreStencil* ars) {
+void GrClipMaskManager::setDrawStateStencil(GrDrawState* drawState,
+                                            GrDrawState::AutoRestoreStencil* ars) {
     // We make two copies of the StencilSettings here (except in the early
     // exit scenario. One copy from draw state to the stack var. Then another
     // from the stack var to the gpu. We could make this class hold a ptr to
     // GrGpu's fStencilSettings and eliminate the stack copy here.
 
-    const GrDrawState& drawState = fClipTarget->getDrawState();
-
     // use stencil for clipping if clipping is enabled and the clip
     // has been written into the stencil.
-
     GrStencilSettings settings;
+
     // The GrGpu client may not be using the stencil buffer but we may need to
     // enable it in order to respect a stencil clip.
-    if (drawState.getStencil().isDisabled()) {
+    if (drawState->getStencil().isDisabled()) {
         if (GrClipMaskManager::kRespectClip_StencilClipMode == fClipMode) {
             settings = basic_apply_stencil_clip_settings();
         } else {
             return;
         }
     } else {
-        settings = drawState.getStencil();
+        settings = drawState->getStencil();
     }
 
     // TODO: dynamically attach a stencil buffer
     int stencilBits = 0;
-    GrStencilBuffer* stencilBuffer = drawState.getRenderTarget()->getStencilBuffer();
+    GrStencilBuffer* stencilBuffer = drawState->getRenderTarget()->getStencilBuffer();
     if (stencilBuffer) {
         stencilBits = stencilBuffer->bits();
     }
@@ -939,8 +909,8 @@
     SkASSERT(fClipTarget->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp());
     SkASSERT(fClipTarget->caps()->twoSidedStencilSupport() || !settings.isTwoSided());
     this->adjustStencilParams(&settings, fClipMode, stencilBits);
-    ars->set(fClipTarget->drawState());
-    fClipTarget->drawState()->setStencil(settings);
+    ars->set(drawState);
+    drawState->setStencil(settings);
 }
 
 void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings,
@@ -1045,14 +1015,12 @@
     SkMatrix matrix;
     matrix.setTranslate(SkIntToScalar(-clipSpaceIBounds.fLeft),
                         SkIntToScalar(-clipSpaceIBounds.fTop));
+
     helper.init(maskSpaceIBounds, &matrix, false);
-
     helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x00);
-
     SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
 
     for (GrReducedClip::ElementList::Iter iter(elements.headIter()) ; iter.get(); iter.next()) {
-
         const Element* element = iter.get();
         SkRegion::Op op = element->getOp();
 
@@ -1066,12 +1034,10 @@
                 // invert the entire scene
                 helper.draw(temp, SkRegion::kXOR_Op, false, 0xFF);
             }
-
             SkPath clipPath;
             element->asPath(&clipPath);
             clipPath.toggleInverseFillType();
             helper.draw(clipPath, stroke, SkRegion::kReplace_Op, element->isAA(), 0x00);
-
             continue;
         }
 
@@ -1108,14 +1074,11 @@
     fAACache.setContext(clipTarget->getContext());
 }
 
-void GrClipMaskManager::adjustPathStencilParams(GrStencilSettings* settings) {
-    const GrDrawState& drawState = fClipTarget->getDrawState();
-
+void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBuffer,
+                                                GrStencilSettings* settings) {
     // TODO: dynamically attach a stencil buffer
-    int stencilBits = 0;
-    GrStencilBuffer* stencilBuffer = drawState.getRenderTarget()->getStencilBuffer();
     if (stencilBuffer) {
-        stencilBits = stencilBuffer->bits();
+        int stencilBits = stencilBuffer->bits();
         this->adjustStencilParams(settings, fClipMode, stencilBits);
     }
 }
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index e2824ce..3aec257 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -4,7 +4,6 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
-
 #ifndef GrClipMaskManager_DEFINED
 #define GrClipMaskManager_DEFINED
 
@@ -14,7 +13,6 @@
 #include "GrReducedClip.h"
 #include "GrStencil.h"
 #include "GrTexture.h"
-
 #include "SkClipStack.h"
 #include "SkDeque.h"
 #include "SkPath.h"
@@ -27,7 +25,6 @@
 class GrPathRendererChain;
 class GrTexture;
 class SkPath;
-
 /**
  * The clip mask creator handles the generation of the clip mask. If anti
  * aliasing is requested it will (in the future) generate a single channel
@@ -66,11 +63,12 @@
      * the manager when it must install additional effects to implement the
      * clip. devBounds is optional but can help optimize clipping.
      */
-    bool setupClipping(const GrClipData* clipDataIn,
-                       const SkRect* devBounds,
+    bool setupClipping(GrDrawState*,
                        GrDrawState::AutoRestoreEffects*,
                        GrDrawState::AutoRestoreStencil*,
-                       ScissorState*);
+                       ScissorState*,
+                       const GrClipData* clipDataIn,
+                       const SkRect* devBounds);
 
     /**
      * Purge resources to free up memory. TODO: This class shouldn't hold any long lived refs
@@ -81,6 +79,7 @@
     bool isClipInStencil() const {
         return kStencil_ClipMaskType == fCurrClipMaskType;
     }
+
     bool isClipInAlpha() const {
         return kAlpha_ClipMaskType == fCurrClipMaskType;
     }
@@ -91,7 +90,7 @@
 
     void setClipTarget(GrClipTarget*);
 
-    void adjustPathStencilParams(GrStencilSettings*);
+    void adjustPathStencilParams(const GrStencilBuffer*, GrStencilSettings*);
 
 private:
     /**
@@ -110,23 +109,27 @@
 
     // Attempts to install a series of coverage effects to implement the clip. Return indicates
     // whether the element list was successfully converted to effects.
-    bool installClipEffects(const GrReducedClip::ElementList&,
+    bool installClipEffects(GrDrawState*,
                             GrDrawState::AutoRestoreEffects*,
+                            const GrReducedClip::ElementList&,
                             const SkVector& clipOffset,
                             const SkRect* devBounds);
 
     // Draws the clip into the stencil buffer
-    bool createStencilClipMask(int32_t elementsGenID,
+    bool createStencilClipMask(GrRenderTarget*,
+                               int32_t elementsGenID,
                                GrReducedClip::InitialState initialState,
                                const GrReducedClip::ElementList& elements,
                                const SkIRect& clipSpaceIBounds,
                                const SkIPoint& clipSpaceToStencilOffset);
+
     // Creates an alpha mask of the clip. The mask is a rasterization of elements through the
     // rect specified by clipSpaceIBounds.
     GrTexture* createAlphaClipMask(int32_t elementsGenID,
                                    GrReducedClip::InitialState initialState,
                                    const GrReducedClip::ElementList& elements,
                                    const SkIRect& clipSpaceIBounds);
+
     // Similar to createAlphaClipMask but it rasterizes in SW and uploads to the result texture.
     GrTexture* createSoftwareClipMask(int32_t elementsGenID,
                                       GrReducedClip::InitialState initialState,
@@ -137,26 +140,32 @@
     // Returns NULL if not found.
     GrTexture* getCachedMaskTexture(int32_t elementsGenID, const SkIRect& clipSpaceIBounds);
 
-
     // Handles allocation (if needed) of a clip alpha-mask texture for both the sw-upload
     // or gpu-rendered cases.
     GrTexture* allocMaskTexture(int32_t elementsGenID,
                                 const SkIRect& clipSpaceIBounds,
                                 bool willUpload);
 
-    bool useSWOnlyPath(const GrReducedClip::ElementList& elements);
+    bool useSWOnlyPath(const GrDrawState*, const GrReducedClip::ElementList& elements);
 
     // Draws a clip element into the target alpha mask. The caller should have already setup the
     // desired blend operation. Optionally if the caller already selected a path renderer it can
     // be passed. Otherwise the function will select one if the element is a path.
-    bool drawElement(GrTexture* target, const SkClipStack::Element*, GrPathRenderer* = NULL);
+    bool drawElement(GrDrawState*,
+                     GrTexture* target,
+                     const SkClipStack::Element*,
+                     GrPathRenderer* pr = NULL);
 
     // Determines whether it is possible to draw the element to both the stencil buffer and the
     // alpha mask simultaneously. If so and the element is a path a compatible path renderer is
     // also returned.
-    bool canStencilAndDrawElement(GrTexture* target, const SkClipStack::Element*, GrPathRenderer**);
+    bool canStencilAndDrawElement(GrDrawState*,
+                                  GrTexture* target,
+                                  GrPathRenderer**,
+                                  const SkClipStack::Element*);
 
-    void mergeMask(GrTexture* dstMask,
+    void mergeMask(GrDrawState*,
+                   GrTexture* dstMask,
                    GrTexture* srcMask,
                    SkRegion::Op op,
                    const SkIRect& dstBound,
@@ -166,13 +175,12 @@
 
     void setupCache(const SkClipStack& clip,
                     const SkIRect& bounds);
-
     /**
      * Called prior to return control back the GrGpu in setupClipping. It
      * updates the GrGpu with stencil settings that account stencil-based
      * clipping.
      */
-    void setDrawStateStencil(GrDrawState::AutoRestoreStencil* asr);
+    void setDrawStateStencil(GrDrawState*, GrDrawState::AutoRestoreStencil*);
 
     /**
      * Adjusts the stencil settings to account for interaction with stencil
@@ -199,5 +207,4 @@
 
     typedef SkNoncopyable INHERITED;
 };
-
 #endif // GrClipMaskManager_DEFINED
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index e7449da..657e57d 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -60,9 +60,6 @@
 
 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
 
-// Glorified typedef to avoid including GrDrawState.h in GrContext.h
-class GrContext::AutoRestoreEffects : public GrDrawState::AutoRestoreEffects {};
-
 class GrContext::AutoCheckFlush {
 public:
     AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); }
@@ -95,7 +92,6 @@
 }
 
 GrContext::GrContext(const Options& opts) : fOptions(opts) {
-    fDrawState = NULL;
     fGpu = NULL;
     fClip = NULL;
     fPathRendererChain = NULL;
@@ -124,8 +120,6 @@
 }
 
 void GrContext::initCommon() {
-    fDrawState = SkNEW(GrDrawState);
-
     fResourceCache2 = SkNEW(GrResourceCache2);
     fResourceCache2->setOverBudgetCallback(OverBudgetCB, this);
 
@@ -164,7 +158,6 @@
     fGpu->unref();
     SkSafeUnref(fPathRendererChain);
     SkSafeUnref(fSoftwarePathRenderer);
-    fDrawState->unref();
 }
 
 void GrContext::abandonContext() {
@@ -326,9 +319,8 @@
     GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
 
     if (texture) {
-        GrDrawTarget::AutoStateRestore asr(fDrawBuffer, GrDrawTarget::kReset_ASRInit);
-        GrDrawState* drawState = fDrawBuffer->drawState();
-        drawState->setRenderTarget(texture->asRenderTarget());
+        GrDrawState drawState;
+        drawState.setRenderTarget(texture->asRenderTarget());
 
         // if filtering is not desired then we want to ensure all
         // texels in the resampled image are copies of texels from
@@ -336,21 +328,21 @@
         GrTextureParams params(SkShader::kClamp_TileMode,
                                filter ? GrTextureParams::kBilerp_FilterMode :
                                         GrTextureParams::kNone_FilterMode);
-        drawState->addColorTextureProcessor(clampedTexture, SkMatrix::I(), params);
+        drawState.addColorTextureProcessor(clampedTexture, SkMatrix::I(), params);
 
-        drawState->setGeometryProcessor(
+        drawState.setGeometryProcessor(
                 GrDefaultGeoProcFactory::CreateAndSetAttribs(
-                        drawState,
+                        &drawState,
                         GrDefaultGeoProcFactory::kPosition_GPType |
                         GrDefaultGeoProcFactory::kLocalCoord_GPType))->unref();
 
-        GrDrawTarget::AutoReleaseGeometry arg(fDrawBuffer, 4, 0);
+        GrDrawTarget::AutoReleaseGeometry arg(fDrawBuffer, 4, drawState.getVertexStride(),  0);
 
         if (arg.succeeded()) {
             SkPoint* verts = (SkPoint*) arg.vertices();
             verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 * sizeof(SkPoint));
             verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(SkPoint));
-            fDrawBuffer->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
+            fDrawBuffer->drawNonIndexed(&drawState, kTriangleFan_GrPrimitiveType, 0, 4);
         }
     } else {
         // TODO: Our CPU stretch doesn't filter. But we create separate
@@ -564,10 +556,9 @@
     ASSERT_OWNED_RESOURCE(renderTarget);
     SkASSERT(renderTarget);
 
-    AutoRestoreEffects are;
     AutoCheckFlush acf(this);
     GR_CREATE_TRACE_MARKER_CONTEXT("GrContext::clear", this);
-    GrDrawTarget* target = this->prepareToDraw(NULL, &are, &acf);
+    GrDrawTarget* target = this->prepareToDraw(NULL, NULL, &acf);
     if (NULL == target) {
         return;
     }
@@ -644,19 +635,19 @@
 }
 
 static bool apply_aa_to_rect(GrDrawTarget* target,
+                             GrDrawState* ds,
+                             SkRect* devBoundRect,
                              const SkRect& rect,
                              SkScalar strokeWidth,
-                             const SkMatrix& combinedMatrix,
-                             SkRect* devBoundRect) {
-    if (!target->getDrawState().canTweakAlphaForCoverage() &&
-        target->shouldDisableCoverageAAForBlend()) {
+                             const SkMatrix& combinedMatrix) {
+    if (!ds->canTweakAlphaForCoverage() && !ds->couldApplyCoverage(*target->caps())) {
 #ifdef SK_DEBUG
         //SkDebugf("Turning off AA to correctly apply blend.\n");
 #endif
         return false;
     }
-    const GrDrawState& drawState = target->getDrawState();
-    if (drawState.getRenderTarget()->isMultisampled()) {
+
+    if (ds->getRenderTarget()->isMultisampled()) {
         return false;
     }
 
@@ -698,22 +689,22 @@
         return;
     }
 
-    AutoRestoreEffects are;
     AutoCheckFlush acf(this);
-    GrDrawTarget* target = this->prepareToDraw(&paint, &are, &acf);
+    GrDrawState drawState;
+    GrDrawTarget* target = this->prepareToDraw(&drawState, &paint, &acf);
     if (NULL == target) {
         return;
     }
 
     GR_CREATE_TRACE_MARKER("GrContext::drawRect", target);
     SkScalar width = NULL == strokeInfo ? -1 : strokeInfo->getStrokeRec().getWidth();
-    SkMatrix matrix = target->drawState()->getViewMatrix();
+    SkMatrix matrix = drawState.getViewMatrix();
 
     // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
     // cases where the RT is fully inside a stroke.
     if (width < 0) {
         SkRect rtRect;
-        target->getDrawState().getRenderTarget()->getBoundsRect(&rtRect);
+        drawState.getRenderTarget()->getBoundsRect(&rtRect);
         SkRect clipSpaceRTRect = rtRect;
         bool checkClip = false;
         if (this->getClip()) {
@@ -745,22 +736,26 @@
     }
 
     SkRect devBoundRect;
-    bool needAA = paint.isAntiAlias() &&
-                  !target->getDrawState().getRenderTarget()->isMultisampled();
-    bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix, &devBoundRect);
+    bool needAA = paint.isAntiAlias() && !drawState.getRenderTarget()->isMultisampled();
+    bool doAA = needAA && apply_aa_to_rect(target, &drawState, &devBoundRect, rect, width, matrix);
 
     if (doAA) {
         GrDrawState::AutoViewMatrixRestore avmr;
-        if (!avmr.setIdentity(target->drawState())) {
+        if (!avmr.setIdentity(&drawState)) {
             return;
         }
+
         if (width >= 0) {
             const SkStrokeRec& strokeRec = strokeInfo->getStrokeRec();
-            fAARectRenderer->strokeAARect(target, rect, matrix, devBoundRect, strokeRec);
+            fAARectRenderer->strokeAARect(target,
+                                          &drawState,
+                                          rect,
+                                          matrix,
+                                          devBoundRect,
+                                          strokeRec);
         } else {
             // filled AA rect
-            fAARectRenderer->fillAARect(target,
-                                        rect, matrix, devBoundRect);
+            fAARectRenderer->fillAARect(target, &drawState, rect, matrix, devBoundRect);
         }
         return;
     }
@@ -771,9 +766,12 @@
         // unitSquareVertexBuffer()
 
         static const int worstCaseVertCount = 10;
-        target->drawState()->setDefaultVertexAttribs();
-        target->drawState()->setGeometryProcessor(GrDefaultGeoProcFactory::Create(false))->unref();
-        GrDrawTarget::AutoReleaseGeometry geo(target, worstCaseVertCount, 0);
+        drawState.setDefaultVertexAttribs();
+        drawState.setGeometryProcessor(GrDefaultGeoProcFactory::Create(false))->unref();
+        GrDrawTarget::AutoReleaseGeometry geo(target,
+                                              worstCaseVertCount,
+                                              drawState.getVertexStride(),
+                                              0);
 
         if (!geo.succeeded()) {
             SkDebugf("Failed to get space for vertices!\n");
@@ -799,10 +797,10 @@
             vertex[4].set(rect.fLeft, rect.fTop);
         }
 
-        target->drawNonIndexed(primType, 0, vertCount);
+        target->drawNonIndexed(&drawState, primType, 0, vertCount);
     } else {
         // filled BW rect
-        target->drawSimpleRect(rect);
+        target->drawSimpleRect(&drawState, rect);
     }
 }
 
@@ -810,16 +808,16 @@
                                const SkRect& dstRect,
                                const SkRect& localRect,
                                const SkMatrix* localMatrix) {
-    AutoRestoreEffects are;
     AutoCheckFlush acf(this);
-    GrDrawTarget* target = this->prepareToDraw(&paint, &are, &acf);
+    GrDrawState drawState;
+    GrDrawTarget* target = this->prepareToDraw(&drawState, &paint, &acf);
     if (NULL == target) {
         return;
     }
 
     GR_CREATE_TRACE_MARKER("GrContext::drawRectToRect", target);
 
-    target->drawRect(dstRect, &localRect, localMatrix);
+    target->drawRect(&drawState, dstRect, &localRect, localMatrix);
 }
 
 static void set_vertex_attributes(GrDrawState* drawState,
@@ -855,23 +853,22 @@
                              const GrColor colors[],
                              const uint16_t indices[],
                              int indexCount) {
-    AutoRestoreEffects are;
     AutoCheckFlush acf(this);
+    GrDrawState drawState;
     GrDrawTarget::AutoReleaseGeometry geo; // must be inside AutoCheckFlush scope
 
-    GrDrawTarget* target = this->prepareToDraw(&paint, &are, &acf);
+    GrDrawTarget* target = this->prepareToDraw(&drawState, &paint, &acf);
     if (NULL == target) {
         return;
     }
-    GrDrawState* drawState = target->drawState();
 
     GR_CREATE_TRACE_MARKER("GrContext::drawVertices", target);
 
     int colorOffset = -1, texOffset = -1;
-    set_vertex_attributes(drawState, texCoords, colors, &colorOffset, &texOffset);
+    set_vertex_attributes(&drawState, texCoords, colors, &colorOffset, &texOffset);
 
-    size_t VertexStride = drawState->getVertexStride();
-    if (!geo.set(target, vertexCount, indexCount)) {
+    size_t vertexStride = drawState.getVertexStride();
+    if (!geo.set(target, vertexCount, vertexStride, indexCount)) {
         SkDebugf("Failed to get space for vertices!\n");
         return;
     }
@@ -886,7 +883,7 @@
         if (colorOffset >= 0) {
             *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
         }
-        curVertex = (void*)((intptr_t)curVertex + VertexStride);
+        curVertex = (void*)((intptr_t)curVertex + vertexStride);
     }
 
     // we don't currently apply offscreen AA to this path. Need improved
@@ -896,9 +893,9 @@
         for (int i = 0; i < indexCount; ++i) {
             curIndex[i] = indices[i];
         }
-        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
+        target->drawIndexed(&drawState, primitiveType, 0, 0, vertexCount, indexCount);
     } else {
-        target->drawNonIndexed(primitiveType, 0, vertexCount);
+        target->drawNonIndexed(&drawState, primitiveType, 0, vertexCount);
     }
 }
 
@@ -918,9 +915,9 @@
         return;
     }
 
-    AutoRestoreEffects are;
     AutoCheckFlush acf(this);
-    GrDrawTarget* target = this->prepareToDraw(&paint, &are, &acf);
+    GrDrawState drawState;
+    GrDrawTarget* target = this->prepareToDraw(&drawState, &paint, &acf);
     if (NULL == target) {
         return;
     }
@@ -929,10 +926,11 @@
 
     const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
 
-    if (!fOvalRenderer->drawRRect(target, this, paint.isAntiAlias(), rrect, strokeRec)) {
+    if (!fOvalRenderer->drawRRect(target, &drawState, this, paint.isAntiAlias(), rrect,
+                                  strokeRec)) {
         SkPath path;
         path.addRRect(rrect);
-        this->internalDrawPath(target, paint.isAntiAlias(), path, strokeInfo);
+        this->internalDrawPath(target, &drawState, paint.isAntiAlias(), path, strokeInfo);
     }
 }
 
@@ -945,20 +943,20 @@
        return;
     }
 
-    AutoRestoreEffects are;
     AutoCheckFlush acf(this);
-    GrDrawTarget* target = this->prepareToDraw(&paint, &are, &acf);
+    GrDrawState drawState;
+    GrDrawTarget* target = this->prepareToDraw(&drawState, &paint, &acf);
 
     GR_CREATE_TRACE_MARKER("GrContext::drawDRRect", target);
 
-    if (!fOvalRenderer->drawDRRect(target, this, paint.isAntiAlias(), outer, inner)) {
+    if (!fOvalRenderer->drawDRRect(target, &drawState, this, paint.isAntiAlias(), outer, inner)) {
         SkPath path;
         path.addRRect(inner);
         path.addRRect(outer);
         path.setFillType(SkPath::kEvenOdd_FillType);
 
         GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle);
-        this->internalDrawPath(target, paint.isAntiAlias(), path, fillRec);
+        this->internalDrawPath(target, &drawState, paint.isAntiAlias(), path, fillRec);
     }
 }
 
@@ -978,9 +976,9 @@
         return;
     }
 
-    AutoRestoreEffects are;
     AutoCheckFlush acf(this);
-    GrDrawTarget* target = this->prepareToDraw(&paint, &are, &acf);
+    GrDrawState drawState;
+    GrDrawTarget* target = this->prepareToDraw(&drawState, &paint, &acf);
     if (NULL == target) {
         return;
     }
@@ -990,15 +988,16 @@
     const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
 
 
-    if (!fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), oval, strokeRec)) {
+    if (!fOvalRenderer->drawOval(target, &drawState, this, paint.isAntiAlias(), oval, strokeRec)) {
         SkPath path;
         path.addOval(oval);
-        this->internalDrawPath(target, paint.isAntiAlias(), path, strokeInfo);
+        this->internalDrawPath(target, &drawState, paint.isAntiAlias(), path, strokeInfo);
     }
 }
 
 // Can 'path' be drawn as a pair of filled nested rectangles?
 static bool is_nested_rects(GrDrawTarget* target,
+                            GrDrawState* drawState,
                             const SkPath& path,
                             const SkStrokeRec& stroke,
                             SkRect rects[2]) {
@@ -1008,16 +1007,13 @@
         return false;
     }
 
-    const GrDrawState& drawState = target->getDrawState();
-
     // TODO: this restriction could be lifted if we were willing to apply
     // the matrix to all the points individually rather than just to the rect
-    if (!drawState.getViewMatrix().preservesAxisAlignment()) {
+    if (!drawState->getViewMatrix().preservesAxisAlignment()) {
         return false;
     }
 
-    if (!target->getDrawState().canTweakAlphaForCoverage() &&
-        target->shouldDisableCoverageAAForBlend()) {
+    if (!drawState->canTweakAlphaForCoverage() && !drawState->couldApplyCoverage(*target->caps())) {
         return false;
     }
 
@@ -1066,19 +1062,18 @@
     if (strokeInfo.isDashed()) {
         SkPoint pts[2];
         if (path.isLine(pts)) {
-            AutoRestoreEffects are;
             AutoCheckFlush acf(this);
-            GrDrawTarget* target = this->prepareToDraw(&paint, &are, &acf);
+            GrDrawState drawState;
+            GrDrawTarget* target = this->prepareToDraw(&drawState, &paint, &acf);
             if (NULL == target) {
                 return;
-            }
-            GrDrawState* drawState = target->drawState();
+            };
 
-            SkMatrix origViewMatrix = drawState->getViewMatrix();
+            SkMatrix origViewMatrix = drawState.getViewMatrix();
             GrDrawState::AutoViewMatrixRestore avmr;
-            if (avmr.setIdentity(target->drawState())) {
-                if (GrDashingEffect::DrawDashLine(pts, paint, strokeInfo, fGpu, target,
-                                                  origViewMatrix)) {
+            if (avmr.setIdentity(&drawState)) {
+                if (GrDashingEffect::DrawDashLine(fGpu, target, &drawState, pts, paint,
+                                                  strokeInfo, origViewMatrix)) {
                     return;
                 }
             }
@@ -1103,32 +1098,31 @@
     // cache. This presents a potential hazard for buffered drawing. However,
     // the writePixels that uploads to the scratch will perform a flush so we're
     // OK.
-    AutoRestoreEffects are;
     AutoCheckFlush acf(this);
-    GrDrawTarget* target = this->prepareToDraw(&paint, &are, &acf);
+    GrDrawState drawState;
+    GrDrawTarget* target = this->prepareToDraw(&drawState, &paint, &acf);
     if (NULL == target) {
         return;
     }
-    GrDrawState* drawState = target->drawState();
 
     GR_CREATE_TRACE_MARKER1("GrContext::drawPath", target, "Is Convex", path.isConvex());
 
     const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
 
-    bool useCoverageAA = paint.isAntiAlias() && !drawState->getRenderTarget()->isMultisampled();
+    bool useCoverageAA = paint.isAntiAlias() && !drawState.getRenderTarget()->isMultisampled();
 
     if (useCoverageAA && strokeRec.getWidth() < 0 && !path.isConvex()) {
         // Concave AA paths are expensive - try to avoid them for special cases
         SkRect rects[2];
 
-        if (is_nested_rects(target, path, strokeRec, rects)) {
-            SkMatrix origViewMatrix = drawState->getViewMatrix();
+        if (is_nested_rects(target, &drawState, path, strokeRec, rects)) {
+            SkMatrix origViewMatrix = drawState.getViewMatrix();
             GrDrawState::AutoViewMatrixRestore avmr;
-            if (!avmr.setIdentity(target->drawState())) {
+            if (!avmr.setIdentity(&drawState)) {
                 return;
             }
 
-            fAARectRenderer->fillAANestedRects(target, rects, origViewMatrix);
+            fAARectRenderer->fillAANestedRects(target, &drawState, rects, origViewMatrix);
             return;
         }
     }
@@ -1137,12 +1131,16 @@
     bool isOval = path.isOval(&ovalRect);
 
     if (!isOval || path.isInverseFillType()
-        || !fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), ovalRect, strokeRec)) {
-        this->internalDrawPath(target, paint.isAntiAlias(), path, strokeInfo);
+        || !fOvalRenderer->drawOval(target, &drawState, this, paint.isAntiAlias(), ovalRect,
+                                    strokeRec)) {
+        this->internalDrawPath(target, &drawState, paint.isAntiAlias(), path, strokeInfo);
     }
 }
 
-void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path,
+void GrContext::internalDrawPath(GrDrawTarget* target,
+                                 GrDrawState* drawState,
+                                 bool useAA,
+                                 const SkPath& path,
                                  const GrStrokeInfo& strokeInfo) {
     SkASSERT(!path.isEmpty());
 
@@ -1154,20 +1152,20 @@
     // aa. If we have some future driver-mojo path AA that can do the right
     // thing WRT to the blend then we'll need some query on the PR.
     bool useCoverageAA = useAA &&
-        !target->getDrawState().getRenderTarget()->isMultisampled() &&
-        !target->shouldDisableCoverageAAForBlend();
+        !drawState->getRenderTarget()->isMultisampled() &&
+        drawState->couldApplyCoverage(*target->caps());
 
 
     GrPathRendererChain::DrawType type =
         useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
-                           GrPathRendererChain::kColor_DrawType;
+                        GrPathRendererChain::kColor_DrawType;
 
     const SkPath* pathPtr = &path;
     SkTLazy<SkPath> tmpPath;
     SkTCopyOnFirstWrite<SkStrokeRec> stroke(strokeInfo.getStrokeRec());
 
     // Try a 1st time without stroking the path and without allowing the SW renderer
-    GrPathRenderer* pr = this->getPathRenderer(*pathPtr, *stroke, target, false, type);
+    GrPathRenderer* pr = this->getPathRenderer(target, drawState, *pathPtr, *stroke, false, type);
 
     if (NULL == pr) {
         if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*stroke, this->getMatrix(), NULL)) {
@@ -1182,7 +1180,7 @@
         }
 
         // This time, allow SW renderer
-        pr = this->getPathRenderer(*pathPtr, *stroke, target, true, type);
+        pr = this->getPathRenderer(target, drawState, *pathPtr, *stroke, true, type);
     }
 
     if (NULL == pr) {
@@ -1192,7 +1190,7 @@
         return;
     }
 
-    pr->drawPath(*pathPtr, *stroke, target, useCoverageAA);
+    pr->drawPath(target, drawState, *pathPtr, *stroke, useCoverageAA);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1328,13 +1326,13 @@
     // The bracket ensures we pop the stack if we wind up flushing below.
     {
         GrDrawTarget* drawTarget = this->prepareToDraw(NULL, NULL, NULL);
-        GrDrawTarget::AutoGeometryAndStatePush agasp(drawTarget, GrDrawTarget::kReset_ASRInit,
-                                                     &matrix);
-        GrDrawState* drawState = drawTarget->drawState();
-        drawState->addColorProcessor(fp);
-        drawState->setRenderTarget(renderTarget);
-        drawState->disableState(GrDrawState::kClip_StateBit);
-        drawTarget->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)));
+        GrDrawTarget::AutoGeometryPush agp(drawTarget);
+
+        GrDrawState drawState(matrix);
+        drawState.addColorProcessor(fp);
+        drawState.setRenderTarget(renderTarget);
+        drawTarget->drawSimpleRect(&drawState, SkRect::MakeWH(SkIntToScalar(width),
+                                                              SkIntToScalar(height)));
     }
 
     if (kFlushWrites_PixelOp & pixelOpsFlags) {
@@ -1448,15 +1446,14 @@
                 // clear to the caller that a draw operation (i.e., drawSimpleRect)
                 // can be invoked in this method
                 {
-                    GrDrawTarget::AutoGeometryAndStatePush agasp(fDrawBuffer,
-                                                                 GrDrawTarget::kReset_ASRInit);
-                    GrDrawState* drawState = fDrawBuffer->drawState();
+                    GrDrawTarget::AutoGeometryPush agp(fDrawBuffer);
+                    GrDrawState drawState;
                     SkASSERT(fp);
-                    drawState->addColorProcessor(fp);
+                    drawState.addColorProcessor(fp);
 
-                    drawState->setRenderTarget(tempTexture->asRenderTarget());
+                    drawState.setRenderTarget(tempTexture->asRenderTarget());
                     SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
-                    fDrawBuffer->drawSimpleRect(rect);
+                    fDrawBuffer->drawSimpleRect(&drawState, rect);
                     // we want to read back from the scratch's origin
                     left = 0;
                     top = 0;
@@ -1508,9 +1505,8 @@
 void GrContext::discardRenderTarget(GrRenderTarget* renderTarget) {
     SkASSERT(renderTarget);
     ASSERT_OWNED_RESOURCE(renderTarget);
-    AutoRestoreEffects are;
     AutoCheckFlush acf(this);
-    GrDrawTarget* target = this->prepareToDraw(NULL, &are, &acf);
+    GrDrawTarget* target = this->prepareToDraw(NULL, NULL, &acf);
     if (NULL == target) {
         return;
     }
@@ -1545,43 +1541,34 @@
     }
 }
 
-////////////////////////////////////////////////////////////////////////////////
-
-GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint,
-                                       AutoRestoreEffects* are,
-                                       AutoCheckFlush* acf) {
-    // All users of this draw state should be freeing up all effects when they're done.
-    // Otherwise effects that own resources may keep those resources alive indefinitely.
-    SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageStages() &&
-             !fDrawState->hasGeometryProcessor());
-
+GrDrawTarget* GrContext::prepareToDraw(GrDrawState* ds,
+                                       const GrPaint* paint,
+                                       const AutoCheckFlush* acf) {
     if (NULL == fGpu) {
         return NULL;
     }
 
     ASSERT_OWNED_RESOURCE(fRenderTarget.get());
-    if (paint) {
-        SkASSERT(are);
-        SkASSERT(acf);
-        are->set(fDrawState);
-        fDrawState->setFromPaint(*paint, fViewMatrix, fRenderTarget.get());
+    if (ds) {
+        if (paint) {
+            SkASSERT(acf);
+            ds->setFromPaint(*paint, fViewMatrix, fRenderTarget.get());
 #if GR_DEBUG_PARTIAL_COVERAGE_CHECK
-        if ((paint->hasMask() || 0xff != paint->fCoverage) &&
-            !fDrawState->couldApplyCoverage(fGpu->caps())) {
-            SkDebugf("Partial pixel coverage will be incorrectly blended.\n");
-        }
+            if ((paint->hasMask() || 0xff != paint->fCoverage) &&
+                !fDrawState->couldApplyCoverage(fGpu->caps())) {
+                SkDebugf("Partial pixel coverage will be incorrectly blended.\n");
+            }
 #endif
-        // Clear any vertex attributes configured for the previous use of the
-        // GrDrawState which can effect which blend optimizations are in effect.
-        fDrawState->setDefaultVertexAttribs();
-    } else {
-        fDrawState->reset(fViewMatrix);
-        fDrawState->setRenderTarget(fRenderTarget.get());
+            // Clear any vertex attributes configured for the previous use of the
+            // GrDrawState which can effect which blend optimizations are in effect.
+            ds->setDefaultVertexAttribs();
+        } else {
+            ds->reset(fViewMatrix);
+            ds->setRenderTarget(fRenderTarget.get());
+        }
+        ds->setState(GrDrawState::kClip_StateBit, fClip && !fClip->fClipStack->isWideOpen());
     }
-    fDrawState->setState(GrDrawState::kClip_StateBit, fClip &&
-                                                     !fClip->fClipStack->isWideOpen());
     fDrawBuffer->setClip(fClip);
-    SkASSERT(fDrawState == fDrawBuffer->drawState());
     return fDrawBuffer;
 }
 
@@ -1591,9 +1578,10 @@
  * Due to its expense, the software path renderer has split out so it can
  * can be individually allowed/disallowed via the "allowSW" boolean.
  */
-GrPathRenderer* GrContext::getPathRenderer(const SkPath& path,
+GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
+                                           const GrDrawState* drawState,
+                                           const SkPath& path,
                                            const SkStrokeRec& stroke,
-                                           const GrDrawTarget* target,
                                            bool allowSW,
                                            GrPathRendererChain::DrawType drawType,
                                            GrPathRendererChain::StencilSupport* stencilSupport) {
@@ -1602,9 +1590,10 @@
         fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this));
     }
 
-    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path,
+    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(target,
+                                                             drawState,
+                                                             path,
                                                              stroke,
-                                                             target,
                                                              drawType,
                                                              stencilSupport);
 
@@ -1657,8 +1646,6 @@
     fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (fGpu,
                                                    fDrawBufferVBAllocPool,
                                                    fDrawBufferIBAllocPool));
-
-    fDrawBuffer->setDrawState(fDrawState);
 }
 
 GrDrawTarget* GrContext::getTextTarget() {
diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp
index e4ac225..3b31e87 100644
--- a/src/gpu/GrDefaultPathRenderer.cpp
+++ b/src/gpu/GrDefaultPathRenderer.cpp
@@ -163,10 +163,11 @@
 #endif
 }
 
-GrPathRenderer::StencilSupport GrDefaultPathRenderer::onGetStencilSupport(
-                                                            const SkPath& path,
-                                                            const SkStrokeRec& stroke,
-                                                            const GrDrawTarget*) const {
+GrPathRenderer::StencilSupport
+GrDefaultPathRenderer::onGetStencilSupport(const GrDrawTarget*,
+                                           const GrDrawState*,
+                                           const SkPath& path,
+                                           const SkStrokeRec& stroke) const {
     if (single_pass_path(path, stroke)) {
         return GrPathRenderer::kNoRestriction_StencilSupport;
     } else {
@@ -188,14 +189,15 @@
     *((*indices)++) = edgeV0Idx + 1;
 }
 
-bool GrDefaultPathRenderer::createGeom(const SkPath& path,
-                                       const SkStrokeRec& stroke,
-                                       SkScalar srcSpaceTol,
-                                       GrDrawTarget* target,
+bool GrDefaultPathRenderer::createGeom(GrDrawTarget* target,
+                                       GrDrawState* drawState,
                                        GrPrimitiveType* primType,
                                        int* vertexCnt,
                                        int* indexCnt,
-                                       GrDrawTarget::AutoReleaseGeometry* arg) {
+                                       GrDrawTarget::AutoReleaseGeometry* arg,
+                                       const SkPath& path,
+                                       const SkStrokeRec& stroke,
+                                       SkScalar srcSpaceTol) {
     {
     SkScalar srcSpaceTolSqd = SkScalarMul(srcSpaceTol, srcSpaceTol);
     int contourCnt;
@@ -231,8 +233,8 @@
         }
     }
 
-    target->drawState()->setDefaultVertexAttribs();
-    if (!arg->set(target, maxPts, maxIdxs)) {
+    drawState->setDefaultVertexAttribs();
+    if (!arg->set(target, maxPts, drawState->getVertexStride(), maxIdxs)) {
         return false;
     }
 
@@ -324,20 +326,19 @@
     return true;
 }
 
-bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
+bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target,
+                                             GrDrawState* drawState,
+                                             const SkPath& path,
                                              const SkStrokeRec& origStroke,
-                                             GrDrawTarget* target,
                                              bool stencilOnly) {
-
-    SkMatrix viewM = target->getDrawState().getViewMatrix();
+    SkMatrix viewM = drawState->getViewMatrix();
     SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke);
 
     SkScalar hairlineCoverage;
-    if (IsStrokeHairlineOrEquivalent(*stroke, target->getDrawState().getViewMatrix(),
+    if (IsStrokeHairlineOrEquivalent(*stroke, drawState->getViewMatrix(),
                                      &hairlineCoverage)) {
-        uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage *
-                                                 target->getDrawState().getCoverage());
-        target->drawState()->setCoverage(newCoverage);
+        uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage * drawState->getCoverage());
+        drawState->setCoverage(newCoverage);
 
         if (!stroke->isHairlineStyle()) {
             stroke.writable()->setHairlineStyle();
@@ -351,20 +352,18 @@
     int indexCnt;
     GrPrimitiveType primType;
     GrDrawTarget::AutoReleaseGeometry arg;
-    if (!this->createGeom(path,
-                          *stroke,
-                          tol,
-                          target,
+    if (!this->createGeom(target,
+                          drawState,
                           &primType,
                           &vertexCnt,
                           &indexCnt,
-                          &arg)) {
+                          &arg,
+                          path,
+                          *stroke,
+                          tol)) {
         return false;
     }
 
-    SkASSERT(target);
-    GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit);
-    GrDrawState* drawState = target->drawState();
     bool colorWritesWereDisabled = drawState->isColorWriteDisabled();
     // face culling doesn't make sense here
     SkASSERT(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
@@ -491,8 +490,8 @@
             } else {
                 bounds = path.getBounds();
             }
-            GrDrawTarget::AutoGeometryAndStatePush agasp(target, GrDrawTarget::kPreserve_ASRInit);
-            target->drawSimpleRect(bounds);
+            GrDrawTarget::AutoGeometryPush agp(target);
+            target->drawSimpleRect(drawState, bounds);
         } else {
             if (passCount > 1) {
                 drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
@@ -500,41 +499,50 @@
             GrDrawState::AutoRestoreEffects are(drawState);
             drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(false))->unref();
             if (indexCnt) {
-                target->drawIndexed(primType, 0, 0,
-                                    vertexCnt, indexCnt, &devBounds);
+                target->drawIndexed(drawState,
+                                    primType,
+                                    0,
+                                    0,
+                                    vertexCnt,
+                                    indexCnt,
+                                    &devBounds);
             } else {
-                target->drawNonIndexed(primType, 0, vertexCnt, &devBounds);
+                target->drawNonIndexed(drawState, primType, 0, vertexCnt, &devBounds);
             }
         }
     }
     return true;
 }
 
-bool GrDefaultPathRenderer::canDrawPath(const SkPath& path,
+bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget* target,
+                                        const GrDrawState* drawState,
+                                        const SkPath& path,
                                         const SkStrokeRec& stroke,
-                                        const GrDrawTarget* target,
                                         bool antiAlias) const {
     // this class can draw any path with any fill but doesn't do any anti-aliasing.
 
     return !antiAlias && !(SkPath::kConic_SegmentMask & path.getSegmentMasks()) &&
         (stroke.isFillStyle() ||
-         IsStrokeHairlineOrEquivalent(stroke, target->getDrawState().getViewMatrix(), NULL));
+         IsStrokeHairlineOrEquivalent(stroke, drawState->getViewMatrix(), NULL));
 }
 
-bool GrDefaultPathRenderer::onDrawPath(const SkPath& path,
+bool GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target,
+                                       GrDrawState* drawState,
+                                       const SkPath& path,
                                        const SkStrokeRec& stroke,
-                                       GrDrawTarget* target,
                                        bool antiAlias) {
-    return this->internalDrawPath(path,
+    return this->internalDrawPath(target,
+                                  drawState,
+                                  path,
                                   stroke,
-                                  target,
                                   false);
 }
 
-void GrDefaultPathRenderer::onStencilPath(const SkPath& path,
-                                          const SkStrokeRec& stroke,
-                                          GrDrawTarget* target) {
+void GrDefaultPathRenderer::onStencilPath(GrDrawTarget* target,
+                                          GrDrawState* drawState,
+                                          const SkPath& path,
+                                          const SkStrokeRec& stroke) {
     SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType());
     SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType());
-    this->internalDrawPath(path, stroke, target, true);
+    this->internalDrawPath(target, drawState, path, stroke, true);
 }
diff --git a/src/gpu/GrDefaultPathRenderer.h b/src/gpu/GrDefaultPathRenderer.h
index c60afcc..0f90daa 100644
--- a/src/gpu/GrDefaultPathRenderer.h
+++ b/src/gpu/GrDefaultPathRenderer.h
@@ -19,39 +19,45 @@
 public:
     GrDefaultPathRenderer(bool separateStencilSupport, bool stencilWrapOpsSupport);
 
-    virtual bool canDrawPath(const SkPath&,
+    virtual bool canDrawPath(const GrDrawTarget*,
+                             const GrDrawState*,
+                             const SkPath&,
                              const SkStrokeRec&,
-                             const GrDrawTarget*,
                              bool antiAlias) const SK_OVERRIDE;
 
 private:
 
-    virtual StencilSupport onGetStencilSupport(const SkPath&,
-                                               const SkStrokeRec&,
-                                               const GrDrawTarget*) const SK_OVERRIDE;
+    virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
+                                               const GrDrawState*,
+                                               const SkPath&,
+                                               const SkStrokeRec&) const SK_OVERRIDE;
 
-    virtual bool onDrawPath(const SkPath&,
+    virtual bool onDrawPath(GrDrawTarget*,
+                            GrDrawState*,
+                            const SkPath&,
                             const SkStrokeRec&,
-                            GrDrawTarget*,
                             bool antiAlias) SK_OVERRIDE;
 
-    virtual void onStencilPath(const SkPath&,
-                               const SkStrokeRec&,
-                               GrDrawTarget*) SK_OVERRIDE;
+    virtual void onStencilPath(GrDrawTarget*,
+                               GrDrawState*,
+                               const SkPath&,
+                               const SkStrokeRec&) SK_OVERRIDE;
 
-    bool internalDrawPath(const SkPath&,
+    bool internalDrawPath(GrDrawTarget*,
+                          GrDrawState*,
+                          const SkPath&,
                           const SkStrokeRec&,
-                          GrDrawTarget*,
                           bool stencilOnly);
 
-    bool createGeom(const SkPath&,
-                    const SkStrokeRec&,
-                    SkScalar srcSpaceTol,
-                    GrDrawTarget*,
+    bool createGeom(GrDrawTarget*,
+                    GrDrawState*,
                     GrPrimitiveType*,
                     int* vertexCnt,
                     int* indexCnt,
-                    GrDrawTarget::AutoReleaseGeometry*);
+                    GrDrawTarget::AutoReleaseGeometry*,
+                    const SkPath&,
+                    const SkStrokeRec&,
+                    SkScalar srcSpaceTol);
 
     bool    fSeparateStencil;
     bool    fStencilWrapOps;
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index 58c8121..db98238 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -96,7 +96,6 @@
 }
 
 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
-    this->finish();
     SkSafeSetNull(fGammaTexture);
 }
 
@@ -382,21 +381,21 @@
     return GrColorPackRGBA(r, g, b, 0xff);
 }
 
-static void* alloc_vertices(GrDrawTarget* drawTarget, int numVertices, bool useColorVerts) {
+static size_t get_vertex_stride(bool useColorVerts) {
+    return useColorVerts ? (2 * sizeof(SkPoint) + sizeof(GrColor)) :
+                           (2 * sizeof(SkPoint));
+}
+
+static void* alloc_vertices(GrDrawTarget* drawTarget,
+                            int numVertices,
+                            bool useColorVerts) {
     if (numVertices <= 0) {
         return NULL;
     }
 
-    // set up attributes
-    if (useColorVerts) {
-        drawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
-                                    SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
-    } else {
-        drawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
-                                    SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
-    }
     void* vertices = NULL;
     bool success = drawTarget->reserveVertexAndIndexSpace(numVertices,
+                                                          get_vertex_stride(useColorVerts),
                                                           0,
                                                           &vertices,
                                                           NULL);
@@ -578,7 +577,9 @@
     if (NULL == fVertices) {
         int maxQuadVertices = kVerticesPerGlyph * fContext->getQuadIndexBuffer()->maxQuads();
         fAllocVertexCount = SkMin32(fTotalVertexCount, maxQuadVertices);
-        fVertices = alloc_vertices(fDrawTarget, fAllocVertexCount, useColorVerts);
+        fVertices = alloc_vertices(fDrawTarget,
+                                   fAllocVertexCount,
+                                   useColorVerts);
     }
 
     SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX + SK_DistanceFieldInset);
@@ -588,10 +589,7 @@
 
     fVertexBounds.joinNonEmptyArg(glyphRect);
 
-    size_t vertSize = fUseLCDText ? (2 * sizeof(SkPoint))
-                                  : (2 * sizeof(SkPoint) + sizeof(GrColor));
-    
-    SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexStride());
+    size_t vertSize = get_vertex_stride(useColorVerts);
 
     SkPoint* positions = reinterpret_cast<SkPoint*>(
                                reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex);
@@ -607,9 +605,6 @@
                               SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + th)),
                               vertSize);
     if (useColorVerts) {
-        if (0xFF == GrColorUnpackA(fPaint.getColor())) {
-            fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
-        }
         // color comes after position.
         GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
         for (int i = 0; i < 4; ++i) {
@@ -623,15 +618,27 @@
     return true;
 }
 
+// We use color vertices if we aren't drawing LCD text
+static void set_vertex_attributes(GrDrawState* drawState, bool useColorVerts) {
+    // set up attributes
+    if (useColorVerts) {
+        drawState->setVertexAttribs<gTextVertexWithColorAttribs>(
+                                    SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
+    } else {
+        drawState->setVertexAttribs<gTextVertexAttribs>(
+                                    SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
+    }
+}
+
 void GrDistanceFieldTextContext::flush() {
     if (NULL == fDrawTarget) {
         return;
     }
 
-    GrDrawState* drawState = fDrawTarget->drawState();
-    GrDrawState::AutoRestoreEffects are(drawState);
-
-    drawState->setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget());
+    GrDrawState drawState;
+    drawState.setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget());
+    bool useColorVerts = !fUseLCDText;
+    set_vertex_attributes(&drawState, useColorVerts);
 
     if (fCurrVertex > 0) {
         // setup our sampler state for our text texture/atlas
@@ -648,7 +655,7 @@
         this->setupCoverageEffect(filteredColor);
 
         // Effects could be stored with one of the cache objects (atlas?)
-        drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
+        drawState.setGeometryProcessor(fCachedGeometryProcessor.get());
 
         // Set draw state
         if (fUseLCDText) {
@@ -658,28 +665,34 @@
                 fPaint.numColorStages()) {
                 SkDebugf("LCD Text will not draw correctly.\n");
             }
-            SkASSERT(!drawState->hasColorVertexAttribute());
+            SkASSERT(!drawState.hasColorVertexAttribute());
             // We don't use the GrPaint's color in this case because it's been premultiplied by
             // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
             // the mask texture color. The end result is that we get
             //            mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
             int a = SkColorGetA(fSkPaint.getColor());
             // paintAlpha
-            drawState->setColor(SkColorSetARGB(a, a, a, a));
+            drawState.setColor(SkColorSetARGB(a, a, a, a));
             // paintColor
-            drawState->setBlendConstant(colorNoPreMul);
-            drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
+            drawState.setBlendConstant(colorNoPreMul);
+            drawState.setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
         } else {
+            if (0xFF == GrColorUnpackA(fPaint.getColor())) {
+                drawState.setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
+            }
             // set back to normal in case we took LCD path previously.
-            drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+            drawState.setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
             // We're using per-vertex color.
-            SkASSERT(drawState->hasColorVertexAttribute());
+            SkASSERT(drawState.hasColorVertexAttribute());
         }
         int nGlyphs = fCurrVertex / kVerticesPerGlyph;
         fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
-        fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
+        fDrawTarget->drawIndexedInstances(&drawState,
+                                          kTriangles_GrPrimitiveType,
                                           nGlyphs,
-                                          kVerticesPerGlyph, kIndicesPerGlyph, &fVertexBounds);
+                                          kVerticesPerGlyph,
+                                          kIndicesPerGlyph,
+                                          &fVertexBounds);
         fDrawTarget->resetVertexSource();
         fVertices = NULL;
         fTotalVertexCount -= fCurrVertex;
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 974aff4..baa7564 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -25,10 +25,8 @@
 class GrPaint;
 class GrTexture;
 
-class GrDrawState : public SkRefCnt {
+class GrDrawState {
 public:
-    SK_DECLARE_INST_COUNT(GrDrawState)
-
     GrDrawState() {
         SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
         this->reset();
@@ -42,7 +40,7 @@
     /**
      * Copies another draw state.
      **/
-    GrDrawState(const GrDrawState& state) : INHERITED() {
+    GrDrawState(const GrDrawState& state) {
         SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
         *this = state;
     }
@@ -872,8 +870,6 @@
     mutable bool fCoverageProcInfoValid;
 
     friend class GrOptDrawState;
-
-    typedef SkRefCnt INHERITED;
 };
 
 GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 3d858c3..cd1e0b5 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -93,9 +93,6 @@
     , fContext(context)
     , fGpuTraceMarkerCount(0) {
     SkASSERT(context);
-    fDrawState = &fDefaultDrawState;
-    // We assume that fDrawState always owns a ref to the object it points at.
-    fDefaultDrawState.ref();
     GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
 #ifdef SK_DEBUG
     geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
@@ -112,7 +109,6 @@
     SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
     SkASSERT(kNone_GeometrySrcType == geoSrc.fIndexSrc);
     SkASSERT(kNone_GeometrySrcType == geoSrc.fVertexSrc);
-    fDrawState->unref();
 }
 
 void GrDrawTarget::releaseGeometry() {
@@ -133,18 +129,6 @@
     return fClip;
 }
 
-void GrDrawTarget::setDrawState(GrDrawState*  drawState) {
-    SkASSERT(fDrawState);
-    if (NULL == drawState) {
-        drawState = &fDefaultDrawState;
-    }
-    if (fDrawState != drawState) {
-        fDrawState->unref();
-        drawState->ref();
-        fDrawState = drawState;
-    }
-}
-
 bool GrDrawTarget::reserveVertexSpace(size_t vertexSize,
                                       int vertexCount,
                                       void** vertices) {
@@ -191,11 +175,11 @@
 }
 
 bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount,
+                                              size_t vertexStride,
                                               int indexCount,
                                               void** vertices,
                                               void** indices) {
-    size_t vertexStride = this->drawState()->getVertexStride();
-    this->willReserveVertexAndIndexSpace(vertexCount, indexCount);
+    this->willReserveVertexAndIndexSpace(vertexCount, vertexStride, indexCount);
     if (vertexCount) {
         if (!this->reserveVertexSpace(vertexStride, vertexCount, vertices)) {
             if (indexCount) {
@@ -215,7 +199,8 @@
     return true;
 }
 
-bool GrDrawTarget::geometryHints(int32_t* vertexCount,
+bool GrDrawTarget::geometryHints(size_t vertexStride,
+                                 int32_t* vertexCount,
                                  int32_t* indexCount) const {
     if (vertexCount) {
         *vertexCount = -1;
@@ -266,13 +251,13 @@
     }
 }
 
-void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) {
+void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer, size_t vertexStride) {
     this->releasePreviousVertexSource();
     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
     geoSrc.fVertexSrc    = kBuffer_GeometrySrcType;
     geoSrc.fVertexBuffer = buffer;
     buffer->ref();
-    geoSrc.fVertexSize = this->drawState()->getVertexStride();
+    geoSrc.fVertexSize = vertexStride;
 }
 
 void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
@@ -320,10 +305,12 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
-                             int startIndex, int vertexCount,
+bool GrDrawTarget::checkDraw(const GrDrawState& drawState,
+                             GrPrimitiveType type,
+                             int startVertex,
+                             int startIndex,
+                             int vertexCount,
                              int indexCount) const {
-    const GrDrawState& drawState = this->getDrawState();
 #ifdef SK_DEBUG
     const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
     int maxVertex = startVertex + vertexCount;
@@ -395,13 +382,15 @@
     return true;
 }
 
-bool GrDrawTarget::setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds) {
-    if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDstColor()) {
+bool GrDrawTarget::setupDstReadIfNecessary(GrDrawState* ds,
+                                           GrDeviceCoordTexture* dstCopy,
+                                           const SkRect* drawBounds) {
+    if (this->caps()->dstReadInShaderSupport() || !ds->willEffectReadDstColor()) {
         return true;
     }
-    GrRenderTarget* rt = this->drawState()->getRenderTarget();
     SkIRect copyRect;
     const GrClipData* clip = this->getClip();
+    GrRenderTarget* rt = ds->getRenderTarget();
     clip->getConservativeBounds(rt, &copyRect);
 
     if (drawBounds) {
@@ -443,18 +432,22 @@
     }
 }
 
-void GrDrawTarget::drawIndexed(GrPrimitiveType type,
+void GrDrawTarget::drawIndexed(GrDrawState* ds,
+                               GrPrimitiveType type,
                                int startVertex,
                                int startIndex,
                                int vertexCount,
                                int indexCount,
                                const SkRect* devBounds) {
-    if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
+    SkASSERT(ds);
+    if (indexCount > 0 &&
+        this->checkDraw(*ds, type, startVertex, startIndex, vertexCount, indexCount)) {
+
         // Setup clip
         GrClipMaskManager::ScissorState scissorState;
         GrDrawState::AutoRestoreEffects are;
         GrDrawState::AutoRestoreStencil ars;
-        if (!this->setupClip(devBounds, &are, &ars, &scissorState)) {
+        if (!this->setupClip(devBounds, &are, &ars, ds, &scissorState)) {
             return;
         }
 
@@ -473,23 +466,26 @@
             info.setDevBounds(*devBounds);
         }
         // TODO: We should continue with incorrect blending.
-        if (!this->setupDstReadIfNecessary(&info)) {
+        if (!this->setupDstReadIfNecessary(ds, &info)) {
             return;
         }
-        this->onDraw(info, scissorState);
+        this->onDraw(*ds, info, scissorState);
     }
 }
 
-void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
+void GrDrawTarget::drawNonIndexed(GrDrawState* ds,
+                                  GrPrimitiveType type,
                                   int startVertex,
                                   int vertexCount,
                                   const SkRect* devBounds) {
-    if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
+    SkASSERT(ds);
+    if (vertexCount > 0 && this->checkDraw(*ds, type, startVertex, -1, vertexCount, -1)) {
+
         // Setup clip
         GrClipMaskManager::ScissorState scissorState;
         GrDrawState::AutoRestoreEffects are;
         GrDrawState::AutoRestoreStencil ars;
-        if (!this->setupClip(devBounds, &are, &ars, &scissorState)) {
+        if (!this->setupClip(devBounds, &are, &ars, ds, &scissorState)) {
             return;
         }
 
@@ -509,10 +505,10 @@
         }
 
         // TODO: We should continue with incorrect blending.
-        if (!this->setupDstReadIfNecessary(&info)) {
+        if (!this->setupDstReadIfNecessary(ds, &info)) {
             return;
         }
-        this->onDraw(info, scissorState);
+        this->onDraw(*ds, info, scissorState);
     }
 }
 
@@ -535,6 +531,7 @@
 }
 
 void GrDrawTarget::getPathStencilSettingsForFilltype(GrPathRendering::FillType fill,
+                                                     const GrStencilBuffer* sb,
                                                      GrStencilSettings* outStencilSettings) {
 
     switch (fill) {
@@ -547,94 +544,112 @@
             *outStencilSettings = even_odd_path_stencil_settings();
             break;
     }
-    this->clipMaskManager()->adjustPathStencilParams(outStencilSettings);
+    this->clipMaskManager()->adjustPathStencilParams(sb, outStencilSettings);
 }
 
-void GrDrawTarget::stencilPath(const GrPath* path, GrPathRendering::FillType fill) {
+void GrDrawTarget::stencilPath(GrDrawState* ds,
+                               const GrPath* path,
+                               GrPathRendering::FillType fill) {
     // TODO: extract portions of checkDraw that are relevant to path stenciling.
     SkASSERT(path);
     SkASSERT(this->caps()->pathRenderingSupport());
+    SkASSERT(ds);
 
     // Setup clip
     GrClipMaskManager::ScissorState scissorState;
     GrDrawState::AutoRestoreEffects are;
     GrDrawState::AutoRestoreStencil ars;
-    if (!this->setupClip(NULL, &are, &ars, &scissorState)) {
+    if (!this->setupClip(NULL, &are, &ars, ds, &scissorState)) {
         return;
     }
 
     // set stencil settings for path
     GrStencilSettings stencilSettings;
-    this->getPathStencilSettingsForFilltype(fill, &stencilSettings);
+    this->getPathStencilSettingsForFilltype(fill,
+                                            ds->getRenderTarget()->getStencilBuffer(),
+                                            &stencilSettings);
 
-    this->onStencilPath(path, scissorState, stencilSettings);
+    this->onStencilPath(*ds, path, scissorState, stencilSettings);
 }
 
-void GrDrawTarget::drawPath(const GrPath* path, GrPathRendering::FillType fill) {
+void GrDrawTarget::drawPath(GrDrawState* ds,
+                            const GrPath* path,
+                            GrPathRendering::FillType fill) {
     // TODO: extract portions of checkDraw that are relevant to path rendering.
     SkASSERT(path);
     SkASSERT(this->caps()->pathRenderingSupport());
+    SkASSERT(ds);
 
     SkRect devBounds = path->getBounds();
-    SkMatrix viewM = this->drawState()->getViewMatrix();
+    SkMatrix viewM = ds->getViewMatrix();
     viewM.mapRect(&devBounds);
 
     // Setup clip
     GrClipMaskManager::ScissorState scissorState;
     GrDrawState::AutoRestoreEffects are;
     GrDrawState::AutoRestoreStencil ars;
-    if (!this->setupClip(&devBounds, &are, &ars, &scissorState)) {
+    if (!this->setupClip(&devBounds, &are, &ars, ds, &scissorState)) {
        return;
     }
 
     // set stencil settings for path
     GrStencilSettings stencilSettings;
-    this->getPathStencilSettingsForFilltype(fill, &stencilSettings);
+    this->getPathStencilSettingsForFilltype(fill,
+                                            ds->getRenderTarget()->getStencilBuffer(),
+                                            &stencilSettings);
 
     GrDeviceCoordTexture dstCopy;
-    if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) {
+    if (!this->setupDstReadIfNecessary(ds, &dstCopy, &devBounds)) {
         return;
     }
 
-    this->onDrawPath(path, scissorState, stencilSettings, dstCopy.texture() ? &dstCopy : NULL);
+    this->onDrawPath(*ds, path, scissorState, stencilSettings, dstCopy.texture() ? &dstCopy : NULL);
 }
 
-void GrDrawTarget::drawPaths(const GrPathRange* pathRange,
-                             const uint32_t indices[], int count,
-                             const float transforms[], PathTransformType transformsType,
+void GrDrawTarget::drawPaths(GrDrawState* ds,
+                             const GrPathRange* pathRange,
+                             const uint32_t indices[],
+                             int count,
+                             const float transforms[],
+                             PathTransformType transformsType,
                              GrPathRendering::FillType fill) {
     SkASSERT(this->caps()->pathRenderingSupport());
     SkASSERT(pathRange);
     SkASSERT(indices);
     SkASSERT(transforms);
+    SkASSERT(ds);
 
     // Setup clip
     GrClipMaskManager::ScissorState scissorState;
     GrDrawState::AutoRestoreEffects are;
     GrDrawState::AutoRestoreStencil ars;
 
-    if (!this->setupClip(NULL, &are, &ars, &scissorState)) {
+    if (!this->setupClip(NULL, &are, &ars, ds, &scissorState)) {
         return;
     }
 
     // set stencil settings for path
     GrStencilSettings stencilSettings;
-    this->getPathStencilSettingsForFilltype(fill, &stencilSettings);
+    this->getPathStencilSettingsForFilltype(fill,
+                                            ds->getRenderTarget()->getStencilBuffer(),
+                                            &stencilSettings);
 
     // Don't compute a bounding box for setupDstReadIfNecessary(), we'll opt
     // instead for it to just copy the entire dst. Realistically this is a moot
     // point, because any context that supports NV_path_rendering will also
     // support NV_blend_equation_advanced.
     GrDeviceCoordTexture dstCopy;
-    if (!this->setupDstReadIfNecessary(&dstCopy, NULL)) {
+    if (!this->setupDstReadIfNecessary(ds, &dstCopy, NULL)) {
         return;
     }
 
-    this->onDrawPaths(pathRange, indices, count, transforms, transformsType, scissorState,
+    this->onDrawPaths(*ds, pathRange, indices, count, transforms, transformsType, scissorState,
                       stencilSettings, dstCopy.texture() ? &dstCopy : NULL);
 }
 
-void GrDrawTarget::clear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
+void GrDrawTarget::clear(const SkIRect* rect,
+                         GrColor color,
+                         bool canIgnoreRect,
                          GrRenderTarget* renderTarget) {
     if (fCaps->useDrawInsteadOfClear()) {
         // This works around a driver bug with clear by drawing a rect instead.
@@ -646,14 +661,13 @@
             // We first issue a discard() since that may help tilers.
             this->discard(renderTarget);
         }
-        AutoStateRestore asr(this, kReset_ASRInit, &SkMatrix::I());
 
-        this->drawState()->setColor(color);
-        this->drawState()->disableState(GrDrawState::kClip_StateBit);
-        this->drawState()->disableState(GrDrawState::kHWAntialias_StateBit);
-        this->drawState()->setRenderTarget(renderTarget);
+        GrDrawState drawState;
 
-        this->drawSimpleRect(*rect);
+        drawState.setColor(color);
+        drawState.setRenderTarget(renderTarget);
+
+        this->drawSimpleRect(&drawState, *rect);
     } else {       
         this->onClear(rect, color, canIgnoreRect, renderTarget);
     }
@@ -700,11 +714,14 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
+void GrDrawTarget::drawIndexedInstances(GrDrawState* ds,
+                                        GrPrimitiveType type,
                                         int instanceCount,
                                         int verticesPerInstance,
                                         int indicesPerInstance,
                                         const SkRect* devBounds) {
+    SkASSERT(ds);
+
     if (!verticesPerInstance || !indicesPerInstance) {
         return;
     }
@@ -718,7 +735,7 @@
     GrClipMaskManager::ScissorState scissorState;
     GrDrawState::AutoRestoreEffects are;
     GrDrawState::AutoRestoreStencil ars;
-    if (!this->setupClip(devBounds, &are, &ars, &scissorState)) {
+    if (!this->setupClip(devBounds, &are, &ars, ds, &scissorState)) {
         return;
     }
 
@@ -734,21 +751,21 @@
         info.setDevBounds(*devBounds);
     }
     // TODO: We should continue with incorrect blending.
-    if (!this->setupDstReadIfNecessary(&info)) {
+    if (!this->setupDstReadIfNecessary(ds, &info)) {
         return;
     }
-
     while (instanceCount) {
         info.fInstanceCount = SkTMin(instanceCount, maxInstancesPerDraw);
         info.fVertexCount = info.fInstanceCount * verticesPerInstance;
         info.fIndexCount = info.fInstanceCount * indicesPerInstance;
 
-        if (this->checkDraw(type,
+        if (this->checkDraw(*ds,
+                            type,
                             info.fStartVertex,
                             info.fStartIndex,
                             info.fVertexCount,
                             info.fIndexCount)) {
-            this->onDraw(info, scissorState);
+            this->onDraw(*ds, info, scissorState);
         }
         info.fStartVertex += info.fVertexCount;
         instanceCount -= info.fInstanceCount;
@@ -757,82 +774,13 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-GrDrawTarget::AutoStateRestore::AutoStateRestore() {
-    fDrawTarget = NULL;
-}
-
-GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
-                                                 ASRInit init,
-                                                 const SkMatrix* vm) {
-    fDrawTarget = NULL;
-    this->set(target, init, vm);
-}
-
-GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
-    if (fDrawTarget) {
-        fDrawTarget->setDrawState(fSavedState);
-        fSavedState->unref();
-    }
-}
-
-void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init, const SkMatrix* vm) {
-    SkASSERT(NULL == fDrawTarget);
-    fDrawTarget = target;
-    fSavedState = target->drawState();
-    SkASSERT(fSavedState);
-    fSavedState->ref();
-    if (kReset_ASRInit == init) {
-        if (NULL == vm) {
-            // calls the default cons
-            fTempState.init();
-        } else {
-            SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*vm));
-        }
-    } else {
-        SkASSERT(kPreserve_ASRInit == init);
-        if (NULL == vm) {
-            fTempState.set(*fSavedState);
-        } else {
-            SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*fSavedState, *vm));
-        }
-    }
-    target->setDrawState(fTempState.get());
-}
-
-bool GrDrawTarget::AutoStateRestore::setIdentity(GrDrawTarget* target, ASRInit init) {
-    SkASSERT(NULL == fDrawTarget);
-    fDrawTarget = target;
-    fSavedState = target->drawState();
-    SkASSERT(fSavedState);
-    fSavedState->ref();
-    if (kReset_ASRInit == init) {
-        // calls the default cons
-        fTempState.init();
-    } else {
-        SkASSERT(kPreserve_ASRInit == init);
-        // calls the copy cons
-        fTempState.set(*fSavedState);
-        if (!fTempState.get()->setIdentityViewMatrix()) {
-            // let go of any resources held by the temp
-            fTempState.get()->reset();
-            fDrawTarget = NULL;
-            fSavedState->unref();
-            fSavedState = NULL;
-            return false;
-        }
-    }
-    target->setDrawState(fTempState.get());
-    return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
                                          GrDrawTarget*  target,
                                          int vertexCount,
+                                         size_t vertexStride,
                                          int indexCount) {
     fTarget = NULL;
-    this->set(target, vertexCount, indexCount);
+    this->set(target, vertexCount, vertexStride, indexCount);
 }
 
 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
@@ -845,12 +793,14 @@
 
 bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget*  target,
                                             int vertexCount,
+                                            size_t vertexStride,
                                             int indexCount) {
     this->reset();
     fTarget = target;
     bool success = true;
     if (fTarget) {
         success = target->reserveVertexAndIndexSpace(vertexCount,
+                                                     vertexStride,
                                                      indexCount,
                                                      &fVertices,
                                                      &fIndices);
@@ -966,23 +916,23 @@
     GrRenderTarget* rt = dst->asRenderTarget();
     GrTexture* tex = src->asTexture();
 
-    GrDrawTarget::AutoStateRestore asr(this, kReset_ASRInit);
-    this->drawState()->setRenderTarget(rt);
+    GrDrawState drawState;
+    drawState.setRenderTarget(rt);
     SkMatrix matrix;
     matrix.setTranslate(SkIntToScalar(clippedSrcRect.fLeft - clippedDstPoint.fX),
                         SkIntToScalar(clippedSrcRect.fTop - clippedDstPoint.fY));
     matrix.postIDiv(tex->width(), tex->height());
-    this->drawState()->addColorTextureProcessor(tex, matrix);
+    drawState.addColorTextureProcessor(tex, matrix);
     SkIRect dstRect = SkIRect::MakeXYWH(clippedDstPoint.fX,
                                         clippedDstPoint.fY,
                                         clippedSrcRect.width(),
                                         clippedSrcRect.height());
-    this->drawSimpleRect(dstRect);
+    this->drawSimpleRect(&drawState, dstRect);
     return true;
 }
 
-bool GrDrawTarget::canCopySurface(GrSurface* dst,
-                                  GrSurface* src,
+bool GrDrawTarget::canCopySurface(const GrSurface* dst,
+                                  const GrSurface* src,
                                   const SkIRect& srcRect,
                                   const SkIPoint& dstPoint) {
     SkASSERT(dst);
@@ -1187,10 +1137,12 @@
 bool GrClipTarget::setupClip(const SkRect* devBounds,
                              GrDrawState::AutoRestoreEffects* are,
                              GrDrawState::AutoRestoreStencil* ars,
+                             GrDrawState* ds,
                              GrClipMaskManager::ScissorState* scissorState) {
-    return fClipMaskManager.setupClipping(this->getClip(),
-                                          devBounds,
+    return fClipMaskManager.setupClipping(ds,
                                           are,
                                           ars,
-                                          scissorState);
+                                          scissorState,
+                                          this->getClip(),
+                                          devBounds);
 }
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 75a2f25..a41fc43 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -67,34 +67,6 @@
     const GrClipData* getClip() const;
 
     /**
-     * Sets the draw state object for the draw target. Note that this does not
-     * make a copy. The GrDrawTarget will take a reference to passed object.
-     * Passing NULL will cause the GrDrawTarget to use its own internal draw
-     * state object rather than an externally provided one.
-     */
-    void setDrawState(GrDrawState*  drawState);
-
-    /**
-     * Read-only access to the GrDrawTarget's current draw state.
-     */
-    const GrDrawState& getDrawState() const { return *fDrawState; }
-
-    /**
-     * Read-write access to the GrDrawTarget's current draw state. Note that
-     * this doesn't ref.
-     */
-    GrDrawState* drawState() { return fDrawState; }
-
-    /** When we're using coverage AA but the blend is incompatible (given gpu
-     * limitations) we should disable AA. */
-    bool shouldDisableCoverageAAForBlend() const {
-        // Enable below if we should draw with AA even when it produces
-        // incorrect blending.
-        // return false;
-        return !this->getDrawState().couldApplyCoverage(*this->caps());
-    }
-
-    /**
      * There are three types of "sources" of geometry (vertices and indices) for
      * draw calls made on the target. When performing an indexed draw, the
      * indices and vertices can use different source types. Once a source is
@@ -168,6 +140,7 @@
      *                     non-zero. Illegal to pass NULL if indexCount > 0.
      */
      bool reserveVertexAndIndexSpace(int vertexCount,
+                                     size_t vertexStride,
                                      int indexCount,
                                      void** vertices,
                                      void** indices);
@@ -194,8 +167,7 @@
      *
      * @return  true if target should be flushed based on the input values.
      */
-    virtual bool geometryHints(int* vertexCount,
-                               int* indexCount) const;
+    virtual bool geometryHints(size_t vertexStride, int* vertexCount, int* indexCount) const;
 
     /**
      * Sets source of vertex data for the next draw. Data does not have to be
@@ -205,7 +177,7 @@
      *                      unlocked before draw call. Vertex size is queried
      *                      from current GrDrawState.
      */
-    void setVertexSourceToBuffer(const GrVertexBuffer* buffer);
+    void setVertexSourceToBuffer(const GrVertexBuffer* buffer, size_t vertexStride);
 
     /**
      * Sets source of index data for the next indexed draw. Data does not have
@@ -267,7 +239,8 @@
      * @param devBounds    optional bounds hint. This is a promise from the caller,
      *                     not a request for clipping.
      */
-    void drawIndexed(GrPrimitiveType type,
+    void drawIndexed(GrDrawState*,
+                     GrPrimitiveType type,
                      int startVertex,
                      int startIndex,
                      int vertexCount,
@@ -285,7 +258,8 @@
      * @param devBounds    optional bounds hint. This is a promise from the caller,
      *                     not a request for clipping.
      */
-    void drawNonIndexed(GrPrimitiveType type,
+    void drawNonIndexed(GrDrawState*,
+                        GrPrimitiveType type,
                         int startVertex,
                         int vertexCount,
                         const SkRect* devBounds = NULL);
@@ -296,13 +270,13 @@
      * on the draw state (if possible in the 3D API).  Note, we will never have an inverse fill
      * with stencil path
      */
-    void stencilPath(const GrPath*, GrPathRendering::FillType fill);
+    void stencilPath(GrDrawState*, const GrPath*, GrPathRendering::FillType fill);
 
     /**
      * Draws a path. Fill must not be a hairline. It will respect the HW
      * antialias flag on the draw state (if possible in the 3D API).
      */
-    void drawPath(const GrPath*, GrPathRendering::FillType fill);
+    void drawPath(GrDrawState*, const GrPath*, GrPathRendering::FillType fill);
 
     /**
      * Draws many paths. It will respect the HW
@@ -316,9 +290,11 @@
                               PathTransformSize(transformsType) * count elements
      * @param fill            Fill type for drawing all the paths
      */
-    void drawPaths(const GrPathRange* pathRange,
-                   const uint32_t indices[], int count,
-                   const float transforms[], PathTransformType transformsType,
+    void drawPaths(GrDrawState*, const GrPathRange* pathRange,
+                   const uint32_t indices[],
+                   int count,
+                   const float transforms[],
+                   PathTransformType transformsType,
                    GrPathRendering::FillType fill);
 
     /**
@@ -333,22 +309,23 @@
      *                    then srcRect will be transformed by srcMatrix.
      *                    srcMatrix can be NULL when no srcMatrix is desired.
      */
-    void drawRect(const SkRect& rect,
+    void drawRect(GrDrawState* ds,
+                  const SkRect& rect,
                   const SkRect* localRect,
                   const SkMatrix* localMatrix) {
         AutoGeometryPush agp(this);
-        this->onDrawRect(rect, localRect, localMatrix);
+        this->onDrawRect(ds, rect, localRect, localMatrix);
     }
 
     /**
      * Helper for drawRect when the caller doesn't need separate local rects or matrices.
      */
-    void drawSimpleRect(const SkRect& rect) {
-        this->drawRect(rect, NULL, NULL);
+    void drawSimpleRect(GrDrawState* ds, const SkRect& rect) {
+        this->drawRect(ds, rect, NULL, NULL);
     }
-    void drawSimpleRect(const SkIRect& irect) {
+    void drawSimpleRect(GrDrawState* ds, const SkIRect& irect) {
         SkRect rect = SkRect::Make(irect);
-        this->drawRect(rect, NULL, NULL);
+        this->drawRect(ds, rect, NULL, NULL);
     }
 
     /**
@@ -381,7 +358,8 @@
      * @param devBounds    optional bounds hint. This is a promise from the caller,
      *                     not a request for clipping.
      */
-    void drawIndexedInstances(GrPrimitiveType type,
+    void drawIndexedInstances(GrDrawState*,
+                              GrPrimitiveType type,
                               int instanceCount,
                               int verticesPerInstance,
                               int indicesPerInstance,
@@ -392,7 +370,9 @@
      * rect is NULL, otherwise just the rect. If canIgnoreRect is set then the entire render target
      * can be optionally cleared.
      */
-    void clear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
+    void clear(const SkIRect* rect,
+               GrColor color,
+               bool canIgnoreRect,
                GrRenderTarget* renderTarget);
 
     /**
@@ -438,8 +418,8 @@
      * Function that determines whether a copySurface call would succeed without
      * performing the copy.
      */
-    virtual bool canCopySurface(GrSurface* dst,
-                                GrSurface* src,
+    virtual bool canCopySurface(const GrSurface* dst,
+                                const GrSurface* src,
                                 const SkIRect& srcRect,
                                 const SkIPoint& dstPoint);
 
@@ -457,136 +437,19 @@
      */
     virtual void purgeResources() {};
 
-    class DrawInfo;
-    /**
-     * For subclass internal use to invoke a call to onDraw(). See DrawInfo below.
-     */
-    void executeDraw(const DrawInfo& info,
-                     const GrClipMaskManager::ScissorState& scissorState) {
-        this->onDraw(info, scissorState);
-    }
-
-    /**
-     * For subclass internal use to invoke a call to onStencilPath().
-     */
-    void executeStencilPath(const GrPath* path,
-                            const GrClipMaskManager::ScissorState& scissorState,
-                            const GrStencilSettings& stencilSettings) {
-        this->onStencilPath(path, scissorState, stencilSettings);
-    }
-
-    /**
-     * For subclass internal use to invoke a call to onDrawPath().
-     */
-    void executeDrawPath(const GrPath* path,
-                         const GrClipMaskManager::ScissorState& scissorState,
-                         const GrStencilSettings& stencilSettings,
-                         const GrDeviceCoordTexture* dstCopy) {
-        this->onDrawPath(path, scissorState, stencilSettings, dstCopy);
-    }
-
-    /**
-     * For subclass internal use to invoke a call to onDrawPaths().
-     */
-    void executeDrawPaths(const GrPathRange* pathRange,
-                          const uint32_t indices[],
-                          int count,
-                          const float transforms[],
-                          PathTransformType transformsType,
-                          const GrClipMaskManager::ScissorState& scissorState,
-                          const GrStencilSettings& stencilSettings,
-                          const GrDeviceCoordTexture* dstCopy) {
-        this->onDrawPaths(pathRange, indices, count, transforms, transformsType,
-                          scissorState, stencilSettings, dstCopy);
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * See AutoStateRestore below.
-     */
-    enum ASRInit {
-        kPreserve_ASRInit,
-        kReset_ASRInit
-    };
-
-    /**
-     * Saves off the current state and restores it in the destructor. It will
-     * install a new GrDrawState object on the target (setDrawState) and restore
-     * the previous one in the destructor. The caller should call drawState() to
-     * get the new draw state after the ASR is installed.
-     *
-     * GrDrawState* state = target->drawState();
-     * AutoStateRestore asr(target, GrDrawTarget::kReset_ASRInit).
-     * state->setRenderTarget(rt); // state refers to the GrDrawState set on
-     *                             // target before asr was initialized.
-     *                             // Therefore, rt is set on the GrDrawState
-     *                             // that will be restored after asr's
-     *                             // destructor rather than target's current
-     *                             // GrDrawState.
-     */
-    class AutoStateRestore : public ::SkNoncopyable {
-    public:
-        /**
-         * Default ASR will have no effect unless set() is subsequently called.
-         */
-        AutoStateRestore();
-
-        /**
-         * Saves the state on target. The state will be restored when the ASR
-         * is destroyed. If this constructor is used do not call set().
-         *
-         * @param init  Should the newly installed GrDrawState be a copy of the
-         *              previous state or a default-initialized GrDrawState.
-         * @param viewMatrix Optional view matrix. If init = kPreserve then the draw state's
-         *                   matrix will be preconcat'ed with the param. All stages will be
-                             updated to compensate for the matrix change. If init == kReset
-                             then the draw state's matrix will be this matrix.
-         */
-        AutoStateRestore(GrDrawTarget* target, ASRInit init, const SkMatrix* viewMatrix = NULL);
-
-        ~AutoStateRestore();
-
-        /**
-         * Saves the state on target. The state will be restored when the ASR
-         * is destroyed. This should only be called once per ASR object and only
-         * when the default constructor was used. For nested saves use multiple
-         * ASR objects.
-         *
-         * @param init  Should the newly installed GrDrawState be a copy of the
-         *              previous state or a default-initialized GrDrawState.
-         * @param viewMatrix Optional view matrix. If init = kPreserve then the draw state's
-         *                   matrix will be preconcat'ed with the param. All stages will be
-                             updated to compensate for the matrix change. If init == kReset
-                             then the draw state's matrix will be this matrix.
-         */
-        void set(GrDrawTarget* target, ASRInit init, const SkMatrix* viewMatrix = NULL);
-
-        /**
-         * Like set() but makes the view matrix identity. When init is kReset it is as though
-         * NULL was passed to set's viewMatrix param. When init is kPreserve it is as though
-         * the inverse view matrix was passed. If kPreserve is passed and the draw state's matrix
-         * is not invertible then this may fail.
-         */
-        bool setIdentity(GrDrawTarget* target, ASRInit init);
-
-    private:
-        GrDrawTarget*                       fDrawTarget;
-        SkTLazy<GrDrawState>                fTempState;
-        GrDrawState*                        fSavedState;
-    };
-
     ////////////////////////////////////////////////////////////////////////////
 
     class AutoReleaseGeometry : public ::SkNoncopyable {
     public:
         AutoReleaseGeometry(GrDrawTarget*  target,
                             int            vertexCount,
+                            size_t         vertexStride,
                             int            indexCount);
         AutoReleaseGeometry();
         ~AutoReleaseGeometry();
         bool set(GrDrawTarget*  target,
                  int            vertexCount,
+                 size_t         vertexStride,
                  int            indexCount);
         bool succeeded() const { return SkToBool(fTarget); }
         void* vertices() const { SkASSERT(this->succeeded()); return fVertices; }
@@ -632,8 +495,7 @@
      */
     class AutoGeometryPush : public ::SkNoncopyable {
     public:
-        AutoGeometryPush(GrDrawTarget* target)
-            : fAttribRestore(target->drawState()) {
+        AutoGeometryPush(GrDrawTarget* target) {
             SkASSERT(target);
             fTarget = target;
             target->pushGeometrySource();
@@ -643,32 +505,6 @@
 
     private:
         GrDrawTarget*                           fTarget;
-        GrDrawState::AutoVertexAttribRestore    fAttribRestore;
-    };
-
-    /**
-     * Combination of AutoGeometryPush and AutoStateRestore. The vertex attribs will be in default
-     * state regardless of ASRInit value.
-     */
-    class AutoGeometryAndStatePush : public ::SkNoncopyable {
-    public:
-        AutoGeometryAndStatePush(GrDrawTarget* target,
-                                 ASRInit init,
-                                 const SkMatrix* viewMatrix = NULL)
-            : fState(target, init, viewMatrix) {
-            SkASSERT(target);
-            fTarget = target;
-            target->pushGeometrySource();
-            if (kPreserve_ASRInit == init) {
-                target->drawState()->setDefaultVertexAttribs();
-            }
-        }
-
-        ~AutoGeometryAndStatePush() { fTarget->popGeometrySource(); }
-
-    private:
-        AutoStateRestore fState;
-        GrDrawTarget*    fTarget;
     };
 
     ///////////////////////////////////////////////////////////////////////////
@@ -830,15 +666,19 @@
     // Makes a copy of the dst if it is necessary for the draw. Returns false if a copy is required
     // but couldn't be made. Otherwise, returns true.  This method needs to be protected because it
     // needs to be accessed by GLPrograms to setup a correct drawstate
-    bool setupDstReadIfNecessary(DrawInfo* info) {
-        return this->setupDstReadIfNecessary(&info->fDstCopy, info->getDevBounds());
+    bool setupDstReadIfNecessary(GrDrawState* ds, DrawInfo* info) {
+        return this->setupDstReadIfNecessary(ds, &info->fDstCopy, info->getDevBounds());
     }
-    bool setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds);
+    bool setupDstReadIfNecessary(GrDrawState*,
+                                 GrDeviceCoordTexture* dstCopy,
+                                 const SkRect* drawBounds);
 
 private:
     // A subclass can optionally overload this function to be notified before
     // vertex and index space is reserved.
-    virtual void willReserveVertexAndIndexSpace(int vertexCount, int indexCount) {}
+    virtual void willReserveVertexAndIndexSpace(int vertexCount,
+                                                size_t vertexStride,
+                                                int indexCount) {}
 
     // implemented by subclass to allocate space for reserved geom
     virtual bool onReserveVertexSpace(size_t vertexSize, int vertexCount, void** vertices) = 0;
@@ -850,20 +690,26 @@
     virtual void geometrySourceWillPush() = 0;
     virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) = 0;
     // subclass called to perform drawing
-    virtual void onDraw(const DrawInfo&, const GrClipMaskManager::ScissorState&) = 0;
+    virtual void onDraw(const GrDrawState&,
+                        const DrawInfo&,
+                        const GrClipMaskManager::ScissorState&) = 0;
     // TODO copy in order drawbuffer onDrawRect to here
-    virtual void onDrawRect(const SkRect& rect,
+    virtual void onDrawRect(GrDrawState*,
+                            const SkRect& rect,
                             const SkRect* localRect,
                             const SkMatrix* localMatrix) = 0;
 
-    virtual void onStencilPath(const GrPath*,
+    virtual void onStencilPath(const GrDrawState&,
+                               const GrPath*,
                                const GrClipMaskManager::ScissorState&,
                                const GrStencilSettings&) = 0;
-    virtual void onDrawPath(const GrPath*,
+    virtual void onDrawPath(const GrDrawState&,
+                            const GrPath*,
                             const GrClipMaskManager::ScissorState&,
                             const GrStencilSettings&,
                             const GrDeviceCoordTexture* dstCopy) = 0;
-    virtual void onDrawPaths(const GrPathRange*,
+    virtual void onDrawPaths(const GrDrawState&,
+                             const GrPathRange*,
                              const uint32_t indices[],
                              int count,
                              const float transforms[],
@@ -884,8 +730,11 @@
 
     // called by drawIndexed and drawNonIndexed. Use a negative indexCount to
     // indicate non-indexed drawing.
-    bool checkDraw(GrPrimitiveType type, int startVertex,
-                   int startIndex, int vertexCount,
+    bool checkDraw(const GrDrawState&,
+                   GrPrimitiveType type,
+                   int startVertex,
+                   int startIndex,
+                   int vertexCount,
                    int indexCount) const;
     // called when setting a new vert/idx source to unref prev vb/ib
     void releasePreviousVertexSource();
@@ -893,11 +742,14 @@
 
     // Check to see if this set of draw commands has been sent out
     virtual bool       isIssued(uint32_t drawID) { return true; }
-    void getPathStencilSettingsForFilltype(GrPathRendering::FillType, GrStencilSettings*);
+    void getPathStencilSettingsForFilltype(GrPathRendering::FillType,
+                                           const GrStencilBuffer*,
+                                           GrStencilSettings*);
     virtual GrClipMaskManager* clipMaskManager() = 0;
     virtual bool setupClip(const SkRect* devBounds,
                            GrDrawState::AutoRestoreEffects* are,
                            GrDrawState::AutoRestoreStencil* ars,
+                           GrDrawState*,
                            GrClipMaskManager::ScissorState* scissorState) = 0;
 
     enum {
@@ -905,8 +757,6 @@
     };
     SkSTArray<kPreallocGeoSrcStateStackCnt, GeometrySrcState, true> fGeoSrcStateStack;
     const GrClipData*                                               fClip;
-    GrDrawState*                                                    fDrawState;
-    GrDrawState                                                     fDefaultDrawState;
     // The context owns us, not vice-versa, so this ptr is not ref'ed by DrawTarget.
     GrContext*                                                      fContext;
     // To keep track that we always have at least as many debug marker adds as removes
@@ -959,6 +809,7 @@
     virtual bool setupClip(const SkRect* devBounds,
                            GrDrawState::AutoRestoreEffects* are,
                            GrDrawState::AutoRestoreStencil* ars,
+                           GrDrawState*,
                            GrClipMaskManager::ScissorState* scissorState) SK_OVERRIDE;
 
     typedef GrDrawTarget INHERITED;
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index dfc71fe..5c25927 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -360,8 +360,8 @@
     // classes must keep this consistent with their implementation of onCopySurface(). The inputs
     // are the same as onCopySurface(), i.e. srcRect and dstPoint are clipped to be inside the src
     // and dst bounds.
-    virtual bool canCopySurface(GrSurface* dst,
-                                GrSurface* src,
+    virtual bool canCopySurface(const GrSurface* dst,
+                                const GrSurface* src,
                                 const SkIRect& srcRect,
                                 const SkIPoint& dstPoint) = 0;
 
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index c180cc6..b0504b7 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -133,34 +133,33 @@
 
 static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
 
-void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect,
+void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds,
+                                     const SkRect& rect,
                                      const SkRect* localRect,
                                      const SkMatrix* localMatrix) {
-    GrDrawState* drawState = this->drawState();
-    GrDrawState::AutoRestoreEffects are(drawState);
+    GrDrawState::AutoRestoreEffects are(ds);
 
-    GrColor color = drawState->getColor();
+    GrColor color = ds->getColor();
+    set_vertex_attributes(ds, SkToBool(localRect),  color);
 
-    set_vertex_attributes(drawState, SkToBool(localRect),  color);
-
-    AutoReleaseGeometry geo(this, 4, 0);
+    AutoReleaseGeometry geo(this, 4, ds->getVertexStride(), 0);
     if (!geo.succeeded()) {
         SkDebugf("Failed to get space for vertices!\n");
         return;
     }
 
     // Go to device coords to allow batching across matrix changes
-    SkMatrix matrix = drawState->getViewMatrix();
+    SkMatrix matrix = ds->getViewMatrix();
 
     // When the caller has provided an explicit source rect for a stage then we don't want to
     // modify that stage's matrix. Otherwise if the effect is generating its source rect from
     // the vertex positions then we have to account for the view matrix change.
     GrDrawState::AutoViewMatrixRestore avmr;
-    if (!avmr.setIdentity(drawState)) {
+    if (!avmr.setIdentity(ds)) {
         return;
     }
 
-    size_t vstride = drawState->getVertexStride();
+    size_t vstride = ds->getVertexStride();
 
     geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
     matrix.mapPointsWithStride(geo.positions(), vstride, 4);
@@ -189,19 +188,16 @@
     }
 
     this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
-    this->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
-
-    // to ensure that stashing the drawState ptr is valid
-    SkASSERT(this->drawState() == drawState);
+    this->drawIndexedInstances(ds, kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds);
 }
 
-int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info,
+int GrInOrderDrawBuffer::concatInstancedDraw(const GrDrawState& ds,
+                                             const DrawInfo& info,
                                              const GrClipMaskManager::ScissorState& scissorState) {
     SkASSERT(!fCmdBuffer.empty());
     SkASSERT(info.isInstanced());
 
     const GeometrySrcState& geomSrc = this->getGeomSrc();
-    const GrDrawState& drawState = this->getDrawState();
 
     // we only attempt to concat the case when reserved verts are used with a client-specified index
     // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated
@@ -243,8 +239,7 @@
     instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
 
     // update the amount of reserved vertex data actually referenced in draws
-    size_t vertexBytes = instancesToConcat * info.verticesPerInstance() *
-                         drawState.getVertexStride();
+    size_t vertexBytes = instancesToConcat * info.verticesPerInstance() * ds.getVertexStride();
     poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
 
     draw->fInfo.adjustInstanceCount(instancesToConcat);
@@ -262,12 +257,13 @@
     return instancesToConcat;
 }
 
-void GrInOrderDrawBuffer::onDraw(const DrawInfo& info,
+void GrInOrderDrawBuffer::onDraw(const GrDrawState& ds,
+                                 const DrawInfo& info,
                                  const GrClipMaskManager::ScissorState& scissorState) {
     GeometryPoolState& poolState = fGeoPoolStateStack.back();
-    const GrDrawState& drawState = this->getDrawState();
 
-    this->recordStateIfNecessary(GrGpu::PrimTypeToDrawType(info.primitiveType()),
+    this->recordStateIfNecessary(ds,
+                                 GrGpu::PrimTypeToDrawType(info.primitiveType()),
                                  info.getDstCopy());
 
     const GrVertexBuffer* vb;
@@ -288,7 +284,7 @@
 
     Draw* draw;
     if (info.isInstanced()) {
-        int instancesConcated = this->concatInstancedDraw(info, scissorState);
+        int instancesConcated = this->concatInstancedDraw(ds, info, scissorState);
         if (info.instanceCount() > instancesConcated) {
             draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, scissorState, vb, ib));
             draw->fInfo.adjustInstanceCount(-instancesConcated);
@@ -303,7 +299,7 @@
     // Adjust the starting vertex and index when we are using reserved or array sources to
     // compensate for the fact that the data was inserted into a larger vb/ib owned by the pool.
     if (kBuffer_GeometrySrcType != this->getGeomSrc().fVertexSrc) {
-        size_t bytes = (info.vertexCount() + info.startVertex()) * drawState.getVertexStride();
+        size_t bytes = (info.vertexCount() + info.startVertex()) * ds.getVertexStride();
         poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, bytes);
         draw->fInfo.adjustStartVertex(poolState.fPoolStartVertex);
     }
@@ -315,23 +311,25 @@
     }
 }
 
-void GrInOrderDrawBuffer::onStencilPath(const GrPath* path,
+void GrInOrderDrawBuffer::onStencilPath(const GrDrawState& ds,
+                                        const GrPath* path,
                                         const GrClipMaskManager::ScissorState& scissorState,
                                         const GrStencilSettings& stencilSettings) {
     // Only compare the subset of GrDrawState relevant to path stenciling?
-    this->recordStateIfNecessary(GrGpu::kStencilPath_DrawType, NULL);
+    this->recordStateIfNecessary(ds, GrGpu::kStencilPath_DrawType, NULL);
     StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
     sp->fScissorState = scissorState;
     sp->fStencilSettings = stencilSettings;
     this->recordTraceMarkersIfNecessary();
 }
 
-void GrInOrderDrawBuffer::onDrawPath(const GrPath* path,
+void GrInOrderDrawBuffer::onDrawPath(const GrDrawState& ds,
+                                     const GrPath* path,
                                      const GrClipMaskManager::ScissorState& scissorState,
                                      const GrStencilSettings& stencilSettings,
                                      const GrDeviceCoordTexture* dstCopy) {
     // TODO: Only compare the subset of GrDrawState relevant to path covering?
-    this->recordStateIfNecessary(GrGpu::kDrawPath_DrawType, dstCopy);
+    this->recordStateIfNecessary(ds, GrGpu::kDrawPath_DrawType, dstCopy);
     DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
     if (dstCopy) {
         dp->fDstCopy = *dstCopy;
@@ -341,7 +339,8 @@
     this->recordTraceMarkersIfNecessary();
 }
 
-void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
+void GrInOrderDrawBuffer::onDrawPaths(const GrDrawState& ds,
+                                      const GrPathRange* pathRange,
                                       const uint32_t indices[],
                                       int count,
                                       const float transforms[],
@@ -353,7 +352,7 @@
     SkASSERT(indices);
     SkASSERT(transforms);
 
-    this->recordStateIfNecessary(GrGpu::kDrawPaths_DrawType, dstCopy);
+    this->recordStateIfNecessary(ds, GrGpu::kDrawPaths_DrawType, dstCopy);
 
     uint32_t* savedIndices = fPathIndexBuffer.append(count, indices);
     float* savedTransforms = fPathTransformBuffer.append(count *
@@ -373,7 +372,7 @@
             scissorState == previous->fScissorState &&
             stencilSettings == previous->fStencilSettings &&
             path_fill_type_is_winding(stencilSettings) &&
-            !this->getDrawState().willBlendWithDst()) {
+            !ds.willBlendWithDst()) {
             // Fold this DrawPaths call into the one previous.
             previous->fCount += count;
             return;
@@ -396,11 +395,8 @@
 
 void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
                                   bool canIgnoreRect, GrRenderTarget* renderTarget) {
+    SkASSERT(renderTarget);
     SkIRect r;
-    if (NULL == renderTarget) {
-        renderTarget = this->drawState()->getRenderTarget();
-        SkASSERT(renderTarget);
-    }
     if (NULL == rect) {
         // We could do something smart and remove previous draws and clears to
         // the current render target. If we get that smart we have to make sure
@@ -419,10 +415,7 @@
 void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
                                            bool insideClip,
                                            GrRenderTarget* renderTarget) {
-    if (NULL == renderTarget) {
-        renderTarget = this->drawState()->getRenderTarget();
-        SkASSERT(renderTarget);
-    }
+    SkASSERT(renderTarget);
     ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
     clr->fRect = rect;
     clr->fInsideClip = insideClip;
@@ -493,7 +486,7 @@
         }
 
         if (kSetState_Cmd == strip_trace_bit(iter->fType)) {
-            const SetState* ss = reinterpret_cast<const SetState*>(iter.get());
+            SetState* ss = reinterpret_cast<SetState*>(iter.get());
             currentOptState.reset(GrOptDrawState::Create(ss->fState,
                                                          fDstGpu,
                                                          &ss->fDstCopy,
@@ -592,8 +585,8 @@
     }
 }
 
-bool GrInOrderDrawBuffer::canCopySurface(GrSurface* dst,
-                                         GrSurface* src,
+bool GrInOrderDrawBuffer::canCopySurface(const GrSurface* dst,
+                                         const GrSurface* src,
                                          const SkIRect& srcRect,
                                          const SkIPoint& dstPoint) {
     return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint) ||
@@ -605,6 +598,7 @@
 }
 
 void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(int vertexCount,
+                                                         size_t vertexStride,
                                                          int indexCount) {
     // We use geometryHints() to know whether to flush the draw buffer. We
     // can't flush if we are inside an unbalanced pushGeometrySource.
@@ -628,12 +622,13 @@
     if (!insideGeoPush &&
         !unreleasedVertexSpace &&
         !unreleasedIndexSpace &&
-        this->geometryHints(&vcount, &icount)) {
+        this->geometryHints(vertexStride, &vcount, &icount)) {
         this->flush();
     }
 }
 
-bool GrInOrderDrawBuffer::geometryHints(int* vertexCount,
+bool GrInOrderDrawBuffer::geometryHints(size_t vertexStride,
+                                        int* vertexCount,
                                         int* indexCount) const {
     // we will recommend a flush if the data could fit in a single
     // preallocated buffer but none are left and it can't fit
@@ -650,7 +645,6 @@
         *indexCount = currIndices;
     }
     if (vertexCount) {
-        size_t vertexStride = this->getDrawState().getVertexStride();
         int32_t currVertices = fVertexPool.currentBufferVertices(vertexStride);
         if (*vertexCount > currVertices &&
             (!fVertexPool.preallocatedBuffersRemaining() &&
@@ -753,10 +747,11 @@
     }
 }
 
-void GrInOrderDrawBuffer::recordStateIfNecessary(GrGpu::DrawType drawType,
+void GrInOrderDrawBuffer::recordStateIfNecessary(const GrDrawState& ds,
+                                                 GrGpu::DrawType drawType,
                                                  const GrDeviceCoordTexture* dstCopy) {
     if (!fLastState) {
-        SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (this->getDrawState()));
+        SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (ds));
         fLastState = &ss->fState;
         if (dstCopy) {
             ss->fDstCopy = *dstCopy;
@@ -766,10 +761,9 @@
         this->recordTraceMarkersIfNecessary();
         return;
     }
-    const GrDrawState& curr = this->getDrawState();
-    switch (GrDrawState::CombineIfPossible(*fLastState, curr, *this->caps())) {
+    switch (GrDrawState::CombineIfPossible(*fLastState, ds, *this->caps())) {
         case GrDrawState::kIncompatible_CombinedState: {
-            SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (curr));
+            SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (ds));
             fLastState = &ss->fState;
             if (dstCopy) {
                 ss->fDstCopy = *dstCopy;
@@ -788,7 +782,7 @@
             // Note that this goes away when we move GrIODB over to taking optimized snapshots
             // of draw states.
             fLastState->~GrDrawState();
-            SkNEW_PLACEMENT_ARGS(fLastState, GrDrawState, (curr));
+            SkNEW_PLACEMENT_ARGS(fLastState, GrDrawState, (ds));
             this->convertDrawStateToPendingExec(fLastState);
             break;
     }
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 4129d0a..c898236 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -73,7 +73,8 @@
     virtual DrawToken getCurrentDrawToken() { return DrawToken(this, fDrawID); }
 
     // overrides from GrDrawTarget
-    virtual bool geometryHints(int* vertexCount,
+    virtual bool geometryHints(size_t vertexStride,
+                               int* vertexCount,
                                int* indexCount) const SK_OVERRIDE;
 
     virtual bool copySurface(GrSurface* dst,
@@ -81,8 +82,8 @@
                              const SkIRect& srcRect,
                              const SkIPoint& dstPoint)  SK_OVERRIDE;
 
-    virtual bool canCopySurface(GrSurface* dst,
-                                GrSurface* src,
+    virtual bool canCopySurface(const GrSurface* dst,
+                                const GrSurface* src,
                                 const SkIRect& srcRect,
                                 const SkIPoint& dstPoint) SK_OVERRIDE;
 
@@ -248,19 +249,25 @@
     typedef GrTRecorder<Cmd, TCmdAlign> CmdBuffer;
 
     // overrides from GrDrawTarget
-    virtual void onDraw(const DrawInfo&, const GrClipMaskManager::ScissorState&) SK_OVERRIDE;
-    virtual void onDrawRect(const SkRect& rect,
+    virtual void onDraw(const GrDrawState&,
+                        const DrawInfo&,
+                        const GrClipMaskManager::ScissorState&) SK_OVERRIDE;
+    virtual void onDrawRect(GrDrawState*,
+                            const SkRect& rect,
                             const SkRect* localRect,
                             const SkMatrix* localMatrix) SK_OVERRIDE;
 
-    virtual void onStencilPath(const GrPath*,
+    virtual void onStencilPath(const GrDrawState&,
+                               const GrPath*,
                                const GrClipMaskManager::ScissorState&,
                                const GrStencilSettings&) SK_OVERRIDE;
-    virtual void onDrawPath(const GrPath*,
+    virtual void onDrawPath(const GrDrawState&,
+                            const GrPath*,
                             const GrClipMaskManager::ScissorState&,
                             const GrStencilSettings&,
                             const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
-    virtual void onDrawPaths(const GrPathRange*,
+    virtual void onDrawPaths(const GrDrawState&,
+                             const GrPathRange*,
                              const uint32_t indices[],
                              int count,
                              const float transforms[],
@@ -283,14 +290,17 @@
     virtual void geometrySourceWillPush() SK_OVERRIDE;
     virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) SK_OVERRIDE;
     virtual void willReserveVertexAndIndexSpace(int vertexCount,
+                                                size_t vertexStride,
                                                 int indexCount) SK_OVERRIDE;
 
     // Attempts to concat instances from info onto the previous draw. info must represent an
     // instanced draw. The caller must have already recorded a new draw state and clip if necessary.
-    int concatInstancedDraw(const DrawInfo& info, const GrClipMaskManager::ScissorState&);
+    int concatInstancedDraw(const GrDrawState&,
+                            const DrawInfo&,
+                            const GrClipMaskManager::ScissorState&);
 
     // Determines whether the current draw operation requieres a new drawstate and if so records it.
-    void recordStateIfNecessary(GrGpu::DrawType, const GrDeviceCoordTexture*);
+    void recordStateIfNecessary(const GrDrawState&, GrGpu::DrawType, const GrDeviceCoordTexture*);
     // We lazily record clip changes in order to skip clips that have no effect.
     void recordClipIfNecessary();
     // Records any trace markers for a command after adding it to the buffer.
diff --git a/src/gpu/GrOptDrawState.h b/src/gpu/GrOptDrawState.h
index cef32b6..c44bb6f 100644
--- a/src/gpu/GrOptDrawState.h
+++ b/src/gpu/GrOptDrawState.h
@@ -30,8 +30,10 @@
      * Returns a snapshot of the current optimized state. The GrOptDrawState is reffed and ownership
      * is given to the caller.
      */
-    static GrOptDrawState* Create(const GrDrawState& drawState, GrGpu*,
-                                  const GrDeviceCoordTexture* dstCopy, GrGpu::DrawType drawType);
+    static GrOptDrawState* Create(const GrDrawState& drawState,
+                                  GrGpu*,
+                                  const GrDeviceCoordTexture* dstCopy,
+                                  GrGpu::DrawType drawType);
 
     bool operator== (const GrOptDrawState& that) const;
 
diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
index 2bb674a..42844ee 100644
--- a/src/gpu/GrOvalRenderer.cpp
+++ b/src/gpu/GrOvalRenderer.cpp
@@ -481,12 +481,16 @@
     SkSafeSetNull(fStrokeRRectIndexBuffer);
 }
 
-bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bool useAA,
-                              const SkRect& oval, const SkStrokeRec& stroke)
+bool GrOvalRenderer::drawOval(GrDrawTarget* target,
+                              GrDrawState* drawState,
+                              const GrContext* context,
+                              bool useAA,
+                              const SkRect& oval,
+                              const SkStrokeRec& stroke)
 {
     bool useCoverageAA = useAA &&
-        !target->getDrawState().getRenderTarget()->isMultisampled() &&
-        !target->shouldDisableCoverageAAForBlend();
+        !drawState->getRenderTarget()->isMultisampled() &&
+        drawState->couldApplyCoverage(*target->caps());
 
     if (!useCoverageAA) {
         return false;
@@ -497,13 +501,13 @@
     // we can draw circles
     if (SkScalarNearlyEqual(oval.width(), oval.height())
         && circle_stays_circle(vm)) {
-        this->drawCircle(target, context, useCoverageAA, oval, stroke);
+        this->drawCircle(target, drawState, context, useCoverageAA, oval, stroke);
     // if we have shader derivative support, render as device-independent
     } else if (target->caps()->shaderDerivativeSupport()) {
-        return this->drawDIEllipse(target, context, useCoverageAA, oval, stroke);
+        return this->drawDIEllipse(target, drawState, context, useCoverageAA, oval, stroke);
     // otherwise axis-aligned ellipses only
     } else if (vm.rectStaysRect()) {
-        return this->drawEllipse(target, context, useCoverageAA, oval, stroke);
+        return this->drawEllipse(target, drawState, context, useCoverageAA, oval, stroke);
     } else {
         return false;
     }
@@ -520,13 +524,12 @@
 };
 
 void GrOvalRenderer::drawCircle(GrDrawTarget* target,
+                                GrDrawState* drawState,
                                 const GrContext* context,
                                 bool useCoverageAA,
                                 const SkRect& circle,
                                 const SkStrokeRec& stroke)
 {
-    GrDrawState* drawState = target->drawState();
-
     const SkMatrix& vm = drawState->getViewMatrix();
     SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY());
     vm.mapPoints(&center, 1);
@@ -541,7 +544,7 @@
     drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircleVertexAttribs),
                                                       sizeof(CircleVertex));
 
-    GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
+    GrDrawTarget::AutoReleaseGeometry geo(target, 4, drawState->getVertexStride(),  0);
     if (!geo.succeeded()) {
         SkDebugf("Failed to get space for vertices!\n");
         return;
@@ -608,7 +611,7 @@
     verts[3].fInnerRadius = innerRadius;
 
     target->setIndexSourceToBuffer(context->getGpu()->getQuadIndexBuffer());
-    target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &bounds);
+    target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 4, 6, &bounds);
     target->resetIndexSource();
 }
 
@@ -629,12 +632,12 @@
 };
 
 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
+                                 GrDrawState* drawState,
                                  const GrContext* context,
                                  bool useCoverageAA,
                                  const SkRect& ellipse,
                                  const SkStrokeRec& stroke)
 {
-    GrDrawState* drawState = target->drawState();
 #ifdef SK_DEBUG
     {
         // we should have checked for this previously
@@ -704,7 +707,7 @@
     drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllipseVertexAttribs),
                                                        sizeof(EllipseVertex));
 
-    GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
+    GrDrawTarget::AutoReleaseGeometry geo(target, 4, drawState->getVertexStride(),  0);
     if (!geo.succeeded()) {
         SkDebugf("Failed to get space for vertices!\n");
         return false;
@@ -757,19 +760,19 @@
     verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
 
     target->setIndexSourceToBuffer(context->getGpu()->getQuadIndexBuffer());
-    target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &bounds);
+    target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 4, 6, &bounds);
     target->resetIndexSource();
 
     return true;
 }
 
 bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target,
+                                   GrDrawState* drawState,
                                    const GrContext* context,
                                    bool useCoverageAA,
                                    const SkRect& ellipse,
                                    const SkStrokeRec& stroke)
 {
-    GrDrawState* drawState = target->drawState();
     const SkMatrix& vm = drawState->getViewMatrix();
 
     SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
@@ -824,7 +827,7 @@
     drawState->setVertexAttribs<gDIEllipseVertexAttribs>(SK_ARRAY_COUNT(gDIEllipseVertexAttribs),
                                                          sizeof(DIEllipseVertex));
 
-    GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
+    GrDrawTarget::AutoReleaseGeometry geo(target, 4, drawState->getVertexStride(),  0);
     if (!geo.succeeded()) {
         SkDebugf("Failed to get space for vertices!\n");
         return false;
@@ -871,7 +874,7 @@
     verts[3].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, -innerRatioY - offsetDy);
 
     target->setIndexSourceToBuffer(context->getGpu()->getQuadIndexBuffer());
-    target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &bounds);
+    target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 4, 6, &bounds);
     target->resetIndexSource();
 
     return true;
@@ -922,11 +925,15 @@
     }
 }
 
-bool GrOvalRenderer::drawDRRect(GrDrawTarget* target, GrContext* context, bool useAA,
-                                const SkRRect& origOuter, const SkRRect& origInner) {
+bool GrOvalRenderer::drawDRRect(GrDrawTarget* target,
+                                GrDrawState* drawState,
+                                GrContext* context,
+                                bool useAA,
+                                const SkRRect& origOuter,
+                                const SkRRect& origInner) {
     bool applyAA = useAA &&
-                   !target->getDrawState().getRenderTarget()->isMultisampled() &&
-                   !target->shouldDisableCoverageAAForBlend();
+                   !drawState->getRenderTarget()->isMultisampled() &&
+                   drawState->couldApplyCoverage(*target->caps());
     GrDrawState::AutoRestoreEffects are;
     if (!origInner.isEmpty()) {
         SkTCopyOnFirstWrite<SkRRect> inner(origInner);
@@ -942,12 +949,12 @@
         if (NULL == fp) {
             return false;
         }
-        are.set(target->drawState());
-        target->drawState()->addCoverageProcessor(fp)->unref();
+        are.set(drawState);
+        drawState->addCoverageProcessor(fp)->unref();
     }
 
     SkStrokeRec fillRec(SkStrokeRec::kFill_InitStyle);
-    if (this->drawRRect(target, context, useAA, origOuter, fillRec)) {
+    if (this->drawRRect(target, drawState, context, useAA, origOuter, fillRec)) {
         return true;
     }
 
@@ -965,30 +972,34 @@
         return false;
     }
     if (!are.isSet()) {
-        are.set(target->drawState());
+        are.set(drawState);
     }
     GrDrawState::AutoViewMatrixRestore avmr;
-    if (!avmr.setIdentity(target->drawState())) {
+    if (!avmr.setIdentity(drawState)) {
         return false;
     }
-    target->drawState()->addCoverageProcessor(effect)->unref();
+    drawState->addCoverageProcessor(effect)->unref();
     SkRect bounds = outer->getBounds();
     if (applyAA) {
         bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
     }
-    target->drawRect(bounds, NULL, NULL);
+    target->drawRect(drawState, bounds, NULL, NULL);
     return true;
 }
 
-bool GrOvalRenderer::drawRRect(GrDrawTarget* target, GrContext* context, bool useAA,
-                               const SkRRect& rrect, const SkStrokeRec& stroke) {
+bool GrOvalRenderer::drawRRect(GrDrawTarget* target,
+                               GrDrawState* drawState,
+                               GrContext* context,
+                               bool useAA,
+                               const SkRRect& rrect,
+                               const SkStrokeRec& stroke) {
     if (rrect.isOval()) {
-        return this->drawOval(target, context, useAA, rrect.getBounds(), stroke);
+        return this->drawOval(target, drawState, context, useAA, rrect.getBounds(), stroke);
     }
 
     bool useCoverageAA = useAA &&
-        !target->getDrawState().getRenderTarget()->isMultisampled() &&
-        !target->shouldDisableCoverageAAForBlend();
+        !drawState->getRenderTarget()->isMultisampled() &&
+        drawState->couldApplyCoverage(*target->caps());
 
     // only anti-aliased rrects for now
     if (!useCoverageAA) {
@@ -1048,7 +1059,6 @@
     }
 
     // reset to device coordinates
-    GrDrawState* drawState = target->drawState();
     GrDrawState::AutoViewMatrixRestore avmr;
     if (!avmr.setIdentity(drawState)) {
         return false;
@@ -1065,7 +1075,7 @@
         drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircleVertexAttribs),
                                                           sizeof(CircleVertex));
 
-        GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
+        GrDrawTarget::AutoReleaseGeometry geo(target, 16, drawState->getVertexStride(),  0);
         if (!geo.succeeded()) {
             SkDebugf("Failed to get space for vertices!\n");
             return false;
@@ -1146,7 +1156,8 @@
         int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
                                       SK_ARRAY_COUNT(gRRectIndices);
         target->setIndexSourceToBuffer(indexBuffer);
-        target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 16, indexCnt, &bounds);
+        target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 16, indexCnt,
+                                     &bounds);
 
     // otherwise we use the ellipse renderer
     } else {
@@ -1187,7 +1198,7 @@
 
         isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0);
 
-        GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
+        GrDrawTarget::AutoReleaseGeometry geo(target, 16, drawState->getVertexStride(),  0);
         if (!geo.succeeded()) {
             SkDebugf("Failed to get space for vertices!\n");
             return false;
@@ -1253,7 +1264,8 @@
         int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
                                       SK_ARRAY_COUNT(gRRectIndices);
         target->setIndexSourceToBuffer(indexBuffer);
-        target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 16, indexCnt, &bounds);
+        target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 16, indexCnt,
+                                     &bounds);
     }
 
     target->resetIndexSource();
diff --git a/src/gpu/GrOvalRenderer.h b/src/gpu/GrOvalRenderer.h
index 96f9b3a..abad623 100644
--- a/src/gpu/GrOvalRenderer.h
+++ b/src/gpu/GrOvalRenderer.h
@@ -31,21 +31,42 @@
 
     void reset();
 
-    bool drawOval(GrDrawTarget* target, const GrContext* context, bool useAA,
-                  const SkRect& oval, const SkStrokeRec& stroke);
-    bool drawRRect(GrDrawTarget* target, GrContext* context, bool useAA,
-                   const SkRRect& rrect, const SkStrokeRec& stroke);
-    bool drawDRRect(GrDrawTarget* target, GrContext* context, bool useAA,
-                    const SkRRect& outer, const SkRRect& inner);
+    bool drawOval(GrDrawTarget*,
+                  GrDrawState*,
+                  const GrContext*,
+                  bool useAA,
+                  const SkRect& oval,
+                  const SkStrokeRec& stroke);
+    bool drawRRect(GrDrawTarget*,
+                   GrDrawState*,
+                   GrContext*,
+                   bool useAA,
+                   const SkRRect& rrect,
+                   const SkStrokeRec& stroke);
+    bool drawDRRect(GrDrawTarget* target,
+                    GrDrawState*,
+                    GrContext* context,
+                    bool useAA,
+                    const SkRRect& outer,
+                    const SkRRect& inner);
 
 private:
-    bool drawEllipse(GrDrawTarget* target, const GrContext* context, bool useCoverageAA,
+    bool drawEllipse(GrDrawTarget* target,
+                     GrDrawState*,
+                     const GrContext* context,
+                     bool useCoverageAA,
                      const SkRect& ellipse,
                      const SkStrokeRec& stroke);
-    bool drawDIEllipse(GrDrawTarget* target, const GrContext* context, bool useCoverageAA,
+    bool drawDIEllipse(GrDrawTarget* target,
+                       GrDrawState*,
+                       const GrContext* context,
+                       bool useCoverageAA,
                        const SkRect& ellipse,
                        const SkStrokeRec& stroke);
-    void drawCircle(GrDrawTarget* target, const GrContext* context, bool useCoverageAA,
+    void drawCircle(GrDrawTarget* target,
+                    GrDrawState*,
+                    const GrContext* context,
+                    bool useCoverageAA,
                     const SkRect& circle,
                     const SkStrokeRec& stroke);
 
diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h
index 0720c3f..8f2d465 100644
--- a/src/gpu/GrPathRenderer.h
+++ b/src/gpu/GrPathRenderer.h
@@ -81,11 +81,12 @@
      * @param path      the path that will be drawn
      * @param stroke    the stroke information (width, join, cap).
      */
-    StencilSupport getStencilSupport(const SkPath& path,
-                                     const SkStrokeRec& stroke,
-                                     const GrDrawTarget* target) const {
+    StencilSupport getStencilSupport(const GrDrawTarget* target,
+                                     const GrDrawState* drawState,
+                                     const SkPath& path,
+                                     const SkStrokeRec& stroke) const {
         SkASSERT(!path.isInverseFillType());
-        return this->onGetStencilSupport(path, stroke, target);
+        return this->onGetStencilSupport(target, drawState, path, stroke);
     }
 
     /**
@@ -100,9 +101,10 @@
      *
      * @return  true if the path can be drawn by this object, false otherwise.
      */
-    virtual bool canDrawPath(const SkPath& path,
+    virtual bool canDrawPath(const GrDrawTarget* target,
+                             const GrDrawState* drawState,
+                             const SkPath& path,
                              const SkStrokeRec& rec,
-                             const GrDrawTarget* target,
                              bool antiAlias) const = 0;
     /**
      * Draws the path into the draw target. If getStencilSupport() would return kNoRestriction then
@@ -113,15 +115,17 @@
      * @param target                target that the path will be rendered to
      * @param antiAlias             true if anti-aliasing is required.
      */
-    bool drawPath(const SkPath& path,
+    bool drawPath(GrDrawTarget* target,
+                  GrDrawState* ds,
+                  const SkPath& path,
                   const SkStrokeRec& stroke,
-                  GrDrawTarget* target,
                   bool antiAlias) {
         SkASSERT(!path.isEmpty());
-        SkASSERT(this->canDrawPath(path, stroke, target, antiAlias));
-        SkASSERT(target->drawState()->getStencil().isDisabled() ||
-                 kNoRestriction_StencilSupport == this->getStencilSupport(path, stroke, target));
-        return this->onDrawPath(path, stroke, target, antiAlias);
+        SkASSERT(this->canDrawPath(target, ds, path, stroke, antiAlias));
+        SkASSERT(ds->getStencil().isDisabled() ||
+                 kNoRestriction_StencilSupport == this->getStencilSupport(target, ds, path,
+                                                                          stroke));
+        return this->onDrawPath(target, ds, path, stroke, antiAlias);
     }
 
     /**
@@ -132,10 +136,13 @@
      * @param stroke                the stroke information (width, join, cap)
      * @param target                target that the path will be rendered to
      */
-    void stencilPath(const SkPath& path, const SkStrokeRec& stroke, GrDrawTarget* target) {
+    void stencilPath(GrDrawTarget* target,
+                     GrDrawState* ds,
+                     const SkPath& path,
+                     const SkStrokeRec& stroke) {
         SkASSERT(!path.isEmpty());
-        SkASSERT(kNoSupport_StencilSupport != this->getStencilSupport(path, stroke, target));
-        this->onStencilPath(path, stroke, target);
+        SkASSERT(kNoSupport_StencilSupport != this->getStencilSupport(target, ds, path, stroke));
+        this->onStencilPath(target, ds, path, stroke);
     }
 
     // Helper for determining if we can treat a thin stroke as a hairline w/ coverage.
@@ -156,27 +163,30 @@
     /**
      * Subclass overrides if it has any limitations of stenciling support.
      */
-    virtual StencilSupport onGetStencilSupport(const SkPath&,
-                                               const SkStrokeRec&,
-                                               const GrDrawTarget*) const {
+    virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
+                                               const GrDrawState*,
+                                               const SkPath&,
+                                               const SkStrokeRec&) const {
         return kNoRestriction_StencilSupport;
     }
 
     /**
      * Subclass implementation of drawPath()
      */
-    virtual bool onDrawPath(const SkPath& path,
-                            const SkStrokeRec& stroke,
-                            GrDrawTarget* target,
+    virtual bool onDrawPath(GrDrawTarget*,
+                            GrDrawState*,
+                            const SkPath&,
+                            const SkStrokeRec&,
                             bool antiAlias) = 0;
 
     /**
      * Subclass implementation of stencilPath(). Subclass must override iff it ever returns
      * kStencilOnly in onGetStencilSupport().
      */
-    virtual void onStencilPath(const SkPath& path,  const SkStrokeRec& stroke, GrDrawTarget* target) {
-        GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit);
-        GrDrawState* drawState = target->drawState();
+    virtual void onStencilPath(GrDrawTarget* target,
+                               GrDrawState* drawState,
+                               const SkPath& path,
+                               const SkStrokeRec& stroke) {
         GR_STATIC_CONST_SAME_STENCIL(kIncrementStencil,
                                      kReplace_StencilOp,
                                      kReplace_StencilOp,
@@ -186,7 +196,7 @@
                                      0xffff);
         drawState->setStencil(kIncrementStencil);
         drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
-        this->drawPath(path, stroke, target, false);
+        this->drawPath(target, drawState, path, stroke, false);
     }
 
     // Helper for getting the device bounds of a path. Inverse filled paths will have bounds set
diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp
index 8108572..5c3f1c9 100644
--- a/src/gpu/GrPathRendererChain.cpp
+++ b/src/gpu/GrPathRendererChain.cpp
@@ -31,9 +31,10 @@
     return pr;
 }
 
-GrPathRenderer* GrPathRendererChain::getPathRenderer(const SkPath& path,
+GrPathRenderer* GrPathRendererChain::getPathRenderer(const GrDrawTarget* target,
+                                                     const GrDrawState* drawState,
+                                                     const SkPath& path,
                                                      const SkStrokeRec& stroke,
-                                                     const GrDrawTarget* target,
                                                      DrawType drawType,
                                                      StencilSupport* stencilSupport) {
     if (!fInit) {
@@ -58,11 +59,12 @@
 
 
     for (int i = 0; i < fChain.count(); ++i) {
-        if (fChain[i]->canDrawPath(path, stroke, target, antiAlias)) {
+        if (fChain[i]->canDrawPath(target, drawState, path, stroke, antiAlias)) {
             if (GrPathRenderer::kNoSupport_StencilSupport != minStencilSupport) {
-                GrPathRenderer::StencilSupport support = fChain[i]->getStencilSupport(path,
-                                                                                      stroke,
-                                                                                      target);
+                GrPathRenderer::StencilSupport support = fChain[i]->getStencilSupport(target,
+                                                                                      drawState,
+                                                                                      path,
+                                                                                      stroke);
                 if (support < minStencilSupport) {
                     continue;
                 } else if (stencilSupport) {
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index 2a2e161..590a040 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -347,9 +347,8 @@
 
 void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture,
                                               GrDrawTarget* target,
+                                              GrDrawState* drawState,
                                               const SkIRect& rect) {
-    GrDrawState* drawState = target->drawState();
-
     GrDrawState::AutoViewMatrixRestore avmr;
     if (!avmr.setIdentity(drawState)) {
         return;
@@ -376,5 +375,5 @@
                                                        GrTextureParams::kNone_FilterMode,
                                                        kPosition_GrCoordSet))->unref();
 
-    target->drawSimpleRect(dstRect);
+    target->drawSimpleRect(drawState, dstRect);
 }
diff --git a/src/gpu/GrSWMaskHelper.h b/src/gpu/GrSWMaskHelper.h
index 22d04ef..54a3897 100644
--- a/src/gpu/GrSWMaskHelper.h
+++ b/src/gpu/GrSWMaskHelper.h
@@ -92,6 +92,7 @@
     // output of DrawPathMaskToTexture.
     static void DrawToTargetWithPathMask(GrTexture* texture,
                                          GrDrawTarget* target,
+                                         GrDrawState* drawState,
                                          const SkIRect& rect);
 
 private:
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 0d3ef62..9a9cf32 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -11,9 +11,10 @@
 #include "GrSWMaskHelper.h"
 
 ////////////////////////////////////////////////////////////////////////////////
-bool GrSoftwarePathRenderer::canDrawPath(const SkPath&,
+bool GrSoftwarePathRenderer::canDrawPath(const GrDrawTarget*,
+                                         const GrDrawState*,
+                                         const SkPath&,
                                          const SkStrokeRec&,
-                                         const GrDrawTarget*,
                                          bool antiAlias) const {
     if (NULL == fContext) {
         return false;
@@ -22,10 +23,11 @@
     return true;
 }
 
-GrPathRenderer::StencilSupport GrSoftwarePathRenderer::onGetStencilSupport(
-    const SkPath&,
-    const SkStrokeRec&,
-    const GrDrawTarget*) const {
+GrPathRenderer::StencilSupport
+GrSoftwarePathRenderer::onGetStencilSupport(const GrDrawTarget*,
+                                            const GrDrawState*,
+                                            const SkPath&,
+                                            const SkStrokeRec&) const {
     return GrPathRenderer::kNoSupport_StencilSupport;
 }
 
@@ -36,12 +38,13 @@
 // path bounds will be a subset of the clip bounds. returns false if
 // path bounds would be empty.
 bool get_path_and_clip_bounds(const GrDrawTarget* target,
+                              const GrDrawState* drawState,
                               const SkPath& path,
                               const SkMatrix& matrix,
                               SkIRect* devPathBounds,
                               SkIRect* devClipBounds) {
     // compute bounds as intersection of rt size, clip, and path
-    const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
+    const GrRenderTarget* rt = drawState->getRenderTarget();
     if (NULL == rt) {
         return false;
     }
@@ -74,32 +77,33 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 void draw_around_inv_path(GrDrawTarget* target,
+                          GrDrawState* drawState,
                           const SkIRect& devClipBounds,
                           const SkIRect& devPathBounds) {
     GrDrawState::AutoViewMatrixRestore avmr;
-    if (!avmr.setIdentity(target->drawState())) {
+    if (!avmr.setIdentity(drawState)) {
         return;
     }
     SkRect rect;
     if (devClipBounds.fTop < devPathBounds.fTop) {
         rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
                   devClipBounds.fRight, devPathBounds.fTop);
-        target->drawSimpleRect(rect);
+        target->drawSimpleRect(drawState, rect);
     }
     if (devClipBounds.fLeft < devPathBounds.fLeft) {
         rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
                   devPathBounds.fLeft, devPathBounds.fBottom);
-        target->drawSimpleRect(rect);
+        target->drawSimpleRect(drawState, rect);
     }
     if (devClipBounds.fRight > devPathBounds.fRight) {
         rect.iset(devPathBounds.fRight, devPathBounds.fTop,
                   devClipBounds.fRight, devPathBounds.fBottom);
-        target->drawSimpleRect(rect);
+        target->drawSimpleRect(drawState, rect);
     }
     if (devClipBounds.fBottom > devPathBounds.fBottom) {
         rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
                   devClipBounds.fRight, devClipBounds.fBottom);
-        target->drawSimpleRect(rect);
+        target->drawSimpleRect(drawState, rect);
     }
 }
 
@@ -107,24 +111,23 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 // return true on success; false on failure
-bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
+bool GrSoftwarePathRenderer::onDrawPath(GrDrawTarget* target,
+                                        GrDrawState* drawState,
+                                        const SkPath& path,
                                         const SkStrokeRec& stroke,
-                                        GrDrawTarget* target,
                                         bool antiAlias) {
 
     if (NULL == fContext) {
         return false;
     }
 
-    GrDrawState* drawState = target->drawState();
-
     SkMatrix vm = drawState->getViewMatrix();
 
     SkIRect devPathBounds, devClipBounds;
-    if (!get_path_and_clip_bounds(target, path, vm,
+    if (!get_path_and_clip_bounds(target, drawState, path, vm,
                                   &devPathBounds, &devClipBounds)) {
         if (path.isInverseFillType()) {
-            draw_around_inv_path(target, devClipBounds, devPathBounds);
+            draw_around_inv_path(target, drawState, devClipBounds, devPathBounds);
         }
         return true;
     }
@@ -137,10 +140,11 @@
         return false;
     }
 
-    GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, devPathBounds);
+    GrDrawState copy = *drawState;
+    GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, &copy, devPathBounds);
 
     if (path.isInverseFillType()) {
-        draw_around_inv_path(target, devClipBounds, devPathBounds);
+        draw_around_inv_path(target, drawState, devClipBounds, devPathBounds);
     }
 
     return true;
diff --git a/src/gpu/GrSoftwarePathRenderer.h b/src/gpu/GrSoftwarePathRenderer.h
index bc35532..620e00b 100644
--- a/src/gpu/GrSoftwarePathRenderer.h
+++ b/src/gpu/GrSoftwarePathRenderer.h
@@ -23,18 +23,21 @@
         : fContext(context) {
     }
 
-    virtual bool canDrawPath(const SkPath&,
+    virtual bool canDrawPath(const GrDrawTarget*,
+                             const GrDrawState*,
+                             const SkPath&,
                              const SkStrokeRec&,
-                             const GrDrawTarget*,
                              bool antiAlias) const SK_OVERRIDE;
 protected:
-    virtual StencilSupport onGetStencilSupport(const SkPath&,
-                                               const SkStrokeRec&,
-                                               const GrDrawTarget*) const SK_OVERRIDE;
+    virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
+                                               const GrDrawState*,
+                                               const SkPath&,
+                                               const SkStrokeRec&) const SK_OVERRIDE;
 
-    virtual bool onDrawPath(const SkPath&,
+    virtual bool onDrawPath(GrDrawTarget*,
+                            GrDrawState*,
+                            const SkPath&,
                             const SkStrokeRec&,
-                            GrDrawTarget*,
                             bool antiAlias) SK_OVERRIDE;
 
 private:
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index 6ed4b9e..022ed94 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -50,20 +50,22 @@
     fGpu->unref();
 }
 
-bool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path,
+bool GrStencilAndCoverPathRenderer::canDrawPath(const GrDrawTarget* target,
+                                                const GrDrawState* drawState,
+                                                const SkPath& path,
                                                 const SkStrokeRec& stroke,
-                                                const GrDrawTarget* target,
                                                 bool antiAlias) const {
     return !stroke.isHairlineStyle() &&
            !antiAlias && // doesn't do per-path AA, relies on the target having MSAA
-           target->getDrawState().getRenderTarget()->getStencilBuffer() &&
-           target->getDrawState().getStencil().isDisabled();
+           drawState->getRenderTarget()->getStencilBuffer() &&
+           drawState->getStencil().isDisabled();
 }
 
 GrPathRenderer::StencilSupport
-GrStencilAndCoverPathRenderer::onGetStencilSupport(const SkPath&,
-                                                   const SkStrokeRec& ,
-                                                   const GrDrawTarget*) const {
+GrStencilAndCoverPathRenderer::onGetStencilSupport(const GrDrawTarget*,
+                                                   const GrDrawState*,
+                                                   const SkPath&,
+                                                   const SkStrokeRec&) const {
     return GrPathRenderer::kStencilOnly_StencilSupport;
 }
 
@@ -78,22 +80,23 @@
     return path.detach();
 }
 
-void GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path,
-                                                  const SkStrokeRec& stroke,
-                                                  GrDrawTarget* target) {
+void GrStencilAndCoverPathRenderer::onStencilPath(GrDrawTarget* target,
+                                                  GrDrawState* drawState,
+                                                  const SkPath& path,
+                                                  const SkStrokeRec& stroke) {
     SkASSERT(!path.isInverseFillType());
     SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke));
-    target->stencilPath(p, convert_skpath_filltype(path.getFillType()));
+    target->stencilPath(drawState, p, convert_skpath_filltype(path.getFillType()));
 }
 
-bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path,
+bool GrStencilAndCoverPathRenderer::onDrawPath(GrDrawTarget* target,
+                                               GrDrawState* drawState,
+                                               const SkPath& path,
                                                const SkStrokeRec& stroke,
-                                               GrDrawTarget* target,
                                                bool antiAlias) {
     SkASSERT(!antiAlias);
     SkASSERT(!stroke.isHairlineStyle());
 
-    GrDrawState* drawState = target->drawState();
     SkASSERT(drawState->getStencil().isDisabled());
 
     SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke));
@@ -113,7 +116,7 @@
         drawState->setStencil(kInvertedStencilPass);
 
         // fake inverse with a stencil and cover
-        target->stencilPath(p, convert_skpath_filltype(path.getFillType()));
+        target->stencilPath(drawState, p, convert_skpath_filltype(path.getFillType()));
 
         GrDrawState::AutoViewMatrixRestore avmr;
         SkRect bounds = SkRect::MakeLTRB(0, 0,
@@ -130,7 +133,7 @@
         } else {
             avmr.setIdentity(drawState);
         }
-        target->drawSimpleRect(bounds);
+        target->drawSimpleRect(drawState, bounds);
     } else {
         GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
             kZero_StencilOp,
@@ -141,9 +144,9 @@
             0xffff);
 
         drawState->setStencil(kStencilPass);
-        target->drawPath(p, convert_skpath_filltype(path.getFillType()));
+        target->drawPath(drawState, p, convert_skpath_filltype(path.getFillType()));
     }
 
-    target->drawState()->stencil()->setDisabled();
+    drawState->stencil()->setDisabled();
     return true;
 }
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.h b/src/gpu/GrStencilAndCoverPathRenderer.h
index 9ebcec9..dacdcd0 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.h
+++ b/src/gpu/GrStencilAndCoverPathRenderer.h
@@ -25,24 +25,28 @@
 
     virtual ~GrStencilAndCoverPathRenderer();
 
-    virtual bool canDrawPath(const SkPath&,
+    virtual bool canDrawPath(const GrDrawTarget*,
+                             const GrDrawState*,
+                             const SkPath&,
                              const SkStrokeRec&,
-                             const GrDrawTarget*,
                              bool antiAlias) const SK_OVERRIDE;
 
 protected:
-    virtual StencilSupport onGetStencilSupport(const SkPath&,
-                                               const SkStrokeRec&,
-                                               const GrDrawTarget*) const SK_OVERRIDE;
+    virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
+                                               const GrDrawState*,
+                                               const SkPath&,
+                                               const SkStrokeRec&) const SK_OVERRIDE;
 
-    virtual bool onDrawPath(const SkPath&,
+    virtual bool onDrawPath(GrDrawTarget*,
+                            GrDrawState*,
+                            const SkPath&,
                             const SkStrokeRec&,
-                            GrDrawTarget*,
                             bool antiAlias) SK_OVERRIDE;
 
-    virtual void onStencilPath(const SkPath&,
-                               const SkStrokeRec&,
-                               GrDrawTarget*) SK_OVERRIDE;
+    virtual void onStencilPath(GrDrawTarget*,
+                               GrDrawState*,
+                               const SkPath&,
+                               const SkStrokeRec&) SK_OVERRIDE;
 
 private:
     GrStencilAndCoverPathRenderer(GrGpu*);
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index 14a14a0..d70593e 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -333,10 +333,9 @@
                                     &fGlyphCache->getDescriptor(), gpuStroke);
     }
 
-    fStateRestore.set(fDrawTarget->drawState());
+    fStateRestore.set(&fDrawState);
 
-    fDrawTarget->drawState()->setFromPaint(fPaint, fContext->getMatrix(),
-                                           fContext->getRenderTarget());
+    fDrawState.setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget());
 
     GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
                                  kZero_StencilOp,
@@ -346,7 +345,7 @@
                                  0x0000,
                                  0xffff);
 
-    *fDrawTarget->drawState()->stencil() = kStencilPass;
+    *fDrawState.stencil() = kStencilPass;
 
     SkASSERT(0 == fPendingGlyphCount);
 }
@@ -368,7 +367,7 @@
         return;
     }
 
-    fDrawTarget->drawPaths(fGlyphs, fIndexBuffer, fPendingGlyphCount, fTransformBuffer,
+    fDrawTarget->drawPaths(&fDrawState, fGlyphs, fIndexBuffer, fPendingGlyphCount, fTransformBuffer,
                            GrPathRendering::kTranslate_PathTransformType,
                            GrPathRendering::kWinding_FillType);
 
@@ -384,7 +383,7 @@
     SkGlyphCache::AttachCache(fGlyphCache);
     fGlyphCache = NULL;
 
-    fDrawTarget->drawState()->stencil()->setDisabled();
+    fDrawState.stencil()->setDisabled();
     fStateRestore.set(NULL);
     fContext->setMatrix(fContextInitialMatrix);
     GrTextContext::finish();
diff --git a/src/gpu/GrStencilAndCoverTextContext.h b/src/gpu/GrStencilAndCoverTextContext.h
index 535ebdb..dabd3b3 100644
--- a/src/gpu/GrStencilAndCoverTextContext.h
+++ b/src/gpu/GrStencilAndCoverTextContext.h
@@ -9,7 +9,6 @@
 #define GrStencilAndCoverTextContext_DEFINED
 
 #include "GrTextContext.h"
-#include "GrDrawState.h"
 #include "GrDrawTarget.h"
 #include "SkStrokeRec.h"
 
@@ -52,6 +51,7 @@
         kMaxPerformance_RenderMode,
     };
 
+    GrDrawState                     fDrawState;
     GrDrawState::AutoRestoreEffects fStateRestore;
     SkScalar                        fTextRatio;
     float                           fTextInverseRatio;
diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp
index 5286984..5c03189 100644
--- a/src/gpu/GrTest.cpp
+++ b/src/gpu/GrTest.cpp
@@ -17,7 +17,6 @@
     fContext.reset(SkRef(ctx));
     fDrawTarget.reset(SkRef(target));
 
-    SkNEW_IN_TLAZY(&fASR, GrDrawTarget::AutoStateRestore, (target, GrDrawTarget::kReset_ASRInit));
     SkNEW_IN_TLAZY(&fACR, GrDrawTarget::AutoClipRestore, (target));
     SkNEW_IN_TLAZY(&fAGP, GrDrawTarget::AutoGeometryPush, (target));
 }
@@ -73,8 +72,8 @@
 
     virtual void discard(GrRenderTarget*) SK_OVERRIDE { }
 
-    virtual bool canCopySurface(GrSurface* dst,
-                                GrSurface* src,
+    virtual bool canCopySurface(const GrSurface* dst,
+                                const GrSurface* src,
                                 const SkIRect& srcRect,
                                 const SkIPoint& dstPoint) SK_OVERRIDE { return false; };
 
diff --git a/src/gpu/GrTest.h b/src/gpu/GrTest.h
index 5e61c29..e63d11e 100644
--- a/src/gpu/GrTest.h
+++ b/src/gpu/GrTest.h
@@ -24,7 +24,6 @@
     GrDrawTarget* target() { return fDrawTarget.get(); }
 
 private:
-    SkTLazy<GrDrawTarget::AutoStateRestore> fASR;
     SkTLazy<GrDrawTarget::AutoClipRestore>  fACR;
     SkTLazy<GrDrawTarget::AutoGeometryPush> fAGP;
 
diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp
index af96ef6..71d92cb 100644
--- a/src/gpu/effects/GrDashingEffect.cpp
+++ b/src/gpu/effects/GrDashingEffect.cpp
@@ -29,8 +29,9 @@
 
 // Returns whether or not the gpu can fast path the dash line effect.
 static bool can_fast_path_dash(const SkPoint pts[2], const GrStrokeInfo& strokeInfo,
-                               const GrDrawTarget& target, const SkMatrix& viewMatrix) {
-    if (target.getDrawState().getRenderTarget()->isMultisampled()) {
+                               const GrDrawTarget& target, const GrDrawState& ds,
+                               const SkMatrix& viewMatrix) {
+    if (ds.getRenderTarget()->isMultisampled()) {
         return false;
     }
 
@@ -170,11 +171,11 @@
     matrix.mapPoints(&verts[idx], 4);
 }
 
-bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const GrPaint& paint,
-                                   const GrStrokeInfo& strokeInfo, GrGpu* gpu,
-                                   GrDrawTarget* target, const SkMatrix& vm) {
+bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, GrDrawState* drawState,
+                                   const SkPoint pts[2], const GrPaint& paint,
+                                   const GrStrokeInfo& strokeInfo, const SkMatrix& vm) {
 
-    if (!can_fast_path_dash(pts, strokeInfo, *target, vm)) {
+    if (!can_fast_path_dash(pts, strokeInfo, *target, *drawState, vm)) {
         return false;
     }
 
@@ -319,7 +320,6 @@
 
     SkScalar devBloat = useAA ? 0.5f : 0.f;
 
-    GrDrawState* drawState = target->drawState();
     if (devIntervals[1] <= 0.f && useAA) {
         // Case when we end up drawing a solid AA rect
         // Reset the start rect to draw this single solid rect
@@ -372,7 +372,9 @@
     totalRectCnt += hasStartRect ? 1 : 0;
     totalRectCnt += hasEndRect ? 1 : 0;
 
-    GrDrawTarget::AutoReleaseGeometry geo(target, totalRectCnt * 4, 0);
+    GrDrawTarget::AutoReleaseGeometry geo(target,
+                                          totalRectCnt * 4,
+                                          drawState->getVertexStride(), 0);
     if (!geo.succeeded()) {
         SkDebugf("Failed to get space for vertices!\n");
         return false;
@@ -438,7 +440,7 @@
     }
 
     target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
-    target->drawIndexedInstances(kTriangles_GrPrimitiveType, totalRectCnt, 4, 6);
+    target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, totalRectCnt, 4, 6);
     target->resetIndexSource();
     return true;
 }
diff --git a/src/gpu/effects/GrDashingEffect.h b/src/gpu/effects/GrDashingEffect.h
index 331b6c8..14df1ae 100644
--- a/src/gpu/effects/GrDashingEffect.h
+++ b/src/gpu/effects/GrDashingEffect.h
@@ -13,6 +13,7 @@
 #include "SkPathEffect.h"
 
 class GrGpu;
+class GrDrawState;
 class GrDrawTarget;
 class GrGeometryProcessor;
 class GrPaint;
@@ -22,8 +23,9 @@
 class SkPath;
 
 namespace GrDashingEffect {
-    bool DrawDashLine(const SkPoint pts[2], const GrPaint& paint, const GrStrokeInfo& strokeInfo,
-                      GrGpu* gpu, GrDrawTarget* target, const SkMatrix& vm);
+    bool DrawDashLine(GrGpu*, GrDrawTarget*, GrDrawState*, const SkPoint pts[2],
+                      const GrPaint& paint, const GrStrokeInfo& strokeInfo,
+                      const SkMatrix& vm);
 
     enum DashCap {
         kRound_DashCap,
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 89f26ef..a17329f 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -2490,8 +2490,8 @@
     return copied;
 }
 
-bool GrGpuGL::canCopySurface(GrSurface* dst,
-                             GrSurface* src,
+bool GrGpuGL::canCopySurface(const GrSurface* dst,
+                             const GrSurface* src,
                              const SkIRect& srcRect,
                              const SkIPoint& dstPoint) {
     // This mirrors the logic in onCopySurface.  We prefer our base makes the copy if we need to
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 3757d76..778ee16 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -100,8 +100,8 @@
                              const SkIRect& srcRect,
                              const SkIPoint& dstPoint) SK_OVERRIDE;
 
-    virtual bool canCopySurface(GrSurface* dst,
-                                GrSurface* src,
+    virtual bool canCopySurface(const GrSurface* dst,
+                                const GrSurface* src,
                                 const SkIRect& srcRect,
                                 const SkIPoint& dstPoint) SK_OVERRIDE;