Drawstate on stack

BUG=skia:

Review URL: https://codereview.chromium.org/732693002
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);
     }
 }