Reland "GrClips provided as pointers to GrRTC"

This reverts commit 074414fed53efcab7f33b06454958707419e37d8.

Reason for revert: updated to guard against nullptr before calling
quickContains(rrect).

Original change's description:
> Revert "GrClips provided as pointers to GrRTC"
>
> This reverts commit 226b689471a0fbb7400bc166032458278957541b.
>
> Reason for revert: Breaks Android roller
>
> Original change's description:
> > GrClips provided as pointers to GrRTC
> >
> > A null clip represents no high-level clipping is necessary (the implicit
> > clip to the render target's logical dimensions is fine).
> >
> > This also removes GrNoClip and GrFixedClip::Disabled() since they are
> > replaced with just nullptr.
> >
> > By allowing nullptr to represent no intended clipping, it makes it easier
> > to require GrClip and GrAppliedClip objects to know about the dimensions
> > of the device. If we required a non-null clip object to represent no
> > clipping, we'd have to have an instance for each device based on its
> > size and that just became cumbersome.
> >
> > Bug: skia:10205
> > Change-Id: Ie30cc71820b92d99356d393a4c98c8677082e761
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/290539
> > Commit-Queue: Michael Ludwig <michaelludwig@google.com>
> > Reviewed-by: Brian Salomon <bsalomon@google.com>
>
> TBR=bsalomon@google.com,csmartdalton@google.com,michaelludwig@google.com
>
> Change-Id: I42c4828bcf016ee3d30d5c20b771be96e125817b
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: skia:10205
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/292856
> Reviewed-by: Weston Tracey <westont@google.com>
> Commit-Queue: Weston Tracey <westont@google.com>

TBR=bsalomon@google.com,csmartdalton@google.com,michaelludwig@google.com,westont@google.com

# Not skipping CQ checks because this is a reland.

Bug: skia:10205
Change-Id: I5715a4de3b7c8847b73020dc4937d3816d879803
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/292876
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 24755d1..9677ffe 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -81,11 +81,11 @@
             , fRenderTargetContext(renderTargetContext)
             , fGlyphPainter{*renderTargetContext} {}
 
-    void addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) override {
+    void addDrawOp(const GrClip* clip, std::unique_ptr<GrAtlasTextOp> op) override {
         fRenderTargetContext->addDrawOp(clip, std::move(op));
     }
 
-    void drawShape(const GrClip& clip,
+    void drawShape(const GrClip* clip,
                    const SkPaint& paint,
                    const SkMatrixProvider& matrixProvider,
                    const GrStyledShape& shape) override {
@@ -448,7 +448,7 @@
     return fOpsTask.get();
 }
 
-void GrRenderTargetContext::drawGlyphRunList(const GrClip& clip,
+void GrRenderTargetContext::drawGlyphRunList(const GrClip* clip,
                                              const SkMatrixProvider& matrixProvider,
                                              const SkGlyphRunList& blob) {
     ASSERT_SINGLE_OWNER
@@ -544,7 +544,7 @@
             SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
             GrPaint paint;
             clear_to_grpaint(color, &paint);
-            this->addDrawOp(GrFixedClip::Disabled(),
+            this->addDrawOp(nullptr,
                             GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
                                                         rtRect));
         } else {
@@ -556,7 +556,7 @@
             GrPaint paint;
             clear_to_grpaint(color, &paint);
 
-            this->addDrawOp(GrFixedClip::Disabled(),
+            this->addDrawOp(nullptr,
                             GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
                                                         SkRect::Make(scissorState.rect())));
         } else {
@@ -572,7 +572,7 @@
     }
 }
 
-void GrRenderTargetContext::drawPaint(const GrClip& clip,
+void GrRenderTargetContext::drawPaint(const GrClip* clip,
                                       GrPaint&& paint,
                                       const SkMatrix& viewMatrix) {
     // Start with the render target, since that is the maximum content we could possibly fill.
@@ -623,8 +623,13 @@
     return true;
 }
 
+static SkIRect get_clip_bounds(const GrRenderTargetContext* rtc, const GrClip* clip) {
+    return clip ? clip->getConservativeBounds(rtc->width(), rtc->height())
+                : SkIRect::MakeWH(rtc->width(), rtc->height());
+}
+
 GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimization(
-        const GrClip& clip, const SkPMColor4f* constColor,
+        const GrClip* clip, const SkPMColor4f* constColor,
         const GrUserStencilSettings* stencilSettings, GrAA* aa, DrawQuad* quad) {
     // Optimization requirements:
     // 1. kDiscard applies when clip bounds and quad bounds do not intersect
@@ -685,8 +690,8 @@
     // regular draws so that if we fully cover the render target, that can stop being anti-aliased.
     GrAA clipAA = stencilSettings ? *aa : GrAA::kNo;
     bool axisAlignedClip = true;
-    if (!clip.quickContains(rtRect)) {
-        if (!clip.isRRect(rtRect, &clipRRect, &clipAA)) {
+    if (clip && !clip->quickContains(rtRect)) {
+        if (!clip->isRRect(rtRect, &clipRRect, &clipAA)) {
             axisAlignedClip = false;
         }
     }
@@ -752,7 +757,7 @@
                 // we can draw the rrect directly and ignore the edge flags
                 GrPaint paint;
                 clear_to_grpaint(*constColor, &paint);
-                this->drawRRect(GrFixedClip::Disabled(), std::move(paint), clipAA, SkMatrix::I(),
+                this->drawRRect(nullptr, std::move(paint), clipAA, SkMatrix::I(),
                                 clipRRect, GrStyle::SimpleFill());
                 return QuadOptimization::kSubmitted;
             } else {
@@ -764,7 +769,7 @@
     }
 
     // Crop the quad to the conservative bounds of the clip.
-    SkRect clipBounds = SkRect::Make(clip.getConservativeBounds(rtRect.width(), rtRect.height()));
+    SkRect clipBounds = SkRect::Make(get_clip_bounds(this, clip));
 
     // One final check for discarding, since we may have gone here directly due to a complex clip
     if (!clipBounds.intersects(drawBounds)) {
@@ -779,7 +784,7 @@
     return QuadOptimization::kCropped;
 }
 
-void GrRenderTargetContext::drawFilledQuad(const GrClip& clip,
+void GrRenderTargetContext::drawFilledQuad(const GrClip* clip,
                                            GrPaint&& paint,
                                            GrAA aa,
                                            DrawQuad* quad,
@@ -802,8 +807,7 @@
     QuadOptimization opt = this->attemptQuadOptimization(clip, constColor, ss, &aa, quad);
     if (opt >= QuadOptimization::kClipApplied) {
         // These optimizations require caller to add an op themselves
-        const GrClip& finalClip = opt == QuadOptimization::kClipApplied ? GrFixedClip::Disabled()
-                                                                        : clip;
+        const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip;
         GrAAType aaType = ss ? (aa == GrAA::kYes ? GrAAType::kMSAA : GrAAType::kNone)
                              : this->chooseAAType(aa);
         this->addDrawOp(finalClip, GrFillRectOp::Make(fContext, std::move(paint), aaType,
@@ -812,7 +816,7 @@
     // All other optimization levels were completely handled inside attempt(), so no extra op needed
 }
 
-void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip,
+void GrRenderTargetContext::drawTexturedQuad(const GrClip* clip,
                                              GrSurfaceProxyView proxyView,
                                              SkAlphaType srcAlphaType,
                                              sk_sp<GrColorSpaceXform> textureXform,
@@ -837,8 +841,7 @@
     SkASSERT(opt != QuadOptimization::kSubmitted);
     if (opt != QuadOptimization::kDiscarded) {
         // And the texture op if not discarded
-        const GrClip& finalClip = opt == QuadOptimization::kClipApplied ? GrFixedClip::Disabled()
-                                                                        : clip;
+        const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip;
         GrAAType aaType = this->chooseAAType(aa);
         auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
         auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
@@ -852,7 +855,7 @@
     }
 }
 
-void GrRenderTargetContext::drawRect(const GrClip& clip,
+void GrRenderTargetContext::drawRect(const GrClip* clip,
                                      GrPaint&& paint,
                                      GrAA aa,
                                      const SkMatrix& viewMatrix,
@@ -897,7 +900,7 @@
                                      GrStyledShape(rect, *style));
 }
 
-void GrRenderTargetContext::drawQuadSet(const GrClip& clip, GrPaint&& paint, GrAA aa,
+void GrRenderTargetContext::drawQuadSet(const GrClip* clip, GrPaint&& paint, GrAA aa,
                                         const SkMatrix& viewMatrix, const QuadSetEntry quads[],
                                         int cnt) {
     GrAAType aaType = this->chooseAAType(aa);
@@ -970,9 +973,8 @@
         // Configure the paint to have no impact on the color buffer
         GrPaint paint;
         paint.setXPFactory(GrDisableColorXPFactory::Get());
-        this->addDrawOp(GrFixedClip::Disabled(),
-                        GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
-                                                    rect, ss));
+        this->addDrawOp(nullptr, GrFillRectOp::MakeNonAARect(fContext, std::move(paint),
+                                                             SkMatrix::I(), rect, ss));
     } else {
         GrScissorState scissorState;
         if (scissor) {
@@ -988,7 +990,7 @@
     }
 }
 
-void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip,
+void GrRenderTargetContextPriv::stencilPath(const GrHardClip* clip,
                                             GrAA doStencilMSAA,
                                             const SkMatrix& viewMatrix,
                                             sk_sp<const GrPath> path) {
@@ -1006,12 +1008,17 @@
     // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
     SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
 
-    // Setup clip
+    // Setup clip and reject offscreen paths; we do this explicitly instead of relying on addDrawOp
+    // because GrStencilPathOp is not a draw op as its state depends directly on the choices made
+    // during this clip application.
     GrAppliedHardClip appliedClip;
-    if (!clip.apply(fRenderTargetContext->width(), fRenderTargetContext->height(), &appliedClip,
-                    &bounds)) {
+    if (clip && !clip->apply(fRenderTargetContext->width(), fRenderTargetContext->height(),
+                             &appliedClip, &bounds)) {
         return;
     }
+    // else see FIXME above; we'd normally want to check path bounds with render target bounds,
+    // but as it is, we're just using the full render target so intersecting the two bounds would
+    // do nothing.
 
     std::unique_ptr<GrOp> op = GrStencilPathOp::Make(fRenderTargetContext->fContext,
                                                      viewMatrix,
@@ -1028,7 +1035,7 @@
     fRenderTargetContext->addOp(std::move(op));
 }
 
-void GrRenderTargetContext::drawTextureSet(const GrClip& clip, TextureSetEntry set[],
+void GrRenderTargetContext::drawTextureSet(const GrClip* clip, TextureSetEntry set[],
                                            int cnt, int proxyRunCnt,
                                            GrSamplerState::Filter filter, SkBlendMode mode,
                                            GrAA aa, SkCanvas::SrcRectConstraint constraint,
@@ -1050,7 +1057,7 @@
                                   mode, aaType, constraint, viewMatrix, std::move(texXform));
 }
 
-void GrRenderTargetContext::drawVertices(const GrClip& clip,
+void GrRenderTargetContext::drawVertices(const GrClip* clip,
                                          GrPaint&& paint,
                                          const SkMatrixProvider& matrixProvider,
                                          sk_sp<SkVertices> vertices,
@@ -1074,7 +1081,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrRenderTargetContext::drawAtlas(const GrClip& clip,
+void GrRenderTargetContext::drawAtlas(const GrClip* clip,
                                       GrPaint&& paint,
                                       const SkMatrix& viewMatrix,
                                       int spriteCount,
@@ -1096,7 +1103,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrRenderTargetContext::drawRRect(const GrClip& origClip,
+void GrRenderTargetContext::drawRRect(const GrClip* origClip,
                                       GrPaint&& paint,
                                       GrAA aa,
                                       const SkMatrix& viewMatrix,
@@ -1112,8 +1119,7 @@
        return;
     }
 
-    GrNoClip noclip;
-    const GrClip* clip = &origClip;
+    const GrClip* clip = origClip;
 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
     // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
     // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
@@ -1122,9 +1128,9 @@
     // can be ignored. We'd prefer to fix this in the framework by removing the clips calls. This
     // only works for filled rrects since the stroke width outsets beyond the rrect itself.
     SkRRect devRRect;
-    if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.transform(viewMatrix, &devRRect) &&
-        clip->quickContains(devRRect)) {
-        clip = &noclip;
+    if (clip && stroke.getStyle() == SkStrokeRec::kFill_Style &&
+        rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
+        clip = nullptr;
     }
 #endif
     SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
@@ -1153,12 +1159,12 @@
                 fContext, std::move(paint), viewMatrix, rrect, stroke, this->caps()->shaderCaps());
     }
     if (op) {
-        this->addDrawOp(*clip, std::move(op));
+        this->addDrawOp(clip, std::move(op));
         return;
     }
 
     assert_alive(paint);
-    this->drawShapeUsingPathRenderer(*clip, std::move(paint), aa, viewMatrix,
+    this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
                                      GrStyledShape(rrect, style));
 }
 
@@ -1171,7 +1177,7 @@
     return result;
 }
 
-bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
+bool GrRenderTargetContext::drawFastShadow(const GrClip* clip,
                                            const SkMatrix& viewMatrix,
                                            const SkPath& path,
                                            const SkDrawShadowRec& rec) {
@@ -1366,7 +1372,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
+bool GrRenderTargetContext::drawFilledDRRect(const GrClip* clip,
                                              GrPaint&& paint,
                                              GrAA aa,
                                              const SkMatrix& viewMatrix,
@@ -1455,7 +1461,7 @@
     return true;
 }
 
-void GrRenderTargetContext::drawDRRect(const GrClip& clip,
+void GrRenderTargetContext::drawDRRect(const GrClip* clip,
                                        GrPaint&& paint,
                                        GrAA aa,
                                        const SkMatrix& viewMatrix,
@@ -1486,7 +1492,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrRenderTargetContext::drawRegion(const GrClip& clip,
+void GrRenderTargetContext::drawRegion(const GrClip* clip,
                                        GrPaint&& paint,
                                        GrAA aa,
                                        const SkMatrix& viewMatrix,
@@ -1522,7 +1528,7 @@
     this->addDrawOp(clip, std::move(op));
 }
 
-void GrRenderTargetContext::drawOval(const GrClip& clip,
+void GrRenderTargetContext::drawOval(const GrClip* clip,
                                      GrPaint&& paint,
                                      GrAA aa,
                                      const SkMatrix& viewMatrix,
@@ -1583,7 +1589,7 @@
             GrStyledShape(SkRRect::MakeOval(oval), SkPathDirection::kCW, 2, false, style));
 }
 
-void GrRenderTargetContext::drawArc(const GrClip& clip,
+void GrRenderTargetContext::drawArc(const GrClip* clip,
                                     GrPaint&& paint,
                                     GrAA aa,
                                     const SkMatrix& viewMatrix,
@@ -1622,7 +1628,7 @@
             GrStyledShape::MakeArc(oval, startAngle, sweepAngle, useCenter, style));
 }
 
-void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
+void GrRenderTargetContext::drawImageLattice(const GrClip* clip,
                                              GrPaint&& paint,
                                              const SkMatrix& viewMatrix,
                                              GrSurfaceProxyView view,
@@ -1745,7 +1751,7 @@
                 callback(context, nullptr);
                 return;
             }
-            tempRTC->drawTexture(GrNoClip(), std::move(texProxyView), this->colorInfo().alphaType(),
+            tempRTC->drawTexture(nullptr, std::move(texProxyView), this->colorInfo().alphaType(),
                                  GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
                                  SK_PMColor4fWHITE, srcRectToDraw,
                                  SkRect::MakeWH(srcRect.width(), srcRect.height()), GrAA::kNo,
@@ -1969,7 +1975,7 @@
                 callback(context, nullptr);
                 return;
             }
-            tempRTC->drawTexture(GrNoClip(), std::move(srcView), this->colorInfo().alphaType(),
+            tempRTC->drawTexture(nullptr, std::move(srcView), this->colorInfo().alphaType(),
                                  GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
                                  SK_PMColor4fWHITE, srcRectToDraw, SkRect::Make(srcRect.size()),
                                  GrAA::kNo, GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
@@ -2019,7 +2025,7 @@
     auto yFP = GrColorMatrixFragmentProcessor::Make(yM, false, true, false);
     yPaint.addColorFragmentProcessor(std::move(yFP));
     yPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-    yRTC->fillRectToRect(GrNoClip(), std::move(yPaint), GrAA::kNo, SkMatrix::I(),
+    yRTC->fillRectToRect(nullptr, std::move(yPaint), GrAA::kNo, SkMatrix::I(),
                          dstRectY, dstRectY);
     if (!doSynchronousRead) {
         yTransfer = yRTC->transferPixels(GrColorType::kAlpha_8,
@@ -2041,7 +2047,7 @@
     auto uFP = GrColorMatrixFragmentProcessor::Make(uM, false, true, false);
     uPaint.addColorFragmentProcessor(std::move(uFP));
     uPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-    uRTC->fillRectToRect(GrNoClip(), std::move(uPaint), GrAA::kNo, SkMatrix::I(),
+    uRTC->fillRectToRect(nullptr, std::move(uPaint), GrAA::kNo, SkMatrix::I(),
                          dstRectUV, dstRectUV);
     if (!doSynchronousRead) {
         uTransfer = uRTC->transferPixels(GrColorType::kAlpha_8,
@@ -2063,7 +2069,7 @@
     auto vFP = GrColorMatrixFragmentProcessor::Make(vM, false, true, false);
     vPaint.addColorFragmentProcessor(std::move(vFP));
     vPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-    vRTC->fillRectToRect(GrNoClip(), std::move(vPaint), GrAA::kNo, SkMatrix::I(),
+    vRTC->fillRectToRect(nullptr, std::move(vPaint), GrAA::kNo, SkMatrix::I(),
                          dstRectUV, dstRectUV);
     if (!doSynchronousRead) {
         vTransfer = vRTC->transferPixels(GrColorType::kAlpha_8,
@@ -2197,7 +2203,7 @@
     return true;
 }
 
-void GrRenderTargetContext::drawPath(const GrClip& clip,
+void GrRenderTargetContext::drawPath(const GrClip* clip,
                                      GrPaint&& paint,
                                      GrAA aa,
                                      const SkMatrix& viewMatrix,
@@ -2213,7 +2219,7 @@
     this->drawShape(clip, std::move(paint), aa, viewMatrix, shape);
 }
 
-void GrRenderTargetContext::drawShape(const GrClip& clip,
+void GrRenderTargetContext::drawShape(const GrClip* clip,
                                       GrPaint&& paint,
                                       GrAA aa,
                                       const SkMatrix& viewMatrix,
@@ -2271,7 +2277,7 @@
                                      /* attempt fallback */ false);
 }
 
-bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
+bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip* clip,
                                                    const GrUserStencilSettings* ss,
                                                    SkRegion::Op op,
                                                    bool invert,
@@ -2302,8 +2308,7 @@
     GrAAType aaType = fRenderTargetContext->chooseAAType(aa);
     bool hasUserStencilSettings = !ss->isUnused();
 
-    SkIRect clipConservativeBounds = clip.getConservativeBounds(fRenderTargetContext->width(),
-                                                                fRenderTargetContext->height());
+    SkIRect clipConservativeBounds = get_clip_bounds(fRenderTargetContext, clip);
 
     GrPaint paint;
     paint.setCoverageSetOpXPFactory(op, invert);
@@ -2332,7 +2337,7 @@
                                       std::move(paint),
                                       ss,
                                       fRenderTargetContext,
-                                      &clip,
+                                      clip,
                                       &clipConservativeBounds,
                                       &viewMatrix,
                                       &shape,
@@ -2354,7 +2359,7 @@
     return fRenderTargetContext->asSurfaceProxy()->isBudgeted();
 }
 
-void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip,
+void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip* clip,
                                                        GrPaint&& paint,
                                                        GrAA aa,
                                                        const SkMatrix& viewMatrix,
@@ -2376,7 +2381,7 @@
         return;
     }
 
-    SkIRect clipConservativeBounds = clip.getConservativeBounds(this->width(), this->height());
+    SkIRect clipConservativeBounds = get_clip_bounds(this, clip);
 
     GrStyledShape tempShape;
     GrAAType aaType = this->chooseAAType(aa);
@@ -2441,7 +2446,7 @@
                                       std::move(paint),
                                       &GrUserStencilSettings::kUnused,
                                       this,
-                                      &clip,
+                                      clip,
                                       &clipConservativeBounds,
                                       &viewMatrix,
                                       canDrawArgs.fShape,
@@ -2481,7 +2486,7 @@
             std::move(op), GrTextureResolveManager(this->drawingManager()), *this->caps());
 }
 
-void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op,
+void GrRenderTargetContext::addDrawOp(const GrClip* clip, std::unique_ptr<GrDrawOp> op,
                                       const std::function<WillAddOpFn>& willAddFn) {
     ASSERT_SINGLE_OWNER
     if (fContext->priv().abandoned()) {
@@ -2504,7 +2509,20 @@
         this->setNeedsStencil(usesHWAA);
     }
 
-    if (!clip.apply(fContext, this, usesHWAA, usesUserStencilBits, &appliedClip, &bounds)) {
+    bool skipDraw = false;
+    if (clip) {
+        // Have a complex clip, so defer to its early clip culling
+        if (!clip->apply(fContext, this, usesHWAA, usesUserStencilBits, &appliedClip, &bounds)) {
+            skipDraw = true;
+        }
+    } else {
+        // No clipping, so just clip the bounds against the logical render target dimensions
+        if (!bounds.intersect(this->asSurfaceProxy()->getBoundsRect())) {
+            skipDraw = true;
+        }
+    }
+
+    if (skipDraw) {
         fContext->priv().opMemoryPool()->release(std::move(op));
         return;
     }
@@ -2541,7 +2559,7 @@
                        GrTextureResolveManager(this->drawingManager()), *this->caps());
 }
 
-bool GrRenderTargetContext::setupDstProxyView(const GrClip& clip, const GrOp& op,
+bool GrRenderTargetContext::setupDstProxyView(const GrClip* clip, const GrOp& op,
                                               GrXferProcessor::DstProxyView* dstProxyView) {
     // If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we
     // don't actually have a VkImage to make a copy of. Additionally we don't have the power to
@@ -2563,7 +2581,7 @@
 
     SkIRect copyRect = SkIRect::MakeSize(this->asSurfaceProxy()->dimensions());
 
-    SkIRect clippedRect = clip.getConservativeBounds(this->width(), this->height());
+    SkIRect clippedRect = get_clip_bounds(this, clip);
     SkRect opBounds = op.bounds();
     // If the op has aa bloating or is a infinitely thin geometry (hairline) outset the bounds by
     // 0.5 pixels.
@@ -2633,7 +2651,7 @@
     paint.addColorFragmentProcessor(std::move(fp));
 
     this->fillRectToRect(
-            GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+            nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
             SkRect::MakeXYWH(clippedDstPoint.fX, clippedDstPoint.fY, clippedSrcRect.width(),
                              clippedSrcRect.height()),
             SkRect::Make(clippedSrcRect));