clear stencil clip on draw target

TBR=
BUG=skia:

Review URL: https://codereview.chromium.org/683673002
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 2c3411d..743f191 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -214,7 +214,7 @@
                                       const SkRect* devBounds,
                                       GrDrawState::AutoRestoreEffects* are,
                                       GrDrawState::AutoRestoreStencil* ars,
-                                      GrDrawTarget::ScissorState* scissorState) {
+                                      ScissorState* scissorState) {
     fCurrClipMaskType = kNone_ClipMaskType;
 
     GrReducedClip::ElementList elements(16);
@@ -731,8 +731,9 @@
         SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil buffers");
         clipBit = (1 << (clipBit-1));
 
-        fGpu->clearStencilClip(rt, stencilSpaceIBounds,
-                               GrReducedClip::kAllIn_InitialState == initialState);
+        fGpu->clearStencilClip(stencilSpaceIBounds,
+                               GrReducedClip::kAllIn_InitialState == initialState,
+                               rt);
 
         // walk through each clip element and perform its set op
         // with the existing clip.
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index ca5a247..fe1ff0e 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -11,7 +11,6 @@
 #include "GrClipMaskCache.h"
 #include "GrContext.h"
 #include "GrDrawState.h"
-#include "GrDrawTarget.h"
 #include "GrReducedClip.h"
 #include "GrStencil.h"
 #include "GrTexture.h"
@@ -44,6 +43,16 @@
         , fCurrClipMaskType(kNone_ClipMaskType) {
     }
 
+    // The state of the scissor is controlled by the clip manager, no one else should set
+    // Scissor state.  This should really be on Gpu itself.  We should revist this when GPU
+    // and drawtarget are separate
+    struct ScissorState {
+        ScissorState() : fEnabled(false) {}
+        void set(const SkIRect& rect) { fRect = rect; fEnabled = true; }
+        bool    fEnabled;
+        SkIRect fRect;
+    };
+
     /**
      * Creates a clip mask if necessary as a stencil buffer or alpha texture
      * and sets the GrGpu's scissor and stencil state. If the return is false
@@ -55,7 +64,7 @@
                        const SkRect* devBounds,
                        GrDrawState::AutoRestoreEffects*,
                        GrDrawState::AutoRestoreStencil*,
-                       GrDrawTarget::ScissorState* scissorState);
+                       ScissorState* scissorState);
 
     /**
      * Purge resources to free up memory. TODO: This class shouldn't hold any long lived refs
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 3c2341a..3efa6bf 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -9,6 +9,7 @@
 #define GrDrawTarget_DEFINED
 
 #include "GrClipData.h"
+#include "GrClipMaskManager.h"
 #include "GrContext.h"
 #include "GrDrawState.h"
 #include "GrIndexBuffer.h"
@@ -692,15 +693,6 @@
 
     virtual DrawToken getCurrentDrawToken() { return DrawToken(this, 0); }
 
-    // The state of the scissor is controlled by the clip manager, no one else should set
-    // Scissor state
-    struct ScissorState {
-        ScissorState() : fEnabled(false) {}
-        void set(const SkIRect& rect) { fRect = rect; fEnabled = true; }
-        bool    fEnabled;
-        SkIRect fRect;
-    };
-
 protected:
     // Extend access to GrDrawState::convertToPEndeingExec to subclasses.
     void convertDrawStateToPendingExec(GrDrawState* ds) {
@@ -949,4 +941,19 @@
     typedef SkRefCnt INHERITED;
 };
 
+class GrClipTarget : public GrDrawTarget {
+public:
+    GrClipTarget(GrContext* context) : INHERITED(context) {}
+    /**
+     * Clip Mask Manager(and no one else) needs to clear private stencil bits.
+     * ClipTarget subclass sets clip bit in the stencil buffer. The subclass
+     * is free to clear the remaining bits to zero if masked clears are more
+     * expensive than clearing all bits.
+     */
+    virtual void clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* = NULL) = 0;
+
+private:
+    typedef GrDrawTarget INHERITED;
+};
+
 #endif
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 7e8c4c8..e767d07 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -28,7 +28,7 @@
 #define DEBUG_INVAL_START_IDX -1
 
 GrGpu::GrGpu(GrContext* context)
-    : GrDrawTarget(context)
+    : INHERITED(context)
     , fResetTimestamp(kExpiredTimestamp+1)
     , fResetBits(kAll_GrBackendState)
     , fVertexPool(NULL)
@@ -212,6 +212,20 @@
     this->onClear(renderTarget, rect, color, canIgnoreRect);
 }
 
+void GrGpu::clearStencilClip(const SkIRect& rect,
+                             bool insideClip,
+                             GrRenderTarget* renderTarget) {
+    if (NULL == renderTarget) {
+        renderTarget = this->getDrawState().getRenderTarget();
+    }
+    if (NULL == renderTarget) {
+        SkASSERT(0);
+        return;
+    }
+    this->handleDirtyContext();
+    this->onClearStencilClip(renderTarget, rect, insideClip);
+}
+
 bool GrGpu::readPixels(GrRenderTarget* target,
                        int left, int top, int width, int height,
                        GrPixelConfig config, void* buffer,
@@ -302,7 +316,7 @@
                                    const GrDeviceCoordTexture* dstCopy,
                                    const SkRect* devBounds,
                                    GrDrawState::AutoRestoreEffects* are) {
-    ScissorState scissorState;
+    GrClipMaskManager::ScissorState scissorState;
     GrDrawState::AutoRestoreStencil ars;
     if (!fClipMaskManager.setupClipping(this->getClip(),
                                         devBounds,
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 6814ae9..8fa81d6 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -23,7 +23,7 @@
 class GrStencilBuffer;
 class GrVertexBufferAllocPool;
 
-class GrGpu : public GrDrawTarget {
+class GrGpu : public GrClipTarget {
 public:
 
     /**
@@ -272,6 +272,10 @@
                        bool canIgnoreRect,
                        GrRenderTarget* renderTarget = NULL) SK_OVERRIDE;
 
+    virtual void clearStencilClip(const SkIRect& rect,
+                                  bool insideClip,
+                                  GrRenderTarget* renderTarget = NULL) SK_OVERRIDE;
+
     virtual void purgeResources() SK_OVERRIDE {
         // The clip mask manager can rebuild all its clip masks so just
         // get rid of them all.
@@ -295,11 +299,6 @@
         return fResetTimestamp;
     }
 
-    // GrGpu subclass sets clip bit in the stencil buffer. The subclass is
-    // free to clear the remaining bits to zero if masked clears are more
-    // expensive than clearing all bits.
-    virtual void clearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) = 0;
-
     enum PrivateDrawStateStateBits {
         kFirstBit = (GrDrawState::kLastPublicStateBit << 1),
 
@@ -422,6 +421,13 @@
     virtual void onClear(GrRenderTarget*, const SkIRect* rect, GrColor color,
                          bool canIgnoreRect) = 0;
 
+
+    // Overridden by backend specific classes to perform a clear of the stencil clip bits.  This is
+    // ONLY used by the the clip target
+    virtual void onClearStencilClip(GrRenderTarget*,
+                                    const SkIRect& rect,
+                                    bool insideClip) = 0;
+
     // overridden by backend-specific derived class to perform the draw call.
     virtual void onGpuDraw(const DrawInfo&) = 0;
 
@@ -454,7 +460,7 @@
     // backend-specific flush of the state.
     // returns false if current state is unsupported.
     virtual bool flushGraphicsState(DrawType,
-                                    const ScissorState&,
+                                    const GrClipMaskManager::ScissorState&,
                                     const GrDeviceCoordTexture* dstCopy) = 0;
 
     // clears target's entire stencil buffer to 0
@@ -507,7 +513,7 @@
     // these are mutable so they can be created on-demand
     mutable GrIndexBuffer*                                              fQuadIndexBuffer;
 
-    typedef GrDrawTarget INHERITED;
+    typedef GrClipTarget INHERITED;
 };
 
 #endif
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 47fff6f..dcd09dd 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -17,7 +17,7 @@
 GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
                                          GrVertexBufferAllocPool* vertexPool,
                                          GrIndexBufferAllocPool* indexPool)
-    : GrDrawTarget(gpu->getContext())
+    : INHERITED(gpu->getContext())
     , fCmdBuffer(kCmdBufferInitialSizeInBytes)
     , fLastState(NULL)
     , fLastClip(NULL)
@@ -434,6 +434,19 @@
     this->recordTraceMarkersIfNecessary();
 }
 
+void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
+                                           bool insideClip,
+                                           GrRenderTarget* renderTarget) {
+    if (NULL == renderTarget) {
+        renderTarget = this->drawState()->getRenderTarget();
+        SkASSERT(renderTarget);
+    }
+    ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
+    clr->fRect = rect;
+    clr->fInsideClip = insideClip;
+    this->recordTraceMarkersIfNecessary();
+}
+
 void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
     if (!this->caps()->discardRenderTargetSupport()) {
         return;
@@ -523,7 +536,7 @@
     ++fDrawID;
 }
 
-void GrInOrderDrawBuffer::Draw::execute(GrDrawTarget* gpu) {
+void GrInOrderDrawBuffer::Draw::execute(GrClipTarget* gpu) {
     gpu->setVertexSourceToBuffer(this->vertexBuffer());
     if (fInfo.isIndexed()) {
         gpu->setIndexSourceToBuffer(this->indexBuffer());
@@ -531,30 +544,30 @@
     gpu->executeDraw(fInfo);
 }
 
-void GrInOrderDrawBuffer::StencilPath::execute(GrDrawTarget* gpu) {
+void GrInOrderDrawBuffer::StencilPath::execute(GrClipTarget* gpu) {
     gpu->stencilPath(this->path(), fFill);
 }
 
-void GrInOrderDrawBuffer::DrawPath::execute(GrDrawTarget* gpu) {
+void GrInOrderDrawBuffer::DrawPath::execute(GrClipTarget* gpu) {
     gpu->executeDrawPath(this->path(), fFill, fDstCopy.texture() ? &fDstCopy : NULL);
 }
 
-void GrInOrderDrawBuffer::DrawPaths::execute(GrDrawTarget* gpu) {
+void GrInOrderDrawBuffer::DrawPaths::execute(GrClipTarget* gpu) {
     gpu->executeDrawPaths(this->pathRange(), this->indices(), fCount, this->transforms(),
                           fTransformsType, fFill, fDstCopy.texture() ? &fDstCopy : NULL);
 }
 
-void GrInOrderDrawBuffer::SetState::execute(GrDrawTarget* gpu) {
+void GrInOrderDrawBuffer::SetState::execute(GrClipTarget* gpu) {
     gpu->setDrawState(&fState);
 }
 
-void GrInOrderDrawBuffer::SetClip::execute(GrDrawTarget* gpu) {
+void GrInOrderDrawBuffer::SetClip::execute(GrClipTarget* gpu) {
     // Our fClipData is referenced directly, so we must remain alive for the entire
     // duration of the flush (after which the gpu's previous clip is restored).
     gpu->setClip(&fClipData);
 }
 
-void GrInOrderDrawBuffer::Clear::execute(GrDrawTarget* gpu) {
+void GrInOrderDrawBuffer::Clear::execute(GrClipTarget* gpu) {
     if (GrColor_ILLEGAL == fColor) {
         gpu->discard(this->renderTarget());
     } else {
@@ -562,7 +575,11 @@
     }
 }
 
-void GrInOrderDrawBuffer::CopySurface::execute(GrDrawTarget* gpu) {
+void GrInOrderDrawBuffer::ClearStencilClip::execute(GrClipTarget* gpu) {
+        gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
+}
+
+void GrInOrderDrawBuffer::CopySurface::execute(GrClipTarget* gpu) {
     gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
 }
 
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 421a4a9..7b9a926 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -37,7 +37,7 @@
  * in the GrGpu object that the buffer is played back into. The buffer requires VB and IB pools to
  * store geometry.
  */
-class GrInOrderDrawBuffer : public GrDrawTarget {
+class GrInOrderDrawBuffer : public GrClipTarget {
 public:
 
     /**
@@ -75,11 +75,16 @@
     // overrides from GrDrawTarget
     virtual bool geometryHints(int* vertexCount,
                                int* indexCount) const SK_OVERRIDE;
+
     virtual void clear(const SkIRect* rect,
                        GrColor color,
                        bool canIgnoreRect,
                        GrRenderTarget* renderTarget) SK_OVERRIDE;
 
+    virtual void clearStencilClip(const SkIRect& rect,
+                                  bool insideClip,
+                                  GrRenderTarget* renderTarget) SK_OVERRIDE;
+
     virtual void discard(GrRenderTarget*) SK_OVERRIDE;
 
     virtual void initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) SK_OVERRIDE;
@@ -103,7 +108,7 @@
         Cmd(uint8_t type) : fType(type) {}
         virtual ~Cmd() {}
 
-        virtual void execute(GrDrawTarget*) = 0;
+        virtual void execute(GrClipTarget*) = 0;
 
         uint8_t fType;
     };
@@ -118,7 +123,7 @@
         const GrVertexBuffer* vertexBuffer() const { return fVertexBuffer.get(); }
         const GrIndexBuffer* indexBuffer() const { return fIndexBuffer.get(); }
 
-        virtual void execute(GrDrawTarget*);
+        virtual void execute(GrClipTarget*);
 
         DrawInfo fInfo;
 
@@ -132,7 +137,7 @@
 
         const GrPath* path() const { return fPath.get(); }
 
-        virtual void execute(GrDrawTarget*);
+        virtual void execute(GrClipTarget*);
 
         SkPath::FillType fFill;
 
@@ -145,7 +150,7 @@
 
         const GrPath* path() const { return fPath.get(); }
 
-        virtual void execute(GrDrawTarget*);
+        virtual void execute(GrClipTarget*);
 
         SkPath::FillType        fFill;
         GrDeviceCoordTexture    fDstCopy;
@@ -161,7 +166,7 @@
         uint32_t* indices() { return reinterpret_cast<uint32_t*>(CmdBuffer::GetDataForItem(this)); }
         float* transforms() { return reinterpret_cast<float*>(&this->indices()[fCount]); }
 
-        virtual void execute(GrDrawTarget*);
+        virtual void execute(GrClipTarget*);
 
         size_t                  fCount;
         PathTransformType       fTransformsType;
@@ -178,7 +183,7 @@
 
         GrRenderTarget* renderTarget() const { return fRenderTarget.get(); }
 
-        virtual void execute(GrDrawTarget*);
+        virtual void execute(GrClipTarget*);
 
         SkIRect fRect;
         GrColor fColor;
@@ -188,13 +193,28 @@
         GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget;
     };
 
+    // This command is ONLY used by the clip mask manager to clear the stencil clip bits
+    struct ClearStencilClip : public Cmd {
+        ClearStencilClip(GrRenderTarget* rt) : Cmd(kClear_Cmd), fRenderTarget(rt) {}
+
+        GrRenderTarget* renderTarget() const { return fRenderTarget.get(); }
+
+        virtual void execute(GrClipTarget*);
+
+        SkIRect fRect;
+        bool    fInsideClip;
+
+    private:
+        GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget;
+    };
+
     struct CopySurface : public Cmd {
         CopySurface(GrSurface* dst, GrSurface* src) : Cmd(kCopySurface_Cmd), fDst(dst), fSrc(src) {}
 
         GrSurface* dst() const { return fDst.get(); }
         GrSurface* src() const { return fSrc.get(); }
 
-        virtual void execute(GrDrawTarget*);
+        virtual void execute(GrClipTarget*);
 
         SkIPoint    fDstPoint;
         SkIRect     fSrcRect;
@@ -207,7 +227,7 @@
     struct SetState : public Cmd {
         SetState(const GrDrawState& state) : Cmd(kSetState_Cmd), fState(state) {}
 
-        virtual void execute(GrDrawTarget*);
+        virtual void execute(GrClipTarget*);
 
         GrDrawState fState;
     };
@@ -220,7 +240,7 @@
             fClipData.fOrigin = clipData->fOrigin;
         }
 
-        virtual void execute(GrDrawTarget*);
+        virtual void execute(GrClipTarget*);
 
         GrClipData fClipData;
 
@@ -300,7 +320,7 @@
     GrClipData*                       fLastClip;
 
     SkTArray<GrTraceMarkerSet, false> fGpuCmdMarkers;
-    GrDrawTarget*                     fDstGpu;
+    GrClipTarget*                     fDstGpu;
     bool                              fClipSet;
 
     enum ClipProxyState {
@@ -332,7 +352,7 @@
     bool                                                fFlushing;
     uint32_t                                            fDrawID;
 
-    typedef GrDrawTarget INHERITED;
+    typedef GrClipTarget INHERITED;
 };
 
 #endif
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 88e7be0..f79f90e 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -1359,7 +1359,7 @@
     }
 }
 
-void GrGpuGL::flushScissor(const ScissorState& scissorState,
+void GrGpuGL::flushScissor(const GrClipMaskManager::ScissorState& scissorState,
                            const GrGLIRect& rtViewport,
                            GrSurfaceOrigin rtOrigin) {
     if (scissorState.fEnabled) {
@@ -1420,7 +1420,7 @@
     }
 
     this->flushRenderTarget(glRT, rect);
-    ScissorState scissorState;
+    GrClipMaskManager::ScissorState scissorState;
     scissorState.fEnabled = SkToBool(rect);
     if (scissorState.fEnabled) {
         scissorState.fRect = *rect;
@@ -1511,7 +1511,7 @@
     fHWStencilSettings.invalidate();
 }
 
-void GrGpuGL::clearStencilClip(GrRenderTarget* target, const SkIRect& rect, bool insideClip) {
+void GrGpuGL::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bool insideClip) {
     SkASSERT(target);
 
     // this should only be called internally when we know we have a
@@ -1538,7 +1538,7 @@
     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
     this->flushRenderTarget(glRT, &SkIRect::EmptyIRect());
 
-    ScissorState scissorState;
+    GrClipMaskManager::ScissorState scissorState;
     scissorState.fEnabled = true;
     scissorState.fRect = rect;
     this->flushScissor(scissorState, glRT->getViewport(), glRT->origin());
@@ -1833,7 +1833,7 @@
 
             if (GrGLCaps::kES_Apple_MSFBOType == this->glCaps().msFBOType()) {
                 // Apple's extension uses the scissor as the blit bounds.
-                ScissorState scissorState;
+                GrClipMaskManager::ScissorState scissorState;
                 scissorState.fEnabled = true;
                 scissorState.fRect = dirtyRect;
                 this->flushScissor(scissorState, rt->getViewport(), rt->origin());
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 46d9700..568ce96 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -135,6 +135,10 @@
     virtual void onClear(GrRenderTarget*, const SkIRect* rect, GrColor color,
                          bool canIgnoreRect) SK_OVERRIDE;
 
+    virtual void onClearStencilClip(GrRenderTarget*,
+                                    const SkIRect& rect,
+                                    bool insideClip) SK_OVERRIDE;
+
     virtual bool onReadPixels(GrRenderTarget* target,
                               int left, int top,
                               int width, int height,
@@ -153,10 +157,8 @@
 
 
     virtual void clearStencil(GrRenderTarget*) SK_OVERRIDE;
-    virtual void clearStencilClip(GrRenderTarget*, const SkIRect& rect,
-                                  bool insideClip) SK_OVERRIDE;
     virtual bool flushGraphicsState(DrawType,
-                                    const ScissorState&,
+                                    const GrClipMaskManager::ScissorState&,
                                     const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
 
     // GrDrawTarget overrides
@@ -227,7 +229,7 @@
 
     // flushes the scissor. see the note on flushBoundTextureAndParams about
     // flushing the scissor after that function is called.
-    void flushScissor(const ScissorState&,
+    void flushScissor(const GrClipMaskManager::ScissorState&,
                       const GrGLIRect& rtViewport,
                       GrSurfaceOrigin rtOrigin);
 
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 23de7a8..330f348 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -202,7 +202,7 @@
 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
 
 bool GrGpuGL::flushGraphicsState(DrawType type,
-                                 const ScissorState& scissorState,
+                                 const GrClipMaskManager::ScissorState& scissorState,
                                  const GrDeviceCoordTexture* dstCopy) {
     SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDrawState(),
                                                                  this,