Convert GrClip to an abstract base class
authorcdalton <cdalton@nvidia.com>
Fri, 13 May 2016 17:25:00 +0000 (10:25 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 13 May 2016 17:25:00 +0000 (10:25 -0700)
Converts GrClip to an abstract base class and adds a "GrFixedClip"
implementation. GrFixedClip denotes a clip implemented with fixed-
function hardware. GrFixedClip allows us to remove the stateful
"fClipMode" member from GrClipMaskManager, and in the future will
be able to nicely encapsulate window rectangles.

After this change GrClipMaskManager is just a wrapper around
GrDrawTarget. We may want to consider removing it altogether.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1971343002

Review-Url: https://codereview.chromium.org/1971343002

29 files changed:
gm/texdata.cpp
include/gpu/GrClip.h
include/gpu/GrTypesPriv.h
src/core/SkImageFilter.cpp
src/effects/SkAlphaThresholdFilter.cpp
src/effects/SkBlurMaskFilter.cpp
src/effects/SkDisplacementMapEffect.cpp
src/effects/SkGpuBlurUtils.cpp
src/effects/SkLightingImageFilter.cpp
src/effects/SkMorphologyImageFilter.cpp
src/effects/SkXfermodeImageFilter.cpp
src/gpu/GrBlurUtils.cpp
src/gpu/GrClip.cpp
src/gpu/GrClipMaskManager.cpp
src/gpu/GrClipMaskManager.h
src/gpu/GrContext.cpp
src/gpu/GrDrawContext.cpp
src/gpu/GrDrawContextPriv.h
src/gpu/GrDrawTarget.cpp
src/gpu/GrTextureParamsAdjuster.cpp
src/gpu/GrTextureToYUVPlanes.cpp
src/gpu/GrYUVProvider.cpp
src/gpu/SkGpuDevice.cpp
src/gpu/SkGpuDevice.h
src/gpu/effects/GrConfigConversionEffect.cpp
src/image/SkImage_Gpu.cpp
tests/ClipBoundsTest.cpp
tests/TessellatingPathRendererTests.cpp
tools/gpu/GrTest.cpp

index 494a932..01eedec 100644 (file)
@@ -82,7 +82,7 @@ DEF_SIMPLE_GM_BG(texdata, canvas, 2 * S, 2 * S, SK_ColorBLACK) {
         SkAutoTUnref<GrTexture> au(texture);
 
         // setup new clip
-        GrClip clip(SkRect::MakeWH(2*S, 2*S));
+        GrFixedClip clip(SkIRect::MakeWH(2*S, 2*S));
 
         GrPaint paint;
         paint.setPorterDuffXPFactory(SkXfermode::kSrcOver_Mode);
index fd8b970..68a4eb9 100644 (file)
 #ifndef GrClip_DEFINED
 #define GrClip_DEFINED
 
+#include "GrFragmentProcessor.h"
+#include "GrTypesPriv.h"
 #include "SkClipStack.h"
 
-struct SkIRect;
+class GrClipMaskManager;
+class GrPipelineBuilder;
 
 /**
- * GrClip encapsulates the information required to construct the clip
- * masks. 'A GrClip is either wide open, just an IRect, just a Rect, or a full clipstack.
- * If the clip is a clipstack than the origin is used to translate the stack with
- * respect to device coordinates. This allows us to use a clip stack that is
- * specified for a root device with a layer device that is restricted to a subset
- * of the original canvas. For other clip types the origin will always be (0,0).
- *
- * NOTE: GrClip *must* point to a const clipstack
+ * Produced by GrClip. It provides a set of modifications to the drawing state that are used to
+ * create the final GrPipeline for a GrBatch.
  */
-class GrClip : SkNoncopyable {
+class GrAppliedClip {
 public:
-    GrClip() : fClipType(kWideOpen_ClipType) {
-        fOrigin.setZero();
-    }
+    GrAppliedClip() : fHasStencilClip(false) {}
+    const GrFragmentProcessor* clipCoverageFragmentProcessor() const { return fClipCoverageFP; }
+    const GrScissorState& scissorState() const { return fScissorState; }
+    bool hasStencilClip() const { return fHasStencilClip; }
 
-    GrClip(const SkIRect& rect) : fClipType(kIRect_ClipType) {
-        fOrigin.setZero();
-        fClip.fIRect = rect;
-    }
+private:
+    SkAutoTUnref<const GrFragmentProcessor> fClipCoverageFP;
+    GrScissorState                          fScissorState;
+    bool                                    fHasStencilClip;
 
-    GrClip(const SkRect& rect) : fClipType(kIRect_ClipType) {
-        fOrigin.setZero();
-        fClip.fIRect.fLeft   = SkScalarRoundToInt(rect.fLeft);
-        fClip.fIRect.fTop    = SkScalarRoundToInt(rect.fTop);
-        fClip.fIRect.fRight  = SkScalarRoundToInt(rect.fRight);
-        fClip.fIRect.fBottom = SkScalarRoundToInt(rect.fBottom);
-    }
+    friend class GrFixedClip;
+    friend class GrClipMaskManager;
 
-    ~GrClip() { this->reset(); }
-
-    const GrClip& operator=(const GrClip& other) {
-        this->reset();
-        fClipType = other.fClipType;
-        switch (other.fClipType) {
-            case kWideOpen_ClipType:
-                fOrigin.setZero();
-                break;
-            case kClipStack_ClipType:
-                fClip.fStack = SkRef(other.clipStack());
-                fOrigin = other.origin();
-                break;
-            case kIRect_ClipType:
-                fClip.fIRect = other.irect();
-                fOrigin.setZero();
-                break;
-        }
-        return *this;
-    }
+    typedef SkNoncopyable INHERITED;
+};
 
-    bool operator==(const GrClip& other) const {
-        if (this->clipType() != other.clipType()) {
-            return false;
-        }
-
-        switch (fClipType) {
-            case kWideOpen_ClipType:
-                return true;
-            case kClipStack_ClipType:
-                if (this->origin() != other.origin()) {
-                    return false;
-                }
-
-                if (this->clipStack() && other.clipStack()) {
-                    return *this->clipStack() == *other.clipStack();
-                } else {
-                    return this->clipStack() == other.clipStack();
-                }
-                break;
-            case kIRect_ClipType:
-                return this->irect() == other.irect();
-                break;
-        }
-        SkFAIL("This should not occur\n");
-        return false;
-    }
+/**
+ * GrClip is an abstract base class for applying a clip. It constructs a clip mask if necessary, and
+ * fills out a GrAppliedClip instructing the caller on how to set up the draw state.
+ */
+class GrClip {
+public:
+    virtual bool quickContains(const SkRect&) const = 0;
+    virtual void getConservativeBounds(int width, int height, SkIRect* devResult,
+                                       bool* isIntersectionOfRects = nullptr) const = 0;
+    virtual bool apply(GrClipMaskManager*, const GrPipelineBuilder&, const SkRect* devBounds,
+                       GrAppliedClip*) const = 0;
 
-    bool operator!=(const GrClip& other) const {
-        return !(*this == other);
-    }
+    virtual ~GrClip() {}
+};
 
-    const SkClipStack* clipStack() const {
-        SkASSERT(kClipStack_ClipType == fClipType);
-        return fClip.fStack;
-    }
+/**
+ * Specialized implementation for no clip.
+ */
+class GrNoClip final : public GrClip {
+private:
+    bool quickContains(const SkRect&) const final { return true; }
+    void getConservativeBounds(int width, int height, SkIRect* devResult,
+                               bool* isIntersectionOfRects) const final;
+    bool apply(GrClipMaskManager*, const GrPipelineBuilder&,
+               const SkRect*, GrAppliedClip*) const final { return true; }
+};
 
-    void setClipStack(const SkClipStack* clipStack, const SkIPoint* origin = NULL) {
-        this->reset();
-        if (clipStack->isWideOpen()) {
-            fClipType = kWideOpen_ClipType;
-            fOrigin.setZero();
-        } else {
-            fClipType = kClipStack_ClipType;
-            fClip.fStack = SkRef(clipStack);
-            if (origin) {
-                fOrigin = *origin;
-            } else {
-                fOrigin.setZero();
-            }
-        }
-    }
+/**
+ * GrFixedClip is a clip that can be represented by fixed-function hardware. It never modifies the
+ * stencil buffer itself, but can be configured to use whatever clip is already there.
+ */
+class GrFixedClip final : public GrClip {
+public:
+    GrFixedClip() : fHasStencilClip(false) {}
+    GrFixedClip(const SkIRect& scissorRect) : fScissorState(scissorRect), fHasStencilClip(false) {}
 
-    void setIRect(const SkIRect& irect) {
-        this->reset();
-        fClipType = kIRect_ClipType;
-        fOrigin.setZero();
-        fClip.fIRect = irect;
+    void reset() {
+        fScissorState.setDisabled();
+        fHasStencilClip = false;
     }
 
-    const SkIRect& irect() const {
-        SkASSERT(kIRect_ClipType == fClipType);
-        return fClip.fIRect;
+    void reset(const SkIRect& scissorRect) {
+        fScissorState.set(scissorRect);
+        fHasStencilClip = false;
     }
 
-    void reset() {
-        if (kClipStack_ClipType == fClipType) {
-            fClip.fStack->unref();
-            fClip.fStack = NULL;
-        }
-        fClipType = kWideOpen_ClipType;
-        fOrigin.setZero();
-    }
+    void enableStencilClip(bool enable) { fHasStencilClip = enable; }
 
-    // We support this for all cliptypes to simplify the logic a bit in clip mask manager.
-    // non clipstack clip types MUST have a (0,0) origin
-    const SkIPoint& origin() const {
-        SkASSERT(fClipType == kClipStack_ClipType || (fOrigin.fX == 0 && fOrigin.fY == 0));
-        return fOrigin;
-    }
+    const GrScissorState& scissorState() const { return fScissorState; }
+    bool hasStencilClip() const { return fHasStencilClip; }
 
-    bool isWideOpen(const SkRect& rect) const {
-        return (kWideOpen_ClipType == fClipType) ||
-               (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) ||
-               (kIRect_ClipType == fClipType && this->irect().contains(rect));
-    }
+    bool quickContains(const SkRect&) const final;
+    void getConservativeBounds(int width, int height, SkIRect* devResult,
+                               bool* isIntersectionOfRects) const final;
 
-    bool isWideOpen(const SkIRect& rect) const {
-        return (kWideOpen_ClipType == fClipType) ||
-               (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) ||
-               (kIRect_ClipType == fClipType && this->irect().contains(rect));
-    }
+private:
+    bool apply(GrClipMaskManager*, const GrPipelineBuilder&,
+               const SkRect* devBounds, GrAppliedClip* out) const final;
 
-    bool isWideOpen() const {
-        return (kWideOpen_ClipType == fClipType) ||
-               (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen());
-    }
+    GrScissorState   fScissorState;
+    bool             fHasStencilClip;
+};
 
-    bool quickContains(const SkRect& rect) const {
-        return (kWideOpen_ClipType == fClipType) ||
-               (kClipStack_ClipType == fClipType && this->clipStack()->quickContains(rect)) ||
-               (kIRect_ClipType == fClipType && this->irect().contains(rect));
+/**
+ * GrClipStackClip can apply a generic SkClipStack to the draw state. It may generate clip masks or
+ * write to the stencil buffer during apply().
+ */
+class GrClipStackClip final : public GrClip {
+public:
+    GrClipStackClip(const SkClipStack* stack = nullptr, const SkIPoint* origin = nullptr) {
+        this->reset(stack, origin);
     }
 
-    void getConservativeBounds(int width, int height,
-                               SkIRect* devResult,
-                               bool* isIntersectionOfRects = NULL) const;
-
-    static const GrClip& WideOpen();
+    void reset(const SkClipStack* stack = nullptr, const SkIPoint* origin = nullptr) {
+        fOrigin = origin ? *origin : SkIPoint::Make(0, 0);
+        fStack.reset(SkSafeRef(stack));
+    }
 
-    enum ClipType {
-        kClipStack_ClipType,
-        kWideOpen_ClipType,
-        kIRect_ClipType,
-    };
+    const SkIPoint& origin() const { return fOrigin; }
+    const SkClipStack* clipStack() const { return fStack; }
 
-    ClipType clipType() const { return fClipType; }
+    bool quickContains(const SkRect&) const final;
+    void getConservativeBounds(int width, int height, SkIRect* devResult,
+                               bool* isIntersectionOfRects) const final;
+    bool apply(GrClipMaskManager*, const GrPipelineBuilder&,
+               const SkRect* devBounds, GrAppliedClip*) const final;
 
 private:
-    union Clip {
-        const SkClipStack* fStack;
-        SkIRect fIRect;
-    } fClip;
-
-    SkIPoint fOrigin;
-    ClipType fClipType;
+    SkIPoint                          fOrigin;
+    SkAutoTUnref<const SkClipStack>   fStack;
 };
 
 #endif
index 18bc644..6a6fd54 100644 (file)
@@ -401,6 +401,8 @@ enum GrIOType {
 
 struct GrScissorState {
     GrScissorState() : fEnabled(false) {}
+    GrScissorState(const SkIRect& rect) : fEnabled(true), fRect(rect) {}
+    void setDisabled() { fEnabled = false; }
     void set(const SkIRect& rect) { fRect = rect; fEnabled = true; }
     bool operator==(const GrScissorState& other) const {
         return fEnabled == other.fEnabled &&
index 899083d..c7a5701 100644 (file)
@@ -287,13 +287,13 @@ sk_sp<SkSpecialImage> SkImageFilter::DrawWithFP(GrContext* context,
         return nullptr;
     }
 
+    SkIRect dstIRect = SkIRect::MakeWH(bounds.width(), bounds.height());
     SkRect srcRect = SkRect::Make(bounds);
     SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
-    GrClip clip(dstRect);
+    GrFixedClip clip(dstIRect);
     drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);
 
-    return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(bounds.width(), bounds.height()),
-                                       kNeedNewImageUniqueID_SpecialImage,
+    return SkSpecialImage::MakeFromGpu(dstIRect, kNeedNewImageUniqueID_SpecialImage,
                                        drawContext->asTexture());
 }
 #endif
index a4876c8..b484892 100644 (file)
@@ -114,7 +114,7 @@ sk_sp<GrTexture> SkAlphaThresholdFilterImpl::createMaskTexture(GrContext* contex
     SkRegion::Iterator iter(fRegion);
     drawContext->clear(nullptr, 0x0, true);
 
-    GrClip clip(SkRect::Make(SkIRect::MakeWH(bounds.width(), bounds.height())));
+    GrFixedClip clip(SkIRect::MakeWH(bounds.width(), bounds.height()));
     while (!iter.done()) {
         SkRect rect = SkRect::Make(iter.rect());
         drawContext->drawRect(clip, grPaint, inMatrix, rect);
index 7f076d6..969afc1 100644 (file)
@@ -1278,7 +1278,7 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
             paint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
         }
 
-        drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), SkRect::Make(clipRect));
+        drawContext->drawRect(GrNoClip(), paint, SkMatrix::I(), SkRect::Make(clipRect));
     }
 
     *result = drawContext->asTexture().release();
index befda79..541dbbd 100644 (file)
@@ -342,7 +342,7 @@ sk_sp<SkSpecialImage> SkDisplacementMapEffect::onFilterImage(SkSpecialImage* sou
             return nullptr;
         }
 
-        drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(colorBounds));
+        drawContext->drawRect(GrNoClip(), paint, matrix, SkRect::Make(colorBounds));
 
         offset->fX = bounds.left();
         offset->fY = bounds.top();
index de19d43..b377b41 100644 (file)
@@ -212,7 +212,7 @@ sk_sp<GrDrawContext> GaussianBlur(GrContext* context,
     scale_irect(&srcRect, scaleFactorX, scaleFactorY);
 
     // setup new clip
-    GrClip clip(localDstBounds);
+    GrFixedClip clip(localDstBounds);
 
     sk_sp<GrTexture> srcTexture(sk_ref_sp(origSrc));
 
index d9b2936..7f4dcfd 100644 (file)
@@ -415,11 +415,11 @@ sk_sp<SkSpecialImage> SkLightingImageFilterInternal::filterImageGPU(SkSpecialIma
         return nullptr;
     }
 
-    SkRect dstRect = SkRect::MakeWH(SkIntToScalar(offsetBounds.width()),
-                                    SkIntToScalar(offsetBounds.height()));
+    SkIRect dstIRect = SkIRect::MakeWH(offsetBounds.width(), offsetBounds.height());
+    SkRect dstRect = SkRect::Make(dstIRect);
 
     // setup new clip
-    GrClip clip(dstRect);
+    GrFixedClip clip(dstIRect);
 
     const SkIRect inputBounds = SkIRect::MakeWH(input->width(), input->height());
     SkRect topLeft = SkRect::MakeXYWH(0, 0, 1, 1);
index 121a7fd..bbd236e 100644 (file)
@@ -478,8 +478,7 @@ static sk_sp<SkSpecialImage> apply_morphology(GrContext* context,
     SkASSERT(srcTexture);
 
     // setup new clip
-    const GrClip clip(SkRect::MakeWH(SkIntToScalar(srcTexture->width()),
-                                     SkIntToScalar(srcTexture->height())));
+    const GrFixedClip clip(SkIRect::MakeWH(srcTexture->width(), srcTexture->height()));
 
     const SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height());
     SkIRect srcRect = rect;
index d4756e8..1921e00 100644 (file)
@@ -249,7 +249,7 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter::filterImageGPU(SkSpecialImage* sour
 
     SkMatrix matrix;
     matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
-    drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(bounds));
+    drawContext->drawRect(GrNoClip(), paint, matrix, SkRect::Make(bounds));
 
     return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(bounds.width(), bounds.height()),
                                        kNeedNewImageUniqueID_SpecialImage,
index 40bd6f9..1e85b87 100644 (file)
@@ -125,8 +125,8 @@ static sk_sp<GrTexture> create_mask_GPU(GrContext* context,
     tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
 
     // setup new clip
-    const SkRect clipRect = SkRect::MakeIWH(maskRect.width(), maskRect.height());
-    GrClip clip(clipRect);
+    const SkIRect clipRect = SkIRect::MakeWH(maskRect.width(), maskRect.height());
+    GrFixedClip clip(clipRect);
 
     // Draw the mask into maskTexture with the path's integerized top-left at
     // the origin using tempPaint.
index 5c4a27c..15065aa 100644 (file)
@@ -7,47 +7,83 @@
 
 #include "GrClip.h"
 
-#include "GrSurface.h"
-#include "SkRect.h"
+#include "GrClipMaskManager.h"
 
-///////////////////////////////////////////////////////////////////////////////
+void GrNoClip::getConservativeBounds(int width, int height, SkIRect* devResult,
+                                     bool* isIntersectionOfRects) const {
+    devResult->setXYWH(0, 0, width, height);
+    if (isIntersectionOfRects) {
+        *isIntersectionOfRects = true;
+    }
+}
 
-/**
- * getConservativeBounds returns the conservative bounding box of the clip
- * in device (as opposed to canvas) coordinates. If the bounding box is
- * the result of purely intersections of rects (with an initial replace)
- * isIntersectionOfRects will be set to true.
- */
-void GrClip::getConservativeBounds(int width, int height, SkIRect* devResult,
-                                   bool* isIntersectionOfRects) const {
-    switch (fClipType) {
-        case kWideOpen_ClipType: {
-            devResult->setLTRB(0, 0, width, height);
-            if (isIntersectionOfRects) {
-                *isIntersectionOfRects = true;
-            }
-        } break;
-        case kIRect_ClipType: {
-            *devResult = this->irect();
-            if (isIntersectionOfRects) {
-                *isIntersectionOfRects = true;
-            }
-        } break;
-        case kClipStack_ClipType: {
-            SkRect devBounds;
-            this->clipStack()->getConservativeBounds(-this->origin().fX,
-                                                     -this->origin().fY,
-                                                     width,
-                                                     height,
-                                                     &devBounds,
-                                                     isIntersectionOfRects);
-            devBounds.roundOut(devResult);
-        } break;
+bool GrFixedClip::quickContains(const SkRect& rect) const {
+    if (fHasStencilClip) {
+        return false;
+    }
+    if (!fScissorState.enabled()) {
+        return true;
+    }
+    return fScissorState.rect().contains(rect);
+}
+
+void GrFixedClip::getConservativeBounds(int width, int height, SkIRect* devResult,
+                                        bool* isIntersectionOfRects) const {
+    devResult->setXYWH(0, 0, width, height);
+    if (fScissorState.enabled()) {
+        if (!devResult->intersect(fScissorState.rect())) {
+            devResult->setEmpty();
+        }
+    }
+    if (isIntersectionOfRects) {
+        *isIntersectionOfRects = true;
+    }
+}
+
+bool GrFixedClip::apply(GrClipMaskManager*, const GrPipelineBuilder& pipelineBuilder,
+                        const SkRect* devBounds, GrAppliedClip* out) const {
+    if (fScissorState.enabled()) {
+        const GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
+        SkIRect tightScissor;
+        if (!tightScissor.intersect(fScissorState.rect(),
+                                    SkIRect::MakeWH(rt->width(), rt->height()))) {
+            return false;
+        }
+        if (devBounds && !devBounds->intersects(SkRect::Make(tightScissor))) {
+            return false;
+        }
+        out->fScissorState.set(tightScissor);
+    }
+    out->fHasStencilClip = fHasStencilClip;
+    return true;
+}
+
+bool GrClipStackClip::quickContains(const SkRect& rect) const {
+    if (!fStack) {
+        return true;
+    }
+    return fStack->quickContains(rect.makeOffset(SkIntToScalar(fOrigin.x()),
+                                                 SkIntToScalar(fOrigin.y())));
+}
 
+void GrClipStackClip::getConservativeBounds(int width, int height, SkIRect* devResult,
+                                            bool* isIntersectionOfRects) const {
+    if (!fStack) {
+        devResult->setXYWH(0, 0, width, height);
+        if (isIntersectionOfRects) {
+            *isIntersectionOfRects = true;
+        }
+        return;
     }
+    SkRect devBounds;
+    fStack->getConservativeBounds(-fOrigin.x(), -fOrigin.y(), width, height, &devBounds,
+                                  isIntersectionOfRects);
+    devBounds.roundOut(devResult);
 }
 
-const GrClip& GrClip::WideOpen() {
-    static const GrClip clip;
-    return clip;
+bool GrClipStackClip::apply(GrClipMaskManager* clipMaskManager,
+                            const GrPipelineBuilder& pipelineBuilder, const SkRect* devBounds,
+                            GrAppliedClip* out) const {
+    // TODO: Collapse ClipMaskManager into this class.(?)
+    return clipMaskManager->setupClipping(pipelineBuilder, *this, devBounds, out);
 }
index da128fb..0d2d5b0 100644 (file)
@@ -137,11 +137,6 @@ GrPathRenderer* GrClipMaskManager::GetPathRenderer(GrContext* context,
     return pr;
 }
 
-GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget)
-    : fDrawTarget(drawTarget)
-    , fClipMode(kIgnoreClip_StencilClipMode) {
-}
-
 GrContext* GrClipMaskManager::getContext() {
     return fDrawTarget->cmmAccess().context();
 }
@@ -288,11 +283,11 @@ bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
 // sort out what kind of clip mask needs to be created: alpha, stencil,
 // scissor, or entirely software
 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder,
-                                      const GrClip& clip,
+                                      const GrClipStackClip& clip,
                                       const SkRect* devBounds,
                                       GrAppliedClip* out) {
-    if (kRespectClip_StencilClipMode == fClipMode) {
-        fClipMode = kIgnoreClip_StencilClipMode;
+    if (!clip.clipStack() || clip.clipStack()->isWideOpen()) {
+        return true;
     }
 
     GrReducedClip::ElementList elements;
@@ -306,59 +301,36 @@ bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder,
     SkASSERT(rt);
 
     SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height());
-    if (clip.isWideOpen(clipSpaceRTIBounds)) {
-        return true;
-    }
+    clipSpaceRTIBounds.offset(clip.origin());
 
-    // The clip mask manager always draws with a single IRect so we special case that logic here
-    // Image filters just use a rect, so we also special case that logic
-    switch (clip.clipType()) {
-        case GrClip::kWideOpen_ClipType:
-            SkFAIL("Should have caught this with clip.isWideOpen()");
-            return true;
-        case GrClip::kIRect_ClipType: {
-            SkIRect scissor = clip.irect();
-            if (scissor.intersect(clipSpaceRTIBounds)) {
-                out->fScissorState.set(scissor);
-                out->fHasStencilClip = kIgnoreClip_StencilClipMode != fClipMode;
+    SkIRect clipSpaceReduceQueryBounds;
+#define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0
+    if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) {
+        SkIRect devIBounds = devBounds->roundOut();
+        devIBounds.offset(clip.origin());
+        if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, devIBounds)) {
+            return false;
+        }
+    } else {
+        clipSpaceReduceQueryBounds = clipSpaceRTIBounds;
+    }
+    GrReducedClip::ReduceClipStack(*clip.clipStack(),
+                                    clipSpaceReduceQueryBounds,
+                                    &elements,
+                                    &genID,
+                                    &initialState,
+                                    &clipSpaceIBounds,
+                                    &requiresAA);
+    if (elements.isEmpty()) {
+        if (GrReducedClip::kAllIn_InitialState == initialState) {
+            if (clipSpaceIBounds == clipSpaceRTIBounds) {
                 return true;
             }
+        } else {
             return false;
         }
-        case GrClip::kClipStack_ClipType: {
-            clipSpaceRTIBounds.offset(clip.origin());
-            SkIRect clipSpaceReduceQueryBounds;
-#define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0
-            if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) {
-                SkIRect devIBounds = devBounds->roundOut();
-                devIBounds.offset(clip.origin());
-                if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, devIBounds)) {
-                    return false;
-                }
-            } else {
-                clipSpaceReduceQueryBounds = clipSpaceRTIBounds;
-            }
-            GrReducedClip::ReduceClipStack(*clip.clipStack(),
-                                            clipSpaceReduceQueryBounds,
-                                            &elements,
-                                            &genID,
-                                            &initialState,
-                                            &clipSpaceIBounds,
-                                            &requiresAA);
-            if (elements.isEmpty()) {
-                if (GrReducedClip::kAllIn_InitialState == initialState) {
-                    if (clipSpaceIBounds == clipSpaceRTIBounds) {
-                        return true;
-                    }
-                } else {
-                    return false;
-                }
-            }
-        } break;
     }
 
-    SkASSERT(kIgnoreClip_StencilClipMode == fClipMode); // TODO: Remove fClipMode.
-
     // An element count of 4 was chosen because of the common pattern in Blink of:
     //   isect RR
     //   diff  RR
@@ -452,13 +424,12 @@ bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder,
     SkIRect scissorSpaceIBounds(clipSpaceIBounds);
     scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset);
     out->fScissorState.set(scissorSpaceIBounds);
-    SkASSERT(kRespectClip_StencilClipMode == fClipMode); // TODO: Remove fClipMode.
     out->fHasStencilClip = true;
     return true;
 }
 
 static bool stencil_element(GrDrawContext* dc,
-                            const GrClip& clip,
+                            const GrFixedClip& clip,
                             const GrUserStencilSettings* ss,
                             const SkMatrix& viewMatrix,
                             const SkClipStack::Element* element) {
@@ -603,7 +574,7 @@ GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context,
             }
 #endif
 
-            GrClip clip(maskSpaceIBounds);
+            GrFixedClip clip(maskSpaceIBounds);
 
             // draw directly into the result with the stencil set to make the pixels affected
             // by the clip shape be non-zero.
@@ -645,7 +616,7 @@ GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context,
             paint.setAntiAlias(element->isAA());
             paint.setCoverageSetOpXPFactory(op, false);
 
-            draw_element(dc.get(), GrClip::WideOpen(), paint, translate, element);
+            draw_element(dc.get(), GrNoClip(), paint, translate, element);
         }
     }
 
@@ -681,7 +652,7 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
         // We set the current clip to the bounds so that our recursive draws are scissored to them.
         SkIRect stencilSpaceIBounds(clipSpaceIBounds);
         stencilSpaceIBounds.offset(clipSpaceToStencilOffset);
-        GrClip clip(stencilSpaceIBounds);
+        GrFixedClip clip(stencilSpaceIBounds);
 
         fDrawTarget->cmmAccess().clearStencilClip(stencilSpaceIBounds,
             GrReducedClip::kAllIn_InitialState == initialState, rt);
@@ -703,7 +674,7 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
 
             bool fillInverted = false;
             // enabled at bottom of loop
-            fClipMode = kIgnoreClip_StencilClipMode;
+            clip.enableStencilClip(false);
 
             // This will be used to determine whether the clip shape can be rendered into the
             // stencil with arbitrary stencil settings.
@@ -801,7 +772,7 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
 
             // now we modify the clip bit by rendering either the clip
             // element directly or a bounding rect of the entire clip.
-            fClipMode = kModifyClip_StencilClipMode;
+            clip.enableStencilClip(true);
             for (GrUserStencilSettings const* const* pass = stencilPasses; *pass; ++pass) {
                 pipelineBuilder.setUserStencil(*pass);
 
@@ -832,7 +803,6 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
             }
         }
     }
-    fClipMode = kRespectClip_StencilClipMode;
     return true;
 }
 
index 2b70f02..ef5fbc1 100644 (file)
@@ -17,7 +17,8 @@
 #include "SkTLList.h"
 #include "SkTypes.h"
 
-class GrClip;
+class GrAppliedClip;
+class GrClipStackClip;
 class GrDrawTarget;
 class GrPathRenderer;
 class GrPathRendererChain;
@@ -26,28 +27,6 @@ class GrTexture;
 class SkPath;
 
 /**
- * Produced by GrClipMaskManager. It provides a set of modifications to the drawing state that
- * are used to create the final GrPipeline for a GrBatch. This is a work in progress. It will
- * eventually encapsulate all mechanisms for modifying the scissor, shaders, and stencil state
- * to implement clipping.
- */
-class GrAppliedClip : public SkNoncopyable {
-public:
-    GrAppliedClip() : fHasStencilClip(false) {}
-    const GrFragmentProcessor* clipCoverageFragmentProcessor() const { return fClipCoverageFP; }
-    const GrScissorState& scissorState() const { return fScissorState; }
-    bool hasStencilClip() const { return fHasStencilClip; }
-
-private:
-    SkAutoTUnref<const GrFragmentProcessor> fClipCoverageFP;
-    GrScissorState                          fScissorState;
-    bool                                    fHasStencilClip;
-    friend class GrClipMaskManager;
-
-    typedef SkNoncopyable INHERITED;
-};
-
-/**
  * 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
  * (8bit) mask. If no anti aliasing is requested it will generate a 1-bit
@@ -57,7 +36,7 @@ private:
  */
 class GrClipMaskManager : SkNoncopyable {
 public:
-    GrClipMaskManager(GrDrawTarget* owner);
+    GrClipMaskManager(GrDrawTarget* owner) : fDrawTarget(owner) {}
 
     /**
      * Creates a clip mask if necessary as a stencil buffer or alpha texture
@@ -65,7 +44,7 @@ public:
      * then the draw can be skipped. devBounds is optional but can help optimize
      * clipping.
      */
-    bool setupClipping(const GrPipelineBuilder&, const GrClip&, const SkRect* devBounds,
+    bool setupClipping(const GrPipelineBuilder&, const GrClipStackClip&, const SkRect* devBounds,
                        GrAppliedClip*);
 
 private:
@@ -85,20 +64,6 @@ private:
                                            const SkMatrix& viewMatrix,
                                            const SkClipStack::Element* element);
 
-    /**
-     * Informs the helper function adjustStencilParams() about how the stencil
-     * buffer clip is being used.
-     */
-    enum StencilClipMode {
-        // Draw to the clip bit of the stencil buffer
-        kModifyClip_StencilClipMode,
-        // Clip against the existing representation of the clip in the high bit
-        // of the stencil buffer.
-        kRespectClip_StencilClipMode,
-        // Neither writing to nor clipping against the clip bit.
-        kIgnoreClip_StencilClipMode,
-    };
-
     // Attempts to install a series of coverage effects to implement the clip. Return indicates
     // whether the element list was successfully converted to processors. *fp may be nullptr even
     // when the function succeeds because all the elements were ignored. TODO: Make clip reduction
@@ -146,7 +111,6 @@ private:
     static const int kMaxAnalyticElements = 4;
 
     GrDrawTarget*   fDrawTarget;    // This is our owning draw target.
-    StencilClipMode fClipMode;
 
     typedef SkNoncopyable INHERITED;
 };
index 4235ae8..39916b9 100644 (file)
@@ -373,7 +373,7 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
             paint.addColorFragmentProcessor(fp);
             paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
             SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
-            drawContext->drawRect(GrClip::WideOpen(), paint, matrix, rect, nullptr);
+            drawContext->drawRect(GrNoClip(), paint, matrix, rect, nullptr);
 
             if (kFlushWrites_PixelOp & pixelOpsFlags) {
                 this->flushSurfaceWrites(surface);
@@ -487,7 +487,7 @@ bool GrContext::readSurfacePixels(GrSurface* src,
                 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
                 sk_sp<GrDrawContext> drawContext(
                                             this->drawContext(sk_ref_sp(temp->asRenderTarget())));
-                drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), rect, nullptr);
+                drawContext->drawRect(GrNoClip(), paint, SkMatrix::I(), rect, nullptr);
                 surfaceToRead.reset(SkRef(temp.get()));
                 left = 0;
                 top = 0;
@@ -559,7 +559,7 @@ bool GrContext::applyGamma(GrRenderTarget* dst, GrTexture* src, SkScalar gamma){
 
     SkRect rect;
     src->getBoundsRect(&rect);
-    drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), rect);
+    drawContext->drawRect(GrNoClip(), paint, SkMatrix::I(), rect);
 
     this->flushSurfaceWrites(dst);
     return true;
index 3db0449..549e5eb 100644 (file)
@@ -301,14 +301,8 @@ void GrDrawContext::drawRect(const GrClip& clip,
     if (width < 0) {
         SkRect rtRect;
         fRenderTarget->getBoundsRect(&rtRect);
-        SkRect clipSpaceRTRect = rtRect;
-        bool checkClip = GrClip::kWideOpen_ClipType != clip.clipType();
-        if (checkClip) {
-            clipSpaceRTRect.offset(SkIntToScalar(clip.origin().fX),
-                                   SkIntToScalar(clip.origin().fY));
-        }
         // Does the clip contain the entire RT?
-        if (!checkClip || clip.quickContains(clipSpaceRTRect)) {
+        if (clip.quickContains(rtRect)) {
             SkMatrix invM;
             if (!viewMatrix.invert(&invM)) {
                 return;
@@ -374,7 +368,7 @@ void GrDrawContext::drawRect(const GrClip& clip,
     this->internalDrawPath(clip, paint, viewMatrix, path, *style);
 }
 
-bool GrDrawContextPriv::drawAndStencilRect(const GrClip& clip,
+bool GrDrawContextPriv::drawAndStencilRect(const GrFixedClip& clip,
                                            const GrUserStencilSettings* ss,
                                            SkRegion::Op op,
                                            bool invert,
@@ -839,7 +833,7 @@ void GrDrawContext::drawPath(const GrClip& clip,
     this->internalDrawPath(clip, paint, viewMatrix, path, style);
 }
 
-bool GrDrawContextPriv::drawAndStencilPath(const GrClip& clip,
+bool GrDrawContextPriv::drawAndStencilPath(const GrFixedClip& clip,
                                            const GrUserStencilSettings* ss,
                                            SkRegion::Op op,
                                            bool invert,
index 7f70f89..2fb98ee 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "GrDrawContext.h"
 
+class GrFixedClip;
 struct GrUserStencilSettings;
 
 /** Class that adds methods to GrDrawContext that are only intended for use internal to Skia.
@@ -17,7 +18,7 @@ struct GrUserStencilSettings;
     data members or virtual methods. */
 class GrDrawContextPriv {
 public:
-    bool drawAndStencilRect(const GrClip&,
+    bool drawAndStencilRect(const GrFixedClip&,
                             const GrUserStencilSettings*,
                             SkRegion::Op op,
                             bool invert,
@@ -25,7 +26,7 @@ public:
                             const SkMatrix& viewMatrix,
                             const SkRect&);
 
-    bool drawAndStencilPath(const GrClip&,
+    bool drawAndStencilPath(const GrFixedClip&,
                             const GrUserStencilSettings*,
                             SkRegion::Op op,
                             bool invert,
index 0db31f2..7d92ef9 100644 (file)
@@ -239,7 +239,7 @@ void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder,
                              GrDrawBatch* batch) {
     // Setup clip
     GrAppliedClip appliedClip;
-    if (!fClipMaskManager->setupClipping(pipelineBuilder, clip, &batch->bounds(), &appliedClip)) {
+    if (!clip.apply(fClipMaskManager, pipelineBuilder, &batch->bounds(), &appliedClip)) {
         return;
     }
 
@@ -317,16 +317,14 @@ void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder,
 
     // Setup clip
     GrAppliedClip appliedClip;
-    if (!fClipMaskManager->setupClipping(pipelineBuilder, clip, nullptr, &appliedClip)) {
+    if (!clip.apply(fClipMaskManager, pipelineBuilder, nullptr, &appliedClip)) {
         return;
     }
     // TODO: respect fClipBatchToBounds if we ever start computing bounds here.
 
-    GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
-    if (appliedClip.clipCoverageFragmentProcessor()) {
-        arfps.set(&pipelineBuilder);
-        arfps.addCoverageFragmentProcessor(appliedClip.clipCoverageFragmentProcessor());
-    }
+    // Coverage AA does not make sense when rendering to the stencil buffer. The caller should never
+    // attempt this in a situation that would require coverage AA.
+    SkASSERT(!appliedClip.clipCoverageFragmentProcessor());
 
     GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
     GrStencilAttachment* stencilAttachment = fResourceProvider->attachStencilAttachment(rt);
@@ -378,7 +376,7 @@ void GrDrawTarget::clear(const SkIRect* rect,
         SkAutoTUnref<GrDrawBatch> batch(
                 GrRectBatchFactory::CreateNonAAFill(color, SkMatrix::I(), scalarRect,
                                                     nullptr, nullptr));
-        this->drawBatch(pipelineBuilder, GrClip::WideOpen(), batch);
+        this->drawBatch(pipelineBuilder, GrNoClip(), batch);
     } else {
         GrBatch* batch = new GrClearBatch(*rect, color, renderTarget);
         this->recordBatch(batch);
index 3c4769b..a91ba8a 100644 (file)
@@ -119,7 +119,7 @@ static GrTexture* copy_on_gpu(GrTexture* inputTexture, const SkIRect* subset,
     }
 
     SkRect dstRect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight));
-    drawContext->fillRectToRect(GrClip::WideOpen(), paint, SkMatrix::I(), dstRect, localRect);
+    drawContext->fillRectToRect(GrNoClip(), paint, SkMatrix::I(), dstRect, localRect);
     return copy.release();
 }
 
index 14ebf3c..4215602 100644 (file)
@@ -43,7 +43,7 @@ static bool convert_texture(GrTexture* src, GrDrawContext* dst, int dstW, int ds
     GrPaint paint;
     paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
     paint.addColorFragmentProcessor(fp);
-    dst->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), SkRect::MakeIWH(dstW, dstH));
+    dst->drawRect(GrNoClip(), paint, SkMatrix::I(), SkRect::MakeIWH(dstW, dstH));
     return true;
 }
 
index 970644d..a7281da 100644 (file)
@@ -147,7 +147,7 @@ sk_sp<GrTexture> GrYUVProvider::refAsTexture(GrContext* ctx,
     const SkRect r = SkRect::MakeIWH(yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth,
             yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
 
-    drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), r);
+    drawContext->drawRect(GrNoClip(), paint, SkMatrix::I(), r);
 
     return drawContext->asTexture();
 }
index a0f81e7..a5af472 100644 (file)
@@ -341,7 +341,7 @@ void SkGpuDevice::prepareDraw(const SkDraw& draw) {
 
     SkASSERT(draw.fClipStack && draw.fClipStack == fClipStack);
 
-    fClip.setClipStack(fClipStack, &this->getOrigin());
+    fClip.reset(fClipStack, &this->getOrigin());
 }
 
 GrRenderTarget* SkGpuDevice::accessRenderTarget() {
index 1e02567..e940159 100644 (file)
@@ -153,7 +153,7 @@ private:
 
     SkAutoTUnref<const SkClipStack> fClipStack;
     SkIPoint                        fClipOrigin;
-    GrClip                          fClip;;
+    GrClipStackClip                 fClip;
     // remove when our clients don't rely on accessBitmap()
     SkBitmap                        fLegacyBitmap;
     bool                            fOpaque;
index 6b43606..99a4884 100644 (file)
@@ -232,7 +232,7 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
             break;
         }
 
-        readDrawContext->fillRectToRect(GrClip::WideOpen(),
+        readDrawContext->fillRectToRect(GrNoClip(),
                                         paint1,
                                         SkMatrix::I(),
                                         kDstRect,
@@ -249,7 +249,7 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
             failed = true;
             break;
         }
-        tempDrawContext->fillRectToRect(GrClip::WideOpen(),
+        tempDrawContext->fillRectToRect(GrNoClip(),
                                         paint2,
                                         SkMatrix::I(),
                                         kDstRect,
@@ -264,7 +264,7 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
             break;
         }
 
-        readDrawContext->fillRectToRect(GrClip::WideOpen(),
+        readDrawContext->fillRectToRect(GrNoClip(),
                                         paint3,
                                         SkMatrix::I(),
                                         kDstRect,
index 339dee7..2c24058 100644 (file)
@@ -269,7 +269,7 @@ sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx , SkYUVColorSpace
 
     const SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
 
-    drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), rect);
+    drawContext->drawRect(GrNoClip(), paint, SkMatrix::I(), rect);
     ctx->flushSurfaceWrites(drawContext->accessRenderTarget());
     return sk_make_sp<SkImage_Gpu>(width, height, kNeedNewImageUniqueID,
                                    kOpaque_SkAlphaType,
index 5660afd..246cf6e 100644 (file)
@@ -40,8 +40,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrClipBounds, reporter, ctxInfo) {
     REPORTER_ASSERT(reporter, isIntersectionOfRects);
 
     // wrap the SkClipStack in a GrClip
-    GrClip clipData;
-    clipData.setClipStack(&stack);
+    GrClipStackClip clipData(&stack);
 
     SkIRect devGrClipBound;
     clipData.getConservativeBounds(kXSize, kYSize,
index 62ad6e2..a3eb489 100644 (file)
@@ -239,11 +239,12 @@ static void test_path(GrDrawTarget* dt, GrRenderTarget* rt, GrResourceProvider*
     pipelineBuilder.setXPFactory(
         GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
     pipelineBuilder.setRenderTarget(rt);
+    GrNoClip noClip;
     GrStyle style(SkStrokeRec::kFill_InitStyle);
     GrPathRenderer::DrawPathArgs args;
     args.fTarget = dt;
     args.fPipelineBuilder = &pipelineBuilder;
-    args.fClip = &GrClip::WideOpen();
+    args.fClip = &noClip;
     args.fResourceProvider = rp;
     args.fColor = GrColor_WHITE;
     args.fViewMatrix = &SkMatrix::I();
index 874567d..a301c74 100644 (file)
@@ -168,8 +168,7 @@ void SkGpuDevice::drawTexture(GrTexture* tex, const SkRect& dst, const SkPaint&
 
     grPaint.addColorTextureProcessor(tex, textureMat);
 
-    GrClip clip;
-    fDrawContext->drawRect(clip, grPaint, mat, dst);
+    fDrawContext->drawRect(GrNoClip(), grPaint, mat, dst);
 }
 
 
@@ -260,8 +259,11 @@ void GrDrawContextPriv::testingOnly_drawBatch(const GrPipelineBuilder& pipelineB
     SkDEBUGCODE(fDrawContext->validate();)
     GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::testingOnly_drawBatch");
 
-    const GrClip& drawClip = clip ? *clip : GrClip::WideOpen();
-    fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, drawClip, batch);
+    if (clip) {
+        fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, *clip, batch);
+    } else {
+        fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, GrNoClip(), batch);
+    }
 }
 
 #undef ASSERT_SINGLE_OWNER