Plumb GrContext everywhere

There is no good way to split the monster CL up. This breaks out
the GrContext plumbing but doesn't use it.

Change-Id: I90856d428d372bcec3f8821e6364667b367927d4
Reviewed-on: https://skia-review.googlesource.com/133382
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/gm/beziereffects.cpp b/gm/beziereffects.cpp
index ab9a5fd..dea6150 100644
--- a/gm/beziereffects.cpp
+++ b/gm/beziereffects.cpp
@@ -11,6 +11,7 @@
 #include "sk_tool_utils.h"
 
 #include "GrContext.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 #include "GrPathUtils.h"
 #include "GrRenderTargetContextPriv.h"
@@ -75,12 +76,16 @@
 
     const char* name() const override { return "BezierCubicTestOp"; }
 
-    static std::unique_ptr<GrDrawOp> Make(sk_sp<GrGeometryProcessor> gp, const SkRect& rect,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          sk_sp<GrGeometryProcessor> gp,
+                                          const SkRect& rect,
                                           GrColor color) {
         return std::unique_ptr<GrDrawOp>(new BezierCubicTestOp(std::move(gp), rect, color));
     }
 
 private:
+    friend class ::GrOpMemoryPool; // for ctor
+
     BezierCubicTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color)
             : INHERITED(std::move(gp), rect, color, ClassID()) {}
 
@@ -230,7 +235,7 @@
                     }
 
                     std::unique_ptr<GrDrawOp> op =
-                            BezierCubicTestOp::Make(std::move(gp), bounds, color);
+                            BezierCubicTestOp::Make(context, std::move(gp), bounds, color);
                     renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
                 }
                 ++col;
@@ -254,13 +259,18 @@
 
     const char* name() const override { return "BezierConicTestOp"; }
 
-    static std::unique_ptr<GrDrawOp> Make(sk_sp<GrGeometryProcessor> gp, const SkRect& rect,
-                                          GrColor color, const SkMatrix& klm) {
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          sk_sp<GrGeometryProcessor> gp,
+                                          const SkRect& rect,
+                                          GrColor color,
+                                          const SkMatrix& klm) {
         return std::unique_ptr<GrMeshDrawOp>(
                 new BezierConicTestOp(std::move(gp), rect, color, klm));
     }
 
 private:
+    friend class ::GrOpMemoryPool; // for ctor
+
     BezierConicTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
                       const SkMatrix& klm)
             : INHERITED(std::move(gp), rect, color, ClassID()), fKLM(klm) {}
@@ -406,7 +416,8 @@
                     boundsPaint.setStyle(SkPaint::kStroke_Style);
                     canvas->drawRect(bounds, boundsPaint);
 
-                    std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(gp, bounds, color, klm);
+                    std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(context, gp, bounds,
+                                                                           color, klm);
                     renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
                 }
                 ++col;
@@ -469,12 +480,17 @@
     DEFINE_OP_CLASS_ID
     const char* name() const override { return "BezierQuadTestOp"; }
 
-    static std::unique_ptr<GrDrawOp> Make(sk_sp<GrGeometryProcessor> gp, const SkRect& rect,
-                                          GrColor color, const GrPathUtils::QuadUVMatrix& devToUV) {
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          sk_sp<GrGeometryProcessor> gp,
+                                          const SkRect& rect,
+                                          GrColor color,
+                                          const GrPathUtils::QuadUVMatrix& devToUV) {
         return std::unique_ptr<GrDrawOp>(new BezierQuadTestOp(std::move(gp), rect, color, devToUV));
     }
 
 private:
+    friend class ::GrOpMemoryPool; // for ctor
+
     BezierQuadTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
                      const GrPathUtils::QuadUVMatrix& devToUV)
             : INHERITED(std::move(gp), rect, color, ClassID()), fDevToUV(devToUV) {}
@@ -615,8 +631,8 @@
 
                     GrPathUtils::QuadUVMatrix DevToUV(pts);
 
-                    std::unique_ptr<GrDrawOp> op =
-                            BezierQuadTestOp::Make(gp, bounds, color, DevToUV);
+                    std::unique_ptr<GrDrawOp> op = BezierQuadTestOp::Make(context, gp,
+                                                                          bounds, color, DevToUV);
                     renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
                 }
                 ++col;
diff --git a/gm/bigrrectaaeffect.cpp b/gm/bigrrectaaeffect.cpp
index dee19c5..f3f10ae 100644
--- a/gm/bigrrectaaeffect.cpp
+++ b/gm/bigrrectaaeffect.cpp
@@ -56,6 +56,11 @@
             return;
         }
 
+        GrContext* context = canvas->getGrContext();
+        if (!context) {
+            return;
+        }
+
         SkPaint paint;
 
         int y = kPad;
@@ -90,7 +95,8 @@
                     bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
 
                     renderTargetContext->priv().testingOnly_addDrawOp(
-                            GrRectOpFactory::MakeNonAAFill(std::move(grPaint), SkMatrix::I(),
+                            GrRectOpFactory::MakeNonAAFill(context, std::move(grPaint),
+                                                           SkMatrix::I(),
                                                            bounds, GrAAType::kNone));
                 }
             canvas->restore();
diff --git a/gm/constcolorprocessor.cpp b/gm/constcolorprocessor.cpp
index 26da988..ffeecda 100644
--- a/gm/constcolorprocessor.cpp
+++ b/gm/constcolorprocessor.cpp
@@ -108,7 +108,7 @@
 
                     grPaint.addColorFragmentProcessor(std::move(fp));
                     renderTargetContext->priv().testingOnly_addDrawOp(
-                            GrRectOpFactory::MakeNonAAFill(std::move(grPaint), viewMatrix,
+                            GrRectOpFactory::MakeNonAAFill(context, std::move(grPaint), viewMatrix,
                                                            renderRect, GrAAType::kNone));
 
                     // Draw labels for the input to the processor and the processor to the right of
diff --git a/gm/convexpolyeffect.cpp b/gm/convexpolyeffect.cpp
index fa48e7b..8f8d1b4 100644
--- a/gm/convexpolyeffect.cpp
+++ b/gm/convexpolyeffect.cpp
@@ -11,6 +11,7 @@
 
 #include "GrContext.h"
 #include "GrDefaultGeoProcFactory.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 #include "GrPathUtils.h"
 #include "GrRenderTargetContextPriv.h"
@@ -41,7 +42,9 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkRect& rect) {
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkRect& rect) {
         return std::unique_ptr<GrDrawOp>(new PolyBoundsOp(std::move(paint), rect));
     }
 
@@ -61,6 +64,8 @@
     }
 
 private:
+    friend class ::GrOpMemoryPool; // for ctor
+
     PolyBoundsOp(GrPaint&& paint, const SkRect& rect)
             : INHERITED(ClassID())
             , fColor(paint.getColor())
@@ -181,6 +186,11 @@
             return;
         }
 
+        GrContext* context = canvas->getGrContext();
+        if (!context) {
+            return;
+        }
+
         SkScalar y = 0;
         constexpr SkScalar kDX = 12.f;
         for (PathList::Iter iter(fPaths, PathList::Iter::kHead_IterStart);
@@ -206,7 +216,7 @@
                 grPaint.addCoverageFragmentProcessor(std::move(fp));
 
                 std::unique_ptr<GrDrawOp> op =
-                        PolyBoundsOp::Make(std::move(grPaint), p.getBounds());
+                        PolyBoundsOp::Make(context, std::move(grPaint), p.getBounds());
                 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
 
                 x += SkScalarCeilToScalar(path->getBounds().width() + kDX);
@@ -245,7 +255,8 @@
                 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
                 grPaint.addCoverageFragmentProcessor(std::move(fp));
 
-                std::unique_ptr<GrDrawOp> op = PolyBoundsOp::Make(std::move(grPaint), rect);
+                std::unique_ptr<GrDrawOp> op = PolyBoundsOp::Make(context, std::move(grPaint),
+                                                                  rect);
                 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
 
                 x += SkScalarCeilToScalar(rect.width() + kDX);
diff --git a/gm/rrects.cpp b/gm/rrects.cpp
index ff704c8..143fde3 100644
--- a/gm/rrects.cpp
+++ b/gm/rrects.cpp
@@ -69,6 +69,12 @@
             return;
         }
 
+        GrContext* context = canvas->getGrContext();
+        if (kEffect_Type == fType && !context) {
+            skiagm::GM::DrawGpuOnlyMessage(canvas);
+            return;
+        }
+
         SkPaint paint;
         if (kAA_Draw_Type == fType) {
             paint.setAntiAlias(true);
@@ -112,7 +118,7 @@
                             bounds.outset(2.f, 2.f);
 
                             renderTargetContext->priv().testingOnly_addDrawOp(
-                                    GrRectOpFactory::MakeNonAAFill(std::move(grPaint),
+                                    GrRectOpFactory::MakeNonAAFill(context, std::move(grPaint),
                                                                    SkMatrix::I(), bounds,
                                                                    GrAAType::kNone));
                         } else {
diff --git a/gm/texturedomaineffect.cpp b/gm/texturedomaineffect.cpp
index 63e0111..5b96859 100644
--- a/gm/texturedomaineffect.cpp
+++ b/gm/texturedomaineffect.cpp
@@ -132,7 +132,7 @@
                     const SkMatrix viewMatrix = SkMatrix::MakeTrans(x, y);
                     grPaint.addColorFragmentProcessor(std::move(fp));
                     renderTargetContext->priv().testingOnly_addDrawOp(
-                            GrRectOpFactory::MakeNonAAFill(std::move(grPaint), viewMatrix,
+                            GrRectOpFactory::MakeNonAAFill(context, std::move(grPaint), viewMatrix,
                                                            renderRect, GrAAType::kNone));
                     x += renderRect.width() + kTestPad;
                 }
diff --git a/gm/yuvtorgbeffect.cpp b/gm/yuvtorgbeffect.cpp
index 7b7846d..a730255 100644
--- a/gm/yuvtorgbeffect.cpp
+++ b/gm/yuvtorgbeffect.cpp
@@ -129,7 +129,7 @@
                     SkMatrix viewMatrix;
                     viewMatrix.setTranslate(x, y);
                     renderTargetContext->priv().testingOnly_addDrawOp(
-                            GrRectOpFactory::MakeNonAAFill(std::move(grPaint), viewMatrix,
+                            GrRectOpFactory::MakeNonAAFill(context, std::move(grPaint), viewMatrix,
                                                            renderRect, GrAAType::kNone));
                 }
                 x += renderRect.width() + kTestPad;
@@ -246,7 +246,7 @@
                 viewMatrix.setTranslate(x, y);
                 grPaint.addColorFragmentProcessor(std::move(fp));
                 std::unique_ptr<GrDrawOp> op(GrRectOpFactory::MakeNonAAFill(
-                                std::move(grPaint), viewMatrix, renderRect, GrAAType::kNone));
+                          context, std::move(grPaint), viewMatrix, renderRect, GrAAType::kNone));
                 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
             }
         }
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 65484c3..8cb6447 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -253,6 +253,7 @@
   "$_src/gpu/ops/GrAtlasTextOp.h",
   "$_src/gpu/ops/GrClearOp.cpp",
   "$_src/gpu/ops/GrClearOp.h",
+  "$_src/gpu/ops/GrClearStencilClipOp.cpp",
   "$_src/gpu/ops/GrClearStencilClipOp.h",
   "$_src/gpu/ops/GrCopySurfaceOp.cpp",
   "$_src/gpu/ops/GrCopySurfaceOp.h",
diff --git a/include/private/GrOpList.h b/include/private/GrOpList.h
index 4ec909c..846a583 100644
--- a/include/private/GrOpList.h
+++ b/include/private/GrOpList.h
@@ -38,7 +38,7 @@
     void prepare(GrOpFlushState* flushState);
     bool execute(GrOpFlushState* flushState) { return this->onExecute(flushState); }
 
-    virtual bool copySurface(const GrCaps& caps,
+    virtual bool copySurface(GrContext*,
                              GrSurfaceProxy* dst,
                              GrSurfaceProxy* src,
                              const SkIRect& srcRect,
diff --git a/src/atlastext/SkAtlasTextTarget.cpp b/src/atlastext/SkAtlasTextTarget.cpp
index 09efc3e..0fb9a79 100644
--- a/src/atlastext/SkAtlasTextTarget.cpp
+++ b/src/atlastext/SkAtlasTextTarget.cpp
@@ -6,9 +6,11 @@
  */
 
 #include "SkAtlasTextTarget.h"
+
 #include "GrClip.h"
 #include "GrContextPriv.h"
 #include "GrDrawingManager.h"
+#include "GrMemoryPool.h"
 #include "SkAtlasTextContext.h"
 #include "SkAtlasTextFont.h"
 #include "SkAtlasTextRenderer.h"
@@ -76,10 +78,12 @@
 
 class SkInternalAtlasTextTarget : public GrTextUtils::Target, public SkAtlasTextTarget {
 public:
-    SkInternalAtlasTextTarget(sk_sp<SkAtlasTextContext> context, int width, int height,
+    SkInternalAtlasTextTarget(sk_sp<SkAtlasTextContext> context,
+                              int width, int height,
                               void* handle)
             : GrTextUtils::Target(width, height, kColorSpaceInfo)
-            , SkAtlasTextTarget(std::move(context), width, height, handle) {}
+            , SkAtlasTextTarget(std::move(context), width, height, handle) {
+    }
 
     /** GrTextUtils::Target overrides */
 
@@ -95,6 +99,10 @@
         grPaint->setColor4f(SkColorToPremulGrColor4fLegacy(skPaint.getColor()));
     }
 
+    GrContext* getContext() override {
+        return this->context()->internal().grContext();
+    }
+
     /** SkAtlasTextTarget overrides */
 
     void drawText(const SkGlyphID[], const SkPoint[], int glyphCnt, uint32_t color,
diff --git a/src/gpu/GrMemoryPool.cpp b/src/gpu/GrMemoryPool.cpp
index 32a3612..89e8f01 100644
--- a/src/gpu/GrMemoryPool.cpp
+++ b/src/gpu/GrMemoryPool.cpp
@@ -10,6 +10,7 @@
 #ifdef SK_DEBUG
 #include "SkAtomics.h"
 #endif
+#include "ops/GrOp.h"
 
 #ifdef SK_DEBUG
     #define VALIDATE this->validate()
@@ -17,6 +18,13 @@
     #define VALIDATE
 #endif
 
+void GrOpMemoryPool::release(std::unique_ptr<GrOp> op) {
+    GrOp* tmp = op.release();
+    SkASSERT(tmp);
+    tmp->~GrOp();
+    fMemoryPool.release(tmp);
+}
+
 constexpr size_t GrMemoryPool::kSmallestMinAllocSize;
 
 GrMemoryPool::GrMemoryPool(size_t preallocSize, size_t minAllocSize) {
diff --git a/src/gpu/GrMemoryPool.h b/src/gpu/GrMemoryPool.h
index 825b83a..67991d3 100644
--- a/src/gpu/GrMemoryPool.h
+++ b/src/gpu/GrMemoryPool.h
@@ -9,6 +9,9 @@
 #define GrMemoryPool_DEFINED
 
 #include "GrTypes.h"
+
+#include "SkRefCnt.h"
+
 #ifdef SK_DEBUG
 #include "SkTHash.h"
 #endif
@@ -121,4 +124,30 @@
     };
 };
 
+class GrOp;
+
+// DDL TODO: for the DLL use case this could probably be the non-intrinsic-based style of
+// ref counting
+class GrOpMemoryPool : public SkRefCnt {
+public:
+    GrOpMemoryPool(size_t preallocSize, size_t minAllocSize)
+            : fMemoryPool(preallocSize, minAllocSize) {
+    }
+
+    template <typename Op, typename... OpArgs>
+    std::unique_ptr<Op> allocate(OpArgs&&... opArgs) {
+        char* mem = (char*) fMemoryPool.allocate(sizeof(Op));
+        return std::unique_ptr<Op>(new (mem) Op(std::forward<OpArgs>(opArgs)...));
+    }
+
+    void* allocate(size_t size) {
+        return fMemoryPool.allocate(size);
+    }
+
+    void release(std::unique_ptr<GrOp> op);
+
+private:
+    GrMemoryPool fMemoryPool;
+};
+
 #endif
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index a4c08f3..d829810 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -58,20 +58,20 @@
                      renderTargetContext->colorSpaceInfo())
             , fRenderTargetContext(renderTargetContext) {}
 
-    void addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) {
+    void addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) override {
         fRenderTargetContext->addDrawOp(clip, std::move(op));
     }
 
     void drawPath(const GrClip& clip, const SkPath& path, const SkPaint& paint,
                   const SkMatrix& viewMatrix, const SkMatrix* pathMatrix,
-                  const SkIRect& clipBounds) {
+                  const SkIRect& clipBounds) override {
         GrBlurUtils::drawPathWithMaskFilter(fRenderTargetContext->fContext, fRenderTargetContext,
                                             clip, path, paint, viewMatrix, pathMatrix, clipBounds,
                                             false);
     }
 
     void makeGrPaint(GrMaskFormat maskFormat, const SkPaint& skPaint, const SkMatrix& viewMatrix,
-                     GrPaint* grPaint) {
+                     GrPaint* grPaint) override {
         GrContext* context = fRenderTargetContext->fContext;
         const GrColorSpaceInfo& colorSpaceInfo = fRenderTargetContext->colorSpaceInfo();
         if (kARGB_GrMaskFormat == maskFormat) {
@@ -81,6 +81,10 @@
         }
     }
 
+    GrContext* getContext() override {
+        return fRenderTargetContext->fContext;
+    }
+
 private:
     GrRenderTargetContext* fRenderTargetContext;
 };
@@ -299,7 +303,8 @@
     // This path doesn't handle coalescing of full screen clears b.c. it
     // has to clear the entire render target - not just the content area.
     // It could be done but will take more finagling.
-    std::unique_ptr<GrOp> op(GrClearOp::Make(rtRect, color, !clearRect));
+    std::unique_ptr<GrOp> op(GrClearOp::Make(fRenderTargetContext->fContext, rtRect,
+                                             color, !clearRect));
     if (!op) {
         return;
     }
@@ -331,9 +336,9 @@
     }
 
     if (isFull) {
-        this->getRTOpList()->fullClear(*this->caps(), color);
+        this->getRTOpList()->fullClear(fContext, color);
     } else {
-        std::unique_ptr<GrOp> op(GrClearOp::Make(clip, color, this->asSurfaceProxy()));
+        std::unique_ptr<GrOp> op(GrClearOp::Make(fContext, clip, color, this->asSurfaceProxy()));
         if (!op) {
             return;
         }
@@ -387,7 +392,7 @@
         AutoCheckFlush acf(this->drawingManager());
 
         std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFillWithLocalMatrix(
-                std::move(paint), SkMatrix::I(), localMatrix, r, GrAAType::kNone);
+                fContext, std::move(paint), SkMatrix::I(), localMatrix, r, GrAAType::kNone);
         this->addDrawOp(clip, std::move(op));
     }
 }
@@ -456,9 +461,10 @@
     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
     std::unique_ptr<GrDrawOp> op;
     if (GrAAType::kCoverage == aaType) {
-        op = GrRectOpFactory::MakeAAFill(std::move(paint), viewMatrix, croppedRect, ss);
+        op = GrRectOpFactory::MakeAAFill(fContext, std::move(paint), viewMatrix, croppedRect, ss);
     } else {
-        op = GrRectOpFactory::MakeNonAAFill(std::move(paint), viewMatrix, croppedRect, aaType, ss);
+        op = GrRectOpFactory::MakeNonAAFill(fContext, std::move(paint), viewMatrix, croppedRect,
+                                            aaType, ss);
     }
     if (!op) {
         return false;
@@ -557,11 +563,12 @@
         if (GrAAType::kCoverage == aaType) {
             // The stroke path needs the rect to remain axis aligned (no rotation or skew).
             if (viewMatrix.rectStaysRect()) {
-                op = GrRectOpFactory::MakeAAStroke(std::move(paint), viewMatrix, rect, stroke);
+                op = GrRectOpFactory::MakeAAStroke(fContext, std::move(paint), viewMatrix, rect,
+                                                   stroke);
             }
         } else {
-            op = GrRectOpFactory::MakeNonAAStroke(std::move(paint), viewMatrix, rect, stroke,
-                                                  aaType);
+            op = GrRectOpFactory::MakeNonAAStroke(fContext, std::move(paint), viewMatrix, rect,
+                                                  stroke, aaType);
         }
 
         if (op) {
@@ -586,9 +593,9 @@
 
     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
 
-    std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(
-                                                 clip, insideStencilMask,
-                                                 fRenderTargetContext->fRenderTargetProxy.get()));
+    GrRenderTargetProxy* rtProxy = fRenderTargetContext->fRenderTargetProxy.get();
+    std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(fRenderTargetContext->fContext,
+                                                        clip, insideStencilMask, rtProxy));
     if (!op) {
         return;
     }
@@ -625,7 +632,8 @@
 
     fRenderTargetContext->setNeedsStencil();
 
-    std::unique_ptr<GrOp> op = GrStencilPathOp::Make(viewMatrix,
+    std::unique_ptr<GrOp> op = GrStencilPathOp::Make(fRenderTargetContext->fContext,
+                                                     viewMatrix,
                                                      useHWAA,
                                                      path->getFillType(),
                                                      appliedClip.hasStencilClip(),
@@ -654,8 +662,9 @@
 
     GrPaint paint;
     paint.setXPFactory(GrDisableColorXPFactory::Get());
-    std::unique_ptr<GrDrawOp> op =
-            GrRectOpFactory::MakeNonAAFill(std::move(paint), viewMatrix, rect, aaType, ss);
+    std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFill(fRenderTargetContext->fContext,
+                                                                  std::move(paint), viewMatrix,
+                                                                  rect, aaType, ss);
     fRenderTargetContext->addDrawOp(clip, std::move(op));
 }
 
@@ -709,13 +718,13 @@
     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
     if (GrAAType::kCoverage != aaType) {
         std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFillWithLocalRect(
-                std::move(paint), viewMatrix, croppedRect, croppedLocalRect, aaType);
+                fContext, std::move(paint), viewMatrix, croppedRect, croppedLocalRect, aaType);
         this->addDrawOp(clip, std::move(op));
         return;
     }
 
     std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeAAFillWithLocalRect(
-            std::move(paint), viewMatrix, croppedRect, croppedLocalRect);
+            fContext, std::move(paint), viewMatrix, croppedRect, croppedLocalRect);
     if (op) {
         this->addDrawOp(clip, std::move(op));
         return;
@@ -778,9 +787,9 @@
                           &clippedSrcRect)) {
         return;
     }
-    this->addDrawOp(clip, GrTextureOp::Make(std::move(proxy), filter, color, clippedSrcRect,
-                                            clippedDstRect, aaType, constraint, viewMatrix,
-                                            std::move(colorSpaceXform)));
+    this->addDrawOp(clip, GrTextureOp::Make(fContext, std::move(proxy), filter, color,
+                                            clippedSrcRect, clippedDstRect, aaType, constraint,
+                                            viewMatrix, std::move(colorSpaceXform)));
 }
 
 void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
@@ -804,13 +813,13 @@
     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
     if (GrAAType::kCoverage != aaType) {
         std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFillWithLocalMatrix(
-                std::move(paint), viewMatrix, localMatrix, croppedRect, aaType);
+                fContext, std::move(paint), viewMatrix, localMatrix, croppedRect, aaType);
         this->addDrawOp(clip, std::move(op));
         return;
     }
 
     std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeAAFillWithLocalMatrix(
-            std::move(paint), viewMatrix, localMatrix, croppedRect);
+            fContext, std::move(paint), viewMatrix, localMatrix, croppedRect);
     if (op) {
         this->addDrawOp(clip, std::move(op));
         return;
@@ -846,7 +855,7 @@
     SkASSERT(vertices);
     GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
     std::unique_ptr<GrDrawOp> op = GrDrawVerticesOp::Make(
-            std::move(paint), std::move(vertices), viewMatrix, aaType,
+            fContext, std::move(paint), std::move(vertices), viewMatrix, aaType,
             this->colorSpaceInfo().isGammaCorrect(),
             this->colorSpaceInfo().refColorSpaceXformFromSRGB(), overridePrimType);
     this->addDrawOp(clip, std::move(op));
@@ -869,8 +878,8 @@
     AutoCheckFlush acf(this->drawingManager());
 
     GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
-    std::unique_ptr<GrDrawOp> op = GrDrawAtlasOp::Make(std::move(paint), viewMatrix, aaType,
-                                                       spriteCount, xform, texRect, colors);
+    std::unique_ptr<GrDrawOp> op = GrDrawAtlasOp::Make(fContext, std::move(paint), viewMatrix,
+                                                       aaType, spriteCount, xform, texRect, colors);
     this->addDrawOp(clip, std::move(op));
 }
 
@@ -911,7 +920,8 @@
     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
     if (GrAAType::kCoverage == aaType) {
         const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
-        std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeRRectOp(std::move(paint),
+        std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeRRectOp(fContext,
+                                                                    std::move(paint),
                                                                     viewMatrix,
                                                                     rrect,
                                                                     stroke,
@@ -1019,7 +1029,9 @@
         // which is just 1/umbraRecipAlpha.
         SkScalar blurClamp = SkScalarInvert(umbraRecipAlpha);
 
-        std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(ambientColor, viewMatrix,
+        std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
+                                                             ambientColor,
+                                                             viewMatrix,
                                                              ambientRRect,
                                                              devSpaceAmbientBlur,
                                                              devSpaceInsetWidth,
@@ -1115,7 +1127,9 @@
 
         GrColor spotColor = SkColorToPremulGrColor(rec.fSpotColor);
 
-        std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(spotColor, viewMatrix,
+        std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
+                                                             spotColor,
+                                                             viewMatrix,
                                                              spotShadowRRect,
                                                              2.0f * devSpaceSpotBlur,
                                                              insetWidth);
@@ -1157,8 +1171,8 @@
             auto circleBounds = SkRect::MakeLTRB(cx - avgR, cy - avgR, cx + avgR, cy + avgR);
             SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
             stroke.setStrokeStyle(outerR - innerR);
-            auto op = GrOvalOpFactory::MakeOvalOp(std::move(paint), viewMatrix, circleBounds,
-                                                  GrStyle(stroke, nullptr),
+            auto op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix,
+                                                  circleBounds, GrStyle(stroke, nullptr),
                                                   this->caps()->shaderCaps());
             if (op) {
                 this->addDrawOp(clip, std::move(op));
@@ -1275,8 +1289,8 @@
     }
 
     GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
-    std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(std::move(paint), viewMatrix, region, aaType,
-                                                    ss);
+    std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(fContext, std::move(paint), viewMatrix, region,
+                                                    aaType, ss);
     this->addDrawOp(clip, std::move(op));
 }
 
@@ -1300,8 +1314,8 @@
     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
     if (GrAAType::kCoverage == aaType) {
         const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
-        if (auto op = GrOvalOpFactory::MakeOvalOp(std::move(paint), viewMatrix, oval, style,
-                                                  shaderCaps)) {
+        if (auto op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix, oval,
+                                                  style, shaderCaps)) {
             this->addDrawOp(clip, std::move(op));
             return;
         }
@@ -1331,7 +1345,8 @@
     GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
     if (GrAAType::kCoverage == aaType) {
         const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
-        std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(std::move(paint),
+        std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(fContext,
+                                                                  std::move(paint),
                                                                   viewMatrix,
                                                                   oval,
                                                                   startAngle,
@@ -1365,8 +1380,8 @@
     AutoCheckFlush acf(this->drawingManager());
 
     std::unique_ptr<GrDrawOp> op =
-            GrLatticeOp::MakeNonAA(std::move(paint), viewMatrix, std::move(image), std::move(csxf),
-                                   filter, std::move(iter), dst);
+            GrLatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(image),
+                                   std::move(csxf), filter, std::move(iter), dst);
     this->addDrawOp(clip, std::move(op));
 }
 
@@ -1402,7 +1417,8 @@
         sk_sp<GrSemaphore> sema = resourceProvider->wrapBackendSemaphore(
                 waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
                 kAdopt_GrWrapOwnership);
-        std::unique_ptr<GrOp> waitOp(GrSemaphoreOp::MakeWait(sema, fRenderTargetProxy.get()));
+        std::unique_ptr<GrOp> waitOp(GrSemaphoreOp::MakeWait(fContext, sema,
+                                                             fRenderTargetProxy.get()));
         this->getRTOpList()->addOp(std::move(waitOp), *this->caps());
     }
     return true;
@@ -1508,8 +1524,8 @@
             SkRect rects[2];
 
             if (fills_as_nested_rects(viewMatrix, path, rects)) {
-                std::unique_ptr<GrDrawOp> op =
-                        GrRectOpFactory::MakeAAFillNestedRects(std::move(paint), viewMatrix, rects);
+                std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeAAFillNestedRects(
+                                fContext, std::move(paint), viewMatrix, rects);
                 if (op) {
                     this->addDrawOp(clip, std::move(op));
                 }
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index d605314..d0b4a7d 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -407,7 +407,9 @@
     friend class GrCCAtlas;                          // for access to addDrawOp
     friend class GrCoverageCountingPathRenderer;     // for access to addDrawOp
     // for a unit test
-    friend void test_draw_op(GrRenderTargetContext*, std::unique_ptr<GrFragmentProcessor>,
+    friend void test_draw_op(GrContext*,
+                             GrRenderTargetContext*,
+                             std::unique_ptr<GrFragmentProcessor>,
                              sk_sp<GrTextureProxy>);
 
     void internalClear(const GrFixedClip&, const GrColor, CanClearFullscreen);
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index f98e0f4..b04ec36 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -10,6 +10,7 @@
 #include "GrCaps.h"
 #include "GrGpu.h"
 #include "GrGpuCommandBuffer.h"
+#include "GrMemoryPool.h"
 #include "GrRect.h"
 #include "GrRenderTargetContext.h"
 #include "GrResourceAllocator.h"
@@ -201,7 +202,7 @@
     }
 }
 
-void GrRenderTargetOpList::fullClear(const GrCaps& caps, GrColor color) {
+void GrRenderTargetOpList::fullClear(GrContext* context, GrColor color) {
 
     // This is conservative. If the opList is marked as needing a stencil buffer then there
     // may be a prior op that writes to the stencil buffer. Although the clear will ignore the
@@ -216,30 +217,31 @@
         return;
     }
 
-    std::unique_ptr<GrClearOp> op(GrClearOp::Make(GrFixedClip::Disabled(), color, fTarget.get()));
+    std::unique_ptr<GrClearOp> op(GrClearOp::Make(context, GrFixedClip::Disabled(),
+                                                  color, fTarget.get()));
     if (!op) {
         return;
     }
 
-    this->recordOp(std::move(op), caps);
+    this->recordOp(std::move(op), *context->contextPriv().caps());
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 // This closely parallels GrTextureOpList::copySurface but renderTargetOpLists
 // also store the applied clip and dest proxy with the op
-bool GrRenderTargetOpList::copySurface(const GrCaps& caps,
+bool GrRenderTargetOpList::copySurface(GrContext* context,
                                        GrSurfaceProxy* dst,
                                        GrSurfaceProxy* src,
                                        const SkIRect& srcRect,
                                        const SkIPoint& dstPoint) {
     SkASSERT(dst->asRenderTargetProxy() == fTarget.get());
-    std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(dst, src, srcRect, dstPoint);
+    std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(context, dst, src, srcRect, dstPoint);
     if (!op) {
         return false;
     }
 
-    this->addOp(std::move(op), caps);
+    this->addOp(std::move(op), *context->contextPriv().caps());
     return true;
 }
 
diff --git a/src/gpu/GrRenderTargetOpList.h b/src/gpu/GrRenderTargetOpList.h
index af9b4a4..00b9f5e 100644
--- a/src/gpu/GrRenderTargetOpList.h
+++ b/src/gpu/GrRenderTargetOpList.h
@@ -93,7 +93,7 @@
     void discard();
 
     /** Clears the entire render target */
-    void fullClear(const GrCaps& caps, GrColor color);
+    void fullClear(GrContext*, GrColor color);
 
     /**
      * Copies a pixel rectangle from one surface to another. This call may finalize
@@ -105,7 +105,7 @@
      * depending on the type of surface, configs, etc, and the backend-specific
      * limitations.
      */
-    bool copySurface(const GrCaps& caps,
+    bool copySurface(GrContext*,
                      GrSurfaceProxy* dst,
                      GrSurfaceProxy* src,
                      const SkIRect& srcRect,
@@ -130,6 +130,8 @@
             }
         }
 
+        ~RecordedOp() { }
+
         void visitProxies(const GrOp::VisitProxyFunc& func) const {
             if (fOp) {
                 fOp->visitProxies(func);
@@ -143,8 +145,8 @@
         }
 
         std::unique_ptr<GrOp> fOp;
-        DstProxy fDstProxy;
-        GrAppliedClip* fAppliedClip;
+        DstProxy              fDstProxy;
+        GrAppliedClip*        fAppliedClip;
     };
 
     void purgeOpsWithUninstantiatedProxies() override;
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index bcd9874..16bfbe9 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -14,6 +14,7 @@
 #include "GrOpFlushState.h"
 #include "GrOpList.h"
 #include "GrProxyProvider.h"
+#include "GrSurfaceContextPriv.h"
 #include "GrSWMaskHelper.h"
 #include "SkMakeUnique.h"
 #include "SkSemaphore.h"
@@ -94,9 +95,10 @@
                                            const SkMatrix& viewMatrix,
                                            const SkRect& rect,
                                            const SkMatrix& localMatrix) {
+    GrContext* context = renderTargetContext->surfPriv().getContext();
     renderTargetContext->addDrawOp(clip,
                                    GrRectOpFactory::MakeNonAAFillWithLocalMatrix(
-                                           std::move(paint), viewMatrix, localMatrix, rect,
+                                           context, std::move(paint), viewMatrix, localMatrix, rect,
                                            GrAAType::kNone, &userStencilSettings));
 }
 
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index c288be5..a77addd 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -87,6 +87,6 @@
         return false;
     }
 
-    return this->getOpList()->copySurface(*fContext->contextPriv().caps(), this->asSurfaceProxy(),
+    return this->getOpList()->copySurface(fContext, this->asSurfaceProxy(),
                                           src, srcRect, dstPoint);
 }
diff --git a/src/gpu/GrTextureOpList.cpp b/src/gpu/GrTextureOpList.cpp
index c09dbff..a868b5d 100644
--- a/src/gpu/GrTextureOpList.cpp
+++ b/src/gpu/GrTextureOpList.cpp
@@ -8,6 +8,8 @@
 #include "GrTextureOpList.h"
 
 #include "GrAuditTrail.h"
+#include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrGpu.h"
 #include "GrResourceAllocator.h"
 #include "GrTextureProxy.h"
@@ -113,20 +115,21 @@
 
 // This closely parallels GrRenderTargetOpList::copySurface but renderTargetOpList
 // stores extra data with the op
-bool GrTextureOpList::copySurface(const GrCaps& caps,
+bool GrTextureOpList::copySurface(GrContext* context,
                                   GrSurfaceProxy* dst,
                                   GrSurfaceProxy* src,
                                   const SkIRect& srcRect,
                                   const SkIPoint& dstPoint) {
     SkASSERT(dst == fTarget.get());
 
-    std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(dst, src, srcRect, dstPoint);
+    std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(context, dst, src, srcRect, dstPoint);
     if (!op) {
         return false;
     }
 
-    auto addDependency = [ &caps, this ] (GrSurfaceProxy* p) {
-        this->addDependency(p, caps);
+    const GrCaps* caps = context->contextPriv().caps();
+    auto addDependency = [ caps, this ] (GrSurfaceProxy* p) {
+        this->addDependency(p, *caps);
     };
     op->visitProxies(addDependency);
 
diff --git a/src/gpu/GrTextureOpList.h b/src/gpu/GrTextureOpList.h
index 510a895..d3e3e87 100644
--- a/src/gpu/GrTextureOpList.h
+++ b/src/gpu/GrTextureOpList.h
@@ -48,7 +48,7 @@
      * depending on the type of surface, configs, etc, and the backend-specific
      * limitations.
      */
-    bool copySurface(const GrCaps& caps,
+    bool copySurface(GrContext*,
                      GrSurfaceProxy* dst,
                      GrSurfaceProxy* src,
                      const SkIRect& srcRect,
diff --git a/src/gpu/ccpr/GrCCAtlas.cpp b/src/gpu/ccpr/GrCCAtlas.cpp
index afa82c4..df84ed7 100644
--- a/src/gpu/ccpr/GrCCAtlas.cpp
+++ b/src/gpu/ccpr/GrCCAtlas.cpp
@@ -8,10 +8,12 @@
 #include "GrCCAtlas.h"
 
 #include "GrClip.h"
+#include "GrMemoryPool.h"
 #include "GrOnFlushResourceProvider.h"
 #include "GrSurfaceContextPriv.h"
 #include "GrRectanizer_skyline.h"
 #include "GrRenderTargetContext.h"
+#include "GrSurfaceContextPriv.h"
 #include "GrTextureProxy.h"
 #include "SkMakeUnique.h"
 #include "SkMathPriv.h"
@@ -76,6 +78,8 @@
     }
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     DrawCoverageCountOp(sk_sp<const GrCCPathParser> parser, CoverageCountBatchID batchID,
                         const SkISize& drawBounds)
             : INHERITED(ClassID())
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
index c4be7c5..01913fa 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
@@ -8,6 +8,7 @@
 #include "GrCCDrawPathsOp.h"
 
 #include "GrGpuCommandBuffer.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 #include "ccpr/GrCCPerFlushResources.h"
 #include "ccpr/GrCoverageCountingPathRenderer.h"
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.h b/src/gpu/ccpr/GrCCDrawPathsOp.h
index f43ccd0..303f52b 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.h
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.h
@@ -53,6 +53,8 @@
     void onExecute(GrOpFlushState*) override;
 
 private:
+    friend class GrOpMemoryPool;
+
     GrCCDrawPathsOp(GrPaint&&, const SkIRect& clipIBounds, const SkMatrix&, const SkPath&,
                     const SkRect& devBounds);
 
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index f94f527..3237afe 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -744,10 +744,12 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
                                           const SkPath& path,
                                           const GrUserStencilSettings* stencilSettings) {
-        return Helper::FactoryHelper<AAConvexPathOp>(std::move(paint), viewMatrix, path,
+        return Helper::FactoryHelper<AAConvexPathOp>(context, std::move(paint), viewMatrix, path,
                                                      stencilSettings);
     }
 
@@ -977,7 +979,8 @@
     SkPath path;
     args.fShape->asPath(&path);
 
-    std::unique_ptr<GrDrawOp> op = AAConvexPathOp::Make(std::move(args.fPaint), *args.fViewMatrix,
+    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));
     return true;
@@ -991,7 +994,7 @@
     SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
     SkPath path = GrTest::TestPathConvex(random);
     const GrUserStencilSettings* stencilSettings = GrGetRandomStencil(random, context);
-    return AAConvexPathOp::Make(std::move(paint), viewMatrix, path, stencilSettings);
+    return AAConvexPathOp::Make(context, std::move(paint), viewMatrix, path, stencilSettings);
 }
 
 #endif
diff --git a/src/gpu/ops/GrAAFillRectOp.cpp b/src/gpu/ops/GrAAFillRectOp.cpp
index 45f2952..5472f11 100644
--- a/src/gpu/ops/GrAAFillRectOp.cpp
+++ b/src/gpu/ops/GrAAFillRectOp.cpp
@@ -172,15 +172,16 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
                                           const SkMatrix& viewMatrix,
                                           const SkRect& rect,
                                           const SkRect& devRect,
                                           const SkMatrix* localMatrix,
                                           const GrUserStencilSettings* stencil) {
         SkASSERT(view_matrix_ok_for_aa_fill_rect(viewMatrix));
-        return Helper::FactoryHelper<AAFillRectOp>(std::move(paint), viewMatrix, rect, devRect,
-                                                   localMatrix, stencil);
+        return Helper::FactoryHelper<AAFillRectOp>(context, std::move(paint), viewMatrix, rect,
+                                                   devRect, localMatrix, stencil);
     }
 
     AAFillRectOp(const Helper::MakeArgs& helperArgs,
@@ -361,17 +362,23 @@
 
 namespace GrRectOpFactory {
 
-std::unique_ptr<GrDrawOp> MakeAAFill(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                     const SkRect& rect, const GrUserStencilSettings* stencil) {
+std::unique_ptr<GrDrawOp> MakeAAFill(GrContext* context,
+                                     GrPaint&& paint,
+                                     const SkMatrix& viewMatrix,
+                                     const SkRect& rect,
+                                     const GrUserStencilSettings* stencil) {
     if (!view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
         return nullptr;
     }
     SkRect devRect;
     viewMatrix.mapRect(&devRect, rect);
-    return AAFillRectOp::Make(std::move(paint), viewMatrix, rect, devRect, nullptr, stencil);
+    return AAFillRectOp::Make(context, std::move(paint), viewMatrix, rect, devRect,
+                              nullptr, stencil);
 }
 
-std::unique_ptr<GrDrawOp> MakeAAFillWithLocalMatrix(GrPaint&& paint, const SkMatrix& viewMatrix,
+std::unique_ptr<GrDrawOp> MakeAAFillWithLocalMatrix(GrContext* context,
+                                                    GrPaint&& paint,
+                                                    const SkMatrix& viewMatrix,
                                                     const SkMatrix& localMatrix,
                                                     const SkRect& rect) {
     if (!view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
@@ -379,11 +386,15 @@
     }
     SkRect devRect;
     viewMatrix.mapRect(&devRect, rect);
-    return AAFillRectOp::Make(std::move(paint), viewMatrix, rect, devRect, &localMatrix, nullptr);
+    return AAFillRectOp::Make(context, std::move(paint), viewMatrix, rect, devRect,
+                              &localMatrix, nullptr);
 }
 
-std::unique_ptr<GrDrawOp> MakeAAFillWithLocalRect(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                                  const SkRect& rect, const SkRect& localRect) {
+std::unique_ptr<GrDrawOp> MakeAAFillWithLocalRect(GrContext* context,
+                                                  GrPaint&& paint,
+                                                  const SkMatrix& viewMatrix,
+                                                  const SkRect& rect,
+                                                  const SkRect& localRect) {
     if (!view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
         return nullptr;
     }
@@ -393,7 +404,8 @@
     if (!localMatrix.setRectToRect(rect, localRect, SkMatrix::kFill_ScaleToFit)) {
         return nullptr;
     }
-    return AAFillRectOp::Make(std::move(paint), viewMatrix, rect, devRect, &localMatrix, nullptr);
+    return AAFillRectOp::Make(context, std::move(paint), viewMatrix, rect, devRect,
+                              &localMatrix, nullptr);
 }
 
 }  // namespace GrRectOpFactory
@@ -417,9 +429,10 @@
     if (random->nextBool()) {
         m = GrTest::TestMatrix(random);
     }
-    const GrUserStencilSettings* stencil =
-            random->nextBool() ? nullptr : GrGetRandomStencil(random, context);
-    return AAFillRectOp::Make(std::move(paint), viewMatrix, rect, devRect, localMatrix, stencil);
+    const GrUserStencilSettings* stencil = random->nextBool() ? nullptr
+                                                              : GrGetRandomStencil(random, context);
+    return AAFillRectOp::Make(context, std::move(paint), viewMatrix, rect,
+                              devRect, localMatrix, stencil);
 }
 
 #endif
diff --git a/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
index 2496351..b62c14b 100644
--- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
@@ -765,7 +765,8 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
                                           const SkMatrix& viewMatrix,
                                           const SkPath& path,
                                           const GrStyle& style,
@@ -780,7 +781,8 @@
         const SkStrokeRec& stroke = style.strokeRec();
         SkScalar capLength = SkPaint::kButt_Cap != stroke.getCap() ? hairlineCoverage * 0.5f : 0.0f;
 
-        return Helper::FactoryHelper<AAHairlineOp>(std::move(paint), newCoverage, viewMatrix, path,
+        return Helper::FactoryHelper<AAHairlineOp>(context, std::move(paint), newCoverage,
+                                                   viewMatrix, path,
                                                    devClipBounds, capLength, stencilSettings);
     }
 
@@ -1057,7 +1059,7 @@
     SkPath path;
     args.fShape->asPath(&path);
     std::unique_ptr<GrDrawOp> op =
-            AAHairlineOp::Make(std::move(args.fPaint), *args.fViewMatrix, path,
+            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));
     return true;
@@ -1072,8 +1074,9 @@
     SkPath path = GrTest::TestPath(random);
     SkIRect devClipBounds;
     devClipBounds.setEmpty();
-    return AAHairlineOp::Make(std::move(paint), viewMatrix, path, GrStyle::SimpleHairline(),
-                              devClipBounds, GrGetRandomStencil(random, context));
+    return AAHairlineOp::Make(context, std::move(paint), viewMatrix, path,
+                              GrStyle::SimpleHairline(), devClipBounds,
+                              GrGetRandomStencil(random, context));
 }
 
 #endif
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index 02520c1..5659099 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -135,7 +135,8 @@
 
 public:
     DEFINE_OP_CLASS_ID
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
                                           const SkMatrix& viewMatrix,
                                           const SkPath& path,
                                           SkScalar strokeWidth,
@@ -143,7 +144,8 @@
                                           SkPaint::Join join,
                                           SkScalar miterLimit,
                                           const GrUserStencilSettings* stencilSettings) {
-        return Helper::FactoryHelper<AAFlatteningConvexPathOp>(std::move(paint), viewMatrix, path,
+        return Helper::FactoryHelper<AAFlatteningConvexPathOp>(context, std::move(paint),
+                                                               viewMatrix, path,
                                                                strokeWidth, style, join, miterLimit,
                                                                stencilSettings);
     }
@@ -361,8 +363,8 @@
     SkScalar miterLimit = stroke.getMiter();
 
     std::unique_ptr<GrDrawOp> op = AAFlatteningConvexPathOp::Make(
-            std::move(args.fPaint), *args.fViewMatrix, path, strokeWidth, stroke.getStyle(), join,
-            miterLimit, args.fUserStencilSettings);
+            args.fContext, std::move(args.fPaint), *args.fViewMatrix, path, strokeWidth,
+            stroke.getStyle(), join, miterLimit, args.fUserStencilSettings);
     args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
     return true;
 }
@@ -395,8 +397,8 @@
         miterLimit = random->nextRangeF(0.5f, 2.0f);
     }
     const GrUserStencilSettings* stencilSettings = GrGetRandomStencil(random, context);
-    return AAFlatteningConvexPathOp::Make(std::move(paint), viewMatrix, path, strokeWidth, style,
-                                          join, miterLimit, stencilSettings);
+    return AAFlatteningConvexPathOp::Make(context, std::move(paint), viewMatrix, path, strokeWidth,
+                                          style, join, miterLimit, stencilSettings);
 }
 
 #endif
diff --git a/src/gpu/ops/GrAAStrokeRectOp.cpp b/src/gpu/ops/GrAAStrokeRectOp.cpp
index 193aa5c..b9a6d88 100644
--- a/src/gpu/ops/GrAAStrokeRectOp.cpp
+++ b/src/gpu/ops/GrAAStrokeRectOp.cpp
@@ -120,10 +120,13 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          const SkRect& devOutside, const SkRect& devInside) {
-        return Helper::FactoryHelper<AAStrokeRectOp>(std::move(paint), viewMatrix, devOutside,
-                                                     devInside);
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          const SkRect& devOutside,
+                                          const SkRect& devInside) {
+        return Helper::FactoryHelper<AAStrokeRectOp>(context, std::move(paint), viewMatrix,
+                                                     devOutside, devInside);
     }
 
     AAStrokeRectOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix,
@@ -139,14 +142,17 @@
         fMiterStroke = true;
     }
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          const SkRect& rect, const SkStrokeRec& stroke) {
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          const SkRect& rect,
+                                          const SkStrokeRec& stroke) {
         bool isMiter;
         if (!allowed_stroke(stroke, &isMiter)) {
             return nullptr;
         }
-        return Helper::FactoryHelper<AAStrokeRectOp>(std::move(paint), viewMatrix, rect, stroke,
-                                                     isMiter);
+        return Helper::FactoryHelper<AAStrokeRectOp>(context, std::move(paint), viewMatrix, rect,
+                                                     stroke, isMiter);
     }
 
     AAStrokeRectOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix,
@@ -575,7 +581,8 @@
 
 namespace GrRectOpFactory {
 
-std::unique_ptr<GrDrawOp> MakeAAFillNestedRects(GrPaint&& paint,
+std::unique_ptr<GrDrawOp> MakeAAFillNestedRects(GrContext* context,
+                                                GrPaint&& paint,
                                                 const SkMatrix& viewMatrix,
                                                 const SkRect rects[2]) {
     SkASSERT(viewMatrix.rectStaysRect());
@@ -588,17 +595,18 @@
         if (devOutside.isEmpty()) {
             return nullptr;
         }
-        return MakeAAFill(std::move(paint), viewMatrix, rects[0]);
+        return MakeAAFill(context, std::move(paint), viewMatrix, rects[0]);
     }
 
-    return AAStrokeRectOp::Make(std::move(paint), viewMatrix, devOutside, devInside);
+    return AAStrokeRectOp::Make(context, std::move(paint), viewMatrix, devOutside, devInside);
 }
 
-std::unique_ptr<GrDrawOp> MakeAAStroke(GrPaint&& paint,
+std::unique_ptr<GrDrawOp> MakeAAStroke(GrContext* context,
+                                       GrPaint&& paint,
                                        const SkMatrix& viewMatrix,
                                        const SkRect& rect,
                                        const SkStrokeRec& stroke) {
-    return AAStrokeRectOp::Make(std::move(paint), viewMatrix, rect, stroke);
+    return AAStrokeRectOp::Make(context, std::move(paint), viewMatrix, rect, stroke);
 }
 
 }  // namespace GrRectOpFactory
@@ -623,7 +631,7 @@
     rec.setStrokeParams(SkPaint::kButt_Cap,
                         miterStroke ? SkPaint::kMiter_Join : SkPaint::kBevel_Join, 1.f);
     SkMatrix matrix = GrTest::TestMatrixRectStaysRect(random);
-    return GrRectOpFactory::MakeAAStroke(std::move(paint), matrix, rect, rec);
+    return GrRectOpFactory::MakeAAStroke(context, std::move(paint), matrix, rect, rec);
 }
 
 #endif
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index a83e025..eb39079 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -8,6 +8,7 @@
 #include "GrAtlasTextOp.h"
 
 #include "GrContext.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 #include "GrResourceProvider.h"
 #include "SkMathPriv.h"
@@ -21,6 +22,57 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
+std::unique_ptr<GrAtlasTextOp> GrAtlasTextOp::MakeBitmap(GrContext* context,
+                                                         GrPaint&& paint,
+                                                         GrMaskFormat maskFormat,
+                                                         int glyphCount,
+                                                         bool needsTransform) {
+        std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint)));
+
+        switch (maskFormat) {
+            case kA8_GrMaskFormat:
+                op->fMaskType = kGrayscaleCoverageMask_MaskType;
+                break;
+            case kA565_GrMaskFormat:
+                op->fMaskType = kLCDCoverageMask_MaskType;
+                break;
+            case kARGB_GrMaskFormat:
+                op->fMaskType = kColorBitmapMask_MaskType;
+                break;
+        }
+        op->fNumGlyphs = glyphCount;
+        op->fGeoCount = 1;
+        op->fLuminanceColor = 0;
+        op->fNeedsGlyphTransform = needsTransform;
+        return op;
+    }
+
+std::unique_ptr<GrAtlasTextOp> GrAtlasTextOp::MakeDistanceField(
+                                            GrContext* context,
+                                            GrPaint&& paint,
+                                            int glyphCount,
+                                            const GrDistanceFieldAdjustTable* distanceAdjustTable,
+                                            bool useGammaCorrectDistanceTable,
+                                            SkColor luminanceColor,
+                                            const SkSurfaceProps& props,
+                                            bool isAntiAliased,
+                                            bool useLCD) {
+        std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint)));
+
+        bool isBGR = SkPixelGeometryIsBGR(props.pixelGeometry());
+        bool isLCD = useLCD && SkPixelGeometryIsH(props.pixelGeometry());
+        op->fMaskType = !isAntiAliased ? kAliasedDistanceField_MaskType
+                                       : isLCD ? (isBGR ? kLCDBGRDistanceField_MaskType
+                                                        : kLCDDistanceField_MaskType)
+                                               : kGrayscaleDistanceField_MaskType;
+        op->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable));
+        op->fUseGammaCorrectDistanceTable = useGammaCorrectDistanceTable;
+        op->fLuminanceColor = luminanceColor;
+        op->fNumGlyphs = glyphCount;
+        op->fGeoCount = 1;
+        return op;
+    }
+
 static const int kDistanceAdjustLumShift = 5;
 
 void GrAtlasTextOp::init() {
diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h
index 04f7bae..0318a90 100644
--- a/src/gpu/ops/GrAtlasTextOp.h
+++ b/src/gpu/ops/GrAtlasTextOp.h
@@ -14,6 +14,7 @@
 #include "text/GrGlyphCache.h"
 
 class SkAtlasTextTarget;
+class GrContext;
 
 class GrAtlasTextOp final : public GrMeshDrawOp {
 public:
@@ -40,48 +41,22 @@
         GrColor  fColor;
     };
 
-    static std::unique_ptr<GrAtlasTextOp> MakeBitmap(
-                                GrPaint&& paint, GrMaskFormat maskFormat, int glyphCount,
-                                bool needsTransform) {
-        std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint)));
-
-        switch (maskFormat) {
-            case kA8_GrMaskFormat:
-                op->fMaskType = kGrayscaleCoverageMask_MaskType;
-                break;
-            case kA565_GrMaskFormat:
-                op->fMaskType = kLCDCoverageMask_MaskType;
-                break;
-            case kARGB_GrMaskFormat:
-                op->fMaskType = kColorBitmapMask_MaskType;
-                break;
-        }
-        op->fNumGlyphs = glyphCount;
-        op->fGeoCount = 1;
-        op->fLuminanceColor = 0;
-        op->fNeedsGlyphTransform = needsTransform;
-        return op;
-    }
+    static std::unique_ptr<GrAtlasTextOp> MakeBitmap(GrContext* context,
+                                                     GrPaint&& paint,
+                                                     GrMaskFormat maskFormat,
+                                                     int glyphCount,
+                                                     bool needsTransform);
 
     static std::unique_ptr<GrAtlasTextOp> MakeDistanceField(
-            GrPaint&& paint, int glyphCount, const GrDistanceFieldAdjustTable* distanceAdjustTable,
-            bool useGammaCorrectDistanceTable, SkColor luminanceColor, const SkSurfaceProps& props,
-            bool isAntiAliased, bool useLCD) {
-        std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint)));
-
-        bool isBGR = SkPixelGeometryIsBGR(props.pixelGeometry());
-        bool isLCD = useLCD && SkPixelGeometryIsH(props.pixelGeometry());
-        op->fMaskType = !isAntiAliased ? kAliasedDistanceField_MaskType
-                                       : isLCD ? (isBGR ? kLCDBGRDistanceField_MaskType
-                                                        : kLCDDistanceField_MaskType)
-                                               : kGrayscaleDistanceField_MaskType;
-        op->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable));
-        op->fUseGammaCorrectDistanceTable = useGammaCorrectDistanceTable;
-        op->fLuminanceColor = luminanceColor;
-        op->fNumGlyphs = glyphCount;
-        op->fGeoCount = 1;
-        return op;
-    }
+            GrContext* context,
+            GrPaint&& paint,
+            int glyphCount,
+            const GrDistanceFieldAdjustTable* distanceAdjustTable,
+            bool useGammaCorrectDistanceTable,
+            SkColor luminanceColor,
+            const SkSurfaceProps& props,
+            bool isAntiAliased,
+            bool useLCD);
 
     // To avoid even the initial copy of the struct, we have a getter for the first item which
     // is used to seed the op with its initial geometry.  After seeding, the client should call
@@ -118,6 +93,8 @@
     void executeForTextTarget(SkAtlasTextTarget*);
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     // The minimum number of Geometry we will try to allocate.
     static constexpr auto kMinGeometryAllocated = 12;
 
diff --git a/src/gpu/ops/GrClearOp.cpp b/src/gpu/ops/GrClearOp.cpp
index e54ca6e..70fc160 100644
--- a/src/gpu/ops/GrClearOp.cpp
+++ b/src/gpu/ops/GrClearOp.cpp
@@ -8,9 +8,31 @@
 #include "GrClearOp.h"
 
 #include "GrGpuCommandBuffer.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 #include "GrProxyProvider.h"
 
+std::unique_ptr<GrClearOp> GrClearOp::Make(GrContext* context,
+                                           const GrFixedClip& clip,
+                                           GrColor color,
+                                           GrSurfaceProxy* dstProxy) {
+    const SkIRect rect = SkIRect::MakeWH(dstProxy->width(), dstProxy->height());
+    if (clip.scissorEnabled() && !SkIRect::Intersects(clip.scissorRect(), rect)) {
+        return nullptr;
+    }
+
+    return std::unique_ptr<GrClearOp>(new GrClearOp(clip, color, dstProxy));
+}
+
+std::unique_ptr<GrClearOp> GrClearOp::Make(GrContext* context,
+                                           const SkIRect& rect,
+                                           GrColor color,
+                                           bool fullScreen) {
+    SkASSERT(fullScreen || !rect.isEmpty());
+
+    return std::unique_ptr<GrClearOp>(new GrClearOp(rect, color, fullScreen));
+}
+
 GrClearOp::GrClearOp(const GrFixedClip& clip, GrColor color, GrSurfaceProxy* proxy)
         : INHERITED(ClassID())
         , fClip(clip)
diff --git a/src/gpu/ops/GrClearOp.h b/src/gpu/ops/GrClearOp.h
index 56ecb13..6e76191 100644
--- a/src/gpu/ops/GrClearOp.h
+++ b/src/gpu/ops/GrClearOp.h
@@ -17,22 +17,15 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrClearOp> Make(const GrFixedClip& clip, GrColor color,
-                                           GrSurfaceProxy* dstProxy) {
-        const SkIRect rect = SkIRect::MakeWH(dstProxy->width(), dstProxy->height());
-        if (clip.scissorEnabled() && !SkIRect::Intersects(clip.scissorRect(), rect)) {
-            return nullptr;
-        }
+    static std::unique_ptr<GrClearOp> Make(GrContext* context,
+                                           const GrFixedClip& clip,
+                                           GrColor color,
+                                           GrSurfaceProxy* dstProxy);
 
-        return std::unique_ptr<GrClearOp>(new GrClearOp(clip, color, dstProxy));
-    }
-
-    static std::unique_ptr<GrClearOp> Make(const SkIRect& rect, GrColor color,
-                                           bool fullScreen) {
-        SkASSERT(fullScreen || !rect.isEmpty());
-
-        return std::unique_ptr<GrClearOp>(new GrClearOp(rect, color, fullScreen));
-    }
+    static std::unique_ptr<GrClearOp> Make(GrContext* context,
+                                           const SkIRect& rect,
+                                           GrColor color,
+                                           bool fullScreen);
 
     const char* name() const override { return "Clear"; }
 
@@ -54,6 +47,8 @@
     void setColor(GrColor color) { fColor = color; }
 
 private:
+    friend class GrOpMemoryPool; // for ctors
+
     GrClearOp(const GrFixedClip& clip, GrColor color, GrSurfaceProxy* proxy);
 
     GrClearOp(const SkIRect& rect, GrColor color, bool fullScreen)
diff --git a/src/gpu/ops/GrClearStencilClipOp.cpp b/src/gpu/ops/GrClearStencilClipOp.cpp
new file mode 100644
index 0000000..9a0e75a
--- /dev/null
+++ b/src/gpu/ops/GrClearStencilClipOp.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrClearStencilClipOp.h"
+
+#include "GrGpuCommandBuffer.h"
+#include "GrMemoryPool.h"
+
+std::unique_ptr<GrOp> GrClearStencilClipOp::Make(GrContext* context,
+                                                 const GrFixedClip& clip,
+                                                 bool insideStencilMask,
+                                                 GrRenderTargetProxy* proxy) {
+    return std::unique_ptr<GrOp>(new GrClearStencilClipOp(clip, insideStencilMask, proxy));
+}
+
+void GrClearStencilClipOp::onExecute(GrOpFlushState* state) {
+    SkASSERT(state->rtCommandBuffer());
+    state->rtCommandBuffer()->clearStencilClip(fClip, fInsideStencilMask);
+}
diff --git a/src/gpu/ops/GrClearStencilClipOp.h b/src/gpu/ops/GrClearStencilClipOp.h
index ffd2fd9..3e7ad50 100644
--- a/src/gpu/ops/GrClearStencilClipOp.h
+++ b/src/gpu/ops/GrClearStencilClipOp.h
@@ -9,19 +9,19 @@
 #define GrClearStencilClipOp_DEFINED
 
 #include "GrFixedClip.h"
-#include "GrGpuCommandBuffer.h"
 #include "GrOp.h"
-#include "GrOpFlushState.h"
 #include "GrRenderTargetProxy.h"
 
+class GrOpFlushState;
+
 class GrClearStencilClipOp final : public GrOp {
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrOp> Make(const GrFixedClip& clip, bool insideStencilMask,
-                                      GrRenderTargetProxy* proxy) {
-        return std::unique_ptr<GrOp>(new GrClearStencilClipOp(clip, insideStencilMask, proxy));
-    }
+    static std::unique_ptr<GrOp> Make(GrContext* context,
+                                      const GrFixedClip& clip,
+                                      bool insideStencilMask,
+                                      GrRenderTargetProxy* proxy);
 
     const char* name() const override { return "ClearStencilClip"; }
 
@@ -39,6 +39,8 @@
     }
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     GrClearStencilClipOp(const GrFixedClip& clip, bool insideStencilMask,
                          GrRenderTargetProxy* proxy)
             : INHERITED(ClassID())
@@ -54,10 +56,7 @@
 
     void onPrepare(GrOpFlushState*) override {}
 
-    void onExecute(GrOpFlushState* state) override {
-        SkASSERT(state->rtCommandBuffer());
-        state->rtCommandBuffer()->clearStencilClip(fClip, fInsideStencilMask);
-    }
+    void onExecute(GrOpFlushState* state) override;
 
     const GrFixedClip fClip;
     const bool        fInsideStencilMask;
diff --git a/src/gpu/ops/GrCopySurfaceOp.cpp b/src/gpu/ops/GrCopySurfaceOp.cpp
index 66d9f89..da8e910 100644
--- a/src/gpu/ops/GrCopySurfaceOp.cpp
+++ b/src/gpu/ops/GrCopySurfaceOp.cpp
@@ -6,7 +6,11 @@
  */
 
 #include "GrCopySurfaceOp.h"
+
+#include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrGpu.h"
+#include "GrMemoryPool.h"
 
 // returns true if the read/written rect intersects the src/dst and false if not.
 static bool clip_src_rect_and_dst_point(const GrSurfaceProxy* dst,
@@ -59,7 +63,9 @@
     return !clippedSrcRect->isEmpty();
 }
 
-std::unique_ptr<GrOp> GrCopySurfaceOp::Make(GrSurfaceProxy* dstProxy, GrSurfaceProxy* srcProxy,
+std::unique_ptr<GrOp> GrCopySurfaceOp::Make(GrContext* context,
+                                            GrSurfaceProxy* dstProxy,
+                                            GrSurfaceProxy* srcProxy,
                                             const SkIRect& srcRect,
                                             const SkIPoint& dstPoint) {
     SkASSERT(dstProxy);
diff --git a/src/gpu/ops/GrCopySurfaceOp.h b/src/gpu/ops/GrCopySurfaceOp.h
index 253d9b9..bc0e33f 100644
--- a/src/gpu/ops/GrCopySurfaceOp.h
+++ b/src/gpu/ops/GrCopySurfaceOp.h
@@ -15,7 +15,9 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrOp> Make(GrSurfaceProxy* dst, GrSurfaceProxy* src,
+    static std::unique_ptr<GrOp> Make(GrContext*,
+                                      GrSurfaceProxy* dst,
+                                      GrSurfaceProxy* src,
                                       const SkIRect& srcRect,
                                       const SkIPoint& dstPoint);
 
@@ -37,6 +39,8 @@
     }
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     GrCopySurfaceOp(GrSurfaceProxy* dst, GrSurfaceProxy* src,
                     const SkIRect& srcRect, const SkIPoint& dstPoint)
             : INHERITED(ClassID())
diff --git a/src/gpu/ops/GrDashLinePathRenderer.cpp b/src/gpu/ops/GrDashLinePathRenderer.cpp
index 73c2b3e..7c2ff9e 100644
--- a/src/gpu/ops/GrDashLinePathRenderer.cpp
+++ b/src/gpu/ops/GrDashLinePathRenderer.cpp
@@ -50,8 +50,8 @@
     SkPoint pts[2];
     SkAssertResult(args.fShape->asLine(pts, nullptr));
     std::unique_ptr<GrDrawOp> op =
-            GrDashOp::MakeDashLineOp(std::move(args.fPaint), *args.fViewMatrix, pts, aaMode,
-                                     args.fShape->style(), args.fUserStencilSettings);
+            GrDashOp::MakeDashLineOp(args.fContext, std::move(args.fPaint), *args.fViewMatrix, pts,
+                                     aaMode, args.fShape->style(), args.fUserStencilSettings);
     if (!op) {
         return false;
     }
diff --git a/src/gpu/ops/GrDashOp.cpp b/src/gpu/ops/GrDashOp.cpp
index 1a8bfba..b784b05 100644
--- a/src/gpu/ops/GrDashOp.cpp
+++ b/src/gpu/ops/GrDashOp.cpp
@@ -9,10 +9,12 @@
 #include "GrAppliedClip.h"
 #include "GrCaps.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrCoordTransform.h"
 #include "GrDefaultGeoProcFactory.h"
 #include "GrDrawOpTest.h"
 #include "GrGeometryProcessor.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 #include "GrProcessor.h"
 #include "GrStyle.h"
@@ -263,8 +265,11 @@
         SkScalar fPerpendicularScale;
     };
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const LineData& geometry,
-                                          SkPaint::Cap cap, AAMode aaMode, bool fullDash,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const LineData& geometry,
+                                          SkPaint::Cap cap,
+                                          AAMode aaMode, bool fullDash,
                                           const GrUserStencilSettings* stencilSettings) {
         return std::unique_ptr<GrDrawOp>(
                 new DashOp(std::move(paint), geometry, cap, aaMode, fullDash, stencilSettings));
@@ -322,6 +327,8 @@
     }
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     DashOp(GrPaint&& paint, const LineData& geometry, SkPaint::Cap cap, AAMode aaMode,
            bool fullDash, const GrUserStencilSettings* stencilSettings)
             : INHERITED(ClassID())
@@ -751,7 +758,8 @@
     typedef GrMeshDrawOp INHERITED;
 };
 
-std::unique_ptr<GrDrawOp> GrDashOp::MakeDashLineOp(GrPaint&& paint,
+std::unique_ptr<GrDrawOp> GrDashOp::MakeDashLineOp(GrContext* context,
+                                                   GrPaint&& paint,
                                                    const SkMatrix& viewMatrix,
                                                    const SkPoint pts[2],
                                                    AAMode aaMode,
@@ -802,7 +810,8 @@
     lineData.fIntervals[0] = intervals[0];
     lineData.fIntervals[1] = intervals[1];
 
-    return DashOp::Make(std::move(paint), lineData, cap, aaMode, fullDash, stencilSettings);
+    return DashOp::Make(context, std::move(paint), lineData, cap, aaMode, fullDash,
+                        stencilSettings);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1331,7 +1340,7 @@
 
     GrStyle style(p);
 
-    return GrDashOp::MakeDashLineOp(std::move(paint), viewMatrix, pts, aaMode, style,
+    return GrDashOp::MakeDashLineOp(context, std::move(paint), viewMatrix, pts, aaMode, style,
                                     GrGetRandomStencil(random, context));
 }
 
diff --git a/src/gpu/ops/GrDashOp.h b/src/gpu/ops/GrDashOp.h
index 86ab619..eb48280 100644
--- a/src/gpu/ops/GrDashOp.h
+++ b/src/gpu/ops/GrDashOp.h
@@ -11,6 +11,7 @@
 #include "GrTypes.h"
 #include "SkPathEffect.h"
 
+class GrContext;
 class GrDrawOp;
 class GrPaint;
 class GrStyle;
@@ -24,8 +25,12 @@
 };
 static const int kAAModeCnt = static_cast<int>(AAMode::kCoverageWithMSAA) + 1;
 
-std::unique_ptr<GrDrawOp> MakeDashLineOp(GrPaint&&, const SkMatrix& viewMatrix,
-                                         const SkPoint pts[2], AAMode, const GrStyle& style,
+std::unique_ptr<GrDrawOp> MakeDashLineOp(GrContext*,
+                                         GrPaint&&,
+                                         const SkMatrix& viewMatrix,
+                                         const SkPoint pts[2],
+                                         AAMode,
+                                         const GrStyle& style,
                                          const GrUserStencilSettings*);
 bool CanDrawDashLine(const SkPoint pts[2], const GrStyle& style, const SkMatrix& viewMatrix);
 }
diff --git a/src/gpu/ops/GrDebugMarkerOp.cpp b/src/gpu/ops/GrDebugMarkerOp.cpp
index 1b663ce..ed54965 100644
--- a/src/gpu/ops/GrDebugMarkerOp.cpp
+++ b/src/gpu/ops/GrDebugMarkerOp.cpp
@@ -11,6 +11,7 @@
 #include "GrContext.h"
 #include "GrContextPriv.h"
 #include "GrGpuCommandBuffer.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 
 std::unique_ptr<GrOp> GrDebugMarkerOp::Make(GrContext* context,
diff --git a/src/gpu/ops/GrDebugMarkerOp.h b/src/gpu/ops/GrDebugMarkerOp.h
index 931882e..061f676 100644
--- a/src/gpu/ops/GrDebugMarkerOp.h
+++ b/src/gpu/ops/GrDebugMarkerOp.h
@@ -17,9 +17,9 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrOp> Make(GrContext* context,
-                                      GrRenderTargetProxy* proxy,
-                                      const SkString& str);
+    static std::unique_ptr<GrOp> Make(GrContext*,
+                                      GrRenderTargetProxy*,
+                                      const SkString&);
 
     const char* name() const override { return "DebugMarker"; }
 
@@ -30,6 +30,8 @@
     }
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     GrDebugMarkerOp(GrRenderTargetProxy* proxy, const SkString& str)
             : INHERITED(ClassID())
             , fStr(str) {
diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp
index 91eca93..df6f81f 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -14,6 +14,7 @@
 #include "GrOpFlushState.h"
 #include "GrPathUtils.h"
 #include "GrSimpleMeshDrawOpHelper.h"
+#include "GrSurfaceContextPriv.h"
 #include "SkGeometry.h"
 #include "SkString.h"
 #include "SkStrokeRec.h"
@@ -333,13 +334,19 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkPath& path, SkScalar tolerance,
-                                          uint8_t coverage, const SkMatrix& viewMatrix,
-                                          bool isHairline, GrAAType aaType, const SkRect& devBounds,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkPath& path,
+                                          SkScalar tolerance,
+                                          uint8_t coverage,
+                                          const SkMatrix& viewMatrix,
+                                          bool isHairline,
+                                          GrAAType aaType,
+                                          const SkRect& devBounds,
                                           const GrUserStencilSettings* stencilSettings) {
-        return Helper::FactoryHelper<DefaultPathOp>(std::move(paint), path, tolerance, coverage,
-                                                    viewMatrix, isHairline, aaType, devBounds,
-                                                    stencilSettings);
+        return Helper::FactoryHelper<DefaultPathOp>(context, std::move(paint), path, tolerance,
+                                                    coverage, viewMatrix, isHairline, aaType,
+                                                    devBounds, stencilSettings);
     }
 
     const char* name() const override { return "DefaultPathOp"; }
@@ -480,6 +487,8 @@
                                              const SkMatrix& viewMatrix,
                                              const GrShape& shape,
                                              bool stencilOnly) {
+    GrContext* context = renderTargetContext->surfPriv().getContext();
+
     SkASSERT(GrAAType::kCoverage != aaType);
     SkPath path;
     shape.asPath(&path);
@@ -595,17 +604,19 @@
             renderTargetContext->addDrawOp(
                     clip,
                     GrRectOpFactory::MakeNonAAFillWithLocalMatrix(
-                            std::move(paint), viewM, localMatrix, bounds, aaType, passes[p]));
+                            context, std::move(paint), viewM, localMatrix,
+                            bounds, aaType, passes[p]));
         } else {
             bool stencilPass = stencilOnly || passCount > 1;
             std::unique_ptr<GrDrawOp> op;
             if (stencilPass) {
                 GrPaint stencilPaint;
                 stencilPaint.setXPFactory(GrDisableColorXPFactory::Get());
-                op = DefaultPathOp::Make(std::move(stencilPaint), path, srcSpaceTol, newCoverage,
-                                         viewMatrix, isHairline, aaType, devBounds, passes[p]);
+                op = DefaultPathOp::Make(context, std::move(stencilPaint), path, srcSpaceTol,
+                                         newCoverage, viewMatrix, isHairline, aaType, devBounds,
+                                         passes[p]);
             } else {
-                op = DefaultPathOp::Make(std::move(paint), path, srcSpaceTol, newCoverage,
+                op = DefaultPathOp::Make(context, std::move(paint), path, srcSpaceTol, newCoverage,
                                          viewMatrix, isHairline, aaType, devBounds, passes[p]);
             }
             renderTargetContext->addDrawOp(clip, std::move(op));
@@ -679,8 +690,8 @@
     if (GrFSAAType::kUnifiedMSAA == fsaaType && random->nextBool()) {
         aaType = GrAAType::kMSAA;
     }
-    return DefaultPathOp::Make(std::move(paint), path, srcSpaceTol, coverage, viewMatrix, true,
-                               aaType, bounds, GrGetRandomStencil(random, context));
+    return DefaultPathOp::Make(context, std::move(paint), path, srcSpaceTol, coverage, viewMatrix,
+                               true, aaType, bounds, GrGetRandomStencil(random, context));
 }
 
 #endif
diff --git a/src/gpu/ops/GrDrawAtlasOp.cpp b/src/gpu/ops/GrDrawAtlasOp.cpp
index fa948b7..fa08e55 100644
--- a/src/gpu/ops/GrDrawAtlasOp.cpp
+++ b/src/gpu/ops/GrDrawAtlasOp.cpp
@@ -253,8 +253,9 @@
         aaType = GrAAType::kMSAA;
     }
 
-    return GrDrawAtlasOp::Make(std::move(paint), viewMatrix, aaType, spriteCount, xforms.begin(),
-                               texRects.begin(), hasColors ? colors.begin() : nullptr);
+    return GrDrawAtlasOp::Make(context, std::move(paint), viewMatrix, aaType, spriteCount,
+                               xforms.begin(), texRects.begin(),
+                               hasColors ? colors.begin() : nullptr);
 }
 
 #endif
diff --git a/src/gpu/ops/GrDrawAtlasOp.h b/src/gpu/ops/GrDrawAtlasOp.h
index 55c2aee..3bb7aa1 100644
--- a/src/gpu/ops/GrDrawAtlasOp.h
+++ b/src/gpu/ops/GrDrawAtlasOp.h
@@ -20,10 +20,15 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          GrAAType aaType, int spriteCount, const SkRSXform* xforms,
-                                          const SkRect* rects, const SkColor* colors) {
-        return Helper::FactoryHelper<GrDrawAtlasOp>(std::move(paint), viewMatrix, aaType,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          GrAAType aaType,
+                                          int spriteCount,
+                                          const SkRSXform* xforms,
+                                          const SkRect* rects,
+                                          const SkColor* colors) {
+        return Helper::FactoryHelper<GrDrawAtlasOp>(context, std::move(paint), viewMatrix, aaType,
                                                     spriteCount, xforms, rects, colors);
     }
 
diff --git a/src/gpu/ops/GrDrawPathOp.cpp b/src/gpu/ops/GrDrawPathOp.cpp
index b79654c..a5a98f2 100644
--- a/src/gpu/ops/GrDrawPathOp.cpp
+++ b/src/gpu/ops/GrDrawPathOp.cpp
@@ -7,6 +7,7 @@
 
 #include "GrDrawPathOp.h"
 #include "GrAppliedClip.h"
+#include "GrMemoryPool.h"
 #include "GrRenderTargetContext.h"
 #include "GrRenderTargetPriv.h"
 #include "SkTemplates.h"
@@ -63,6 +64,15 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
+std::unique_ptr<GrDrawOp> GrDrawPathOp::Make(GrContext* context,
+                                             const SkMatrix& viewMatrix,
+                                             GrPaint&& paint,
+                                             GrAAType aaType,
+                                             GrPath* path) {
+    return std::unique_ptr<GrDrawOp>(
+                new GrDrawPathOp(viewMatrix, std::move(paint), aaType, path));
+}
+
 void GrDrawPathOp::onExecute(GrOpFlushState* state) {
     GrPipeline pipeline(this->pipelineInitArgs(*state), this->detachProcessors(),
                         state->detachAppliedClip());
diff --git a/src/gpu/ops/GrDrawPathOp.h b/src/gpu/ops/GrDrawPathOp.h
index 665c3da..7125152 100644
--- a/src/gpu/ops/GrDrawPathOp.h
+++ b/src/gpu/ops/GrDrawPathOp.h
@@ -80,17 +80,19 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, GrPaint&& paint,
-                                          GrAAType aaType, GrPath* path) {
-        return std::unique_ptr<GrDrawOp>(
-                new GrDrawPathOp(viewMatrix, std::move(paint), aaType, path));
-    }
+    static std::unique_ptr<GrDrawOp> Make(GrContext*,
+                                          const SkMatrix& viewMatrix,
+                                          GrPaint&&,
+                                          GrAAType,
+                                          GrPath*);
 
     const char* name() const override { return "DrawPath"; }
 
     SkString dumpInfo() const override;
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     GrDrawPathOp(const SkMatrix& viewMatrix, GrPaint&& paint, GrAAType aaType, const GrPath* path)
             : GrDrawPathOpBase(ClassID(), viewMatrix, std::move(paint), path->getFillType(), aaType)
             , fPath(path) {
diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp
index 112ba8b..b35fee0 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -11,7 +11,8 @@
 #include "GrOpFlushState.h"
 #include "SkGr.h"
 
-std::unique_ptr<GrDrawOp> GrDrawVerticesOp::Make(GrPaint&& paint,
+std::unique_ptr<GrDrawOp> GrDrawVerticesOp::Make(GrContext* context,
+                                                 GrPaint&& paint,
                                                  sk_sp<SkVertices> vertices,
                                                  const SkMatrix& viewMatrix,
                                                  GrAAType aaType,
@@ -21,9 +22,9 @@
     SkASSERT(vertices);
     GrPrimitiveType primType = overridePrimType ? *overridePrimType
                                                 : SkVertexModeToGrPrimitiveType(vertices->mode());
-    return Helper::FactoryHelper<GrDrawVerticesOp>(std::move(paint), std::move(vertices), primType,
-                                                   aaType, gammaCorrect, std::move(colorSpaceXform),
-                                                   viewMatrix);
+    return Helper::FactoryHelper<GrDrawVerticesOp>(context, std::move(paint), std::move(vertices),
+                                                   primType, aaType, gammaCorrect,
+                                                   std::move(colorSpaceXform), viewMatrix);
 }
 
 GrDrawVerticesOp::GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor color,
@@ -418,8 +419,8 @@
     if (GrFSAAType::kUnifiedMSAA == fsaaType && random->nextBool()) {
         aaType = GrAAType::kMSAA;
     }
-    return GrDrawVerticesOp::Make(std::move(paint), std::move(vertices), viewMatrix, aaType,
-                                  linearizeColors, std::move(colorSpaceXform), &type);
+    return GrDrawVerticesOp::Make(context, std::move(paint), std::move(vertices), viewMatrix,
+                                  aaType, linearizeColors, std::move(colorSpaceXform), &type);
 }
 
 #endif
diff --git a/src/gpu/ops/GrDrawVerticesOp.h b/src/gpu/ops/GrDrawVerticesOp.h
index cbbc16e..dccb5ec 100644
--- a/src/gpu/ops/GrDrawVerticesOp.h
+++ b/src/gpu/ops/GrDrawVerticesOp.h
@@ -36,8 +36,13 @@
      * specified. If gammaCorrect is true, the vertex colors will be linearized in the shader to get
      * correct rendering.
      */
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&&, sk_sp<SkVertices>, const SkMatrix& viewMatrix,
-                                          GrAAType, bool gammaCorrect, sk_sp<GrColorSpaceXform>,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&&,
+                                          sk_sp<SkVertices>,
+                                          const SkMatrix& viewMatrix,
+                                          GrAAType,
+                                          bool gammaCorrect,
+                                          sk_sp<GrColorSpaceXform>,
                                           GrPrimitiveType* overridePrimType = nullptr);
 
     GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor, sk_sp<SkVertices>,
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index fec62e9..c06dd26 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -125,13 +125,17 @@
     static const int kVertsPerRect = 4;
     static const int kIndicesPerRect = 6;
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
                                           sk_sp<GrTextureProxy> proxy,
                                           sk_sp<GrColorSpaceXform> colorSpaceXForm,
                                           GrSamplerState::Filter filter,
-                                          std::unique_ptr<SkLatticeIter> iter, const SkRect& dst) {
+                                          std::unique_ptr<SkLatticeIter> iter,
+                                          const SkRect& dst) {
         SkASSERT(proxy);
-        return Helper::FactoryHelper<NonAALatticeOp>(std::move(paint), viewMatrix, std::move(proxy),
+        return Helper::FactoryHelper<NonAALatticeOp>(context, std::move(paint), viewMatrix,
+                                                     std::move(proxy),
                                                      std::move(colorSpaceXForm), filter,
                                                      std::move(iter), dst);
     }
@@ -310,12 +314,15 @@
 }  // anonymous namespace
 
 namespace GrLatticeOp {
-std::unique_ptr<GrDrawOp> MakeNonAA(GrPaint&& paint, const SkMatrix& viewMatrix,
+std::unique_ptr<GrDrawOp> MakeNonAA(GrContext* context,
+                                    GrPaint&& paint,
+                                    const SkMatrix& viewMatrix,
                                     sk_sp<GrTextureProxy> proxy,
                                     sk_sp<GrColorSpaceXform> colorSpaceXform,
                                     GrSamplerState::Filter filter,
-                                    std::unique_ptr<SkLatticeIter> iter, const SkRect& dst) {
-    return NonAALatticeOp::Make(std::move(paint), viewMatrix, std::move(proxy),
+                                    std::unique_ptr<SkLatticeIter> iter,
+                                    const SkRect& dst) {
+    return NonAALatticeOp::Make(context, std::move(paint), viewMatrix, std::move(proxy),
                                 std::move(colorSpaceXform), filter, std::move(iter), dst);
 }
 };
@@ -424,8 +431,8 @@
     auto csxf = GrTest::TestColorXform(random);
     GrSamplerState::Filter filter =
             random->nextBool() ? GrSamplerState::Filter::kNearest : GrSamplerState::Filter::kBilerp;
-    return NonAALatticeOp::Make(std::move(paint), viewMatrix, std::move(proxy), std::move(csxf),
-                                filter, std::move(iter), dst);
+    return NonAALatticeOp::Make(context, std::move(paint), viewMatrix, std::move(proxy),
+                                std::move(csxf), filter, std::move(iter), dst);
 }
 
 #endif
diff --git a/src/gpu/ops/GrLatticeOp.h b/src/gpu/ops/GrLatticeOp.h
index ab3b8ea..ef723ce 100644
--- a/src/gpu/ops/GrLatticeOp.h
+++ b/src/gpu/ops/GrLatticeOp.h
@@ -12,6 +12,7 @@
 #include "GrSamplerState.h"
 #include "SkRefCnt.h"
 
+class GrContext;
 class GrDrawOp;
 class GrPaint;
 class SkLatticeIter;
@@ -21,9 +22,14 @@
 struct SkRect;
 
 namespace GrLatticeOp {
-std::unique_ptr<GrDrawOp> MakeNonAA(GrPaint&&, const SkMatrix& viewMatrix, sk_sp<GrTextureProxy>,
-                                    sk_sp<GrColorSpaceXform>, GrSamplerState::Filter,
-                                    std::unique_ptr<SkLatticeIter>, const SkRect& dst);
+std::unique_ptr<GrDrawOp> MakeNonAA(GrContext*,
+                                    GrPaint&&,
+                                    const SkMatrix& viewMatrix,
+                                    sk_sp<GrTextureProxy>,
+                                    sk_sp<GrColorSpaceXform>,
+                                    GrSamplerState::Filter,
+                                    std::unique_ptr<SkLatticeIter>,
+                                    const SkRect& dst);
 };
 
 #endif
diff --git a/src/gpu/ops/GrNonAAFillRectOp.cpp b/src/gpu/ops/GrNonAAFillRectOp.cpp
index 269f876..20bd599 100644
--- a/src/gpu/ops/GrNonAAFillRectOp.cpp
+++ b/src/gpu/ops/GrNonAAFillRectOp.cpp
@@ -104,13 +104,18 @@
     using Helper = GrSimpleMeshDrawOpHelperWithStencil;
 
 public:
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          const SkRect& rect, const SkRect* localRect,
-                                          const SkMatrix* localMatrix, GrAAType aaType,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          const SkRect& rect,
+                                          const SkRect* localRect,
+                                          const SkMatrix* localMatrix,
+                                          GrAAType aaType,
                                           const GrUserStencilSettings* stencilSettings) {
         SkASSERT(GrAAType::kCoverage != aaType);
-        return Helper::FactoryHelper<NonAAFillRectOp>(std::move(paint), viewMatrix, rect, localRect,
-                                                      localMatrix, aaType, stencilSettings);
+        return Helper::FactoryHelper<NonAAFillRectOp>(context, std::move(paint), viewMatrix, rect,
+                                                      localRect, localMatrix, aaType,
+                                                      stencilSettings);
     }
 
     NonAAFillRectOp() = delete;
@@ -228,12 +233,17 @@
     using Helper = GrSimpleMeshDrawOpHelperWithStencil;
 
 public:
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          const SkRect& rect, const SkRect* localRect,
-                                          const SkMatrix* localMatrix, GrAAType aaType,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          const SkRect& rect,
+                                          const SkRect* localRect,
+                                          const SkMatrix* localMatrix,
+                                          GrAAType aaType,
                                           const GrUserStencilSettings* stencilSettings) {
         SkASSERT(GrAAType::kCoverage != aaType);
-        return Helper::FactoryHelper<NonAAFillRectPerspectiveOp>(std::move(paint), viewMatrix, rect,
+        return Helper::FactoryHelper<NonAAFillRectPerspectiveOp>(context, std::move(paint),
+                                                                 viewMatrix, rect,
                                                                  localRect, localMatrix, aaType,
                                                                  stencilSettings);
     }
@@ -375,39 +385,50 @@
 
 namespace GrRectOpFactory {
 
-std::unique_ptr<GrDrawOp> MakeNonAAFill(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                        const SkRect& rect, GrAAType aaType,
+std::unique_ptr<GrDrawOp> MakeNonAAFill(GrContext* context,
+                                        GrPaint&& paint,
+                                        const SkMatrix& viewMatrix,
+                                        const SkRect& rect,
+                                        GrAAType aaType,
                                         const GrUserStencilSettings* stencilSettings) {
     if (viewMatrix.hasPerspective()) {
-        return NonAAFillRectPerspectiveOp::Make(std::move(paint), viewMatrix, rect, nullptr,
-                                                nullptr, aaType, stencilSettings);
+        return NonAAFillRectPerspectiveOp::Make(context, std::move(paint), viewMatrix, rect,
+                                                nullptr, nullptr, aaType, stencilSettings);
     } else {
-        return NonAAFillRectOp::Make(std::move(paint), viewMatrix, rect, nullptr, nullptr, aaType,
-                                     stencilSettings);
-    }
-}
-
-std::unique_ptr<GrDrawOp> MakeNonAAFillWithLocalMatrix(
-        GrPaint&& paint, const SkMatrix& viewMatrix, const SkMatrix& localMatrix,
-        const SkRect& rect, GrAAType aaType, const GrUserStencilSettings* stencilSettings) {
-    if (viewMatrix.hasPerspective() || localMatrix.hasPerspective()) {
-        return NonAAFillRectPerspectiveOp::Make(std::move(paint), viewMatrix, rect, nullptr,
-                                                &localMatrix, aaType, stencilSettings);
-    } else {
-        return NonAAFillRectOp::Make(std::move(paint), viewMatrix, rect, nullptr, &localMatrix,
+        return NonAAFillRectOp::Make(context, std::move(paint), viewMatrix, rect, nullptr, nullptr,
                                      aaType, stencilSettings);
     }
 }
 
-std::unique_ptr<GrDrawOp> MakeNonAAFillWithLocalRect(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                                     const SkRect& rect, const SkRect& localRect,
+std::unique_ptr<GrDrawOp> MakeNonAAFillWithLocalMatrix(
+                                                    GrContext* context,
+                                                    GrPaint&& paint,
+                                                    const SkMatrix& viewMatrix,
+                                                    const SkMatrix& localMatrix,
+                                                    const SkRect& rect,
+                                                    GrAAType aaType,
+                                                    const GrUserStencilSettings* stencilSettings) {
+    if (viewMatrix.hasPerspective() || localMatrix.hasPerspective()) {
+        return NonAAFillRectPerspectiveOp::Make(context, std::move(paint), viewMatrix, rect,
+                                                nullptr, &localMatrix, aaType, stencilSettings);
+    } else {
+        return NonAAFillRectOp::Make(context, std::move(paint), viewMatrix, rect, nullptr,
+                                     &localMatrix, aaType, stencilSettings);
+    }
+}
+
+std::unique_ptr<GrDrawOp> MakeNonAAFillWithLocalRect(GrContext* context,
+                                                     GrPaint&& paint,
+                                                     const SkMatrix& viewMatrix,
+                                                     const SkRect& rect,
+                                                     const SkRect& localRect,
                                                      GrAAType aaType) {
     if (viewMatrix.hasPerspective()) {
-        return NonAAFillRectPerspectiveOp::Make(std::move(paint), viewMatrix, rect, &localRect,
-                                                nullptr, aaType, nullptr);
+        return NonAAFillRectPerspectiveOp::Make(context, std::move(paint), viewMatrix, rect,
+                                                &localRect, nullptr, aaType, nullptr);
     } else {
-        return NonAAFillRectOp::Make(std::move(paint), viewMatrix, rect, &localRect, nullptr,
-                                     aaType, nullptr);
+        return NonAAFillRectOp::Make(context, std::move(paint), viewMatrix, rect, &localRect,
+                                     nullptr, aaType, nullptr);
     }
 }
 
@@ -430,10 +451,11 @@
     const SkRect* lr = random->nextBool() ? &localRect : nullptr;
     const SkMatrix* lm = random->nextBool() ? &localMatrix : nullptr;
     if (viewMatrix.hasPerspective() || (lm && lm->hasPerspective())) {
-        return NonAAFillRectPerspectiveOp::Make(std::move(paint), viewMatrix, rect, lr, lm, aaType,
-                                                stencil);
+        return NonAAFillRectPerspectiveOp::Make(context, std::move(paint), viewMatrix, rect,
+                                                lr, lm, aaType, stencil);
     } else {
-        return NonAAFillRectOp::Make(std::move(paint), viewMatrix, rect, lr, lm, aaType, stencil);
+        return NonAAFillRectOp::Make(context, std::move(paint), viewMatrix, rect,
+                                     lr, lm, aaType, stencil);
     }
 }
 
diff --git a/src/gpu/ops/GrNonAAStrokeRectOp.cpp b/src/gpu/ops/GrNonAAStrokeRectOp.cpp
index 6e53bea..5e00e55 100644
--- a/src/gpu/ops/GrNonAAStrokeRectOp.cpp
+++ b/src/gpu/ops/GrNonAAStrokeRectOp.cpp
@@ -78,8 +78,11 @@
         return string;
     }
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          const SkRect& rect, const SkStrokeRec& stroke,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          const SkRect& rect,
+                                          const SkStrokeRec& stroke,
                                           GrAAType aaType) {
         if (!allowed_stroke(stroke)) {
             return nullptr;
@@ -91,7 +94,8 @@
         if (stroke.getStyle() == SkStrokeRec::kHairline_Style && aaType != GrAAType::kMSAA) {
             flags |= Helper::Flags::kSnapVerticesToPixelCenters;
         }
-        return Helper::FactoryHelper<NonAAStrokeRectOp>(std::move(paint), flags, viewMatrix, rect,
+        return Helper::FactoryHelper<NonAAStrokeRectOp>(context, std::move(paint), flags,
+                                                        viewMatrix, rect,
                                                         stroke, aaType);
     }
 
@@ -211,12 +215,13 @@
 }  // anonymous namespace
 
 namespace GrRectOpFactory {
-std::unique_ptr<GrDrawOp> MakeNonAAStroke(GrPaint&& paint,
+std::unique_ptr<GrDrawOp> MakeNonAAStroke(GrContext* context,
+                                          GrPaint&& paint,
                                           const SkMatrix& viewMatrix,
                                           const SkRect& rect,
                                           const SkStrokeRec& stroke,
                                           GrAAType aaType) {
-    return NonAAStrokeRectOp::Make(std::move(paint), viewMatrix, rect, stroke, aaType);
+    return NonAAStrokeRectOp::Make(context, std::move(paint), viewMatrix, rect, stroke, aaType);
 }
 }  // namespace GrRectOpFactory
 
@@ -235,7 +240,7 @@
     if (fsaaType == GrFSAAType::kUnifiedMSAA) {
         aaType = random->nextBool() ? GrAAType::kMSAA : GrAAType::kNone;
     }
-    return NonAAStrokeRectOp::Make(std::move(paint), viewMatrix, rect, strokeRec, aaType);
+    return NonAAStrokeRectOp::Make(context, std::move(paint), viewMatrix, rect, strokeRec, aaType);
 }
 
 #endif
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index f6a2a1a..747fa5f 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -867,8 +867,12 @@
         bool fUseCenter;
     };
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          SkPoint center, SkScalar radius, const GrStyle& style,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          SkPoint center,
+                                          SkScalar radius,
+                                          const GrStyle& style,
                                           const ArcParams* arcParams = nullptr) {
         SkASSERT(circle_stays_circle(viewMatrix));
         if (style.hasPathEffect()) {
@@ -901,8 +905,8 @@
                     break;
             }
         }
-        return Helper::FactoryHelper<CircleOp>(std::move(paint), viewMatrix, center, radius, style,
-                                               arcParams);
+        return Helper::FactoryHelper<CircleOp>(context, std::move(paint), viewMatrix, center,
+                                               radius, style, arcParams);
     }
 
     CircleOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix,
@@ -1484,14 +1488,20 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          SkPoint center, SkScalar radius, SkScalar strokeWidth,
-                                          SkScalar startAngle, SkScalar onAngle, SkScalar offAngle,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          SkPoint center,
+                                          SkScalar radius,
+                                          SkScalar strokeWidth,
+                                          SkScalar startAngle,
+                                          SkScalar onAngle,
+                                          SkScalar offAngle,
                                           SkScalar phaseAngle) {
         SkASSERT(circle_stays_circle(viewMatrix));
         SkASSERT(strokeWidth < 2 * radius);
-        return Helper::FactoryHelper<ButtCapDashedCircleOp>(std::move(paint), viewMatrix, center,
-                                                            radius, strokeWidth, startAngle,
+        return Helper::FactoryHelper<ButtCapDashedCircleOp>(context, std::move(paint), viewMatrix,
+                                                            center, radius, strokeWidth, startAngle,
                                                             onAngle, offAngle, phaseAngle);
     }
 
@@ -1790,8 +1800,11 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          const SkRect& ellipse, const SkStrokeRec& stroke) {
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          const SkRect& ellipse,
+                                          const SkStrokeRec& stroke) {
         DeviceSpaceParams params;
         // do any matrix crunching before we reset the draw state for device coords
         params.fCenter = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
@@ -1849,7 +1862,8 @@
             params.fXRadius += scaledStroke.fX;
             params.fYRadius += scaledStroke.fY;
         }
-        return Helper::FactoryHelper<EllipseOp>(std::move(paint), viewMatrix, params, stroke);
+        return Helper::FactoryHelper<EllipseOp>(context, std::move(paint), viewMatrix,
+                                                params, stroke);
     }
 
     EllipseOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix,
@@ -2026,8 +2040,11 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          const SkRect& ellipse, const SkStrokeRec& stroke) {
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          const SkRect& ellipse,
+                                          const SkStrokeRec& stroke) {
         DeviceSpaceParams params;
         params.fCenter = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
         params.fXRadius = SkScalarHalf(ellipse.width());
@@ -2081,7 +2098,7 @@
             (params.fInnerXRadius <= 0 || params.fInnerYRadius <= 0)) {
             params.fStyle = DIEllipseStyle::kFill;
         }
-        return Helper::FactoryHelper<DIEllipseOp>(std::move(paint), params, viewMatrix);
+        return Helper::FactoryHelper<DIEllipseOp>(context, std::move(paint), params, viewMatrix);
     }
 
     DIEllipseOp(Helper::MakeArgs& helperArgs, GrColor color, const DeviceSpaceParams& params,
@@ -2379,11 +2396,16 @@
 
     // A devStrokeWidth <= 0 indicates a fill only. If devStrokeWidth > 0 then strokeOnly indicates
     // whether the rrect is only stroked or stroked and filled.
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          const SkRect& devRect, float devRadius,
-                                          float devStrokeWidth, bool strokeOnly) {
-        return Helper::FactoryHelper<CircularRRectOp>(std::move(paint), viewMatrix, devRect,
-                                                      devRadius, devStrokeWidth, strokeOnly);
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          const SkRect& devRect,
+                                          float devRadius,
+                                          float devStrokeWidth,
+                                          bool strokeOnly) {
+        return Helper::FactoryHelper<CircularRRectOp>(context, std::move(paint), viewMatrix,
+                                                      devRect, devRadius,
+                                                      devStrokeWidth, strokeOnly);
     }
     CircularRRectOp(Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix,
                     const SkRect& devRect, float devRadius, float devStrokeWidth, bool strokeOnly)
@@ -2729,9 +2751,14 @@
 
     // If devStrokeWidths values are <= 0 indicates then fill only. Otherwise, strokeOnly indicates
     // whether the rrect is only stroked or stroked and filled.
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          const SkRect& devRect, float devXRadius, float devYRadius,
-                                          SkVector devStrokeWidths, bool strokeOnly) {
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          const SkRect& devRect,
+                                          float devXRadius,
+                                          float devYRadius,
+                                          SkVector devStrokeWidths,
+                                          bool strokeOnly) {
         SkASSERT(devXRadius > 0.5);
         SkASSERT(devYRadius > 0.5);
         SkASSERT((devStrokeWidths.fX > 0) == (devStrokeWidths.fY > 0));
@@ -2760,7 +2787,8 @@
                 return nullptr;
             }
         }
-        return Helper::FactoryHelper<EllipticalRRectOp>(std::move(paint), viewMatrix, devRect,
+        return Helper::FactoryHelper<EllipticalRRectOp>(context, std::move(paint),
+                                                        viewMatrix, devRect,
                                                         devXRadius, devYRadius, devStrokeWidths,
                                                         strokeOnly);
     }
@@ -2945,7 +2973,8 @@
     typedef GrMeshDrawOp INHERITED;
 };
 
-static std::unique_ptr<GrDrawOp> make_rrect_op(GrPaint&& paint,
+static std::unique_ptr<GrDrawOp> make_rrect_op(GrContext* context,
+                                               GrPaint&& paint,
                                                const SkMatrix& viewMatrix,
                                                const SkRRect& rrect,
                                                const SkStrokeRec& stroke) {
@@ -3006,35 +3035,37 @@
 
     // if the corners are circles, use the circle renderer
     if (isCircular) {
-        return CircularRRectOp::Make(std::move(paint), viewMatrix, bounds, xRadius, scaledStroke.fX,
-                                     isStrokeOnly);
+        return CircularRRectOp::Make(context, std::move(paint), viewMatrix, bounds, xRadius,
+                                     scaledStroke.fX, isStrokeOnly);
         // otherwise we use the ellipse renderer
     } else {
-        return EllipticalRRectOp::Make(std::move(paint), viewMatrix, bounds, xRadius, yRadius,
-                                       scaledStroke, isStrokeOnly);
+        return EllipticalRRectOp::Make(context, std::move(paint), viewMatrix, bounds,
+                                       xRadius, yRadius, scaledStroke, isStrokeOnly);
     }
 }
 
-std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeRRectOp(GrPaint&& paint,
+std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeRRectOp(GrContext* context,
+                                                       GrPaint&& paint,
                                                        const SkMatrix& viewMatrix,
                                                        const SkRRect& rrect,
                                                        const SkStrokeRec& stroke,
                                                        const GrShaderCaps* shaderCaps) {
     if (rrect.isOval()) {
-        return MakeOvalOp(std::move(paint), viewMatrix, rrect.getBounds(), GrStyle(stroke, nullptr),
-                          shaderCaps);
+        return MakeOvalOp(context, std::move(paint), viewMatrix, rrect.getBounds(),
+                          GrStyle(stroke, nullptr), shaderCaps);
     }
 
     if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) {
         return nullptr;
     }
 
-    return make_rrect_op(std::move(paint), viewMatrix, rrect, stroke);
+    return make_rrect_op(context, std::move(paint), viewMatrix, rrect, stroke);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeOvalOp(GrPaint&& paint,
+std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeOvalOp(GrContext* context,
+                                                      GrPaint&& paint,
                                                       const SkMatrix& viewMatrix,
                                                       const SkRect& oval,
                                                       const GrStyle& style,
@@ -3056,7 +3087,8 @@
             auto offInterval = style.dashIntervals()[1];
             if (offInterval == 0) {
                 GrStyle strokeStyle(style.strokeRec(), nullptr);
-                return MakeOvalOp(std::move(paint), viewMatrix, oval, strokeStyle, shaderCaps);
+                return MakeOvalOp(context, std::move(paint), viewMatrix, oval,
+                                  strokeStyle, shaderCaps);
             } else if (onInterval == 0) {
                 // There is nothing to draw but we have no way to indicate that here.
                 return nullptr;
@@ -3067,11 +3099,11 @@
             // Currently this function doesn't accept ovals with different start angles, though
             // it could.
             static const SkScalar kStartAngle = 0.f;
-            return ButtCapDashedCircleOp::Make(std::move(paint), viewMatrix, center, r,
+            return ButtCapDashedCircleOp::Make(context, std::move(paint), viewMatrix, center, r,
                                                style.strokeRec().getWidth(), kStartAngle,
                                                angularOnInterval, angularOffInterval, phaseAngle);
         }
-        return CircleOp::Make(std::move(paint), viewMatrix, center, r, style);
+        return CircleOp::Make(context, std::move(paint), viewMatrix, center, r, style);
     }
 
     if (style.pathEffect()) {
@@ -3080,12 +3112,12 @@
 
     // prefer the device space ellipse op for batchability
     if (viewMatrix.rectStaysRect()) {
-        return EllipseOp::Make(std::move(paint), viewMatrix, oval, style.strokeRec());
+        return EllipseOp::Make(context, std::move(paint), viewMatrix, oval, style.strokeRec());
     }
 
     // Otherwise, if we have shader derivative support, render as device-independent
     if (shaderCaps->shaderDerivativeSupport()) {
-        return DIEllipseOp::Make(std::move(paint), viewMatrix, oval, style.strokeRec());
+        return DIEllipseOp::Make(context, std::move(paint), viewMatrix, oval, style.strokeRec());
     }
 
     return nullptr;
@@ -3093,7 +3125,9 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeArcOp(GrPaint&& paint, const SkMatrix& viewMatrix,
+std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeArcOp(GrContext* context,
+                                                     GrPaint&& paint,
+                                                     const SkMatrix& viewMatrix,
                                                      const SkRect& oval, SkScalar startAngle,
                                                      SkScalar sweepAngle, bool useCenter,
                                                      const GrStyle& style,
@@ -3110,7 +3144,8 @@
     SkPoint center = {oval.centerX(), oval.centerY()};
     CircleOp::ArcParams arcParams = {SkDegreesToRadians(startAngle), SkDegreesToRadians(sweepAngle),
                                      useCenter};
-    return CircleOp::Make(std::move(paint), viewMatrix, center, width / 2.f, style, &arcParams);
+    return CircleOp::Make(context, std::move(paint), viewMatrix,
+                          center, width / 2.f, style, &arcParams);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -3142,7 +3177,8 @@
             arcParamsTmp.fUseCenter = random->nextBool();
             arcParams = &arcParamsTmp;
         }
-        std::unique_ptr<GrDrawOp> op = CircleOp::Make(std::move(paint), viewMatrix, center, radius,
+        std::unique_ptr<GrDrawOp> op = CircleOp::Make(context, std::move(paint), viewMatrix,
+                                                      center, radius,
                                                       GrStyle(stroke, nullptr), arcParams);
         if (op) {
             return op;
@@ -3170,26 +3206,30 @@
     SkScalar offAngle = random->nextRangeScalar(0.01f, 1000.f);
     SkScalar startAngle = random->nextRangeScalar(-1000.f, 1000.f);
     SkScalar phase = random->nextRangeScalar(-1000.f, 1000.f);
-    return ButtCapDashedCircleOp::Make(std::move(paint), viewMatrix, center, radius, strokeWidth,
+    return ButtCapDashedCircleOp::Make(context, std::move(paint), viewMatrix,
+                                       center, radius, strokeWidth,
                                        startAngle, onAngle, offAngle, phase);
 }
 
 GR_DRAW_OP_TEST_DEFINE(EllipseOp) {
     SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
     SkRect ellipse = GrTest::TestSquare(random);
-    return EllipseOp::Make(std::move(paint), viewMatrix, ellipse, GrTest::TestStrokeRec(random));
+    return EllipseOp::Make(context, std::move(paint), viewMatrix, ellipse,
+                           GrTest::TestStrokeRec(random));
 }
 
 GR_DRAW_OP_TEST_DEFINE(DIEllipseOp) {
     SkMatrix viewMatrix = GrTest::TestMatrix(random);
     SkRect ellipse = GrTest::TestSquare(random);
-    return DIEllipseOp::Make(std::move(paint), viewMatrix, ellipse, GrTest::TestStrokeRec(random));
+    return DIEllipseOp::Make(context, std::move(paint), viewMatrix, ellipse,
+                             GrTest::TestStrokeRec(random));
 }
 
 GR_DRAW_OP_TEST_DEFINE(RRectOp) {
     SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
     const SkRRect& rrect = GrTest::TestRRectSimple(random);
-    return make_rrect_op(std::move(paint), viewMatrix, rrect, GrTest::TestStrokeRec(random));
+    return make_rrect_op(context, std::move(paint), viewMatrix, rrect,
+                         GrTest::TestStrokeRec(random));
 }
 
 #endif
diff --git a/src/gpu/ops/GrOvalOpFactory.h b/src/gpu/ops/GrOvalOpFactory.h
index 0c10d6b..117d31d 100644
--- a/src/gpu/ops/GrOvalOpFactory.h
+++ b/src/gpu/ops/GrOvalOpFactory.h
@@ -11,6 +11,7 @@
 #include "GrColor.h"
 #include "SkRefCnt.h"
 
+class GrContext;
 class GrDrawOp;
 class GrPaint;
 class GrShaderCaps;
@@ -25,19 +26,22 @@
  */
 class GrOvalOpFactory {
 public:
-    static std::unique_ptr<GrDrawOp> MakeOvalOp(GrPaint&&,
+    static std::unique_ptr<GrDrawOp> MakeOvalOp(GrContext*,
+                                                GrPaint&&,
                                                 const SkMatrix&,
                                                 const SkRect& oval,
                                                 const GrStyle& style,
                                                 const GrShaderCaps*);
 
-    static std::unique_ptr<GrDrawOp> MakeRRectOp(GrPaint&&,
+    static std::unique_ptr<GrDrawOp> MakeRRectOp(GrContext*,
+                                                 GrPaint&&,
                                                  const SkMatrix&,
                                                  const SkRRect&,
                                                  const SkStrokeRec&,
                                                  const GrShaderCaps*);
 
-    static std::unique_ptr<GrDrawOp> MakeArcOp(GrPaint&&,
+    static std::unique_ptr<GrDrawOp> MakeArcOp(GrContext*,
+                                               GrPaint&&,
                                                const SkMatrix&,
                                                const SkRect& oval,
                                                SkScalar startAngle,
diff --git a/src/gpu/ops/GrRectOpFactory.h b/src/gpu/ops/GrRectOpFactory.h
index e662ab1..29ac10e 100644
--- a/src/gpu/ops/GrRectOpFactory.h
+++ b/src/gpu/ops/GrRectOpFactory.h
@@ -28,41 +28,71 @@
 namespace GrRectOpFactory {
 /** AA Fill */
 
-std::unique_ptr<GrDrawOp> MakeAAFill(GrPaint&&, const SkMatrix&, const SkRect&,
+std::unique_ptr<GrDrawOp> MakeAAFill(GrContext*,
+                                     GrPaint&&,
+                                     const SkMatrix&,
+                                     const SkRect&,
                                      const GrUserStencilSettings* = nullptr);
 
-std::unique_ptr<GrDrawOp> MakeAAFillWithLocalMatrix(GrPaint&&, const SkMatrix& viewMatrix,
-                                                    const SkMatrix& localMatrix, const SkRect&);
+std::unique_ptr<GrDrawOp> MakeAAFillWithLocalMatrix(GrContext*,
+                                                    GrPaint&&,
+                                                    const SkMatrix& viewMatrix,
+                                                    const SkMatrix& localMatrix,
+                                                    const SkRect&);
 
-std::unique_ptr<GrDrawOp> MakeAAFillWithLocalRect(GrPaint&&, const SkMatrix&, const SkRect& rect,
+std::unique_ptr<GrDrawOp> MakeAAFillWithLocalRect(GrContext*,
+                                                  GrPaint&&,
+                                                  const SkMatrix&,
+                                                  const SkRect& rect,
                                                   const SkRect& localRect);
 
 /** Non-AA Fill - GrAAType must be either kNone or kMSAA. */
 
-std::unique_ptr<GrDrawOp> MakeNonAAFill(GrPaint&&, const SkMatrix& viewMatrix, const SkRect& rect,
-                                        GrAAType, const GrUserStencilSettings* = nullptr);
+std::unique_ptr<GrDrawOp> MakeNonAAFill(GrContext*,
+                                        GrPaint&&,
+                                        const SkMatrix& viewMatrix,
+                                        const SkRect& rect,
+                                        GrAAType,
+                                        const GrUserStencilSettings* = nullptr);
 
-std::unique_ptr<GrDrawOp> MakeNonAAFillWithLocalMatrix(GrPaint&&, const SkMatrix& viewMatrix,
-                                                       const SkMatrix& localMatrix, const SkRect&,
+std::unique_ptr<GrDrawOp> MakeNonAAFillWithLocalMatrix(GrContext*,
+                                                       GrPaint&&,
+                                                       const SkMatrix& viewMatrix,
+                                                       const SkMatrix& localMatrix,
+                                                       const SkRect&,
                                                        GrAAType,
                                                        const GrUserStencilSettings* = nullptr);
 
-std::unique_ptr<GrDrawOp> MakeNonAAFillWithLocalRect(GrPaint&&, const SkMatrix&, const SkRect& rect,
-                                                     const SkRect& localRect, GrAAType);
+std::unique_ptr<GrDrawOp> MakeNonAAFillWithLocalRect(GrContext*,
+                                                     GrPaint&&,
+                                                     const SkMatrix&,
+                                                     const SkRect& rect,
+                                                     const SkRect& localRect,
+                                                     GrAAType);
 
 /** AA Stroke */
 
-std::unique_ptr<GrDrawOp> MakeAAStroke(GrPaint&&, const SkMatrix&, const SkRect&,
+std::unique_ptr<GrDrawOp> MakeAAStroke(GrContext*,
+                                       GrPaint&&,
+                                       const SkMatrix&,
+                                       const SkRect&,
                                        const SkStrokeRec&);
 
 // rects[0] == outer rectangle, rects[1] == inner rectangle. Null return means there is nothing to
 // draw rather than failure.
-std::unique_ptr<GrDrawOp> MakeAAFillNestedRects(GrPaint&&, const SkMatrix&, const SkRect rects[2]);
+std::unique_ptr<GrDrawOp> MakeAAFillNestedRects(GrContext*,
+                                                GrPaint&&,
+                                                const SkMatrix&,
+                                                const SkRect rects[2]);
 
 /** Non-AA Stroke - GrAAType must be either kNone or kMSAA. */
 
-std::unique_ptr<GrDrawOp> MakeNonAAStroke(GrPaint&&, const SkMatrix&, const SkRect&,
-                                          const SkStrokeRec&, GrAAType);
+std::unique_ptr<GrDrawOp> MakeNonAAStroke(GrContext*,
+                                          GrPaint&&,
+                                          const SkMatrix&,
+                                          const SkRect&,
+                                          const SkStrokeRec&,
+                                          GrAAType);
 
 }  // namespace GrRectOpFactory
 
diff --git a/src/gpu/ops/GrRegionOp.cpp b/src/gpu/ops/GrRegionOp.cpp
index 5f63f09..9e81d66 100644
--- a/src/gpu/ops/GrRegionOp.cpp
+++ b/src/gpu/ops/GrRegionOp.cpp
@@ -58,11 +58,14 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
-                                          const SkRegion& region, GrAAType aaType,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          const SkRegion& region,
+                                          GrAAType aaType,
                                           const GrUserStencilSettings* stencilSettings = nullptr) {
-        return Helper::FactoryHelper<RegionOp>(std::move(paint), viewMatrix, region, aaType,
-                                               stencilSettings);
+        return Helper::FactoryHelper<RegionOp>(context, std::move(paint), viewMatrix, region,
+                                               aaType, stencilSettings);
     }
 
     RegionOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix,
@@ -174,12 +177,16 @@
 
 namespace GrRegionOp {
 
-std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix, const SkRegion& region,
-                               GrAAType aaType, const GrUserStencilSettings* stencilSettings) {
+std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                               GrPaint&& paint,
+                               const SkMatrix& viewMatrix,
+                               const SkRegion& region,
+                               GrAAType aaType,
+                               const GrUserStencilSettings* stencilSettings) {
     if (aaType != GrAAType::kNone && aaType != GrAAType::kMSAA) {
         return nullptr;
     }
-    return RegionOp::Make(std::move(paint), viewMatrix, region, aaType, stencilSettings);
+    return RegionOp::Make(context, std::move(paint), viewMatrix, region, aaType, stencilSettings);
 }
 }
 
@@ -210,7 +217,7 @@
     if (GrFSAAType::kUnifiedMSAA == fsaaType && random->nextBool()) {
         aaType = GrAAType::kMSAA;
     }
-    return RegionOp::Make(std::move(paint), viewMatrix, region, aaType,
+    return RegionOp::Make(context, std::move(paint), viewMatrix, region, aaType,
                           GrGetRandomStencil(random, context));
 }
 
diff --git a/src/gpu/ops/GrRegionOp.h b/src/gpu/ops/GrRegionOp.h
index b74f78c..e9281f8 100644
--- a/src/gpu/ops/GrRegionOp.h
+++ b/src/gpu/ops/GrRegionOp.h
@@ -10,6 +10,7 @@
 
 #include "GrTypesPriv.h"
 
+class GrContext;
 class GrDrawOp;
 class SkMatrix;
 class SkRegion;
@@ -18,7 +19,11 @@
 
 namespace GrRegionOp {
 /** GrAAType must be kNone or kMSAA. */
-std::unique_ptr<GrDrawOp> Make(GrPaint&&, const SkMatrix& viewMatrix, const SkRegion&, GrAAType,
+std::unique_ptr<GrDrawOp> Make(GrContext*,
+                               GrPaint&&,
+                               const SkMatrix& viewMatrix,
+                               const SkRegion&,
+                               GrAAType,
                                const GrUserStencilSettings* stencilSettings = nullptr);
 }
 
diff --git a/src/gpu/ops/GrSemaphoreOp.cpp b/src/gpu/ops/GrSemaphoreOp.cpp
index a6c9ac7..fedf6b7 100644
--- a/src/gpu/ops/GrSemaphoreOp.cpp
+++ b/src/gpu/ops/GrSemaphoreOp.cpp
@@ -7,16 +7,20 @@
 
 #include "GrSemaphoreOp.h"
 
+#include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrGpu.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 
 class GrSignalSemaphoreOp final : public GrSemaphoreOp {
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrSignalSemaphoreOp> Make(sk_sp<GrSemaphore> semaphore,
-                                                     GrRenderTargetProxy* proxy,
-                                                     bool forceFlush) {
+    static std::unique_ptr<GrOp> Make(GrContext* context,
+                                      sk_sp<GrSemaphore> semaphore,
+                                      GrRenderTargetProxy* proxy,
+                                      bool forceFlush) {
         return std::unique_ptr<GrSignalSemaphoreOp>(new GrSignalSemaphoreOp(std::move(semaphore),
                                                                             proxy,
                                                                             forceFlush));
@@ -25,6 +29,8 @@
     const char* name() const override { return "SignalSemaphore"; }
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     explicit GrSignalSemaphoreOp(sk_sp<GrSemaphore> semaphore, GrRenderTargetProxy* proxy,
                                  bool forceFlush)
             : INHERITED(ClassID(), std::move(semaphore), proxy), fForceFlush(forceFlush) {}
@@ -42,8 +48,9 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrWaitSemaphoreOp> Make(sk_sp<GrSemaphore> semaphore,
-                                                   GrRenderTargetProxy* proxy) {
+    static std::unique_ptr<GrOp> Make(GrContext* context,
+                                      sk_sp<GrSemaphore> semaphore,
+                                      GrRenderTargetProxy* proxy) {
         return std::unique_ptr<GrWaitSemaphoreOp>(new GrWaitSemaphoreOp(std::move(semaphore),
                                                                         proxy));
     }
@@ -51,6 +58,8 @@
     const char* name() const override { return "WaitSemaphore"; }
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     explicit GrWaitSemaphoreOp(sk_sp<GrSemaphore> semaphore, GrRenderTargetProxy* proxy)
             : INHERITED(ClassID(), std::move(semaphore), proxy) {}
 
@@ -63,15 +72,17 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-std::unique_ptr<GrSemaphoreOp> GrSemaphoreOp::MakeSignal(sk_sp<GrSemaphore> semaphore,
-                                                         GrRenderTargetProxy* proxy,
-                                                         bool forceFlush) {
-    return GrSignalSemaphoreOp::Make(std::move(semaphore), proxy, forceFlush);
+std::unique_ptr<GrOp> GrSemaphoreOp::MakeSignal(GrContext* context,
+                                                sk_sp<GrSemaphore> semaphore,
+                                                GrRenderTargetProxy* proxy,
+                                                bool forceFlush) {
+    return GrSignalSemaphoreOp::Make(context, std::move(semaphore), proxy, forceFlush);
 }
 
-std::unique_ptr<GrSemaphoreOp> GrSemaphoreOp::MakeWait(sk_sp<GrSemaphore> semaphore,
-                                                       GrRenderTargetProxy* proxy) {
-    return GrWaitSemaphoreOp::Make(std::move(semaphore), proxy);
+std::unique_ptr<GrOp> GrSemaphoreOp::MakeWait(GrContext* context,
+                                              sk_sp<GrSemaphore> semaphore,
+                                              GrRenderTargetProxy* proxy) {
+    return GrWaitSemaphoreOp::Make(context, std::move(semaphore), proxy);
 }
 
 
diff --git a/src/gpu/ops/GrSemaphoreOp.h b/src/gpu/ops/GrSemaphoreOp.h
index 1acc6a7..234c76c 100644
--- a/src/gpu/ops/GrSemaphoreOp.h
+++ b/src/gpu/ops/GrSemaphoreOp.h
@@ -16,12 +16,14 @@
 
 class GrSemaphoreOp : public GrOp {
 public:
-    static std::unique_ptr<GrSemaphoreOp> MakeSignal(sk_sp<GrSemaphore> semaphore,
-                                                     GrRenderTargetProxy* proxy,
-                                                     bool forceFlush);
+    static std::unique_ptr<GrOp> MakeSignal(GrContext*,
+                                            sk_sp<GrSemaphore>,
+                                            GrRenderTargetProxy*,
+                                            bool forceFlush);
 
-    static std::unique_ptr<GrSemaphoreOp> MakeWait(sk_sp<GrSemaphore> semaphore,
-                                                   GrRenderTargetProxy* proxy);
+    static std::unique_ptr<GrOp> MakeWait(GrContext*,
+                                          sk_sp<GrSemaphore>,
+                                          GrRenderTargetProxy*);
 
 protected:
     GrSemaphoreOp(uint32_t classId, sk_sp<GrSemaphore> semaphore, GrRenderTargetProxy* proxy)
diff --git a/src/gpu/ops/GrShadowRRectOp.cpp b/src/gpu/ops/GrShadowRRectOp.cpp
index 8f5e234..a2ec230 100644
--- a/src/gpu/ops/GrShadowRRectOp.cpp
+++ b/src/gpu/ops/GrShadowRRectOp.cpp
@@ -6,7 +6,11 @@
  */
 
 #include "GrShadowRRectOp.h"
+
+#include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrDrawOpTest.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 #include "SkRRectPriv.h"
 #include "effects/GrShadowGeoProc.h"
@@ -653,7 +657,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 namespace GrShadowRRectOp {
-std::unique_ptr<GrDrawOp> Make(GrColor color,
+std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                               GrColor color,
                                const SkMatrix& viewMatrix,
                                const SkRRect& rrect,
                                SkScalar blurWidth,
@@ -708,14 +713,16 @@
     if (isCircle) {
         SkRect circle = GrTest::TestSquare(random);
         SkRRect rrect = SkRRect::MakeOval(circle);
-        return GrShadowRRectOp::Make(color, viewMatrix, rrect, blurWidth, insetWidth, blurClamp);
+        return GrShadowRRectOp::Make(context, color, viewMatrix, rrect, blurWidth,
+                                     insetWidth, blurClamp);
     } else {
         SkRRect rrect;
         do {
             // This may return a rrect with elliptical corners, which we don't support.
             rrect = GrTest::TestRRectSimple(random);
         } while (!SkRRectPriv::IsSimpleCircular(rrect));
-        return GrShadowRRectOp::Make(color, viewMatrix, rrect, blurWidth, insetWidth, blurClamp);
+        return GrShadowRRectOp::Make(context, color, viewMatrix, rrect, blurWidth,
+                                     insetWidth, blurClamp);
     }
 }
 
diff --git a/src/gpu/ops/GrShadowRRectOp.h b/src/gpu/ops/GrShadowRRectOp.h
index 3d8e92a..2001129 100644
--- a/src/gpu/ops/GrShadowRRectOp.h
+++ b/src/gpu/ops/GrShadowRRectOp.h
@@ -11,6 +11,7 @@
 #include <memory>
 #include "GrColor.h"
 
+class GrContext;
 class GrDrawOp;
 class SkMatrix;
 class SkRRect;
@@ -18,8 +19,13 @@
 
 namespace GrShadowRRectOp {
 
-std::unique_ptr<GrDrawOp> Make(GrColor, const SkMatrix& viewMatrix, const SkRRect& rrect,
-                               SkScalar blurWidth, SkScalar insetWidth, SkScalar blurClamp = 1);
+std::unique_ptr<GrDrawOp> Make(GrContext*,
+                               GrColor,
+                               const SkMatrix& viewMatrix,
+                               const SkRRect& rrect,
+                               SkScalar blurWidth,
+                               SkScalar insetWidth,
+                               SkScalar blurClamp = 1);
 }
 
 #endif
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
index 5aaf1fe..b63728f 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
@@ -8,6 +8,9 @@
 #ifndef GrSimpleMeshDrawOpHelper_DEFINED
 #define GrSimpleMeshDrawOpHelper_DEFINED
 
+#include "GrContext.h"
+#include "GrContextPriv.h"
+#include "GrMemoryPool.h" // only here bc of the templated FactoryHelper
 #include "GrMeshDrawOp.h"
 #include "GrOpFlushState.h"
 #include "GrPipeline.h"
@@ -33,7 +36,7 @@
      * which is public or made accessible via 'friend'.
      */
     template <typename Op, typename... OpArgs>
-    static std::unique_ptr<GrDrawOp> FactoryHelper(GrPaint&& paint, OpArgs... opArgs);
+    static std::unique_ptr<GrDrawOp> FactoryHelper(GrContext*, GrPaint&& paint, OpArgs... opArgs);
 
     enum class Flags : uint32_t {
         kNone = 0x0,
@@ -140,9 +143,10 @@
 
     // using declarations can't be templated, so this is a pass through function instead.
     template <typename Op, typename... OpArgs>
-    static std::unique_ptr<GrDrawOp> FactoryHelper(GrPaint&& paint, OpArgs... opArgs) {
+    static std::unique_ptr<GrDrawOp> FactoryHelper(GrContext* context, GrPaint&& paint,
+                                                   OpArgs... opArgs) {
         return GrSimpleMeshDrawOpHelper::FactoryHelper<Op, OpArgs...>(
-                std::move(paint), std::forward<OpArgs>(opArgs)...);
+                context, std::move(paint), std::forward<OpArgs>(opArgs)...);
     }
 
     GrSimpleMeshDrawOpHelperWithStencil(const MakeArgs&, GrAAType, const GrUserStencilSettings*,
@@ -167,11 +171,13 @@
 };
 
 template <typename Op, typename... OpArgs>
-std::unique_ptr<GrDrawOp> GrSimpleMeshDrawOpHelper::FactoryHelper(GrPaint&& paint,
+std::unique_ptr<GrDrawOp> GrSimpleMeshDrawOpHelper::FactoryHelper(GrContext* context,
+                                                                  GrPaint&& paint,
                                                                   OpArgs... opArgs) {
     MakeArgs makeArgs;
     makeArgs.fSRGBFlags = GrPipeline::SRGBFlagsFromPaint(paint);
     GrColor color = paint.getColor();
+
     if (paint.isTrivial()) {
         makeArgs.fProcessorSet = nullptr;
         return std::unique_ptr<GrDrawOp>(new Op(makeArgs, color, std::forward<OpArgs>(opArgs)...));
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 2ad23cb..4ffe478 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -225,13 +225,17 @@
     using ShapeCache = SkTDynamicHash<ShapeData, ShapeDataKey>;
     using ShapeDataList = GrSmallPathRenderer::ShapeDataList;
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const GrShape& shape,
-                                          const SkMatrix& viewMatrix, GrDrawOpAtlas* atlas,
-                                          ShapeCache* shapeCache, ShapeDataList* shapeList,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const GrShape& shape,
+                                          const SkMatrix& viewMatrix,
+                                          GrDrawOpAtlas* atlas,
+                                          ShapeCache* shapeCache,
+                                          ShapeDataList* shapeList,
                                           bool gammaCorrect,
                                           const GrUserStencilSettings* stencilSettings) {
-        return Helper::FactoryHelper<SmallPathOp>(std::move(paint), shape, viewMatrix, atlas,
-                                                  shapeCache, shapeList, gammaCorrect,
+        return Helper::FactoryHelper<SmallPathOp>(context, std::move(paint), shape, viewMatrix,
+                                                  atlas, shapeCache, shapeList, gammaCorrect,
                                                   stencilSettings);
     }
 
@@ -905,8 +909,8 @@
     }
 
     std::unique_ptr<GrDrawOp> op = SmallPathOp::Make(
-            std::move(args.fPaint), *args.fShape, *args.fViewMatrix, fAtlas.get(), &fShapeCache,
-            &fShapeList, args.fGammaCorrect, args.fUserStencilSettings);
+            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));
 
     return true;
@@ -956,6 +960,7 @@
 };
 
 std::unique_ptr<GrDrawOp> GrSmallPathRenderer::createOp_TestingOnly(
+                                                        GrContext* context,
                                                         GrPaint&& paint,
                                                         const GrShape& shape,
                                                         const SkMatrix& viewMatrix,
@@ -965,8 +970,9 @@
                                                         bool gammaCorrect,
                                                         const GrUserStencilSettings* stencil) {
 
-    return GrSmallPathRenderer::SmallPathOp::Make(std::move(paint), shape, viewMatrix, atlas,
-                                                  shapeCache, shapeList, gammaCorrect, stencil);
+    return GrSmallPathRenderer::SmallPathOp::Make(context, std::move(paint), shape, viewMatrix,
+                                                  atlas, shapeCache, shapeList, gammaCorrect,
+                                                  stencil);
 
 }
 
@@ -992,6 +998,7 @@
     // This path renderer only allows fill styles.
     GrShape shape(GrTest::TestPath(random), GrStyle::SimpleFill());
     return GrSmallPathRenderer::createOp_TestingOnly(
+                                         context,
                                          std::move(paint), shape, viewMatrix,
                                          gTestStruct.fAtlas.get(),
                                          &gTestStruct.fShapeCache,
diff --git a/src/gpu/ops/GrSmallPathRenderer.h b/src/gpu/ops/GrSmallPathRenderer.h
index ab58bdf..c5f8eb8 100644
--- a/src/gpu/ops/GrSmallPathRenderer.h
+++ b/src/gpu/ops/GrSmallPathRenderer.h
@@ -50,10 +50,13 @@
     using ShapeCache = SkTDynamicHash<ShapeData, ShapeDataKey>;
     typedef SkTInternalLList<ShapeData> ShapeDataList;
 
-    static std::unique_ptr<GrDrawOp> createOp_TestingOnly(GrPaint&&, const GrShape&,
+    static std::unique_ptr<GrDrawOp> createOp_TestingOnly(GrContext*,
+                                                          GrPaint&&,
+                                                          const GrShape&,
                                                           const SkMatrix& viewMatrix,
                                                           GrDrawOpAtlas* atlas,
-                                                          ShapeCache*, ShapeDataList*,
+                                                          ShapeCache*,
+                                                          ShapeDataList*,
                                                           bool gammaCorrect,
                                                           const GrUserStencilSettings*);
     struct PathTestStruct;
diff --git a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
index 51cf75d..f395927 100644
--- a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
@@ -155,15 +155,17 @@
             if (GrAAType::kMixedSamples == coverAAType) {
                 coverAAType = GrAAType::kNone;
             }
-            args.fRenderTargetContext->addDrawOp(*args.fClip,
-                                                 GrRectOpFactory::MakeNonAAFillWithLocalMatrix(
-                                                         std::move(args.fPaint), coverMatrix,
-                                                         localMatrix, coverBounds, coverAAType,
-                                                         &kInvertedCoverPass));
+            std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFillWithLocalMatrix(
+                                                         args.fContext, std::move(args.fPaint),
+                                                         coverMatrix, localMatrix, coverBounds,
+                                                         coverAAType, &kInvertedCoverPass);
+
+            args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
         }
     } else {
         std::unique_ptr<GrDrawOp> op =
-                GrDrawPathOp::Make(viewMatrix, std::move(args.fPaint), args.fAAType, path.get());
+                GrDrawPathOp::Make(args.fContext, viewMatrix, std::move(args.fPaint),
+                                   args.fAAType, path.get());
         args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
     }
 
diff --git a/src/gpu/ops/GrStencilPathOp.cpp b/src/gpu/ops/GrStencilPathOp.cpp
index 4c89ec0..5b712cf 100644
--- a/src/gpu/ops/GrStencilPathOp.cpp
+++ b/src/gpu/ops/GrStencilPathOp.cpp
@@ -7,10 +7,24 @@
 
 #include "GrStencilPathOp.h"
 
+#include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrGpu.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 #include "GrRenderTargetPriv.h"
 
+std::unique_ptr<GrOp> GrStencilPathOp::Make(GrContext* context,
+                                            const SkMatrix& viewMatrix,
+                                            bool useHWAA,
+                                            GrPathRendering::FillType fillType,
+                                            bool hasStencilClip,
+                                            const GrScissorState& scissor,
+                                            const GrPath* path) {
+    return std::unique_ptr<GrOp>(new GrStencilPathOp(viewMatrix, useHWAA, fillType,
+                                                     hasStencilClip, scissor, path));
+}
+
 void GrStencilPathOp::onExecute(GrOpFlushState* state) {
     GrRenderTarget* rt = state->drawOpArgs().renderTarget();
     SkASSERT(rt);
diff --git a/src/gpu/ops/GrStencilPathOp.h b/src/gpu/ops/GrStencilPathOp.h
index 64df726..563bdc3 100644
--- a/src/gpu/ops/GrStencilPathOp.h
+++ b/src/gpu/ops/GrStencilPathOp.h
@@ -13,22 +13,20 @@
 #include "GrPathRendering.h"
 #include "GrStencilSettings.h"
 
+class GrContext;
 class GrOpFlushState;
 
 class GrStencilPathOp final : public GrOp {
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrOp> Make(const SkMatrix& viewMatrix,
+    static std::unique_ptr<GrOp> Make(GrContext* context,
+                                      const SkMatrix& viewMatrix,
                                       bool useHWAA,
                                       GrPathRendering::FillType fillType,
                                       bool hasStencilClip,
                                       const GrScissorState& scissor,
-                                      const GrPath* path) {
-
-        return std::unique_ptr<GrOp>(new GrStencilPathOp(viewMatrix, useHWAA, fillType,
-                                                         hasStencilClip, scissor, path));
-    }
+                                      const GrPath* path);
 
     const char* name() const override { return "StencilPathOp"; }
 
@@ -40,6 +38,8 @@
     }
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     GrStencilPathOp(const SkMatrix& viewMatrix,
                     bool useHWAA,
                     GrPathRendering::FillType fillType,
diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp
index 1918f66..51dac5a 100644
--- a/src/gpu/ops/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp
@@ -169,14 +169,16 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
                                           const GrShape& shape,
                                           const SkMatrix& viewMatrix,
                                           SkIRect devClipBounds,
                                           GrAAType aaType,
                                           const GrUserStencilSettings* stencilSettings) {
-        return Helper::FactoryHelper<TessellatingPathOp>(std::move(paint), shape, viewMatrix,
-                                                         devClipBounds, aaType, stencilSettings);
+        return Helper::FactoryHelper<TessellatingPathOp>(context, std::move(paint), shape,
+                                                         viewMatrix, devClipBounds,
+                                                         aaType, stencilSettings);
     }
 
     const char* name() const override { return "TessellatingPathOp"; }
@@ -374,7 +376,8 @@
     args.fClip->getConservativeBounds(args.fRenderTargetContext->width(),
                                       args.fRenderTargetContext->height(),
                                       &clipBoundsI);
-    std::unique_ptr<GrDrawOp> op = TessellatingPathOp::Make(std::move(args.fPaint),
+    std::unique_ptr<GrDrawOp> op = TessellatingPathOp::Make(args.fContext,
+                                                            std::move(args.fPaint),
                                                             *args.fShape,
                                                             *args.fViewMatrix,
                                                             clipBoundsI,
@@ -404,8 +407,8 @@
         GrTest::TestStyle(random, &style);
     } while (!style.isSimpleFill());
     GrShape shape(path, style);
-    return TessellatingPathOp::Make(std::move(paint), shape, viewMatrix, devClipBounds, aaType,
-                                    GrGetRandomStencil(random, context));
+    return TessellatingPathOp::Make(context, std::move(paint), shape, viewMatrix, devClipBounds,
+                                    aaType, GrGetRandomStencil(random, context));
 }
 
 #endif
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 68a5851..2301930 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -8,8 +8,11 @@
 #include "GrTextureOp.h"
 #include "GrAppliedClip.h"
 #include "GrCaps.h"
+#include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrDrawOpTest.h"
 #include "GrGeometryProcessor.h"
+#include "GrMemoryPool.h"
 #include "GrMeshDrawOp.h"
 #include "GrOpFlushState.h"
 #include "GrQuad.h"
@@ -608,10 +611,14 @@
  */
 class TextureOp final : public GrMeshDrawOp {
 public:
-    static std::unique_ptr<GrDrawOp> Make(sk_sp<GrTextureProxy> proxy,
-                                          GrSamplerState::Filter filter, GrColor color,
-                                          const SkRect& srcRect, const SkRect& dstRect,
-                                          GrAAType aaType, SkCanvas::SrcRectConstraint constraint,
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          sk_sp<GrTextureProxy> proxy,
+                                          GrSamplerState::Filter filter,
+                                          GrColor color,
+                                          const SkRect& srcRect,
+                                          const SkRect& dstRect,
+                                          GrAAType aaType,
+                                          SkCanvas::SrcRectConstraint constraint,
                                           const SkMatrix& viewMatrix,
                                           sk_sp<GrColorSpaceXform> csxf) {
         return std::unique_ptr<GrDrawOp>(new TextureOp(std::move(proxy), filter, color, srcRect,
@@ -684,6 +691,7 @@
     DEFINE_OP_CLASS_ID
 
 private:
+    friend class ::GrOpMemoryPool;
 
     // This is used in a heursitic for choosing a code path. We don't care what happens with
     // really large rects, infs, nans, etc.
@@ -1026,12 +1034,18 @@
 
 namespace GrTextureOp {
 
-std::unique_ptr<GrDrawOp> Make(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter,
-                               GrColor color, const SkRect& srcRect, const SkRect& dstRect,
-                               GrAAType aaType, SkCanvas::SrcRectConstraint constraint,
-                               const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform> csxf) {
-    return TextureOp::Make(std::move(proxy), filter, color, srcRect, dstRect, aaType, constraint,
-                           viewMatrix, std::move(csxf));
+std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                               sk_sp<GrTextureProxy> proxy,
+                               GrSamplerState::Filter filter,
+                               GrColor color,
+                               const SkRect& srcRect,
+                               const SkRect& dstRect,
+                               GrAAType aaType,
+                               SkCanvas::SrcRectConstraint constraint,
+                               const SkMatrix& viewMatrix,
+                               sk_sp<GrColorSpaceXform> csxf) {
+    return TextureOp::Make(context, std::move(proxy), filter, color, srcRect, dstRect, aaType,
+                           constraint, viewMatrix, std::move(csxf));
 }
 
 }  // namespace GrTextureOp
@@ -1079,8 +1093,8 @@
     }
     auto constraint = random->nextBool() ? SkCanvas::kStrict_SrcRectConstraint
                                          : SkCanvas::kFast_SrcRectConstraint;
-    return GrTextureOp::Make(std::move(proxy), filter, color, srcRect, rect, aaType, constraint,
-                             viewMatrix, std::move(csxf));
+    return GrTextureOp::Make(context, std::move(proxy), filter, color, srcRect, rect, aaType,
+                             constraint, viewMatrix, std::move(csxf));
 }
 
 #endif
diff --git a/src/gpu/ops/GrTextureOp.h b/src/gpu/ops/GrTextureOp.h
index e99bd0a..7211b5e 100644
--- a/src/gpu/ops/GrTextureOp.h
+++ b/src/gpu/ops/GrTextureOp.h
@@ -25,8 +25,14 @@
  * the rectangle to draw in local coords which will be transformed by 'viewMatrix' to be in device
  * space. 'viewMatrix' must be affine.
  */
-std::unique_ptr<GrDrawOp> Make(sk_sp<GrTextureProxy>, GrSamplerState::Filter, GrColor,
-                               const SkRect& srcRect, const SkRect& dstRect, GrAAType,
-                               SkCanvas::SrcRectConstraint, const SkMatrix& viewMatrix,
+std::unique_ptr<GrDrawOp> Make(GrContext*,
+                               sk_sp<GrTextureProxy>,
+                               GrSamplerState::Filter,
+                               GrColor,
+                               const SkRect& srcRect,
+                               const SkRect& dstRect,
+                               GrAAType,
+                               SkCanvas::SrcRectConstraint,
+                               const SkMatrix& viewMatrix,
                                sk_sp<GrColorSpaceXform>);
 }
diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp
index 00995d0..08491f5 100644
--- a/src/gpu/text/GrTextBlob.cpp
+++ b/src/gpu/text/GrTextBlob.cpp
@@ -252,11 +252,11 @@
     std::unique_ptr<GrAtlasTextOp> op;
     if (info.drawAsDistanceFields()) {
         op = GrAtlasTextOp::MakeDistanceField(
-                std::move(grPaint), glyphCount, distanceAdjustTable,
+                target->getContext(), std::move(grPaint), glyphCount, distanceAdjustTable,
                 target->colorSpaceInfo().isGammaCorrect(), paint.luminanceColor(),
                 props, info.isAntiAliased(), info.hasUseLCDText());
     } else {
-        op = GrAtlasTextOp::MakeBitmap(std::move(grPaint), format, glyphCount,
+        op = GrAtlasTextOp::MakeBitmap(target->getContext(), std::move(grPaint), format, glyphCount,
                                        info.needsTransform());
     }
     GrAtlasTextOp::Geometry& geometry = op->geometry();
diff --git a/src/gpu/text/GrTextBlob.h b/src/gpu/text/GrTextBlob.h
index e34ab88..19128ab 100644
--- a/src/gpu/text/GrTextBlob.h
+++ b/src/gpu/text/GrTextBlob.h
@@ -11,7 +11,6 @@
 #include "GrColor.h"
 #include "GrDrawOpAtlas.h"
 #include "GrGlyphCache.h"
-#include "GrMemoryPool.h"
 #include "GrTextUtils.h"
 #include "SkDescriptor.h"
 #include "SkMaskFilterBase.h"
@@ -25,7 +24,6 @@
 class GrAtlasManager;
 struct GrDistanceFieldAdjustTable;
 struct GrGlyph;
-class GrMemoryPool;
 
 class SkDrawFilter;
 class SkTextBlob;
diff --git a/src/gpu/text/GrTextContext.cpp b/src/gpu/text/GrTextContext.cpp
index b8fe456..2fc1f5b 100644
--- a/src/gpu/text/GrTextContext.cpp
+++ b/src/gpu/text/GrTextContext.cpp
@@ -761,7 +761,9 @@
                                                               GrRenderTargetContext* rtc,
                                                               const SkPaint& skPaint,
                                                               const SkMatrix& viewMatrix,
-                                                              const char* text, int x, int y) {
+                                                              const char* text,
+                                                              int x,
+                                                              int y) {
     auto glyphCache = context->contextPriv().getGlyphCache();
 
     static SkSurfaceProps surfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
diff --git a/src/gpu/text/GrTextContext.h b/src/gpu/text/GrTextContext.h
index 478d4c4..dd82b3c 100644
--- a/src/gpu/text/GrTextContext.h
+++ b/src/gpu/text/GrTextContext.h
@@ -52,10 +52,14 @@
                       const SkMatrix& viewMatrix, const SkSurfaceProps&, const SkTextBlob*,
                       SkScalar x, SkScalar y, SkDrawFilter*, const SkIRect& clipBounds);
 
-    std::unique_ptr<GrDrawOp> createOp_TestingOnly(GrContext*, GrTextContext*,
-                                                   GrRenderTargetContext*, const SkPaint&,
-                                                   const SkMatrix& viewMatrix, const char* text,
-                                                   int x, int y);
+    std::unique_ptr<GrDrawOp> createOp_TestingOnly(GrContext*,
+                                                   GrTextContext*,
+                                                   GrRenderTargetContext*,
+                                                   const SkPaint&,
+                                                   const SkMatrix& viewMatrix,
+                                                   const char* text,
+                                                   int x,
+                                                   int y);
 
     static void SanitizeOptions(Options* options);
     static bool CanDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix,
diff --git a/src/gpu/text/GrTextUtils.h b/src/gpu/text/GrTextUtils.h
index 3a0ad0a..363a91e 100644
--- a/src/gpu/text/GrTextUtils.h
+++ b/src/gpu/text/GrTextUtils.h
@@ -57,6 +57,8 @@
         virtual void makeGrPaint(GrMaskFormat, const SkPaint&, const SkMatrix& viewMatrix,
                                  GrPaint*) = 0;
 
+        virtual GrContext* getContext() = 0;
+
     protected:
         Target(int width, int height, const GrColorSpaceInfo& colorSpaceInfo)
                 : fWidth(width), fHeight(height), fColorSpaceInfo(colorSpaceInfo) {}
diff --git a/tests/GrMeshTest.cpp b/tests/GrMeshTest.cpp
index e612fb4..4535f13 100644
--- a/tests/GrMeshTest.cpp
+++ b/tests/GrMeshTest.cpp
@@ -15,6 +15,7 @@
 #include "GrContextPriv.h"
 #include "GrGeometryProcessor.h"
 #include "GrGpuCommandBuffer.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 #include "GrRenderTargetContext.h"
 #include "GrRenderTargetContextPriv.h"
@@ -261,6 +262,8 @@
     }
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     GrMeshTestOp(std::function<void(DrawMeshHelper*)> testFn)
         : INHERITED(ClassID())
         , fTestFn(testFn) {
diff --git a/tests/GrPipelineDynamicStateTest.cpp b/tests/GrPipelineDynamicStateTest.cpp
index 227fd7c..0f786e7 100644
--- a/tests/GrPipelineDynamicStateTest.cpp
+++ b/tests/GrPipelineDynamicStateTest.cpp
@@ -12,6 +12,7 @@
 #include "GrColor.h"
 #include "GrGeometryProcessor.h"
 #include "GrGpuCommandBuffer.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 #include "GrRenderTargetContext.h"
 #include "GrRenderTargetContextPriv.h"
@@ -113,6 +114,8 @@
     }
 
 private:
+    friend class GrOpMemoryPool;
+
     GrPipelineDynamicStateTestOp(ScissorState scissorState, sk_sp<const GrBuffer> vbuff)
         : INHERITED(ClassID())
         , fScissorState(scissorState)
diff --git a/tests/LazyProxyTest.cpp b/tests/LazyProxyTest.cpp
index 536ef36..c0dcbf9 100644
--- a/tests/LazyProxyTest.cpp
+++ b/tests/LazyProxyTest.cpp
@@ -9,8 +9,9 @@
 
 #include "GrClip.h"
 #include "GrContextPriv.h"
-#include "GrProxyProvider.h"
+#include "GrMemoryPool.h"
 #include "GrOnFlushResourceProvider.h"
+#include "GrProxyProvider.h"
 #include "GrRenderTargetContext.h"
 #include "GrRenderTargetContextPriv.h"
 #include "GrSurfaceProxy.h"
@@ -71,6 +72,8 @@
         }
 
     private:
+        friend class GrOpMemoryPool; // for ctor
+
         Op(GrProxyProvider* proxyProvider, LazyProxyTest* test, bool nullTexture)
                     : GrDrawOp(ClassID()), fTest(test) {
             fProxy = proxyProvider->createFullyLazyProxy([this, nullTexture](
@@ -276,6 +279,8 @@
     }
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     LazyFailedInstantiationTestOp(GrProxyProvider* proxyProvider, int* testExecuteValue,
                                   bool shouldFailInstantiation)
             : INHERITED(ClassID())
@@ -370,6 +375,8 @@
     }
 
 private:
+    friend class GrOpMemoryPool; // for ctor
+
     LazyUninstantiateTestOp(sk_sp<GrTextureProxy> proxy)
             : INHERITED(ClassID())
             , fLazyProxy(std::move(proxy)) {
diff --git a/tests/OnFlushCallbackTest.cpp b/tests/OnFlushCallbackTest.cpp
index e9e4dd0..7932fdc 100644
--- a/tests/OnFlushCallbackTest.cpp
+++ b/tests/OnFlushCallbackTest.cpp
@@ -34,13 +34,18 @@
     DEFINE_OP_CLASS_ID
 
     // This creates an instance of a simple non-AA solid color rect-drawing Op
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkRect& r) {
-        return Helper::FactoryHelper<NonAARectOp>(std::move(paint), r, nullptr, ClassID());
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkRect& r) {
+        return Helper::FactoryHelper<NonAARectOp>(context, std::move(paint), r, nullptr, ClassID());
     }
 
     // This creates an instance of a simple non-AA textured rect-drawing Op
-    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkRect& r, const SkRect& local) {
-        return Helper::FactoryHelper<NonAARectOp>(std::move(paint), r, &local, ClassID());
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrPaint&& paint,
+                                          const SkRect& r,
+                                          const SkRect& local) {
+        return Helper::FactoryHelper<NonAARectOp>(context, std::move(paint), r, &local, ClassID());
     }
 
     GrColor color() const { return fColor; }
@@ -189,8 +194,12 @@
 
     int id() const { return fID; }
 
-    static std::unique_ptr<AtlasedRectOp> Make(GrPaint&& paint, const SkRect& r, int id) {
-        GrDrawOp* op = Helper::FactoryHelper<AtlasedRectOp>(std::move(paint), r, id).release();
+    static std::unique_ptr<AtlasedRectOp> Make(GrContext* context,
+                                               GrPaint&& paint,
+                                               const SkRect& r,
+                                               int id) {
+        GrDrawOp* op = Helper::FactoryHelper<AtlasedRectOp>(context, std::move(paint),
+                                                            r, id).release();
         return std::unique_ptr<AtlasedRectOp>(static_cast<AtlasedRectOp*>(op));
     }
 
@@ -435,7 +444,8 @@
         GrPaint paint;
         paint.addColorFragmentProcessor(std::move(fp));
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-        std::unique_ptr<AtlasedRectOp> op(AtlasedRectOp::Make(std::move(paint), r, start + i));
+        std::unique_ptr<AtlasedRectOp> op(AtlasedRectOp::Make(context,
+                                                              std::move(paint), r, start + i));
 
         AtlasedRectOp* sparePtr = op.get();
 
diff --git a/tests/PrimitiveProcessorTest.cpp b/tests/PrimitiveProcessorTest.cpp
index 36709f8..3a76e6c 100644
--- a/tests/PrimitiveProcessorTest.cpp
+++ b/tests/PrimitiveProcessorTest.cpp
@@ -14,6 +14,7 @@
 #include "GrContextPriv.h"
 #include "GrGeometryProcessor.h"
 #include "GrGpu.h"
+#include "GrMemoryPool.h"
 #include "GrOpFlushState.h"
 #include "GrRenderTargetContext.h"
 #include "GrRenderTargetContextPriv.h"
@@ -31,7 +32,7 @@
 
     const char* name() const override { return "Dummy Op"; }
 
-    static std::unique_ptr<GrDrawOp> Make(int numAttribs) {
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context, int numAttribs) {
         return std::unique_ptr<GrDrawOp>(new Op(numAttribs));
     }
 
@@ -45,6 +46,8 @@
     }
 
 private:
+    friend class ::GrOpMemoryPool;
+
     Op(int numAttribs) : INHERITED(ClassID()), fNumAttribs(numAttribs) {
         this->setBounds(SkRect::MakeWH(1.f, 1.f), HasAABloat::kNo, IsZeroArea::kNo);
     }
@@ -140,14 +143,14 @@
 
     GrPaint grPaint;
     // This one should succeed.
-    renderTargetContext->priv().testingOnly_addDrawOp(Op::Make(attribCnt));
+    renderTargetContext->priv().testingOnly_addDrawOp(Op::Make(context, attribCnt));
     context->flush();
 #if GR_GPU_STATS
     REPORTER_ASSERT(reporter, gpu->stats()->numDraws() == 1);
     REPORTER_ASSERT(reporter, gpu->stats()->numFailedDraws() == 0);
 #endif
     context->contextPriv().resetGpuStats();
-    renderTargetContext->priv().testingOnly_addDrawOp(Op::Make(attribCnt + 1));
+    renderTargetContext->priv().testingOnly_addDrawOp(Op::Make(context, attribCnt + 1));
     context->flush();
 #if GR_GPU_STATS
     REPORTER_ASSERT(reporter, gpu->stats()->numDraws() == 0);
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index b1da1b5..3916436 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -13,6 +13,7 @@
 #include "GrContext.h"
 #include "GrContextPriv.h"
 #include "GrGpuResource.h"
+#include "GrMemoryPool.h"
 #include "GrProxyProvider.h"
 #include "GrRenderTargetContext.h"
 #include "GrRenderTargetContextPriv.h"
@@ -26,7 +27,8 @@
 class TestOp : public GrMeshDrawOp {
 public:
     DEFINE_OP_CLASS_ID
-    static std::unique_ptr<GrDrawOp> Make(std::unique_ptr<GrFragmentProcessor> fp) {
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          std::unique_ptr<GrFragmentProcessor> fp) {
         return std::unique_ptr<GrDrawOp>(new TestOp(std::move(fp)));
     }
 
@@ -48,6 +50,8 @@
     }
 
 private:
+    friend class ::GrOpMemoryPool; // for ctor
+
     TestOp(std::unique_ptr<GrFragmentProcessor> fp)
             : INHERITED(ClassID()), fProcessors(std::move(fp)) {
         this->setBounds(SkRect::MakeWH(100, 100), HasAABloat::kNo, IsZeroArea::kNo);
@@ -201,10 +205,10 @@
                     if (makeClone) {
                         clone = fp->clone();
                     }
-                    std::unique_ptr<GrDrawOp> op(TestOp::Make(std::move(fp)));
+                    std::unique_ptr<GrDrawOp> op(TestOp::Make(context, std::move(fp)));
                     renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
                     if (clone) {
-                        op = TestOp::Make(std::move(clone));
+                        op = TestOp::Make(context, std::move(clone));
                         renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
                     }
                 }
@@ -276,14 +280,16 @@
     return GrColor4f::FromGrColor(input_texel_color(i, j));
 }
 
-void test_draw_op(GrRenderTargetContext* rtc, std::unique_ptr<GrFragmentProcessor> fp,
+void test_draw_op(GrContext* context,
+                  GrRenderTargetContext* rtc,
+                  std::unique_ptr<GrFragmentProcessor> fp,
                   sk_sp<GrTextureProxy> inputDataProxy) {
     GrPaint paint;
     paint.addColorTextureProcessor(std::move(inputDataProxy), SkMatrix::I());
     paint.addColorFragmentProcessor(std::move(fp));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
-    auto op = GrRectOpFactory::MakeNonAAFill(std::move(paint), SkMatrix::I(),
+    auto op = GrRectOpFactory::MakeNonAAFill(context, std::move(paint), SkMatrix::I(),
                                              SkRect::MakeWH(rtc->width(), rtc->height()),
                                              GrAAType::kNone);
     rtc->addDrawOp(GrNoClip(), std::move(op));
@@ -402,7 +408,7 @@
             // Since we transfer away ownership of the original FP, we make a clone.
             auto clone = fp->clone();
 
-            test_draw_op(rtc.get(), std::move(fp), inputTexture);
+            test_draw_op(context, rtc.get(), std::move(fp), inputTexture);
             memset(readData.get(), 0x0, sizeof(GrColor) * kRenderSize * kRenderSize);
             rtc->readPixels(SkImageInfo::Make(kRenderSize, kRenderSize, kRGBA_8888_SkColorType,
                                               kPremul_SkAlphaType),
@@ -536,12 +542,12 @@
             REPORTER_ASSERT(reporter, fp->numChildProcessors() == clone->numChildProcessors());
             REPORTER_ASSERT(reporter, fp->usesLocalCoords() == clone->usesLocalCoords());
             // Draw with original and read back the results.
-            test_draw_op(rtc.get(), std::move(fp), inputTexture);
+            test_draw_op(context, rtc.get(), std::move(fp), inputTexture);
             memset(readData1.get(), 0x0, sizeof(GrColor) * kRenderSize * kRenderSize);
             rtc->readPixels(readInfo, readData1.get(), 0, 0, 0);
 
             // Draw with clone and read back the results.
-            test_draw_op(rtc.get(), std::move(clone), inputTexture);
+            test_draw_op(context, rtc.get(), std::move(clone), inputTexture);
             memset(readData2.get(), 0x0, sizeof(GrColor) * kRenderSize * kRenderSize);
             rtc->readPixels(readInfo, readData2.get(), 0, 0, 0);