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/bench/BulkRectBench.cpp b/bench/BulkRectBench.cpp
index 71f9c3b..1e81df8 100644
--- a/bench/BulkRectBench.cpp
+++ b/bench/BulkRectBench.cpp
@@ -12,7 +12,6 @@
 #include "include/gpu/GrContext.h"
 #include "include/utils/SkRandom.h"
 
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/SkGr.h"
 
@@ -150,7 +149,7 @@
         SkSimpleMatrixProvider matrixProvider(view);
         GrPaint grPaint;
         SkPaintToGrPaint(context, rtc->colorInfo(), paint, matrixProvider, &grPaint);
-        rtc->drawQuadSet(GrNoClip(), std::move(grPaint), GrAA::kYes, view, batch, kRectCount);
+        rtc->drawQuadSet(nullptr, std::move(grPaint), GrAA::kYes, view, batch, kRectCount);
     }
 
     void drawSolidColorsRef(SkCanvas* canvas) const {
diff --git a/gm/clockwise.cpp b/gm/clockwise.cpp
index d4037f2..480252b 100644
--- a/gm/clockwise.cpp
+++ b/gm/clockwise.cpp
@@ -23,7 +23,6 @@
 #include "include/private/SkColorData.h"
 #include "src/gpu/GrBuffer.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrColorSpaceXform.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrGeometryProcessor.h"
@@ -257,7 +256,7 @@
         topLeftRTC->clear(SK_PMColor4fTRANSPARENT);
         topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
         topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
-        rtc->drawTexture(GrNoClip(), topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
+        rtc->drawTexture(nullptr, topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
                          GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver, SK_PMColor4fWHITE,
                          {0, 0, 100, 200}, {100, 0, 200, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
                          SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
@@ -272,7 +271,7 @@
         topLeftRTC->clear(SK_PMColor4fTRANSPARENT);
         topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
         topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
-        rtc->drawTexture(GrNoClip(), topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
+        rtc->drawTexture(nullptr, topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
                          GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver, SK_PMColor4fWHITE,
                          {0, 0, 100, 200}, {200, 0, 300, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
                          SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
diff --git a/gm/drawquadset.cpp b/gm/drawquadset.cpp
index fc086ce..fb24f9d 100644
--- a/gm/drawquadset.cpp
+++ b/gm/drawquadset.cpp
@@ -25,7 +25,6 @@
 #include "include/gpu/GrContext.h"
 #include "include/private/GrTypesPriv.h"
 #include "src/core/SkMatrixProvider.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrPaint.h"
 #include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/SkGr.h"
@@ -87,7 +86,7 @@
                 SkSimpleMatrixProvider matrixProvider(view);
                 GrPaint grPaint;
                 SkPaintToGrPaint(context, rtc->colorInfo(), paint, matrixProvider, &grPaint);
-                rtc->fillRectWithEdgeAA(GrNoClip(), std::move(grPaint), GrAA::kYes,
+                rtc->fillRectWithEdgeAA(nullptr, std::move(grPaint), GrAA::kYes,
                                         static_cast<GrQuadAAFlags>(aa), view, tile);
             } else {
                 // Fallback to solid color on raster backend since the public API only has color
diff --git a/gm/gpu_blur_utils.cpp b/gm/gpu_blur_utils.cpp
index cbf818b..60dcd22 100644
--- a/gm/gpu_blur_utils.cpp
+++ b/gm/gpu_blur_utils.cpp
@@ -9,7 +9,6 @@
 
 #include "include/effects/SkGradientShader.h"
 #include "src/core/SkGpuBlurUtils.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrStyle.h"
 #include "src/gpu/SkGr.h"
@@ -153,7 +152,7 @@
                 paint.addColorFragmentProcessor(std::move(fp));
                 static constexpr float kAlpha = 0.2f;
                 paint.setColor4f({kAlpha, kAlpha, kAlpha, kAlpha});
-                rtc->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, m, SkRect::Make(testArea));
+                rtc->drawRect(nullptr, std::move(paint), GrAA::kNo, m, SkRect::Make(testArea));
             }
             // If we're in ref mode we will create a temp image that has the original image
             // tiled into it and then do a clamp blur with adjusted params that should produce
@@ -174,7 +173,7 @@
                                                       SkRect::Make(srcRect), caps);
                 GrPaint paint;
                 paint.addColorFragmentProcessor(std::move(fp));
-                refSrc->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+                refSrc->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                  SkRect::Make(refRect.size()));
             }
             // Do a blur for each dstRect in the set over our testArea-sized background.
@@ -209,7 +208,7 @@
                                                                            SkBlendMode::kSrcOver);
                     paint.addColorFragmentProcessor(std::move(fp));
                     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-                    rtc->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, m,
+                    rtc->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, m,
                                         SkRect::Make(dstRect), SkRect::Make(blurView.dimensions()));
                 }
                 // Show the outline of the dst rect. Mostly for kDecal but also allows visual
@@ -223,7 +222,7 @@
                     stroke.setStrokeWidth(1.f);
                     GrStyle style(stroke);
                     auto dstR = SkRect::Make(dstRect).makeOutset(0.5f, 0.5f);
-                    rtc->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, m, dstR, &style);
+                    rtc->drawRect(nullptr, std::move(paint), GrAA::kNo, m, dstR, &style);
                 }
             }
             // Show the rect that's being blurred.
@@ -236,7 +235,7 @@
                 stroke.setStrokeWidth(1.f);
                 GrStyle style(stroke);
                 auto srcR = SkRect::Make(srcRect).makeOutset(0.5f, 0.5f);
-                rtc->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, m, srcR, &style);
+                rtc->drawRect(nullptr, std::move(paint), GrAA::kNo, m, srcR, &style);
             }
             trans.fX += testArea.width() + kPad;
         }
diff --git a/gm/sample_matrix_constant.cpp b/gm/sample_matrix_constant.cpp
index 36a3be9..9f4813b 100644
--- a/gm/sample_matrix_constant.cpp
+++ b/gm/sample_matrix_constant.cpp
@@ -9,7 +9,6 @@
 #include "include/effects/SkGradientShader.h"
 #include "src/core/SkMatrixProvider.h"
 #include "src/gpu/GrBitmapTextureMaker.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrRenderTargetContextPriv.h"
 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
@@ -72,7 +71,7 @@
 
         GrPaint paint;
         paint.addCoverageFragmentProcessor(std::move(fp));
-        rtCtx->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
+        rtCtx->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
     }
 
     {
@@ -93,7 +92,6 @@
         auto fp = std::unique_ptr<GrFragmentProcessor>(
                 new SampleMatrixConstantEffect(std::move(gradientFP)));
         paint.addCoverageFragmentProcessor(std::move(fp));
-        rtCtx->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
+        rtCtx->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
     }
 }
-
diff --git a/gm/sample_matrix_variable.cpp b/gm/sample_matrix_variable.cpp
index 3b34502..999c48e 100644
--- a/gm/sample_matrix_variable.cpp
+++ b/gm/sample_matrix_variable.cpp
@@ -9,7 +9,6 @@
 #include "include/effects/SkGradientShader.h"
 #include "src/core/SkMatrixProvider.h"
 #include "src/gpu/GrBitmapTextureMaker.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrRenderTargetContextPriv.h"
 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
@@ -88,7 +87,7 @@
 
         GrPaint paint;
         paint.addCoverageFragmentProcessor(std::move(fp));
-        rtCtx->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
+        rtCtx->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
     }
 
     {
@@ -110,6 +109,6 @@
         auto fp = std::unique_ptr<GrFragmentProcessor>(
                 new SampleMatrixVariableEffect(std::move(gradientFP), -0.5, 1));
         paint.addCoverageFragmentProcessor(std::move(fp));
-        rtCtx->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
+        rtCtx->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
     }
 }
diff --git a/gm/samplelocations.cpp b/gm/samplelocations.cpp
index c5a7f66..f0aa981 100644
--- a/gm/samplelocations.cpp
+++ b/gm/samplelocations.cpp
@@ -22,7 +22,6 @@
 #include "include/private/SkColorData.h"
 #include "src/gpu/GrBuffer.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrColorSpaceXform.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrGeometryProcessor.h"
@@ -364,11 +363,11 @@
     GrPaint coverPaint;
     coverPaint.setColor4f({1,0,0,1});
     coverPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrcOver));
-    rtc->priv().stencilRect(GrNoClip(), &kStencilCover, std::move(coverPaint), GrAA::kNo,
+    rtc->priv().stencilRect(nullptr, &kStencilCover, std::move(coverPaint), GrAA::kNo,
                             SkMatrix::I(), SkRect::MakeWH(200, 200));
 
     // Copy offscreen texture to canvas.
-    rtc->drawTexture(GrNoClip(), offscreenRTC->readSurfaceView(),
+    rtc->drawTexture(nullptr, offscreenRTC->readSurfaceView(),
                      offscreenRTC->colorInfo().alphaType(),
                      GrSamplerState::Filter::kNearest, SkBlendMode::kSrc, SK_PMColor4fWHITE,
                      {0,0,200,200}, {0,0,200,200}, GrAA::kNo, GrQuadAAFlags::kNone,
diff --git a/gm/windowrectangles.cpp b/gm/windowrectangles.cpp
index 5b430ab..932b83f 100644
--- a/gm/windowrectangles.cpp
+++ b/gm/windowrectangles.cpp
@@ -193,9 +193,10 @@
 /**
  * Makes a clip object that enforces the stencil clip bit. Used to visualize the stencil mask.
  */
-static GrStencilClip make_stencil_only_clip() {
-    return GrStencilClip(SkClipStack::kEmptyGenID);
-};
+static const GrStencilClip* make_stencil_only_clip() {
+    static const GrStencilClip kClip(SkClipStack::kEmptyGenID);
+    return &kClip;
+}
 
 DrawResult WindowRectanglesMaskGM::onCoverClipStack(const SkClipStack& stack, SkCanvas* canvas,
                                                         SkString* errorMsg) {
@@ -253,7 +254,7 @@
     // inside window rectangles or outside the scissor should still have the initial checkerboard
     // intact. (This verifies we didn't spend any time modifying those pixels in the mask.)
     AlphaOnlyClip clip(maskRTC->readSurfaceView(), x, y);
-    rtc->drawRect(clip, std::move(paint), GrAA::kYes, SkMatrix::I(),
+    rtc->drawRect(&clip, std::move(paint), GrAA::kYes, SkMatrix::I(),
                   SkRect::Make(SkIRect::MakeXYWH(x, y, maskRTC->width(), maskRTC->height())));
 }
 
@@ -296,7 +297,7 @@
             SkIRect checker = SkIRect::MakeXYWH(x, y, kMaskCheckerSize, kMaskCheckerSize);
             GrPaint paint;
             paint.setXPFactory(GrDisableColorXPFactory::Get());
-            rtc->priv().stencilRect(GrNoClip(), &kSetClip, std::move(paint), GrAA::kNo,
+            rtc->priv().stencilRect(nullptr, &kSetClip, std::move(paint), GrAA::kNo,
                                     SkMatrix::I(), SkRect::Make(checker));
         }
     }
diff --git a/gm/yuvtorgbeffect.cpp b/gm/yuvtorgbeffect.cpp
index 75b01ac..61c3f05 100644
--- a/gm/yuvtorgbeffect.cpp
+++ b/gm/yuvtorgbeffect.cpp
@@ -24,7 +24,6 @@
 #include "include/gpu/GrContext.h"
 #include "include/private/GrTypesPriv.h"
 #include "src/gpu/GrBitmapTextureMaker.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrFragmentProcessor.h"
 #include "src/gpu/GrPaint.h"
@@ -362,7 +361,7 @@
                     GrPaint grPaint;
                     grPaint.addColorFragmentProcessor(std::move(fp));
                     renderTargetContext->drawRect(
-                            GrNoClip(), std::move(grPaint), GrAA::kYes, ctm, rect);
+                            nullptr, std::move(grPaint), GrAA::kYes, ctm, rect);
                 }
                 x += rect.width() + kTestPad;
             }
diff --git a/samplecode/SampleCCPRGeometry.cpp b/samplecode/SampleCCPRGeometry.cpp
index b871d14..23061f6 100644
--- a/samplecode/SampleCCPRGeometry.cpp
+++ b/samplecode/SampleCCPRGeometry.cpp
@@ -14,7 +14,6 @@
 #include "include/core/SkPath.h"
 #include "samplecode/Sample.h"
 #include "src/core/SkRectPriv.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrGpu.h"
 #include "src/gpu/GrMemoryPool.h"
@@ -208,7 +207,7 @@
         paint.addColorFragmentProcessor(
                 std::make_unique<VisualizeCoverageCountFP>());
         paint.setPorterDuffXPFactory(SkBlendMode::kSrcOver);
-        rtc->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+        rtc->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                       SkRect::MakeIWH(this->width(), this->height()));
 
         // Add label.
diff --git a/src/atlastext/SkAtlasTextTarget.cpp b/src/atlastext/SkAtlasTextTarget.cpp
index 6372955..3ae4796 100644
--- a/src/atlastext/SkAtlasTextTarget.cpp
+++ b/src/atlastext/SkAtlasTextTarget.cpp
@@ -96,9 +96,9 @@
 
     /** GrTextTarget overrides */
 
-    void addDrawOp(const GrClip&, std::unique_ptr<GrAtlasTextOp> op) override;
+    void addDrawOp(const GrClip*, std::unique_ptr<GrAtlasTextOp> op) override;
 
-    void drawShape(const GrClip&,
+    void drawShape(const GrClip*,
                    const SkPaint&,
                    const SkMatrixProvider&,
                    const GrStyledShape&) override {
@@ -170,13 +170,13 @@
     auto glyphRunList = builder.useGlyphRunList();
     if (!glyphRunList.empty()) {
         SkSimpleMatrixProvider matrixProvider(this->ctm());
-        atlasTextContext->drawGlyphRunList(grContext, this, GrNoClip(), matrixProvider, props,
+        atlasTextContext->drawGlyphRunList(grContext, this, nullptr, matrixProvider, props,
                                            glyphRunList);
     }
 }
 
-void SkInternalAtlasTextTarget::addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) {
-    SkASSERT(clip.quickContains(SkRect::MakeIWH(fWidth, fHeight)));
+void SkInternalAtlasTextTarget::addDrawOp(const GrClip* clip, std::unique_ptr<GrAtlasTextOp> op) {
+    SkASSERT(!clip || clip->quickContains(SkRect::MakeIWH(fWidth, fHeight)));
     // The SkAtlasTextRenderer currently only handles grayscale SDF glyphs.
     if (op->maskType() != GrAtlasTextOp::kGrayscaleDistanceField_MaskType) {
         return;
diff --git a/src/core/SkBlurMF.cpp b/src/core/SkBlurMF.cpp
index 14be316..2fb4c9f 100644
--- a/src/core/SkBlurMF.cpp
+++ b/src/core/SkBlurMF.cpp
@@ -21,7 +21,6 @@
 
 #if SK_SUPPORT_GPU
 #include "include/private/GrRecordingContext.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrFragmentProcessor.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrRenderTargetContext.h"
@@ -58,7 +57,7 @@
     bool directFilterMaskGPU(GrRecordingContext*,
                              GrRenderTargetContext* renderTargetContext,
                              GrPaint&&,
-                             const GrClip&,
+                             const GrClip*,
                              const SkMatrix& viewMatrix,
                              const GrStyledShape& shape) const override;
     GrSurfaceProxyView filterMaskGPU(GrRecordingContext*,
@@ -722,7 +721,7 @@
 bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrRecordingContext* context,
                                                GrRenderTargetContext* renderTargetContext,
                                                GrPaint&& paint,
-                                               const GrClip& clip,
+                                               const GrClip* clip,
                                                const SkMatrix& viewMatrix,
                                                const GrStyledShape& shape) const {
     SkASSERT(renderTargetContext);
@@ -917,7 +916,7 @@
             paint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
         }
 
-        renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+        renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                       SkRect::Make(clipRect));
     }
 
diff --git a/src/core/SkGlyphRunPainter.cpp b/src/core/SkGlyphRunPainter.cpp
index f686b77..74a1914 100644
--- a/src/core/SkGlyphRunPainter.cpp
+++ b/src/core/SkGlyphRunPainter.cpp
@@ -275,7 +275,7 @@
 
 void GrTextContext::drawGlyphRunList(GrRecordingContext* context,
                                      GrTextTarget* target,
-                                     const GrClip& clip,
+                                     const GrClip* clip,
                                      const SkMatrixProvider& matrixProvider,
                                      const SkSurfaceProps& props,
                                      const SkGlyphRunList& glyphRunList) const {
diff --git a/src/core/SkGpuBlurUtils.cpp b/src/core/SkGpuBlurUtils.cpp
index f1b86ca..0d14284 100644
--- a/src/core/SkGpuBlurUtils.cpp
+++ b/src/core/SkGpuBlurUtils.cpp
@@ -12,7 +12,6 @@
 #if SK_SUPPORT_GPU
 #include "include/private/GrRecordingContext.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrFixedClip.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrRenderTargetContextPriv.h"
@@ -52,7 +51,7 @@
             *renderTargetContext->caps()));
     paint.addColorFragmentProcessor(std::move(conv));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-    renderTargetContext->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+    renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                         SkRect::Make(rtcRect), SkRect::Make(srcRect));
 }
 
@@ -89,7 +88,7 @@
     // 'dstBounds' is actually in 'srcView' proxy space. It represents the blurred area from src
     // space that we want to capture in the new RTC at {0, 0}. Hence, we use its size as the rect to
     // draw and it directly as the local rect.
-    renderTargetContext->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+    renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                         SkRect::Make(dstBounds.size()), SkRect::Make(dstBounds));
 
     return renderTargetContext;
@@ -253,7 +252,7 @@
     paint.addColorFragmentProcessor(std::move(fp));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
-    dstRenderTargetContext->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+    dstRenderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                            SkRect::Make(dstSize), srcBounds);
 
     return dstRenderTargetContext;
@@ -458,7 +457,7 @@
                                               SkRect::Make(dstBounds), *context->priv().caps());
         GrPaint paint;
         paint.addColorFragmentProcessor(std::move(fp));
-        result->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+        result->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                          SkRect::Make(dstBounds.size()));
         return result;
     }
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index 80f4d0b..4694a89 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -26,7 +26,6 @@
 #include "include/private/GrRecordingContext.h"
 #include "src/gpu/GrColorSpaceXform.h"
 #include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrFixedClip.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrTextureProxy.h"
@@ -586,9 +585,8 @@
     SkIRect dstIRect = SkIRect::MakeWH(bounds.width(), bounds.height());
     SkRect srcRect = SkRect::Make(bounds);
     SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
-    GrFixedClip clip(dstIRect);
-    renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
-                                        srcRect);
+    renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
+                                        dstRect, srcRect);
 
     return SkSpecialImage::MakeDeferredFromGpu(
             context, dstIRect, kNeedNewImageUniqueID_SpecialImage,
diff --git a/src/core/SkLegacyGpuBlurUtils.cpp b/src/core/SkLegacyGpuBlurUtils.cpp
index 8be824a..461da44 100644
--- a/src/core/SkLegacyGpuBlurUtils.cpp
+++ b/src/core/SkLegacyGpuBlurUtils.cpp
@@ -12,7 +12,6 @@
 #if SK_SUPPORT_GPU
 #include "include/private/GrRecordingContext.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrFixedClip.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrRenderTargetContextPriv.h"
@@ -100,7 +99,7 @@
     paint.addColorFragmentProcessor(std::move(conv));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     auto srcRect = SkRect::Make(rtcRect.makeOffset(rtcToSrcOffset));
-    renderTargetContext->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+    renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                         SkRect::Make(rtcRect), srcRect);
 }
 
@@ -137,7 +136,7 @@
     // 'dstBounds' is actually in 'srcView' proxy space. It represents the blurred area from src
     // space that we want to capture in the new RTC at {0, 0}. Hence, we use its size as the rect to
     // draw and it directly as the local rect.
-    renderTargetContext->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+    renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                         SkRect::Make(dstBounds.size()), SkRect::Make(dstBounds));
 
     return renderTargetContext;
@@ -317,7 +316,7 @@
         paint.addColorFragmentProcessor(std::move(fp));
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
-        dstRenderTargetContext->fillRectToRect(GrFixedClip::Disabled(), std::move(paint), GrAA::kNo,
+        dstRenderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo,
                                                SkMatrix::I(), SkRect::Make(dstRect),
                                                SkRect::Make(srcRect));
 
@@ -373,13 +372,12 @@
                                           caps);
     paint.addColorFragmentProcessor(std::move(fp));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-    GrFixedClip clip(SkIRect::MakeSize(dstSize));
 
     // TODO: using dstII as dstRect results in some image diffs - why?
     SkIRect dstRect(srcRect);
     scale_irect(&dstRect, scaleFactorX, scaleFactorY);
 
-    dstRenderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
+    dstRenderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                            SkRect::Make(dstRect), SkRect::Make(srcRect));
 
     return dstRenderTargetContext;
diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp
index c840a68..f408c01 100644
--- a/src/core/SkMaskFilter.cpp
+++ b/src/core/SkMaskFilter.cpp
@@ -335,7 +335,7 @@
 bool SkMaskFilterBase::directFilterMaskGPU(GrRecordingContext*,
                                            GrRenderTargetContext*,
                                            GrPaint&&,
-                                           const GrClip&,
+                                           const GrClip*,
                                            const SkMatrix& viewMatrix,
                                            const GrStyledShape&) const {
     return false;
diff --git a/src/core/SkMaskFilterBase.h b/src/core/SkMaskFilterBase.h
index 1d8ecb1..5ac10de 100644
--- a/src/core/SkMaskFilterBase.h
+++ b/src/core/SkMaskFilterBase.h
@@ -116,7 +116,7 @@
     virtual bool directFilterMaskGPU(GrRecordingContext*,
                                      GrRenderTargetContext*,
                                      GrPaint&& paint,
-                                     const GrClip&,
+                                     const GrClip*,
                                      const SkMatrix& viewMatrix,
                                      const GrStyledShape& shape) const;
 
diff --git a/src/effects/imagefilters/SkAlphaThresholdFilter.cpp b/src/effects/imagefilters/SkAlphaThresholdFilter.cpp
index c0f571d..5923d8a 100644
--- a/src/effects/imagefilters/SkAlphaThresholdFilter.cpp
+++ b/src/effects/imagefilters/SkAlphaThresholdFilter.cpp
@@ -19,7 +19,6 @@
 #include "include/private/GrRecordingContext.h"
 #include "src/gpu/GrCaps.h"
 #include "src/gpu/GrColorSpaceXform.h"
-#include "src/gpu/GrFixedClip.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrTextureProxy.h"
@@ -112,14 +111,13 @@
     SkRegion::Iterator iter(fRegion);
     rtContext->clear(SK_PMColor4fTRANSPARENT);
 
-    GrFixedClip clip(SkIRect::MakeWH(bounds.width(), bounds.height()));
     while (!iter.done()) {
         GrPaint paint;
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
         SkRect rect = SkRect::Make(iter.rect());
 
-        rtContext->drawRect(clip, std::move(paint), GrAA::kNo, inMatrix, rect);
+        rtContext->drawRect(nullptr, std::move(paint), GrAA::kNo, inMatrix, rect);
 
         iter.next();
     }
diff --git a/src/effects/imagefilters/SkArithmeticImageFilter.cpp b/src/effects/imagefilters/SkArithmeticImageFilter.cpp
index df7465f..783a970 100644
--- a/src/effects/imagefilters/SkArithmeticImageFilter.cpp
+++ b/src/effects/imagefilters/SkArithmeticImageFilter.cpp
@@ -18,7 +18,6 @@
 #if SK_SUPPORT_GPU
 #include "include/effects/SkRuntimeEffect.h"
 #include "include/private/GrRecordingContext.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrColorSpaceXform.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrRenderTargetContext.h"
@@ -403,7 +402,7 @@
 
     SkMatrix matrix;
     matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
-    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix,
+    renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, matrix,
                                   SkRect::Make(bounds));
 
     return SkSpecialImage::MakeDeferredFromGpu(context,
diff --git a/src/effects/imagefilters/SkDisplacementMapEffect.cpp b/src/effects/imagefilters/SkDisplacementMapEffect.cpp
index 14e541d..b448289 100644
--- a/src/effects/imagefilters/SkDisplacementMapEffect.cpp
+++ b/src/effects/imagefilters/SkDisplacementMapEffect.cpp
@@ -17,7 +17,6 @@
 #if SK_SUPPORT_GPU
 #include "include/private/GrRecordingContext.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrColorSpaceXform.h"
 #include "src/gpu/GrCoordTransform.h"
 #include "src/gpu/GrRecordingContextPriv.h"
@@ -367,7 +366,7 @@
             return nullptr;
         }
 
-        renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix,
+        renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, matrix,
                                       SkRect::Make(colorBounds));
 
         offset->fX = bounds.left();
diff --git a/src/effects/imagefilters/SkLightingImageFilter.cpp b/src/effects/imagefilters/SkLightingImageFilter.cpp
index 89984d9..933171c 100644
--- a/src/effects/imagefilters/SkLightingImageFilter.cpp
+++ b/src/effects/imagefilters/SkLightingImageFilter.cpp
@@ -19,7 +19,6 @@
 #if SK_SUPPORT_GPU
 #include "include/private/GrRecordingContext.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrFixedClip.h"
 #include "src/gpu/GrFragmentProcessor.h"
 #include "src/gpu/GrPaint.h"
 #include "src/gpu/GrRecordingContextPriv.h"
@@ -444,7 +443,6 @@
     void drawRect(GrRenderTargetContext*,
                   GrSurfaceProxyView srcView,
                   const SkMatrix& matrix,
-                  const GrClip& clip,
                   const SkRect& dstRect,
                   BoundaryMode boundaryMode,
                   const SkIRect* srcBounds,
@@ -461,7 +459,6 @@
 void SkLightingImageFilterInternal::drawRect(GrRenderTargetContext* renderTargetContext,
                                              GrSurfaceProxyView srcView,
                                              const SkMatrix& matrix,
-                                             const GrClip& clip,
                                              const SkRect& dstRect,
                                              BoundaryMode boundaryMode,
                                              const SkIRect* srcBounds,
@@ -472,8 +469,8 @@
                                           *renderTargetContext->caps());
     paint.addColorFragmentProcessor(std::move(fp));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-    renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
-                                        srcRect);
+    renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
+                                        dstRect, srcRect);
 }
 
 sk_sp<SkSpecialImage> SkLightingImageFilterInternal::filterImageGPU(
@@ -499,9 +496,6 @@
     SkIRect dstIRect = SkIRect::MakeWH(offsetBounds.width(), offsetBounds.height());
     SkRect dstRect = SkRect::Make(dstIRect);
 
-    // setup new clip
-    GrFixedClip clip(dstIRect);
-
     const SkIRect inputBounds = SkIRect::MakeWH(input->width(), input->height());
     SkRect topLeft = SkRect::MakeXYWH(0, 0, 1, 1);
     SkRect top = SkRect::MakeXYWH(1, 0, dstRect.width() - 2, 1);
@@ -514,23 +508,23 @@
     SkRect bottomRight = SkRect::MakeXYWH(dstRect.width() - 1, dstRect.height() - 1, 1, 1);
 
     const SkIRect* pSrcBounds = inputBounds.contains(offsetBounds) ? nullptr : &inputBounds;
-    this->drawRect(renderTargetContext.get(), inputView, matrix, clip, topLeft,
+    this->drawRect(renderTargetContext.get(), inputView, matrix, topLeft,
                    kTopLeft_BoundaryMode, pSrcBounds, offsetBounds);
-    this->drawRect(renderTargetContext.get(), inputView, matrix, clip, top,
+    this->drawRect(renderTargetContext.get(), inputView, matrix, top,
                    kTop_BoundaryMode, pSrcBounds, offsetBounds);
-    this->drawRect(renderTargetContext.get(), inputView, matrix, clip, topRight,
+    this->drawRect(renderTargetContext.get(), inputView, matrix, topRight,
                    kTopRight_BoundaryMode, pSrcBounds, offsetBounds);
-    this->drawRect(renderTargetContext.get(), inputView, matrix, clip, left,
+    this->drawRect(renderTargetContext.get(), inputView, matrix, left,
                    kLeft_BoundaryMode, pSrcBounds, offsetBounds);
-    this->drawRect(renderTargetContext.get(), inputView, matrix, clip, interior,
+    this->drawRect(renderTargetContext.get(), inputView, matrix, interior,
                    kInterior_BoundaryMode, pSrcBounds, offsetBounds);
-    this->drawRect(renderTargetContext.get(), inputView, matrix, clip, right,
+    this->drawRect(renderTargetContext.get(), inputView, matrix, right,
                    kRight_BoundaryMode, pSrcBounds, offsetBounds);
-    this->drawRect(renderTargetContext.get(), inputView, matrix, clip, bottomLeft,
+    this->drawRect(renderTargetContext.get(), inputView, matrix, bottomLeft,
                    kBottomLeft_BoundaryMode, pSrcBounds, offsetBounds);
-    this->drawRect(renderTargetContext.get(), inputView, matrix, clip, bottom,
+    this->drawRect(renderTargetContext.get(), inputView, matrix, bottom,
                    kBottom_BoundaryMode, pSrcBounds, offsetBounds);
-    this->drawRect(renderTargetContext.get(), std::move(inputView), matrix, clip, bottomRight,
+    this->drawRect(renderTargetContext.get(), std::move(inputView), matrix, bottomRight,
                    kBottomRight_BoundaryMode, pSrcBounds, offsetBounds);
 
     return SkSpecialImage::MakeDeferredFromGpu(
diff --git a/src/effects/imagefilters/SkMorphologyImageFilter.cpp b/src/effects/imagefilters/SkMorphologyImageFilter.cpp
index 7f3f4c8..3a6da5e 100644
--- a/src/effects/imagefilters/SkMorphologyImageFilter.cpp
+++ b/src/effects/imagefilters/SkMorphologyImageFilter.cpp
@@ -20,7 +20,6 @@
 #include "include/private/GrRecordingContext.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrCoordTransform.h"
-#include "src/gpu/GrFixedClip.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrTexture.h"
@@ -473,7 +472,6 @@
 #endif
 
 static void apply_morphology_rect(GrRenderTargetContext* renderTargetContext,
-                                  const GrClip& clip,
                                   GrSurfaceProxyView view,
                                   SkAlphaType srcAlphaType,
                                   const SkIRect& srcRect,
@@ -486,12 +484,11 @@
     paint.addColorFragmentProcessor(GrMorphologyEffect::Make(std::move(view), srcAlphaType,
                                                              direction, radius, morphType, bounds));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-    renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
+    renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                         SkRect::Make(dstRect), SkRect::Make(srcRect));
 }
 
 static void apply_morphology_rect_no_bounds(GrRenderTargetContext* renderTargetContext,
-                                            const GrClip& clip,
                                             GrSurfaceProxyView view,
                                             SkAlphaType srcAlphaType,
                                             const SkIRect& srcRect,
@@ -503,12 +500,11 @@
     paint.addColorFragmentProcessor(
             GrMorphologyEffect::Make(std::move(view), srcAlphaType, direction, radius, morphType));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-    renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
+    renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                         SkRect::Make(dstRect), SkRect::Make(srcRect));
 }
 
 static void apply_morphology_pass(GrRenderTargetContext* renderTargetContext,
-                                  const GrClip& clip,
                                   GrSurfaceProxyView view,
                                   SkAlphaType srcAlphaType,
                                   const SkIRect& srcRect,
@@ -541,17 +537,16 @@
     }
     if (middleSrcRect.width() <= 0) {
         // radius covers srcRect; use bounds over entire draw
-        apply_morphology_rect(renderTargetContext, clip, std::move(view), srcAlphaType, srcRect,
+        apply_morphology_rect(renderTargetContext, std::move(view), srcAlphaType, srcRect,
                               dstRect, radius, morphType, bounds, direction);
     } else {
         // Draw upper and lower margins with bounds; middle without.
-        apply_morphology_rect(renderTargetContext, clip, view, srcAlphaType, lowerSrcRect,
+        apply_morphology_rect(renderTargetContext, view, srcAlphaType, lowerSrcRect,
                               lowerDstRect, radius, morphType, bounds, direction);
-        apply_morphology_rect(renderTargetContext, clip, view, srcAlphaType, upperSrcRect,
+        apply_morphology_rect(renderTargetContext, view, srcAlphaType, upperSrcRect,
                               upperDstRect, radius, morphType, bounds, direction);
-        apply_morphology_rect_no_bounds(renderTargetContext, clip, std::move(view),
-                                        srcAlphaType, middleSrcRect, middleDstRect, radius,
-                                        morphType, direction);
+        apply_morphology_rect_no_bounds(renderTargetContext, std::move(view), srcAlphaType,
+                                        middleSrcRect, middleDstRect, radius, morphType, direction);
     }
 }
 
@@ -566,9 +561,6 @@
 
     GrSurfaceProxy* proxy = srcView.proxy();
 
-    // setup new clip
-    const GrFixedClip clip(SkIRect::MakeSize(proxy->dimensions()));
-
     const SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height());
     SkIRect srcRect = rect;
     // Map into proxy space
@@ -583,7 +575,7 @@
             return nullptr;
         }
 
-        apply_morphology_pass(dstRTContext.get(), clip, std::move(srcView), srcAlphaType,
+        apply_morphology_pass(dstRTContext.get(), std::move(srcView), srcAlphaType,
                               srcRect, dstRect, radius.fWidth, morphType, MorphDirection::kX);
         SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom,
                                               dstRect.width(), radius.fHeight);
@@ -603,7 +595,7 @@
             return nullptr;
         }
 
-        apply_morphology_pass(dstRTContext.get(), clip, std::move(srcView), srcAlphaType,
+        apply_morphology_pass(dstRTContext.get(), std::move(srcView), srcAlphaType,
                               srcRect, dstRect, radius.fHeight, morphType, MorphDirection::kY);
 
         srcView = dstRTContext->readSurfaceView();
diff --git a/src/effects/imagefilters/SkXfermodeImageFilter.cpp b/src/effects/imagefilters/SkXfermodeImageFilter.cpp
index ff9af1c..211fc64 100644
--- a/src/effects/imagefilters/SkXfermodeImageFilter.cpp
+++ b/src/effects/imagefilters/SkXfermodeImageFilter.cpp
@@ -17,7 +17,6 @@
 #if SK_SUPPORT_GPU
 #include "include/private/GrRecordingContext.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrColorSpaceXform.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrRenderTargetContext.h"
@@ -310,7 +309,7 @@
 
     SkMatrix matrix;
     matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
-    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix,
+    renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, matrix,
                                   SkRect::Make(bounds));
 
     return SkSpecialImage::MakeDeferredFromGpu(context,
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index ebbfe91..e348f4b 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -43,7 +43,7 @@
 // is already burnt into the mask this boils down to a rect draw.
 // Return true if the mask was successfully drawn.
 static bool draw_mask(GrRenderTargetContext* renderTargetContext,
-                      const GrClip& clip,
+                      const GrClip* clip,
                       const SkMatrix& viewMatrix,
                       const SkIRect& maskRect,
                       GrPaint&& paint,
@@ -70,7 +70,7 @@
 
 static bool sw_draw_with_mask_filter(GrRecordingContext* context,
                                      GrRenderTargetContext* renderTargetContext,
-                                     const GrClip& clipData,
+                                     const GrClip* clipData,
                                      const SkMatrix& viewMatrix,
                                      const GrStyledShape& shape,
                                      const SkMaskFilter* filter,
@@ -207,7 +207,7 @@
     // maskPaint.
     SkMatrix viewMatrix = origViewMatrix;
     viewMatrix.postTranslate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRect.fTop));
-    rtContext->drawShape(clip, std::move(maskPaint), GrAA::kYes, viewMatrix, shape);
+    rtContext->drawShape(&clip, std::move(maskPaint), GrAA::kYes, viewMatrix, shape);
     return rtContext;
 }
 
@@ -239,14 +239,16 @@
 // Gets the shape bounds, the clip bounds, and the intersection (if any). Returns false if there
 // is no intersection.
 static bool get_shape_and_clip_bounds(GrRenderTargetContext* renderTargetContext,
-                                      const GrClip& clip,
+                                      const GrClip* clip,
                                       const GrStyledShape& shape,
                                       const SkMatrix& matrix,
                                       SkIRect* unclippedDevShapeBounds,
                                       SkIRect* devClipBounds) {
     // compute bounds as intersection of rt size, clip, and path
-    *devClipBounds = clip.getConservativeBounds(renderTargetContext->width(),
-                                                renderTargetContext->height());
+    *devClipBounds = clip ? clip->getConservativeBounds(renderTargetContext->width(),
+                                                        renderTargetContext->height())
+                          : SkIRect::MakeWH(renderTargetContext->width(),
+                                            renderTargetContext->height());
 
     if (!get_unclipped_shape_dev_bounds(shape, matrix, unclippedDevShapeBounds)) {
         *unclippedDevShapeBounds = SkIRect::MakeEmpty();
@@ -258,7 +260,7 @@
 
 static void draw_shape_with_mask_filter(GrRecordingContext* context,
                                         GrRenderTargetContext* renderTargetContext,
-                                        const GrClip& clip,
+                                        const GrClip* clip,
                                         GrPaint&& paint,
                                         const SkMatrix& viewMatrix,
                                         const SkMaskFilterBase* maskFilter,
@@ -282,12 +284,8 @@
         shape = tmpShape.get();
     }
 
-    if (maskFilter->directFilterMaskGPU(context,
-                                        renderTargetContext,
-                                        std::move(paint),
-                                        clip,
-                                        viewMatrix,
-                                        *shape)) {
+    if (maskFilter->directFilterMaskGPU(context, renderTargetContext, std::move(paint), clip,
+                                        viewMatrix, *shape)) {
         // the mask filter was able to draw itself directly, so there's nothing
         // left to do.
         return;
@@ -301,8 +299,7 @@
 
     SkIRect unclippedDevShapeBounds, devClipBounds;
     if (!get_shape_and_clip_bounds(renderTargetContext, clip, *shape, viewMatrix,
-                                   &unclippedDevShapeBounds,
-                                   &devClipBounds)) {
+                                   &unclippedDevShapeBounds, &devClipBounds)) {
         // TODO: just cons up an opaque mask here
         if (!inverseFilled) {
             return;
@@ -439,7 +436,7 @@
 
 void GrBlurUtils::drawShapeWithMaskFilter(GrRecordingContext* context,
                                           GrRenderTargetContext* renderTargetContext,
-                                          const GrClip& clip,
+                                          const GrClip* clip,
                                           const GrStyledShape& shape,
                                           GrPaint&& paint,
                                           const SkMatrix& viewMatrix,
@@ -450,7 +447,7 @@
 
 void GrBlurUtils::drawShapeWithMaskFilter(GrRecordingContext* context,
                                           GrRenderTargetContext* renderTargetContext,
-                                          const GrClip& clip,
+                                          const GrClip* clip,
                                           const SkPaint& paint,
                                           const SkMatrixProvider& matrixProvider,
                                           const GrStyledShape& shape) {
diff --git a/src/gpu/GrBlurUtils.h b/src/gpu/GrBlurUtils.h
index 45ce4ef..fa0be4e 100644
--- a/src/gpu/GrBlurUtils.h
+++ b/src/gpu/GrBlurUtils.h
@@ -36,7 +36,7 @@
      */
     void drawShapeWithMaskFilter(GrRecordingContext*,
                                  GrRenderTargetContext*,
-                                 const GrClip&,
+                                 const GrClip*,
                                  const SkPaint&,
                                  const SkMatrixProvider&,
                                  const GrStyledShape&);
@@ -47,7 +47,7 @@
      */
     void drawShapeWithMaskFilter(GrRecordingContext*,
                                  GrRenderTargetContext*,
-                                 const GrClip&,
+                                 const GrClip*,
                                  const GrStyledShape&,
                                  GrPaint&&,
                                  const SkMatrix& viewMatrix,
diff --git a/src/gpu/GrClip.h b/src/gpu/GrClip.h
index d85338b..cec96d0 100644
--- a/src/gpu/GrClip.h
+++ b/src/gpu/GrClip.h
@@ -160,15 +160,4 @@
     }
 };
 
-/**
- * Specialized implementation for no clip.
- */
-class GrNoClip final : public GrHardClip {
-private:
-    bool quickContains(const SkRect&) const final { return true; }
-    bool quickContains(const SkRRect&) const final { return true; }
-    bool apply(int rtWidth, int rtHeight, GrAppliedHardClip*, SkRect*) const final { return true; }
-    bool isRRect(const SkRect&, SkRRect*, GrAA*) const override { return false; }
-};
-
 #endif
diff --git a/src/gpu/GrFixedClip.cpp b/src/gpu/GrFixedClip.cpp
index 51f2f9d..2f826fb 100644
--- a/src/gpu/GrFixedClip.cpp
+++ b/src/gpu/GrFixedClip.cpp
@@ -63,8 +63,3 @@
 
     return true;
 }
-
-const GrFixedClip& GrFixedClip::Disabled() {
-    static const GrFixedClip disabled = GrFixedClip();
-    return disabled;
-}
diff --git a/src/gpu/GrFixedClip.h b/src/gpu/GrFixedClip.h
index 1f175f8..017c3ff 100644
--- a/src/gpu/GrFixedClip.h
+++ b/src/gpu/GrFixedClip.h
@@ -47,8 +47,6 @@
     bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const override;
     bool apply(int rtWidth, int rtHeight, GrAppliedHardClip*, SkRect*) const override;
 
-    static const GrFixedClip& Disabled();
-
 private:
     GrScissorState       fScissorState;
     GrWindowRectsState   fWindowRectsState;
diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h
index 47e6536..c42b9ee 100644
--- a/src/gpu/GrPathRenderer.h
+++ b/src/gpu/GrPathRenderer.h
@@ -127,7 +127,6 @@
             SkASSERT(fContext);
             SkASSERT(fUserStencilSettings);
             SkASSERT(fRenderTargetContext);
-            SkASSERT(fClip);
             SkASSERT(fClipConservativeBounds);
             SkASSERT(fViewMatrix);
             SkASSERT(fShape);
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index b25098e..0e01895 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -693,7 +693,7 @@
             GrPaint paint;
             paint.setCoverageSetOpXPFactory((SkRegion::Op)element->getOp(),
                                             element->isInverseFilled());
-            rtc->priv().stencilRect(clip, ss, std::move(paint), aa, viewMatrix,
+            rtc->priv().stencilRect(&clip, ss, std::move(paint), aa, viewMatrix,
                                     element->getDeviceSpaceRect());
             return true;
         }
@@ -704,7 +704,7 @@
                 path.toggleInverseFillType();
             }
 
-            return rtc->priv().drawAndStencilPath(clip, ss, (SkRegion::Op)element->getOp(),
+            return rtc->priv().drawAndStencilPath(&clip, ss, (SkRegion::Op)element->getOp(),
                                                   element->isInverseFilled(), aa, viewMatrix, path);
         }
     }
@@ -724,7 +724,7 @@
             SkDEBUGFAIL("Should never get here with an empty element.");
             break;
         case SkClipStack::Element::DeviceSpaceType::kRect:
-            rtc->drawRect(clip, std::move(paint), aa, viewMatrix, element->getDeviceSpaceRect());
+            rtc->drawRect(&clip, std::move(paint), aa, viewMatrix, element->getDeviceSpaceRect());
             break;
         default: {
             SkPath path;
@@ -733,7 +733,7 @@
                 path.toggleInverseFillType();
             }
 
-            rtc->drawPath(clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill());
+            rtc->drawPath(&clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill());
             break;
         }
     }
@@ -757,7 +757,7 @@
         GrPaint paint;
         paint.setColor4f(initialCoverage);
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-        rtc->drawRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
+        rtc->drawRect(&clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
                       SkRect::Make(clip.scissorRect()));
     } else {
         rtc->priv().clearAtLeast(clip.scissorRect(), initialCoverage);
@@ -802,7 +802,7 @@
 
             GrPaint paint;
             paint.setCoverageSetOpXPFactory(op, !invert);
-            rtc->priv().stencilRect(clip, &kDrawOutsideElement, std::move(paint), GrAA::kNo,
+            rtc->priv().stencilRect(&clip, &kDrawOutsideElement, std::move(paint), GrAA::kNo,
                                     translate, SkRect::Make(fScissor));
         } else {
             // all the remaining ops can just be directly draw into the accumulation buffer
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));
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index abf3b8c..21d12e4 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -140,7 +140,7 @@
 
     ~GrRenderTargetContext() override;
 
-    virtual void drawGlyphRunList(const GrClip&, const SkMatrixProvider&, const SkGlyphRunList&);
+    virtual void drawGlyphRunList(const GrClip*, const SkMatrixProvider&, const SkGlyphRunList&);
 
     /**
      * Provides a perfomance hint that the render target's contents are allowed
@@ -164,7 +164,7 @@
     /**
      *  Draw everywhere (respecting the clip) with the paint.
      */
-    void drawPaint(const GrClip&, GrPaint&&, const SkMatrix& viewMatrix);
+    void drawPaint(const GrClip*, GrPaint&&, const SkMatrix& viewMatrix);
 
     /**
      * Draw the rect using a paint.
@@ -175,7 +175,7 @@
      *                     allowed.
      * The rects coords are used to access the paint (through texture matrix)
      */
-    void drawRect(const GrClip&,
+    void drawRect(const GrClip*,
                   GrPaint&& paint,
                   GrAA,
                   const SkMatrix& viewMatrix,
@@ -191,7 +191,7 @@
      * @param rectToDraw   the rectangle to draw
      * @param localRect    the rectangle of shader coordinates applied to rectToDraw
      */
-    void fillRectToRect(const GrClip& clip,
+    void fillRectToRect(const GrClip* clip,
                         GrPaint&& paint,
                         GrAA aa,
                         const SkMatrix& viewMatrix,
@@ -205,7 +205,7 @@
     /**
      * Fills a rect with a paint and a localMatrix.
      */
-    void fillRectWithLocalMatrix(const GrClip& clip,
+    void fillRectWithLocalMatrix(const GrClip* clip,
                                  GrPaint&& paint,
                                  GrAA aa,
                                  const SkMatrix& viewMatrix,
@@ -223,7 +223,7 @@
      * This is a specialized version of fillQuadWithEdgeAA, but is kept separate since knowing
      * the geometry is a rectangle affords more optimizations.
      */
-    void fillRectWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA,
+    void fillRectWithEdgeAA(const GrClip* clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA,
                             const SkMatrix& viewMatrix, const SkRect& rect,
                             const SkRect* optionalLocalRect = nullptr) {
         const SkRect& localRect = optionalLocalRect ? *optionalLocalRect : rect;
@@ -243,7 +243,7 @@
      * The last argument, 'optionalLocalQuad', can be null if no separate local coordinates are
      * necessary.
      */
-    void fillQuadWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA,
+    void fillQuadWithEdgeAA(const GrClip* clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA,
                             const SkMatrix& viewMatrix, const SkPoint points[4],
                             const SkPoint optionalLocalPoints[4]) {
         const SkPoint* localPoints = optionalLocalPoints ? optionalLocalPoints : points;
@@ -261,7 +261,7 @@
     };
 
     // TODO(michaelludwig) - remove if the bulk API is not useful for SkiaRenderer
-    void drawQuadSet(const GrClip& clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix,
+    void drawQuadSet(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix,
                      const QuadSetEntry[], int cnt);
 
     /**
@@ -270,7 +270,7 @@
      * specifies the rectangle to draw in local coords which will be transformed by 'viewMatrix' to
      * device space.
      */
-    void drawTexture(const GrClip& clip, GrSurfaceProxyView view, SkAlphaType srcAlphaType,
+    void drawTexture(const GrClip* clip, GrSurfaceProxyView view, SkAlphaType srcAlphaType,
                      GrSamplerState::Filter filter, SkBlendMode mode, const SkPMColor4f& color,
                      const SkRect& srcRect, const SkRect& dstRect, GrAA aa, GrQuadAAFlags edgeAA,
                      SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix,
@@ -289,7 +289,7 @@
      * 'subset' is null, it's equivalent to using the fast src rect constraint. If 'subset' is
      * provided, the strict src rect constraint is applied using 'subset'.
      */
-    void drawTextureQuad(const GrClip& clip, GrSurfaceProxyView view, GrColorType srcColorType,
+    void drawTextureQuad(const GrClip* clip, GrSurfaceProxyView view, GrColorType srcColorType,
                          SkAlphaType srcAlphaType, GrSamplerState::Filter filter, SkBlendMode mode,
                          const SkPMColor4f& color, const SkPoint srcQuad[4],
                          const SkPoint dstQuad[4], GrAA aa, GrQuadAAFlags edgeAA,
@@ -323,7 +323,7 @@
      * can be inferred from the array within this function, but the information is already known
      * by SkGpuDevice, so no need to incur another iteration over the array.
      */
-    void drawTextureSet(const GrClip&, TextureSetEntry[], int cnt, int proxyRunCnt,
+    void drawTextureSet(const GrClip*, TextureSetEntry[], int cnt, int proxyRunCnt,
                         GrSamplerState::Filter, SkBlendMode mode, GrAA aa,
                         SkCanvas::SrcRectConstraint, const SkMatrix& viewMatrix,
                         sk_sp<GrColorSpaceXform> texXform);
@@ -337,7 +337,7 @@
      * @param rrect       the roundrect to draw
      * @param style       style to apply to the rrect. Currently path effects are not allowed.
      */
-    void drawRRect(const GrClip&,
+    void drawRRect(const GrClip*,
                    GrPaint&&,
                    GrAA,
                    const SkMatrix& viewMatrix,
@@ -352,7 +352,7 @@
      * @param path         the path to shadow
      * @param rec          parameters for shadow rendering
      */
-    bool drawFastShadow(const GrClip&,
+    bool drawFastShadow(const GrClip*,
                         const SkMatrix& viewMatrix,
                         const SkPath& path,
                         const SkDrawShadowRec& rec);
@@ -367,7 +367,7 @@
      * @param outer        the outer roundrect
      * @param inner        the inner roundrect
      */
-    void drawDRRect(const GrClip&,
+    void drawDRRect(const GrClip*,
                     GrPaint&&,
                     GrAA,
                     const SkMatrix& viewMatrix,
@@ -383,7 +383,7 @@
      * @param path          the path to draw
      * @param style         style to apply to the path.
      */
-    void drawPath(const GrClip&,
+    void drawPath(const GrClip*,
                   GrPaint&&,
                   GrAA,
                   const SkMatrix& viewMatrix,
@@ -398,7 +398,7 @@
      * @param viewMatrix    transformation matrix
      * @param shape         the shape to draw
      */
-    void drawShape(const GrClip&,
+    void drawShape(const GrClip*,
                    GrPaint&&,
                    GrAA,
                    const SkMatrix& viewMatrix,
@@ -414,7 +414,7 @@
      * @param   overridePrimType primitive type to draw. If NULL, derive prim type from vertices.
      * @param   effect           runtime effect that will handle custom vertex attributes.
      */
-    void drawVertices(const GrClip&,
+    void drawVertices(const GrClip*,
                       GrPaint&& paint,
                       const SkMatrixProvider& matrixProvider,
                       sk_sp<SkVertices> vertices,
@@ -433,7 +433,7 @@
      * @param   colors          optional array of per-sprite colors, supercedes
      *                          the paint's color field.
      */
-    void drawAtlas(const GrClip&,
+    void drawAtlas(const GrClip*,
                    GrPaint&& paint,
                    const SkMatrix& viewMatrix,
                    int spriteCount,
@@ -450,7 +450,7 @@
      * @param region        the region to be drawn
      * @param style         style to apply to the region
      */
-    void drawRegion(const GrClip&,
+    void drawRegion(const GrClip*,
                     GrPaint&& paint,
                     GrAA aa,
                     const SkMatrix& viewMatrix,
@@ -467,7 +467,7 @@
      * @param oval          the bounding rect of the oval.
      * @param style         style to apply to the oval. Currently path effects are not allowed.
      */
-    void drawOval(const GrClip&,
+    void drawOval(const GrClip*,
                   GrPaint&& paint,
                   GrAA,
                   const SkMatrix& viewMatrix,
@@ -488,7 +488,7 @@
      *                      omitted.
      * @param style         style to apply to the oval.
      */
-    void drawArc(const GrClip&,
+    void drawArc(const GrClip*,
                  GrPaint&& paint,
                  GrAA,
                  const SkMatrix& viewMatrix,
@@ -501,7 +501,7 @@
     /**
      * Draw the image as a set of rects, specified by |iter|.
      */
-    void drawImageLattice(const GrClip&,
+    void drawImageLattice(const GrClip*,
                           GrPaint&&,
                           const SkMatrix& viewMatrix,
                           GrSurfaceProxyView,
@@ -622,7 +622,7 @@
     void internalStencilClear(const SkIRect* scissor, bool insideStencilMask);
 
     // Only consumes the GrPaint if successful.
-    bool drawFilledDRRect(const GrClip& clip,
+    bool drawFilledDRRect(const GrClip* clip,
                           GrPaint&& paint,
                           GrAA,
                           const SkMatrix& viewMatrix,
@@ -638,7 +638,7 @@
     //
     // 'stencilSettings' are provided merely for decision making purposes; When non-null,
     // optimization strategies that submit special ops are avoided.
-    QuadOptimization attemptQuadOptimization(const GrClip& clip,
+    QuadOptimization attemptQuadOptimization(const GrClip* clip,
                                              const SkPMColor4f* constColor,
                                              const GrUserStencilSettings* stencilSettings,
                                              GrAA* aa,
@@ -648,7 +648,7 @@
     // can choose between coverage, MSAA as per chooseAAType(). This will always attempt to apply
     // quad optimizations, so all quad/rect public APIs should rely on this function for consistent
     // clipping behavior. 'quad' will be modified in place to reflect final rendered geometry.
-    void drawFilledQuad(const GrClip& clip,
+    void drawFilledQuad(const GrClip* clip,
                         GrPaint&& paint,
                         GrAA aa,
                         DrawQuad* quad,
@@ -656,7 +656,7 @@
 
     // Like drawFilledQuad but does not require using a GrPaint or FP for texturing.
     // 'quad' may be modified in place to reflect final geometry.
-    void drawTexturedQuad(const GrClip& clip,
+    void drawTexturedQuad(const GrClip* clip,
                           GrSurfaceProxyView proxyView,
                           SkAlphaType alphaType,
                           sk_sp<GrColorSpaceXform> textureXform,
@@ -669,7 +669,7 @@
 
     // If 'attemptShapeFallback' is true, and the original shape had been simplfied, this
     // will re-route through drawShape() to see if we can avoid path rendering one more time.
-    void drawShapeUsingPathRenderer(const GrClip&, GrPaint&&, GrAA, const SkMatrix&,
+    void drawShapeUsingPathRenderer(const GrClip*, GrPaint&&, GrAA, const SkMatrix&,
                                     const GrStyledShape&, bool attemptShapeFallback = true);
 
     void addOp(std::unique_ptr<GrOp>);
@@ -680,13 +680,15 @@
     // op list. Before adding the op to an op list the WillAddOpFn is called. Note that it
     // will not be called in the event that the op is discarded. Moreover, the op may merge into
     // another op after the function is called (either before addDrawOp returns or some time later).
-    void addDrawOp(const GrClip&, std::unique_ptr<GrDrawOp>,
+    //
+    // If the clip pointer is null, no clipping will be performed.
+    void addDrawOp(const GrClip*, std::unique_ptr<GrDrawOp>,
                    const std::function<WillAddOpFn>& = std::function<WillAddOpFn>());
 
     // Makes a copy of the proxy if it is necessary for the draw and places the texture that should
     // be used by GrXferProcessor to access the destination color in 'result'. If the return
     // value is false then a texture copy could not be made.
-    bool SK_WARN_UNUSED_RESULT setupDstProxyView(const GrClip&, const GrOp& op,
+    bool SK_WARN_UNUSED_RESULT setupDstProxyView(const GrClip*, const GrOp& op,
                                                  GrXferProcessor::DstProxyView* result);
 
     class AsyncReadResult;
diff --git a/src/gpu/GrRenderTargetContextPriv.h b/src/gpu/GrRenderTargetContextPriv.h
index cad91f1..c09713f 100644
--- a/src/gpu/GrRenderTargetContextPriv.h
+++ b/src/gpu/GrRenderTargetContextPriv.h
@@ -57,7 +57,7 @@
     // care to only provide hard clips or we could get stuck in a loop. The general clip is needed
     // so that path renderers can use this function.
     void stencilRect(
-            const GrClip& clip, const GrUserStencilSettings* ss, GrPaint&& paint,
+            const GrClip* clip, const GrUserStencilSettings* ss, GrPaint&& paint,
             GrAA doStencilMSAA, const SkMatrix& viewMatrix, const SkRect& rect,
             const SkMatrix* localMatrix = nullptr) {
         // Since this provides stencil settings to drawFilledQuad, it performs a different AA type
@@ -69,13 +69,13 @@
     }
 
     void stencilPath(
-            const GrHardClip&, GrAA doStencilMSAA, const SkMatrix& viewMatrix, sk_sp<const GrPath>);
+            const GrHardClip*, GrAA doStencilMSAA, const SkMatrix& viewMatrix, sk_sp<const GrPath>);
 
     /**
      * Draws a path, either AA or not, and touches the stencil buffer with the user stencil settings
      * for each color sample written.
      */
-    bool drawAndStencilPath(const GrHardClip&,
+    bool drawAndStencilPath(const GrHardClip*,
                             const GrUserStencilSettings*,
                             SkRegion::Op op,
                             bool invert,
@@ -99,7 +99,7 @@
 
     using WillAddOpFn = GrRenderTargetContext::WillAddOpFn;
     void testingOnly_addDrawOp(std::unique_ptr<GrDrawOp>);
-    void testingOnly_addDrawOp(const GrClip&, std::unique_ptr<GrDrawOp>,
+    void testingOnly_addDrawOp(const GrClip*, std::unique_ptr<GrDrawOp>,
                                const std::function<WillAddOpFn>& = std::function<WillAddOpFn>());
 
     bool refsWrappedObjects() const {
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index ec0ce46..9212325 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -68,15 +68,17 @@
 // Gets the shape bounds, the clip bounds, and the intersection (if any). Returns false if there
 // is no intersection.
 bool GrSoftwarePathRenderer::GetShapeAndClipBounds(GrRenderTargetContext* renderTargetContext,
-                                                   const GrClip& clip,
+                                                   const GrClip* clip,
                                                    const GrStyledShape& shape,
                                                    const SkMatrix& matrix,
                                                    SkIRect* unclippedDevShapeBounds,
                                                    SkIRect* clippedDevShapeBounds,
                                                    SkIRect* devClipBounds) {
     // compute bounds as intersection of rt size, clip, and path
-    *devClipBounds = clip.getConservativeBounds(renderTargetContext->width(),
-                                                renderTargetContext->height());
+    *devClipBounds = clip ? clip->getConservativeBounds(renderTargetContext->width(),
+                                                        renderTargetContext->height())
+                          : SkIRect::MakeWH(renderTargetContext->width(),
+                                            renderTargetContext->height());
 
     if (!get_unclipped_shape_dev_bounds(shape, matrix, unclippedDevShapeBounds)) {
         *unclippedDevShapeBounds = SkIRect::MakeEmpty();
@@ -95,7 +97,7 @@
 void GrSoftwarePathRenderer::DrawNonAARect(GrRenderTargetContext* renderTargetContext,
                                            GrPaint&& paint,
                                            const GrUserStencilSettings& userStencilSettings,
-                                           const GrClip& clip,
+                                           const GrClip* clip,
                                            const SkMatrix& viewMatrix,
                                            const SkRect& rect,
                                            const SkMatrix& localMatrix) {
@@ -106,7 +108,7 @@
 void GrSoftwarePathRenderer::DrawAroundInvPath(GrRenderTargetContext* renderTargetContext,
                                                GrPaint&& paint,
                                                const GrUserStencilSettings& userStencilSettings,
-                                               const GrClip& clip,
+                                               const GrClip* clip,
                                                const SkMatrix& viewMatrix,
                                                const SkIRect& devClipBounds,
                                                const SkIRect& devPathBounds) {
@@ -147,7 +149,7 @@
         GrRenderTargetContext* renderTargetContext,
         GrPaint&& paint,
         const GrUserStencilSettings& userStencilSettings,
-        const GrClip& clip,
+        const GrClip* clip,
         const SkMatrix& viewMatrix,
         const SkIPoint& textureOriginInDeviceSpace,
         const SkIRect& deviceSpaceRectToDraw) {
@@ -241,13 +243,13 @@
                     args.fShape->hasUnstyledKey() && (GrAAType::kCoverage == args.fAAType);
 
     if (!GetShapeAndClipBounds(args.fRenderTargetContext,
-                               *args.fClip, *args.fShape,
+                               args.fClip, *args.fShape,
                                *args.fViewMatrix, &unclippedDevShapeBounds,
                                &clippedDevShapeBounds,
                                &devClipBounds)) {
         if (inverseFilled) {
             DrawAroundInvPath(args.fRenderTargetContext, std::move(args.fPaint),
-                              *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix,
+                              *args.fUserStencilSettings, args.fClip, *args.fViewMatrix,
                               devClipBounds, unclippedDevShapeBounds);
         }
         return true;
@@ -382,11 +384,11 @@
     SkASSERT(view);
     if (inverseFilled) {
         DrawAroundInvPath(args.fRenderTargetContext, GrPaint::Clone(args.fPaint),
-                          *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix, devClipBounds,
+                          *args.fUserStencilSettings, args.fClip, *args.fViewMatrix, devClipBounds,
                           unclippedDevShapeBounds);
     }
     DrawToTargetWithShapeMask(std::move(view), args.fRenderTargetContext, std::move(args.fPaint),
-                              *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix,
+                              *args.fUserStencilSettings, args.fClip, *args.fViewMatrix,
                               SkIPoint{boundsForMask->fLeft, boundsForMask->fTop}, *boundsForMask);
 
     return true;
diff --git a/src/gpu/GrSoftwarePathRenderer.h b/src/gpu/GrSoftwarePathRenderer.h
index d24d48a..7b93166 100644
--- a/src/gpu/GrSoftwarePathRenderer.h
+++ b/src/gpu/GrSoftwarePathRenderer.h
@@ -27,7 +27,7 @@
     }
 
     static bool GetShapeAndClipBounds(GrRenderTargetContext*,
-                                      const GrClip& clip,
+                                      const GrClip* clip,
                                       const GrStyledShape& shape,
                                       const SkMatrix& matrix,
                                       SkIRect* unclippedDevShapeBounds,
@@ -38,14 +38,14 @@
     static void DrawNonAARect(GrRenderTargetContext* renderTargetContext,
                               GrPaint&& paint,
                               const GrUserStencilSettings& userStencilSettings,
-                              const GrClip& clip,
+                              const GrClip* clip,
                               const SkMatrix& viewMatrix,
                               const SkRect& rect,
                               const SkMatrix& localMatrix);
     static void DrawAroundInvPath(GrRenderTargetContext* renderTargetContext,
                                   GrPaint&& paint,
                                   const GrUserStencilSettings& userStencilSettings,
-                                  const GrClip& clip,
+                                  const GrClip* clip,
                                   const SkMatrix& viewMatrix,
                                   const SkIRect& devClipBounds,
                                   const SkIRect& devPathBounds);
@@ -57,7 +57,7 @@
                                           GrRenderTargetContext* renderTargetContext,
                                           GrPaint&& paint,
                                           const GrUserStencilSettings& userStencilSettings,
-                                          const GrClip& clip,
+                                          const GrClip* clip,
                                           const SkMatrix& viewMatrix,
                                           const SkIPoint& textureOriginInDeviceSpace,
                                           const SkIRect& deviceSpaceRectToDraw);
diff --git a/src/gpu/GrStencilMaskHelper.cpp b/src/gpu/GrStencilMaskHelper.cpp
index 3adab6d..c4bd9b9 100644
--- a/src/gpu/GrStencilMaskHelper.cpp
+++ b/src/gpu/GrStencilMaskHelper.cpp
@@ -278,7 +278,7 @@
                               const SkRect& rect, GrAA aa) {
     GrPaint paint;
     paint.setXPFactory(GrDisableColorXPFactory::Get());
-    rtc->priv().stencilRect(clip, ss, std::move(paint), aa, matrix, rect);
+    rtc->priv().stencilRect(&clip, ss, std::move(paint), aa, matrix, rect);
 }
 
 static void draw_path(GrRecordingContext* context, GrRenderTargetContext* rtc,
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index 3e8aa6b..9805dd8 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -10,7 +10,6 @@
 #include "include/private/GrRecordingContext.h"
 #include "src/core/SkAutoPixmapStorage.h"
 #include "src/gpu/GrAuditTrail.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrDataUtils.h"
 #include "src/gpu/GrDrawingManager.h"
@@ -240,7 +239,7 @@
         paint.addColorFragmentProcessor(std::move(fp));
 
         tempCtx->asRenderTargetContext()->fillRectToRect(
-                GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+                nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                 SkRect::MakeWH(dstInfo.width(), dstInfo.height()),
                 SkRect::MakeXYWH(pt.fX, pt.fY, dstInfo.width(), dstInfo.height()));
 
@@ -426,7 +425,7 @@
             paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
             paint.addColorFragmentProcessor(std::move(fp));
             this->asRenderTargetContext()->fillRectToRect(
-                    GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+                    nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                     SkRect::MakeXYWH(pt.fX, pt.fY, srcInfo.width(), srcInfo.height()),
                     SkRect::MakeWH(srcInfo.width(), srcInfo.height()));
         } else {
@@ -553,7 +552,7 @@
             return nullptr;
         }
         // 1-to-1 draw can always be kFast.
-        linearRTC->drawTexture(GrNoClip(), std::move(texView), srcAlphaType,
+        linearRTC->drawTexture(nullptr, std::move(texView), srcAlphaType,
                                GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
                                SK_PMColor4fWHITE, SkRect::Make(srcRect),
                                SkRect::Make(srcRect.size()), GrAA::kNo, GrQuadAAFlags::kNone,
@@ -619,8 +618,8 @@
             GrPaint paint;
             paint.addColorFragmentProcessor(std::move(fp));
             paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-            tempB->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
-                                  dstRect);
+            tempB->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
+                                    dstRect);
         } else {
             auto filter = rescaleQuality == kNone_SkFilterQuality ? GrSamplerState::Filter::kNearest
                                                                   : GrSamplerState::Filter::kBilerp;
@@ -629,10 +628,9 @@
             if (nextDims.width() <= srcRect.width() && nextDims.height() <= srcRect.height()) {
                 constraint = SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint;
             }
-            tempB->drawTexture(GrNoClip(), std::move(texView), srcAlphaType, filter,
-                               SkBlendMode::kSrc, SK_PMColor4fWHITE, SkRect::Make(srcRect), dstRect,
-                               GrAA::kNo, GrQuadAAFlags::kNone, constraint, SkMatrix::I(),
-                               std::move(xform));
+            tempB->drawTexture(nullptr, std::move(texView), srcAlphaType, filter, SkBlendMode::kSrc,
+                               SK_PMColor4fWHITE, SkRect::Make(srcRect), dstRect, GrAA::kNo,
+                               GrQuadAAFlags::kNone, constraint, SkMatrix::I(), std::move(xform));
         }
         texView = tempB->readSurfaceView();
         tempA = std::move(tempB);
@@ -715,4 +713,3 @@
     this->onValidate();
 }
 #endif
-
diff --git a/src/gpu/GrYUVProvider.cpp b/src/gpu/GrYUVProvider.cpp
index 6a25a79..3d5668c 100644
--- a/src/gpu/GrYUVProvider.cpp
+++ b/src/gpu/GrYUVProvider.cpp
@@ -16,7 +16,6 @@
 #include "src/core/SkYUVPlanesCache.h"
 #include "src/gpu/GrBitmapTextureMaker.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrColorSpaceXform.h"
 #include "src/gpu/GrProxyProvider.h"
 #include "src/gpu/GrRecordingContextPriv.h"
@@ -191,7 +190,7 @@
                                      yuvSizeInfo.fSizes[0].fHeight);
 
     SkMatrix m = SkEncodedOriginToMatrix(yuvSizeInfo.fOrigin, r.width(), r.height());
-    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, m, r);
+    renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, m, r);
 
     SkASSERT(renderTargetContext->asTextureProxy());
     return renderTargetContext->readSurfaceView();
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 2e1d9e8..e7df248 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -125,7 +125,8 @@
         : INHERITED(make_info(renderTargetContext.get(), SkToBool(flags & kIsOpaque_Flag)),
                     renderTargetContext->surfaceProps())
         , fContext(SkRef(context))
-        , fRenderTargetContext(std::move(renderTargetContext)) {
+        , fRenderTargetContext(std::move(renderTargetContext))
+        , fClip(&this->cs()) {
     if (flags & kNeedClear_Flag) {
         this->clearAll();
     }
@@ -721,13 +722,16 @@
             SkRect clipGeometry = SkRect::MakeWH(clipImage->width(), clipImage->height());
             if (!clipGeometry.contains(inverseClipMatrix.mapRect(dstRect))) {
                 // Draw the clip geometry since it is smaller, using dstRect as an extra scissor
-                SkClipStack clip(this->cs());
-                clip.clipDevRect(SkIRect::MakeXYWH(left, top, subset.width(), subset.height()),
-                                 SkClipOp::kIntersect);
+                SkClipStack dstRectClip(this->cs());
+                dstRectClip.clipDevRect(
+                        SkIRect::MakeXYWH(left, top, subset.width(), subset.height()),
+                        SkClipOp::kIntersect);
+                GrClipStackClip clip(&dstRectClip);
                 SkMatrix local = SkMatrix::Concat(SkMatrix::MakeRectToRect(
                         dstRect, srcRect, SkMatrix::kFill_ScaleToFit), ctm);
-                fRenderTargetContext->fillRectWithLocalMatrix(GrClipStackClip(&clip),
-                        std::move(grPaint), GrAA(paint.isAntiAlias()), ctm, clipGeometry, local);
+                fRenderTargetContext->fillRectWithLocalMatrix(&clip, std::move(grPaint),
+                                                              GrAA(paint.isAntiAlias()), ctm,
+                                                              clipGeometry, local);
                 return;
             }
             // Else fall through and draw the subset since that is contained in the clip geometry
@@ -1136,7 +1140,6 @@
     }
     GrPaint grPaint;
     grPaint.setXPFactory(GrDisableColorXPFactory::Get());
-    GrNoClip noClip;
     static constexpr GrUserStencilSettings kDrawToStencil(
         GrUserStencilSettings::StaticInit<
             0x1,
@@ -1146,7 +1149,7 @@
             GrUserStencilOp::kReplace,
             0x1>()
     );
-    rtc->drawRegion(noClip, std::move(grPaint), GrAA::kNo, SkMatrix::I(), clipRegion,
+    rtc->drawRegion(nullptr, std::move(grPaint), GrAA::kNo, SkMatrix::I(), clipRegion,
                     GrStyle::SimpleFill(), &kDrawToStencil);
     return true;
 }
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 664aaf0..870ecdd 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -129,6 +129,7 @@
     // We want these unreffed in RenderTargetContext, GrContext order.
     sk_sp<GrContext> fContext;
     std::unique_ptr<GrRenderTargetContext> fRenderTargetContext;
+    GrClipStackClip  fClip;
 
     enum Flags {
         kNeedClear_Flag = 1 << 0,  //!< Surface requires an initial clear
@@ -148,7 +149,7 @@
 
     bool forceConservativeRasterClip() const override { return true; }
 
-    GrClipStackClip clip() const { return GrClipStackClip(&this->cs()); }
+    const GrClip* clip() const { return &fClip; }
 
     sk_sp<SkSpecialImage> filterTexture(SkSpecialImage*,
                                         int left, int top,
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index 3534b6c..c19971f 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -125,12 +125,13 @@
 // Given a bitmap, an optional src rect, and a context with a clip and matrix determine what
 // pixels from the bitmap are necessary.
 static SkIRect determine_clipped_src_rect(int width, int height,
-                                          const GrClip& clip,
+                                          const GrClip* clip,
                                           const SkMatrix& viewMatrix,
                                           const SkMatrix& srcToDstRect,
                                           const SkISize& imageDimensions,
                                           const SkRect* srcRectPtr) {
-    SkIRect clippedSrcIRect = clip.getConservativeBounds(width, height);
+    SkIRect clippedSrcIRect = clip ? clip->getConservativeBounds(width, height)
+                                   : SkIRect::MakeWH(width, height);
     SkMatrix inv = SkMatrix::Concat(viewMatrix, srcToDstRect);
     if (!inv.invert(&inv)) {
         return SkIRect::MakeEmpty();
@@ -154,7 +155,7 @@
 // tileSize and clippedSubset are valid if true is returned
 static bool should_tile_image_id(GrContext* context,
                                  SkISize rtSize,
-                                 const GrClip& clip,
+                                 const GrClip* clip,
                                  uint32_t imageID,
                                  const SkISize& imageSize,
                                  const SkMatrix& ctm,
@@ -319,7 +320,7 @@
 }
 
 // Assumes srcRect and dstRect have already been optimized to fit the proxy
-static void draw_texture(GrRenderTargetContext* rtc, const GrClip& clip, const SkMatrix& ctm,
+static void draw_texture(GrRenderTargetContext* rtc, const GrClip* clip, const SkMatrix& ctm,
                          const SkPaint& paint, const SkRect& srcRect, const SkRect& dstRect,
                          const SkPoint dstClip[4], GrAA aa, GrQuadAAFlags aaFlags,
                          SkCanvas::SrcRectConstraint constraint, GrSurfaceProxyView view,
@@ -382,7 +383,7 @@
 // Assumes srcRect and dstRect have already been optimized to fit the proxy.
 static void draw_texture_producer(GrContext* context,
                                   GrRenderTargetContext* rtc,
-                                  const GrClip& clip,
+                                  const GrClip* clip,
                                   const SkMatrixProvider& matrixProvider,
                                   const SkPaint& paint,
                                   GrTextureProducer* producer,
@@ -510,7 +511,7 @@
 
 void draw_tiled_bitmap(GrContext* context,
                        GrRenderTargetContext* rtc,
-                       const GrClip& clip,
+                       const GrClip* clip,
                        const SkBitmap& bitmap,
                        int tileSize,
                        const SkMatrixProvider& matrixProvider,
diff --git a/src/gpu/ccpr/GrCCPerFlushResources.cpp b/src/gpu/ccpr/GrCCPerFlushResources.cpp
index 9101b1d..dde97ae 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.cpp
+++ b/src/gpu/ccpr/GrCCPerFlushResources.cpp
@@ -8,7 +8,6 @@
 #include "src/gpu/ccpr/GrCCPerFlushResources.h"
 
 #include "include/private/GrRecordingContext.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrMemoryPool.h"
 #include "src/gpu/GrOnFlushResourceProvider.h"
 #include "src/gpu/GrRecordingContextPriv.h"
@@ -541,7 +540,7 @@
                 auto op = CopyAtlasOp::Make(
                         rtc->surfPriv().getContext(), sk_ref_sp(this), copyRange.fSrcProxy,
                         baseCopyInstance, endCopyInstance, atlas.drawBounds());
-                rtc->addDrawOp(GrNoClip(), std::move(op));
+                rtc->addDrawOp(nullptr, std::move(op));
             }
             baseCopyInstance = endCopyInstance;
         }
@@ -580,7 +579,7 @@
                         rtc->surfPriv().getContext(), sk_ref_sp(this), atlas.getFillBatchID(),
                         atlas.getStrokeBatchID(), atlas.drawBounds());
             }
-            rtc->addDrawOp(GrNoClip(), std::move(op));
+            rtc->addDrawOp(nullptr, std::move(op));
             if (rtc->asSurfaceProxy()->requiresManualMSAAResolve()) {
                 onFlushRP->addTextureResolveTask(sk_ref_sp(rtc->asTextureProxy()),
                                                  GrSurfaceProxy::ResolveFlags::kMSAA);
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index bc56c5d..eb4cae7 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -9,8 +9,8 @@
 
 #include "include/pathops/SkPathOps.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrProxyProvider.h"
+#include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/ccpr/GrCCClipProcessor.h"
 #include "src/gpu/ccpr/GrCCDrawPathsOp.h"
 #include "src/gpu/ccpr/GrCCPathCache.h"
@@ -167,11 +167,8 @@
 bool GrCoverageCountingPathRenderer::onDrawPath(const DrawPathArgs& args) {
     SkASSERT(!fFlushing);
 
-    GrRenderTargetContext* rtc = args.fRenderTargetContext;
-    SkIRect clipIBounds = args.fClip->getConservativeBounds(rtc->width(), rtc->height());
-
-    auto op = GrCCDrawPathsOp::Make(args.fContext, clipIBounds, *args.fViewMatrix, *args.fShape,
-                                    std::move(args.fPaint));
+    auto op = GrCCDrawPathsOp::Make(args.fContext, *args.fClipConservativeBounds, *args.fViewMatrix,
+                                    *args.fShape, std::move(args.fPaint));
     this->recordOp(std::move(op), args);
     return true;
 }
@@ -183,7 +180,7 @@
             op->cast<GrCCDrawPathsOp>()->addToOwningPerOpsTaskPaths(
                     sk_ref_sp(this->lookupPendingPaths(opsTaskID)));
         };
-        args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op),
+        args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op),
                                              addToOwningPerOpsTaskPaths);
     }
 }
diff --git a/src/gpu/effects/GrConfigConversionEffect.fp b/src/gpu/effects/GrConfigConversionEffect.fp
index 6e08ad3..c66f283 100644
--- a/src/gpu/effects/GrConfigConversionEffect.fp
+++ b/src/gpu/effects/GrConfigConversionEffect.fp
@@ -8,7 +8,6 @@
 @header {
     #include "include/gpu/GrContext.h"
     #include "src/gpu/GrBitmapTextureMaker.h"
-    #include "src/gpu/GrClip.h"
     #include "src/gpu/GrContextPriv.h"
     #include "src/gpu/GrImageInfo.h"
     #include "src/gpu/GrRenderTargetContext.h"
@@ -84,8 +83,7 @@
         paint1.addColorFragmentProcessor(pmToUPM->clone());
         paint1.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
-        readRTC->fillRectToRect(GrNoClip(), std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect,
-                                kRect);
+        readRTC->fillRectToRect(nullptr, std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect, kRect);
         if (!readRTC->readPixels(ii, firstRead, 0, {0, 0})) {
             return false;
         }
@@ -99,16 +97,14 @@
         paint2.addColorFragmentProcessor(std::move(upmToPM));
         paint2.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
-        tempRTC->fillRectToRect(GrNoClip(), std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect,
-                                kRect);
+        tempRTC->fillRectToRect(nullptr, std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect, kRect);
 
         paint3.addColorFragmentProcessor(GrTextureEffect::Make(tempRTC->readSurfaceView(),
                                                                kPremul_SkAlphaType));
         paint3.addColorFragmentProcessor(std::move(pmToUPM));
         paint3.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
-        readRTC->fillRectToRect(GrNoClip(), std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect,
-                                kRect);
+        readRTC->fillRectToRect(nullptr, std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect, kRect);
 
         if (!readRTC->readPixels(ii, secondRead, 0, {0, 0})) {
             return false;
diff --git a/src/gpu/effects/GrRRectBlurEffect.fp b/src/gpu/effects/GrRRectBlurEffect.fp
index 739dc40..8a66bc2 100644
--- a/src/gpu/effects/GrRRectBlurEffect.fp
+++ b/src/gpu/effects/GrRRectBlurEffect.fp
@@ -19,7 +19,6 @@
     #include "src/core/SkGpuBlurUtils.h"
     #include "src/core/SkRRectPriv.h"
     #include "src/gpu/GrCaps.h"
-    #include "src/gpu/GrClip.h"
     #include "src/gpu/GrPaint.h"
     #include "src/gpu/GrProxyProvider.h"
     #include "src/gpu/GrRecordingContextPriv.h"
@@ -65,7 +64,7 @@
         GrPaint paint;
 
         rtc->clear(SK_PMColor4fTRANSPARENT);
-        rtc->drawRRect(GrNoClip(), std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw,
+        rtc->drawRRect(nullptr, std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw,
                        GrStyle::SimpleFill());
 
         GrSurfaceProxyView srcView = rtc->readSurfaceView();
diff --git a/src/gpu/effects/generated/GrConfigConversionEffect.h b/src/gpu/effects/generated/GrConfigConversionEffect.h
index f6172b9..1c8c1b6 100644
--- a/src/gpu/effects/generated/GrConfigConversionEffect.h
+++ b/src/gpu/effects/generated/GrConfigConversionEffect.h
@@ -15,7 +15,6 @@
 
 #include "include/gpu/GrContext.h"
 #include "src/gpu/GrBitmapTextureMaker.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrImageInfo.h"
 #include "src/gpu/GrRenderTargetContext.h"
@@ -93,8 +92,7 @@
         paint1.addColorFragmentProcessor(pmToUPM->clone());
         paint1.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
-        readRTC->fillRectToRect(GrNoClip(), std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect,
-                                kRect);
+        readRTC->fillRectToRect(nullptr, std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect, kRect);
         if (!readRTC->readPixels(ii, firstRead, 0, {0, 0})) {
             return false;
         }
@@ -108,16 +106,14 @@
         paint2.addColorFragmentProcessor(std::move(upmToPM));
         paint2.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
-        tempRTC->fillRectToRect(GrNoClip(), std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect,
-                                kRect);
+        tempRTC->fillRectToRect(nullptr, std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect, kRect);
 
         paint3.addColorFragmentProcessor(
                 GrTextureEffect::Make(tempRTC->readSurfaceView(), kPremul_SkAlphaType));
         paint3.addColorFragmentProcessor(std::move(pmToUPM));
         paint3.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
-        readRTC->fillRectToRect(GrNoClip(), std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect,
-                                kRect);
+        readRTC->fillRectToRect(nullptr, std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect, kRect);
 
         if (!readRTC->readPixels(ii, secondRead, 0, {0, 0})) {
             return false;
diff --git a/src/gpu/effects/generated/GrRRectBlurEffect.h b/src/gpu/effects/generated/GrRRectBlurEffect.h
index e26a5c9..bf19d5c 100644
--- a/src/gpu/effects/generated/GrRRectBlurEffect.h
+++ b/src/gpu/effects/generated/GrRRectBlurEffect.h
@@ -19,7 +19,6 @@
 #include "src/core/SkGpuBlurUtils.h"
 #include "src/core/SkRRectPriv.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrPaint.h"
 #include "src/gpu/GrProxyProvider.h"
 #include "src/gpu/GrRecordingContextPriv.h"
@@ -67,7 +66,7 @@
         GrPaint paint;
 
         rtc->clear(SK_PMColor4fTRANSPARENT);
-        rtc->drawRRect(GrNoClip(), std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw,
+        rtc->drawRRect(nullptr, std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw,
                        GrStyle::SimpleFill());
 
         GrSurfaceProxyView srcView = rtc->readSurfaceView();
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index e427a4a..70eb0ba 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -915,7 +915,7 @@
     std::unique_ptr<GrDrawOp> op = AAConvexPathOp::Make(args.fContext, std::move(args.fPaint),
                                                         *args.fViewMatrix,
                                                         path, args.fUserStencilSettings);
-    args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+    args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
     return true;
 }
 
diff --git a/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
index 537d0f1..8a0a1b8 100644
--- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
@@ -15,12 +15,12 @@
 #include "src/gpu/GrAuditTrail.h"
 #include "src/gpu/GrBuffer.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrDefaultGeoProcFactory.h"
 #include "src/gpu/GrDrawOpTest.h"
 #include "src/gpu/GrOpFlushState.h"
 #include "src/gpu/GrProcessor.h"
 #include "src/gpu/GrProgramInfo.h"
+#include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrResourceProvider.h"
 #include "src/gpu/GrStyle.h"
 #include "src/gpu/effects/GrBezierEffect.h"
@@ -1272,14 +1272,13 @@
                               "GrAAHairlinePathRenderer::onDrawPath");
     SkASSERT(args.fRenderTargetContext->numSamples() <= 1);
 
-    SkIRect devClipBounds = args.fClip->getConservativeBounds(args.fRenderTargetContext->width(),
-                                                              args.fRenderTargetContext->height());
     SkPath path;
     args.fShape->asPath(&path);
     std::unique_ptr<GrDrawOp> op =
             AAHairlineOp::Make(args.fContext, std::move(args.fPaint), *args.fViewMatrix, path,
-                               args.fShape->style(), devClipBounds, args.fUserStencilSettings);
-    args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+                               args.fShape->style(), *args.fClipConservativeBounds,
+                               args.fUserStencilSettings);
+    args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
     return true;
 }
 
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index d6d6449..9c67fd8 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -405,7 +405,7 @@
     std::unique_ptr<GrDrawOp> op = AAFlatteningConvexPathOp::Make(
             args.fContext, std::move(args.fPaint), *args.fViewMatrix, path, strokeWidth,
             stroke.getStyle(), join, miterLimit, args.fUserStencilSettings);
-    args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+    args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
     return true;
 }
 
diff --git a/src/gpu/ops/GrDashLinePathRenderer.cpp b/src/gpu/ops/GrDashLinePathRenderer.cpp
index 96fc06c..e5cf9e4 100644
--- a/src/gpu/ops/GrDashLinePathRenderer.cpp
+++ b/src/gpu/ops/GrDashLinePathRenderer.cpp
@@ -53,6 +53,6 @@
     if (!op) {
         return false;
     }
-    args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+    args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
     return true;
 }
diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp
index 7f4f634..6b906b6 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -537,7 +537,7 @@
                                              GrPaint&& paint,
                                              GrAAType aaType,
                                              const GrUserStencilSettings& userStencilSettings,
-                                             const GrClip& clip,
+                                             const GrClip* clip,
                                              const SkMatrix& viewMatrix,
                                              const GrStyledShape& shape,
                                              bool stencilOnly) {
@@ -705,7 +705,7 @@
 
     return this->internalDrawPath(
             args.fRenderTargetContext, std::move(args.fPaint), aaType, *args.fUserStencilSettings,
-            *args.fClip, *args.fViewMatrix, *args.fShape, false);
+            args.fClip, *args.fViewMatrix, *args.fShape, false);
 }
 
 void GrDefaultPathRenderer::onStencilPath(const StencilPathArgs& args) {
@@ -720,7 +720,7 @@
 
     this->internalDrawPath(
             args.fRenderTargetContext, std::move(paint), aaType, GrUserStencilSettings::kUnused,
-            *args.fClip, *args.fViewMatrix, *args.fShape, true);
+            args.fClip, *args.fViewMatrix, *args.fShape, true);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/ops/GrDefaultPathRenderer.h b/src/gpu/ops/GrDefaultPathRenderer.h
index e709964..7b0a32d 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.h
+++ b/src/gpu/ops/GrDefaultPathRenderer.h
@@ -35,7 +35,7 @@
                           GrPaint&&,
                           GrAAType,
                           const GrUserStencilSettings&,
-                          const GrClip&,
+                          const GrClip*,
                           const SkMatrix& viewMatrix,
                           const GrStyledShape&,
                           bool stencilOnly);
diff --git a/src/gpu/ops/GrFillRectOp.cpp b/src/gpu/ops/GrFillRectOp.cpp
index 9e27f9d..645a0f7 100644
--- a/src/gpu/ops/GrFillRectOp.cpp
+++ b/src/gpu/ops/GrFillRectOp.cpp
@@ -524,7 +524,7 @@
 }
 
 void GrFillRectOp::AddFillRectOps(GrRenderTargetContext* rtc,
-                                  const GrClip& clip,
+                                  const GrClip* clip,
                                   GrRecordingContext* context,
                                   GrPaint&& paint,
                                   GrAAType aaType,
diff --git a/src/gpu/ops/GrFillRectOp.h b/src/gpu/ops/GrFillRectOp.h
index 947ee7c..4a8f211 100644
--- a/src/gpu/ops/GrFillRectOp.h
+++ b/src/gpu/ops/GrFillRectOp.h
@@ -49,7 +49,7 @@
     // Bulk API for drawing quads with a single op
     // TODO(michaelludwig) - remove if the bulk API is not useful for SkiaRenderer
     static void AddFillRectOps(GrRenderTargetContext*,
-                               const GrClip& clip,
+                               const GrClip* clip,
                                GrRecordingContext*,
                                GrPaint&&,
                                GrAAType,
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 075376d..0f3ab8a 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -885,7 +885,7 @@
     std::unique_ptr<GrDrawOp> op = SmallPathOp::Make(
             args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix, fAtlas.get(),
             &fShapeCache, &fShapeList, args.fGammaCorrect, args.fUserStencilSettings);
-    args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+    args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
 
     return true;
 }
diff --git a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
index 59a8bf7..61f6a11 100644
--- a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
@@ -101,7 +101,7 @@
                               "GrStencilAndCoverPathRenderer::onStencilPath");
     sk_sp<GrPath> p(get_gr_path(fResourceProvider, *args.fShape));
     args.fRenderTargetContext->priv().stencilPath(
-            *args.fClip, args.fDoStencilMSAA, *args.fViewMatrix, std::move(p));
+            args.fClip, args.fDoStencilMSAA, *args.fViewMatrix, std::move(p));
 }
 
 bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) {
@@ -126,7 +126,7 @@
 
         // fake inverse with a stencil and cover
         GrAppliedClip appliedClip;
-        if (!args.fClip->apply(
+        if (args.fClip && !args.fClip->apply(
                 args.fContext, args.fRenderTargetContext, doStencilMSAA, true, &appliedClip,
                 &devBounds)) {
             return true;
@@ -142,7 +142,7 @@
         // Just ignore the analytic FPs (if any) during the stencil pass. They will still clip the
         // final draw and it is meaningless to multiply by coverage when drawing to stencil.
         args.fRenderTargetContext->priv().stencilPath(
-                stencilClip, GrAA(doStencilMSAA), viewMatrix, std::move(path));
+                &stencilClip, GrAA(doStencilMSAA), viewMatrix, std::move(path));
 
         {
             static constexpr GrUserStencilSettings kInvertedCoverPass(
@@ -179,14 +179,14 @@
                 doStencilMSAA = GrAA::kYes;
             }
             args.fRenderTargetContext->priv().stencilRect(
-                    *args.fClip, &kInvertedCoverPass, std::move(args.fPaint), doStencilMSAA,
+                    args.fClip, &kInvertedCoverPass, std::move(args.fPaint), doStencilMSAA,
                     coverMatrix, coverBounds, &localMatrix);
         }
     } else {
         std::unique_ptr<GrDrawOp> op = GrDrawPathOp::Make(
                 args.fContext, viewMatrix, std::move(args.fPaint), GrAA(doStencilMSAA),
                 std::move(path));
-        args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+        args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
     }
 
     return true;
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 6beebd4..fb1958b 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -1057,7 +1057,7 @@
 class GrTextureOp::BatchSizeLimiter {
 public:
     BatchSizeLimiter(GrRenderTargetContext* rtc,
-                     const GrClip& clip,
+                     const GrClip* clip,
                      GrRecordingContext* context,
                      int numEntries,
                      GrSamplerState::Filter filter,
@@ -1095,7 +1095,7 @@
 
 private:
     GrRenderTargetContext*      fRTC;
-    const GrClip&               fClip;
+    const GrClip*               fClip;
     GrRecordingContext*         fContext;
     GrSamplerState::Filter      fFilter;
     GrTextureOp::Saturate       fSaturate;
@@ -1109,7 +1109,7 @@
 
 // Greedily clump quad draws together until the index buffer limit is exceeded.
 void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc,
-                                   const GrClip& clip,
+                                   const GrClip* clip,
                                    GrRecordingContext* context,
                                    GrRenderTargetContext::TextureSetEntry set[],
                                    int cnt,
diff --git a/src/gpu/ops/GrTextureOp.h b/src/gpu/ops/GrTextureOp.h
index 404535b..2c1f48e 100644
--- a/src/gpu/ops/GrTextureOp.h
+++ b/src/gpu/ops/GrTextureOp.h
@@ -56,7 +56,7 @@
     // supported, or if the blend mode is not src-over. 'cnt' is the size of the entry array.
     // 'proxyCnt' <= 'cnt' and represents the number of proxy switches within the array.
     static void AddTextureSetOps(GrRenderTargetContext*,
-                                 const GrClip& clip,
+                                 const GrClip* clip,
                                  GrRecordingContext*,
                                  GrRenderTargetContext::TextureSetEntry[],
                                  int cnt,
diff --git a/src/gpu/ops/GrTriangulatingPathRenderer.cpp b/src/gpu/ops/GrTriangulatingPathRenderer.cpp
index 67f8298..7e696c4 100644
--- a/src/gpu/ops/GrTriangulatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTriangulatingPathRenderer.cpp
@@ -11,12 +11,12 @@
 #include "src/core/SkGeometry.h"
 #include "src/gpu/GrAuditTrail.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrDefaultGeoProcFactory.h"
 #include "src/gpu/GrDrawOpTest.h"
 #include "src/gpu/GrEagerVertexAllocator.h"
 #include "src/gpu/GrOpFlushState.h"
 #include "src/gpu/GrProgramInfo.h"
+#include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrResourceCache.h"
 #include "src/gpu/GrResourceProvider.h"
 #include "src/gpu/GrSimpleMesh.h"
@@ -419,12 +419,11 @@
 bool GrTriangulatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
     GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
                               "GrTriangulatingPathRenderer::onDrawPath");
-    SkIRect clipBoundsI = args.fClip->getConservativeBounds(args.fRenderTargetContext->width(),
-                                                            args.fRenderTargetContext->height());
+
     std::unique_ptr<GrDrawOp> op = TriangulatingPathOp::Make(
-            args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix, clipBoundsI,
-            args.fAAType, args.fUserStencilSettings);
-    args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+            args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix,
+            *args.fClipConservativeBounds, args.fAAType, args.fUserStencilSettings);
+    args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
     return true;
 }
 
diff --git a/src/gpu/tessellate/GrTessellationPathRenderer.cpp b/src/gpu/tessellate/GrTessellationPathRenderer.cpp
index ab21f28..34fcfc0 100644
--- a/src/gpu/tessellate/GrTessellationPathRenderer.cpp
+++ b/src/gpu/tessellate/GrTessellationPathRenderer.cpp
@@ -74,13 +74,14 @@
         auto op = pool->allocate<GrDrawAtlasPathOp>(
                 renderTargetContext->numSamples(), sk_ref_sp(fAtlas.textureProxy()),
                 devIBounds, locationInAtlas, transposedInAtlas, *args.fViewMatrix,
-                std::move(args.fPaint)); renderTargetContext->addDrawOp(*args.fClip, std::move(op));
+                std::move(args.fPaint));
+        renderTargetContext->addDrawOp(args.fClip, std::move(op));
         return true;
     }
 
     auto op = pool->allocate<GrTessellatePathOp>(
             *args.fViewMatrix, path, std::move(args.fPaint), args.fAAType);
-    renderTargetContext->addDrawOp(*args.fClip, std::move(op));
+    renderTargetContext->addDrawOp(args.fClip, std::move(op));
     return true;
 }
 
@@ -149,7 +150,7 @@
 
     auto op = args.fContext->priv().opMemoryPool()->allocate<GrTessellatePathOp>(
             *args.fViewMatrix, path, GrPaint(), aaType, GrTessellatePathOp::Flags::kStencilOnly);
-    args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+    args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
 }
 
 void GrTessellationPathRenderer::preFlush(GrOnFlushResourceProvider* onFlushRP,
@@ -199,7 +200,7 @@
             auto op = onFlushRP->opMemoryPool()->allocate<GrTessellatePathOp>(
                     SkMatrix::I(), *uberPath, GrPaint(), aaType,
                     GrTessellatePathOp::Flags::kStencilOnly);
-            rtc->addDrawOp(GrNoClip(), std::move(op));
+            rtc->addDrawOp(nullptr, std::move(op));
         }
     }
 
@@ -235,7 +236,7 @@
 
     auto coverOp = GrFillRectOp::Make(rtc->surfPriv().getContext(), std::move(paint),
                                       GrAAType::kMSAA, &drawQuad, stencil, fillRectFlags);
-    rtc->addDrawOp(GrNoClip(), std::move(coverOp));
+    rtc->addDrawOp(nullptr, std::move(coverOp));
 
     if (rtc->asSurfaceProxy()->requiresManualMSAAResolve()) {
         onFlushRP->addTextureResolveTask(sk_ref_sp(rtc->asTextureProxy()),
diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp
index 2f5806f..2413c75 100644
--- a/src/gpu/text/GrTextBlob.cpp
+++ b/src/gpu/text/GrTextBlob.cpp
@@ -502,7 +502,7 @@
                        const SkSurfaceProps& props,
                        const SkPaint& paint,
                        const SkPMColor4f& filteredColor,
-                       const GrClip& clip,
+                       const GrClip* clip,
                        const SkMatrixProvider& deviceMatrix,
                        SkPoint drawOrigin) {
     for (SubRun* subRun = fFirstSubRun; subRun != nullptr; subRun = subRun->fNextSubRun) {
@@ -560,15 +560,14 @@
             bool skipClip = false;
             SkIRect clipRect = SkIRect::MakeEmpty();
             SkRect rtBounds = SkRect::MakeWH(target->width(), target->height());
-            SkRRect clipRRect;
+            SkRRect clipRRect = SkRRect::MakeRect(rtBounds);
             GrAA aa;
             // We can clip geometrically if we're not using SDFs or transformed glyphs,
             // and we have an axis-aligned rectangular non-AA clip
             if (!subRun->drawAsDistanceFields() &&
                 !subRun->needsTransform() &&
-                clip.isRRect(rtBounds, &clipRRect, &aa) &&
-                clipRRect.isRect() && GrAA::kNo == aa) {
-                skipClip = true;
+                (!clip || (clip->isRRect(rtBounds, &clipRRect, &aa) &&
+                           clipRRect.isRect() && GrAA::kNo == aa))) {
                 // We only need to do clipping work if the subrun isn't contained by the clip
                 SkRect subRunBounds = subRun->deviceRect(deviceMatrix.localToDevice(), drawOrigin);
                 if (!clipRRect.getBounds().contains(subRunBounds)) {
@@ -579,17 +578,13 @@
                         clipRRect.getBounds().round(&clipRect);
                     }
                 }
+                skipClip = true;
             }
 
             auto op = this->makeOp(subRun, deviceMatrix, drawOrigin, clipRect,
                                    paint, filteredColor, props, target);
             if (op) {
-                if (skipClip) {
-                    target->addDrawOp(GrNoClip(), std::move(op));
-                }
-                else {
-                    target->addDrawOp(clip, std::move(op));
-                }
+                target->addDrawOp(skipClip ? nullptr : clip, std::move(op));
             }
         }
     }
diff --git a/src/gpu/text/GrTextBlob.h b/src/gpu/text/GrTextBlob.h
index 58160c2..401f66c 100644
--- a/src/gpu/text/GrTextBlob.h
+++ b/src/gpu/text/GrTextBlob.h
@@ -131,7 +131,7 @@
                const SkSurfaceProps& props,
                const SkPaint& paint,
                const SkPMColor4f& filteredColor,
-               const GrClip& clip,
+               const GrClip* clip,
                const SkMatrixProvider& deviceMatrix,
                SkPoint drawOrigin);
 
diff --git a/src/gpu/text/GrTextContext.h b/src/gpu/text/GrTextContext.h
index 4b90239..d1e5573 100644
--- a/src/gpu/text/GrTextContext.h
+++ b/src/gpu/text/GrTextContext.h
@@ -47,7 +47,7 @@
 
     void drawGlyphRunList(GrRecordingContext*,
                           GrTextTarget*,
-                          const GrClip&,
+                          const GrClip*,
                           const SkMatrixProvider&,
                           const SkSurfaceProps&,
                           const SkGlyphRunList&) const;
diff --git a/src/gpu/text/GrTextTarget.h b/src/gpu/text/GrTextTarget.h
index 9f88eb7..7a834cc 100644
--- a/src/gpu/text/GrTextTarget.h
+++ b/src/gpu/text/GrTextTarget.h
@@ -31,9 +31,9 @@
 
     const GrColorInfo& colorInfo() const { return fColorInfo; }
 
-    virtual void addDrawOp(const GrClip&, std::unique_ptr<GrAtlasTextOp> op) = 0;
+    virtual void addDrawOp(const GrClip*, std::unique_ptr<GrAtlasTextOp> op) = 0;
 
-    virtual void drawShape(const GrClip&,
+    virtual void drawShape(const GrClip*,
                            const SkPaint&,
                            const SkMatrixProvider&,
                            const GrStyledShape&) = 0;
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 3abe49a..4c07c20 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -24,7 +24,6 @@
 #include "src/gpu/GrBackendTextureImageGenerator.h"
 #include "src/gpu/GrBitmapTextureMaker.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrColorSpaceXform.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrDrawingManager.h"
@@ -105,7 +104,7 @@
         paint.addColorFragmentProcessor(std::move(xform));
     }
 
-    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+    renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                   SkRect::MakeIWH(this->width(), this->height()));
     if (!renderTargetContext->asTextureProxy()) {
         return nullptr;
diff --git a/src/image/SkImage_GpuBase.cpp b/src/image/SkImage_GpuBase.cpp
index e156e4e..d676d25 100644
--- a/src/image/SkImage_GpuBase.cpp
+++ b/src/image/SkImage_GpuBase.cpp
@@ -13,7 +13,6 @@
 #include "include/private/GrRecordingContext.h"
 #include "src/core/SkBitmapCache.h"
 #include "src/core/SkTLList.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrImageInfo.h"
 #include "src/gpu/GrProxyProvider.h"
@@ -323,7 +322,7 @@
     }
     paint.addColorFragmentProcessor(std::move(fp));
 
-    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect);
+    renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), rect);
     return true;
 }
 
diff --git a/tests/BulkRectTest.cpp b/tests/BulkRectTest.cpp
index 3519b36..a4de496 100644
--- a/tests/BulkRectTest.cpp
+++ b/tests/BulkRectTest.cpp
@@ -5,7 +5,6 @@
  * found in the LICENSE file.
  */
 #include "src/core/SkBlendModePriv.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrProxyProvider.h"
 #include "src/gpu/GrRenderTargetContext.h"
@@ -54,7 +53,7 @@
 
     GrPaint paint;
     paint.setXPFactory(SkBlendMode_AsXPFactory(blendMode));
-    GrFillRectOp::AddFillRectOps(rtc.get(), GrNoClip(), context, std::move(paint), overallAA,
+    GrFillRectOp::AddFillRectOps(rtc.get(), nullptr, context, std::move(paint), overallAA,
                                  SkMatrix::I(), quads, requestedTotNumQuads);
 
     GrOpsTask* opsTask = rtc->testingOnly_PeekLastOpsTask();
@@ -105,7 +104,7 @@
         set[i].fAAFlags = perQuadAA(i);
     }
 
-    GrTextureOp::AddTextureSetOps(rtc.get(), GrNoClip(), context, set, requestedTotNumQuads,
+    GrTextureOp::AddTextureSetOps(rtc.get(), nullptr, context, set, requestedTotNumQuads,
                                   requestedTotNumQuads, // We alternate so proxyCnt == cnt
                                   GrSamplerState::Filter::kNearest,
                                   GrTextureOp::Saturate::kYes,
diff --git a/tests/DefaultPathRendererTest.cpp b/tests/DefaultPathRendererTest.cpp
index 2e886a3..26799dd 100644
--- a/tests/DefaultPathRendererTest.cpp
+++ b/tests/DefaultPathRendererTest.cpp
@@ -23,7 +23,6 @@
 #include "include/private/GrTypesPriv.h"
 #include "include/private/SkColorData.h"
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrFragmentProcessor.h"
 #include "src/gpu/GrImageInfo.h"
@@ -96,7 +95,7 @@
         auto fp = GrConstColorProcessor::Make(color, GrConstColorProcessor::InputMode::kIgnore);
         paint.addColorFragmentProcessor(std::move(fp));
 
-        rtc->drawPath(GrNoClip(), std::move(paint), GrAA::kNo,
+        rtc->drawPath(nullptr, std::move(paint), GrAA::kNo,
                       SkMatrix::I(), invPath, style);
 
         rtc->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo());
@@ -114,7 +113,7 @@
         auto fp = GrConstColorProcessor::Make(color, GrConstColorProcessor::InputMode::kIgnore);
         paint.addColorFragmentProcessor(std::move(fp));
 
-        rtc->drawPath(GrNoClip(), std::move(paint), GrAA::kNo,
+        rtc->drawPath(nullptr, std::move(paint), GrAA::kNo,
                       SkMatrix::I(), path, style);
 
         SkBitmap bm = read_back(rtc.get(), kBigSize, kBigSize);
diff --git a/tests/GrCCPRTest.cpp b/tests/GrCCPRTest.cpp
index 098c81a..53f9aaa 100644
--- a/tests/GrCCPRTest.cpp
+++ b/tests/GrCCPRTest.cpp
@@ -88,7 +88,6 @@
         GrPaint paint;
         paint.setColor4f({ 0, 1, 0, 1 });
 
-        GrNoClip noClip;
         SkIRect clipBounds = SkIRect::MakeWH(kCanvasSize, kCanvasSize);
 
         GrStyledShape shape;
@@ -104,7 +103,7 @@
         }
 
         fCCPR->testingOnly_drawPathDirectly({
-                fCtx.get(), std::move(paint), &GrUserStencilSettings::kUnused, fRTC.get(), &noClip,
+                fCtx.get(), std::move(paint), &GrUserStencilSettings::kUnused, fRTC.get(), nullptr,
                 &clipBounds, &matrix, &shape, GrAAType::kCoverage, false});
     }
 
@@ -114,7 +113,8 @@
         GrPaint paint;
         paint.setColor4f(color);
 
-        fRTC->drawRect(CCPRClip(fCCPR, clipPath), std::move(paint), GrAA::kYes, SkMatrix::I(),
+        CCPRClip clip(fCCPR, clipPath);
+        fRTC->drawRect(&clip, std::move(paint), GrAA::kYes, SkMatrix::I(),
                        SkRect::MakeIWH(kCanvasSize, kCanvasSize));
     }
 
diff --git a/tests/GrMipMappedTest.cpp b/tests/GrMipMappedTest.cpp
index 56a5ca4..d645c71 100644
--- a/tests/GrMipMappedTest.cpp
+++ b/tests/GrMipMappedTest.cpp
@@ -359,7 +359,7 @@
             context, colorType, nullptr, std::move(renderTarget), kTopLeft_GrSurfaceOrigin,
             nullptr);
 
-    rtc->drawTexture(GrNoClip(), std::move(mipmapView), alphaType, filter, SkBlendMode::kSrcOver,
+    rtc->drawTexture(nullptr, std::move(mipmapView), alphaType, filter, SkBlendMode::kSrcOver,
                      {1,1,1,1}, SkRect::MakeWH(4, 4), SkRect::MakeWH(1,1), GrAA::kYes,
                      GrQuadAAFlags::kAll, SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(),
                      nullptr);
diff --git a/tests/GrSurfaceTest.cpp b/tests/GrSurfaceTest.cpp
index 67b10a5..b6657c0 100644
--- a/tests/GrSurfaceTest.cpp
+++ b/tests/GrSurfaceTest.cpp
@@ -11,12 +11,12 @@
 #include "src/core/SkAutoPixmapStorage.h"
 #include "src/core/SkCompressedDataUtils.h"
 #include "src/gpu/GrBitmapTextureMaker.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrGpu.h"
 #include "src/gpu/GrImageInfo.h"
 #include "src/gpu/GrProxyProvider.h"
 #include "src/gpu/GrRenderTarget.h"
+#include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrResourceProvider.h"
 #include "src/gpu/GrTexture.h"
 #include "src/gpu/GrTexturePriv.h"
@@ -570,7 +570,7 @@
                 GrSwizzle readSwizzle = context->priv().caps()->getReadSwizzle(
                         backendFormat, GrColorType::kRGBA_8888);
                 GrSurfaceProxyView view(std::move(proxy), kTopLeft_GrSurfaceOrigin, readSwizzle);
-                rtc->drawTexture(GrNoClip(), view, kPremul_SkAlphaType,
+                rtc->drawTexture(nullptr, view, kPremul_SkAlphaType,
                                  GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
                                  SkPMColor4f(), SkRect::MakeWH(w, h), SkRect::MakeWH(w, h),
                                  GrAA::kNo, GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
@@ -584,7 +584,7 @@
                 REPORTER_ASSERT(reporter, idleIDs.find(2) == idleIDs.end());
 
                 // This time we move the proxy into the draw.
-                rtc->drawTexture(GrNoClip(), std::move(view), kPremul_SkAlphaType,
+                rtc->drawTexture(nullptr, std::move(view), kPremul_SkAlphaType,
                                  GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
                                  SkPMColor4f(), SkRect::MakeWH(w, h), SkRect::MakeWH(w, h),
                                  GrAA::kNo, GrQuadAAFlags::kNone,
@@ -635,7 +635,7 @@
                             GrSurfaceProxyView view(std::move(proxy), kTopLeft_GrSurfaceOrigin,
                                                     swizzle);
                             rtc->drawTexture(
-                                    GrNoClip(), std::move(view), kPremul_SkAlphaType,
+                                    nullptr, std::move(view), kPremul_SkAlphaType,
                                     GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
                                     SkPMColor4f(), SkRect::MakeWH(w, h), SkRect::MakeWH(w, h),
                                     GrAA::kNo, GrQuadAAFlags::kNone,
diff --git a/tests/LazyProxyTest.cpp b/tests/LazyProxyTest.cpp
index e56f029..9f30090 100644
--- a/tests/LazyProxyTest.cpp
+++ b/tests/LazyProxyTest.cpp
@@ -212,8 +212,9 @@
         auto mockAtlas = GrRenderTargetContext::Make(
                 ctx.get(), GrColorType::kAlpha_F16, nullptr, SkBackingFit::kExact, {10, 10});
         REPORTER_ASSERT(reporter, mockAtlas);
-        rtc->priv().testingOnly_addDrawOp(LazyProxyTest::Clip(&test, mockAtlas->asTextureProxy()),
-                        LazyProxyTest::Op::Make(ctx.get(), proxyProvider, &test, nullTexture));
+        LazyProxyTest::Clip clip(&test, mockAtlas->asTextureProxy());
+        rtc->priv().testingOnly_addDrawOp(
+                &clip, LazyProxyTest::Op::Make(ctx.get(), proxyProvider, &test, nullTexture));
         ctx->priv().testingOnly_flushAndRemoveOnFlushCallbackObject(&test);
     }
 }
diff --git a/tests/OnFlushCallbackTest.cpp b/tests/OnFlushCallbackTest.cpp
index b22c64b..e817b4a 100644
--- a/tests/OnFlushCallbackTest.cpp
+++ b/tests/OnFlushCallbackTest.cpp
@@ -10,7 +10,6 @@
 #include "include/core/SkBitmap.h"
 #include "include/gpu/GrBackendSemaphore.h"
 #include "src/core/SkPointPriv.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrDefaultGeoProcFactory.h"
 #include "src/gpu/GrImageInfo.h"
@@ -484,7 +483,7 @@
         AtlasedRectOp* sparePtr = op.get();
 
         uint32_t opsTaskID;
-        rtc->priv().testingOnly_addDrawOp(GrNoClip(), std::move(op),
+        rtc->priv().testingOnly_addDrawOp(nullptr, std::move(op),
                                           [&opsTaskID](GrOp* op, uint32_t id) { opsTaskID = id; });
         SkASSERT(SK_InvalidUniqueID != opsTaskID);
 
@@ -596,7 +595,7 @@
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
         paint.addColorFragmentProcessor(std::move(fp));
 
-        rtc->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), r);
+        rtc->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), r);
     }
 
     rtc->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo());
diff --git a/tests/PathRendererCacheTests.cpp b/tests/PathRendererCacheTests.cpp
index 33d351d..5251f55 100644
--- a/tests/PathRendererCacheTests.cpp
+++ b/tests/PathRendererCacheTests.cpp
@@ -9,8 +9,8 @@
 
 #include "include/core/SkPath.h"
 #include "include/gpu/GrContext.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrResourceCache.h"
 #include "src/gpu/GrSoftwarePathRenderer.h"
 #include "src/gpu/GrStyle.h"
@@ -38,7 +38,6 @@
     GrPaint paint;
     paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
 
-    GrNoClip noClip;
     SkIRect clipConservativeBounds = SkIRect::MakeWH(renderTargetContext->width(),
                                                      renderTargetContext->height());
     GrStyledShape shape(path, style);
@@ -51,7 +50,7 @@
                                       std::move(paint),
                                       &GrUserStencilSettings::kUnused,
                                       renderTargetContext,
-                                      &noClip,
+                                      nullptr,
                                       &clipConservativeBounds,
                                       &matrix,
                                       &shape,
diff --git a/tests/RectangleTextureTest.cpp b/tests/RectangleTextureTest.cpp
index d4bfe1f..bdb1926 100644
--- a/tests/RectangleTextureTest.cpp
+++ b/tests/RectangleTextureTest.cpp
@@ -9,7 +9,6 @@
 #include "tests/TestUtils.h"
 
 #include "include/gpu/GrContext.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrProxyProvider.h"
 #include "src/gpu/GrRenderTargetContext.h"
@@ -40,7 +39,7 @@
         GrPaint paint;
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
         paint.addColorFragmentProcessor(std::move(fp));
-        rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
+        rtContext->drawPaint(nullptr, std::move(paint), SkMatrix::I());
         TestReadPixels(reporter, rtContext.get(), expectedPixelValues,
                        "RectangleTexture-basic-draw");
     }
diff --git a/tests/TriangulatingPathRendererTests.cpp b/tests/TriangulatingPathRendererTests.cpp
index f2abf19..ff0fc3a 100644
--- a/tests/TriangulatingPathRendererTests.cpp
+++ b/tests/TriangulatingPathRendererTests.cpp
@@ -10,8 +10,8 @@
 #include "include/core/SkPath.h"
 #include "include/effects/SkGradientShader.h"
 #include "include/gpu/GrContext.h"
-#include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrStyle.h"
 #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
 #include "src/gpu/geometry/GrStyledShape.h"
@@ -714,7 +714,6 @@
         paint.addColorFragmentProcessor(std::move(fp));
     }
 
-    GrNoClip noClip;
     SkIRect clipConservativeBounds = SkIRect::MakeWH(renderTargetContext->width(),
                                                      renderTargetContext->height());
     GrStyle style(SkStrokeRec::kFill_InitStyle);
@@ -723,7 +722,7 @@
                                       std::move(paint),
                                       &GrUserStencilSettings::kUnused,
                                       renderTargetContext,
-                                      &noClip,
+                                      nullptr,
                                       &clipConservativeBounds,
                                       &matrix,
                                       &shape,
diff --git a/tools/gpu/GrTest.cpp b/tools/gpu/GrTest.cpp
index 2a030d4..dd5b847 100644
--- a/tools/gpu/GrTest.cpp
+++ b/tools/gpu/GrTest.cpp
@@ -63,11 +63,11 @@
 }
 
 void GrRenderTargetContextPriv::testingOnly_addDrawOp(std::unique_ptr<GrDrawOp> op) {
-    this->testingOnly_addDrawOp(GrNoClip(), std::move(op));
+    this->testingOnly_addDrawOp(nullptr, std::move(op), {});
 }
 
 void GrRenderTargetContextPriv::testingOnly_addDrawOp(
-        const GrClip& clip,
+        const GrClip* clip,
         std::unique_ptr<GrDrawOp> op,
         const std::function<GrRenderTargetContext::WillAddOpFn>& willAddFn) {
     ASSERT_SINGLE_OWNER