add API for Op creation

Introduce three calls on GrOp: Make, MakeWithExtraMemory,
and MakeWithProcessorSet. Instead of returning
unique_ptr<GrOp>, they return a type of GrOp::OpOwner.
GrOp::OpOwner safely deletes the op when it goes out
of scope for either new/delete or GrOpMemoryPool
allocations.

In order to make the code easier to refactor, I
eliminated MakeArg from the helpers.

Change-Id: Icfd697906f3147a8734575d08bd7195e7517383a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/323778
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/gpu/GrDrawOpTest.h b/src/gpu/GrDrawOpTest.h
index fe8047c..39040e9 100644
--- a/src/gpu/GrDrawOpTest.h
+++ b/src/gpu/GrDrawOpTest.h
@@ -26,11 +26,11 @@
 
 /** GrDrawOp subclasses should define test factory functions using this macro. */
 #define GR_DRAW_OP_TEST_DEFINE(Op)                                                              \
-    std::unique_ptr<GrDrawOp> Op##__Test(GrPaint&& paint, SkRandom* random,                     \
-                                         GrRecordingContext* context, int numSamples)
+    GrOp::Owner Op##__Test(GrPaint&& paint, SkRandom* random,                                 \
+                             GrRecordingContext* context, int numSamples)
 #define GR_DRAW_OP_TEST_FRIEND(Op)                                                              \
-    friend std::unique_ptr<GrDrawOp> Op##__Test(GrPaint&& paint, SkRandom* random,              \
-                                                GrRecordingContext* context, int numSamples)
+    friend GrOp::OpOwner Op##__Test(GrPaint&& paint, SkRandom* random,                          \
+                                    GrRecordingContext* context, int numSamples)
 
 /** Helper for op test factories to pick a random stencil state. */
 const GrUserStencilSettings* GrGetRandomStencil(SkRandom* random, GrContext_Base*);
diff --git a/src/gpu/GrMemoryPool.cpp b/src/gpu/GrMemoryPool.cpp
index d1d2c82..02daf3f 100644
--- a/src/gpu/GrMemoryPool.cpp
+++ b/src/gpu/GrMemoryPool.cpp
@@ -133,11 +133,6 @@
     return std::unique_ptr<GrOpMemoryPool>(new (mem) GrOpMemoryPool(preallocSize, minAllocSize));
 }
 
-#if !defined(GR_OP_ALLOCATE_USE_NEW)
-    void GrOpMemoryPool::release(std::unique_ptr<GrOp> op) {
-        GrOp* tmp = op.release();
-        SkASSERT(tmp);
-        tmp->~GrOp();
-        fPool.release(tmp);
-    }
-#endif
+void GrOpMemoryPool::release(void* bytes) {
+    fPool.release(bytes);
+}
diff --git a/src/gpu/GrMemoryPool.h b/src/gpu/GrMemoryPool.h
index 2543fe5..5af02a0 100644
--- a/src/gpu/GrMemoryPool.h
+++ b/src/gpu/GrMemoryPool.h
@@ -119,23 +119,8 @@
     static std::unique_ptr<GrOpMemoryPool> Make(size_t preallocSize, size_t minAllocSize);
     void operator delete(void* p) { ::operator delete(p); }
 
-    template <typename Op, typename... OpArgs>
-    std::unique_ptr<Op> allocate(OpArgs&&... opArgs) {
-        #if defined(GR_OP_ALLOCATE_USE_NEW)
-            void* m = ::operator new(sizeof(Op));
-            Op* op =  new (m) Op(std::forward<OpArgs>(opArgs)...);
-            return std::unique_ptr<Op>(op);
-        #else
-            auto mem = this->allocate(sizeof(Op));
-            return std::unique_ptr<Op>(new (mem) Op(std::forward<OpArgs>(opArgs)...));
-        #endif
-    }
-
     void* allocate(size_t size) { return fPool.allocate(size); }
-
-    #if !defined(GR_OP_ALLOCATE_USE_NEW)
-        void release(std::unique_ptr<GrOp> op);
-    #endif
+    void release(void *);
     bool isEmpty() const { return fPool.isEmpty(); }
 
 private:
diff --git a/src/gpu/GrOnFlushResourceProvider.cpp b/src/gpu/GrOnFlushResourceProvider.cpp
index cca7a5e..4ac8538 100644
--- a/src/gpu/GrOnFlushResourceProvider.cpp
+++ b/src/gpu/GrOnFlushResourceProvider.cpp
@@ -139,8 +139,8 @@
     return fDrawingMgr->getContext()->priv().caps();
 }
 
-GrOpMemoryPool* GrOnFlushResourceProvider::opMemoryPool() const {
-    return fDrawingMgr->getContext()->priv().opMemoryPool();
+GrRecordingContext* GrOnFlushResourceProvider::recordingContext() const {
+    return fDrawingMgr->getContext();
 }
 
 void GrOnFlushResourceProvider::printWarningMessage(const char* msg) const {
diff --git a/src/gpu/GrOnFlushResourceProvider.h b/src/gpu/GrOnFlushResourceProvider.h
index 828b7ce..3a6df37 100644
--- a/src/gpu/GrOnFlushResourceProvider.h
+++ b/src/gpu/GrOnFlushResourceProvider.h
@@ -86,7 +86,7 @@
 
     uint32_t contextID() const;
     const GrCaps* caps() const;
-    GrOpMemoryPool* opMemoryPool() const;
+    GrRecordingContext* recordingContext() const;
 
     void printWarningMessage(const char* msg) const;
 
diff --git a/src/gpu/GrOpsTask.cpp b/src/gpu/GrOpsTask.cpp
index 5c1f946..35850a4 100644
--- a/src/gpu/GrOpsTask.cpp
+++ b/src/gpu/GrOpsTask.cpp
@@ -46,7 +46,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-inline GrOpsTask::OpChain::List::List(std::unique_ptr<GrOp> op)
+inline GrOpsTask::OpChain::List::List(GrOp::Owner op)
         : fHead(std::move(op)), fTail(fHead.get()) {
     this->validate();
 }
@@ -61,7 +61,7 @@
     return *this;
 }
 
-inline std::unique_ptr<GrOp> GrOpsTask::OpChain::List::popHead() {
+inline GrOp::Owner GrOpsTask::OpChain::List::popHead() {
     SkASSERT(fHead);
     auto temp = fHead->cutChain();
     std::swap(temp, fHead);
@@ -72,7 +72,7 @@
     return temp;
 }
 
-inline std::unique_ptr<GrOp> GrOpsTask::OpChain::List::removeOp(GrOp* op) {
+inline GrOp::Owner GrOpsTask::OpChain::List::removeOp(GrOp* op) {
 #ifdef SK_DEBUG
     auto head = op;
     while (head->prevInChain()) { head = head->prevInChain(); }
@@ -94,7 +94,7 @@
     return temp;
 }
 
-inline void GrOpsTask::OpChain::List::pushHead(std::unique_ptr<GrOp> op) {
+inline void GrOpsTask::OpChain::List::pushHead(GrOp::Owner op) {
     SkASSERT(op);
     SkASSERT(op->isChainHead());
     SkASSERT(op->isChainTail());
@@ -107,7 +107,7 @@
     }
 }
 
-inline void GrOpsTask::OpChain::List::pushTail(std::unique_ptr<GrOp> op) {
+inline void GrOpsTask::OpChain::List::pushTail(GrOp::Owner op) {
     SkASSERT(op->isChainTail());
     fTail->chainConcat(std::move(op));
     fTail = fTail->nextInChain();
@@ -124,7 +124,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-GrOpsTask::OpChain::OpChain(std::unique_ptr<GrOp> op,
+GrOpsTask::OpChain::OpChain(GrOp::Owner op,
                             GrProcessorSet::Analysis processorAnalysis,
                             GrAppliedClip* appliedClip, const DstProxyView* dstProxyView)
         : fList{std::move(op)}
@@ -154,12 +154,8 @@
 
 void GrOpsTask::OpChain::deleteOps(GrOpMemoryPool* pool) {
     while (!fList.empty()) {
-        #if defined(GR_OP_ALLOCATE_USE_NEW)
-            // Since the value goes out of scope immediately, the unique_ptr deletes the op.
-            fList.popHead();
-        #else
-            pool->release(fList.popHead());
-        #endif
+        // Since the value goes out of scope immediately, the GrOp::Owner deletes the op.
+        fList.popHead();
     }
 }
 
@@ -202,12 +198,8 @@
             if (merged) {
                 GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(auditTrail, a, chainB.head());
                 if (canBackwardMerge) {
-                    #if defined(GR_OP_ALLOCATE_USE_NEW)
-                        // The unique_ptr releases the op.
-                        chainB.popHead();
-                    #else
-                        arenas->opMemoryPool()->release(chainB.popHead());
-                    #endif
+                    // The GrOp::Owner releases the op.
+                    chainB.popHead();
                 } else {
                     // We merged the contents of b's head into a. We will replace b's head with a in
                     // chain b.
@@ -215,13 +207,9 @@
                     if (a == origATail) {
                         origATail = a->prevInChain();
                     }
-                    std::unique_ptr<GrOp> detachedA = chainA.removeOp(a);
-                    #if defined(GR_OP_ALLOCATE_USE_NEW)
-                        // The unique_ptr releases the op.
-                        chainB.popHead();
-                    #else
-                        arenas->opMemoryPool()->release(chainB.popHead());
-                    #endif
+                    GrOp::Owner detachedA = chainA.removeOp(a);
+                    // The GrOp::Owner releases the op.
+                    chainB.popHead();
                     chainB.pushHead(std::move(detachedA));
                     if (chainA.empty()) {
                         // We merged all the nodes in chain a to chain b.
@@ -297,12 +285,8 @@
                           list->tail()->name(), list->tail()->uniqueID(), list->head()->name(),
                           list->head()->uniqueID());
                 GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(auditTrail, fList.tail(), list->head());
-                #if defined(GR_OP_ALLOCATE_USE_NEW)
-                    // The unique_ptr releases the op.
-                    list->popHead();
-                #else
-                    arenas->opMemoryPool()->release(list->popHead());
-                #endif
+                // The GrOp::Owner releases the op.
+                list->popHead();
                 break;
             }
         }
@@ -338,8 +322,8 @@
     return true;
 }
 
-std::unique_ptr<GrOp> GrOpsTask::OpChain::appendOp(
-        std::unique_ptr<GrOp> op, GrProcessorSet::Analysis processorAnalysis,
+GrOp::Owner GrOpsTask::OpChain::appendOp(
+        GrOp::Owner op, GrProcessorSet::Analysis processorAnalysis,
         const DstProxyView* dstProxyView, const GrAppliedClip* appliedClip, const GrCaps& caps,
         GrRecordingContext::Arenas* arenas, GrAuditTrail* auditTrail) {
     const GrXferProcessor::DstProxyView noDstProxyView;
@@ -811,7 +795,7 @@
 }
 
 void GrOpsTask::recordOp(
-        std::unique_ptr<GrOp> op, GrProcessorSet::Analysis processorAnalysis, GrAppliedClip* clip,
+        GrOp::Owner op, GrProcessorSet::Analysis processorAnalysis, GrAppliedClip* clip,
         const DstProxyView* dstProxyView, const GrCaps& caps) {
     SkDEBUGCODE(op->validate();)
     SkASSERT(processorAnalysis.requiresDstTexture() == (dstProxyView && dstProxyView->proxy()));
@@ -821,9 +805,6 @@
     // A closed GrOpsTask should never receive new/more ops
     SkASSERT(!this->isClosed());
     if (!op->bounds().isFinite()) {
-        #if !defined(GR_OP_ALLOCATE_USE_NEW)
-            fArenas.opMemoryPool()->release(std::move(op));
-        #endif
         return;
     }
 
diff --git a/src/gpu/GrOpsTask.h b/src/gpu/GrOpsTask.h
index f01236c..0db507a 100644
--- a/src/gpu/GrOpsTask.h
+++ b/src/gpu/GrOpsTask.h
@@ -88,7 +88,7 @@
         fSampledProxies.push_back(proxy);
     }
 
-    void addOp(GrDrawingManager* drawingMgr, std::unique_ptr<GrOp> op,
+    void addOp(GrDrawingManager* drawingMgr, GrOp::Owner op,
                GrTextureResolveManager textureResolveManager, const GrCaps& caps) {
         auto addDependency = [ drawingMgr, textureResolveManager, &caps, this ] (
                 GrSurfaceProxy* p, GrMipmapped mipmapped) {
@@ -100,7 +100,7 @@
         this->recordOp(std::move(op), GrProcessorSet::EmptySetAnalysis(), nullptr, nullptr, caps);
     }
 
-    void addDrawOp(GrDrawingManager* drawingMgr, std::unique_ptr<GrDrawOp> op,
+    void addDrawOp(GrDrawingManager* drawingMgr, GrOp::Owner op,
                    const GrProcessorSet::Analysis& processorAnalysis,
                    GrAppliedClip&& clip, const DstProxyView& dstProxyView,
                    GrTextureResolveManager textureResolveManager, const GrCaps& caps) {
@@ -205,8 +205,7 @@
 
     class OpChain {
     public:
-        OpChain(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*,
-                const DstProxyView*);
+        OpChain(GrOp::Owner, GrProcessorSet::Analysis, GrAppliedClip*, const DstProxyView*);
         ~OpChain() {
             // The ops are stored in a GrMemoryPool and must be explicitly deleted via the pool.
             SkASSERT(fList.empty());
@@ -236,9 +235,9 @@
         // Attempts to add 'op' to this chain either by merging or adding to the tail. Returns
         // 'op' to the caller upon failure, otherwise null. Fails when the op and chain aren't of
         // the same op type, have different clips or dst proxies.
-        std::unique_ptr<GrOp> appendOp(std::unique_ptr<GrOp> op, GrProcessorSet::Analysis,
-                                       const DstProxyView*, const GrAppliedClip*, const GrCaps&,
-                                       GrRecordingContext::Arenas*, GrAuditTrail*);
+        GrOp::Owner appendOp(GrOp::Owner op, GrProcessorSet::Analysis,
+                             const DstProxyView*, const GrAppliedClip*, const GrCaps&,
+                             GrRecordingContext::Arenas*, GrAuditTrail*);
 
         void setSkipExecuteFlag() { fSkipExecute = true; }
         bool shouldExecute() const {
@@ -249,7 +248,7 @@
         class List {
         public:
             List() = default;
-            List(std::unique_ptr<GrOp>);
+            List(GrOp::Owner);
             List(List&&);
             List& operator=(List&& that);
 
@@ -257,16 +256,16 @@
             GrOp* head() const { return fHead.get(); }
             GrOp* tail() const { return fTail; }
 
-            std::unique_ptr<GrOp> popHead();
-            std::unique_ptr<GrOp> removeOp(GrOp* op);
-            void pushHead(std::unique_ptr<GrOp> op);
-            void pushTail(std::unique_ptr<GrOp>);
+            GrOp::Owner popHead();
+            GrOp::Owner removeOp(GrOp* op);
+            void pushHead(GrOp::Owner op);
+            void pushTail(GrOp::Owner);
 
             void validate() const;
 
         private:
-            std::unique_ptr<GrOp> fHead;
-            GrOp* fTail = nullptr;
+            GrOp::Owner fHead{nullptr};
+            GrOp* fTail{nullptr};
         };
 
         void validate() const;
@@ -294,7 +293,7 @@
 
     void gatherProxyIntervals(GrResourceAllocator*) const override;
 
-    void recordOp(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*,
+    void recordOp(GrOp::Owner, GrProcessorSet::Analysis, GrAppliedClip*,
                   const DstProxyView*, const GrCaps& caps);
 
     void forwardCombine(const GrCaps&);
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index c612f41..2da5c97 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -849,10 +849,9 @@
                (rect.width() && rect.height())) {
         // Only use the StrokeRectOp for non-empty rectangles. Empty rectangles will be processed by
         // GrStyledShape to handle stroke caps and dashing properly.
-        std::unique_ptr<GrDrawOp> op;
-
         GrAAType aaType = this->chooseAAType(aa);
-        op = GrStrokeRectOp::Make(fContext, std::move(paint), aaType, viewMatrix, rect, stroke);
+        GrOp::Owner op = GrStrokeRectOp::Make(
+                fContext, std::move(paint), aaType, viewMatrix, rect, stroke);
         // op may be null if the stroke is not supported or if using coverage aa and the view matrix
         // does not preserve rectangles.
         if (op) {
@@ -980,12 +979,12 @@
     // but as it is, we're just using the full render target so intersecting the two bounds would
     // do nothing.
 
-    std::unique_ptr<GrOp> op = GrStencilPathOp::Make(fRenderTargetContext->fContext,
-                                                     viewMatrix,
-                                                     GrAA::kYes == doStencilMSAA,
-                                                     appliedClip.hasStencilClip(),
-                                                     appliedClip.scissorState(),
-                                                     std::move(path));
+    GrOp::Owner op = GrStencilPathOp::Make(fRenderTargetContext->fContext,
+                                           viewMatrix,
+                                             GrAA::kYes == doStencilMSAA,
+                                           appliedClip.hasStencilClip(),
+                                           appliedClip.scissorState(),
+                                           std::move(path));
     if (!op) {
         return;
     }
@@ -1037,7 +1036,7 @@
 
     SkASSERT(vertices);
     GrAAType aaType = this->chooseAAType(GrAA::kNo);
-    std::unique_ptr<GrDrawOp> op =
+    GrOp::Owner op =
             GrDrawVerticesOp::Make(fContext, std::move(paint), std::move(vertices), matrixProvider,
                                    aaType, this->colorInfo().refColorSpaceXformFromSRGB(),
                                    overridePrimType, effect);
@@ -1061,8 +1060,8 @@
     AutoCheckFlush acf(this->drawingManager());
 
     GrAAType aaType = this->chooseAAType(GrAA::kNo);
-    std::unique_ptr<GrDrawOp> op = GrDrawAtlasOp::Make(fContext, std::move(paint), viewMatrix,
-                                                       aaType, spriteCount, xform, texRect, colors);
+    GrOp::Owner op = GrDrawAtlasOp::Make(fContext, std::move(paint), viewMatrix,
+                                         aaType, spriteCount, xform, texRect, colors);
     this->addDrawOp(clip, std::move(op));
 }
 
@@ -1129,7 +1128,7 @@
 
     GrAAType aaType = this->chooseAAType(aa);
 
-    std::unique_ptr<GrDrawOp> op;
+    GrOp::Owner op;
     if (GrAAType::kCoverage == aaType && rrect.isSimple() &&
         rrect.getSimpleRadii().fX == rrect.getSimpleRadii().fY &&
         viewMatrix.rectStaysRect() && viewMatrix.isSimilarity()) {
@@ -1248,12 +1247,12 @@
             devSpaceInsetWidth = ambientRRect.width();
         }
 
-        std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
-                                                             ambientColor,
-                                                             viewMatrix,
-                                                             ambientRRect,
-                                                             devSpaceAmbientBlur,
-                                                             devSpaceInsetWidth);
+        GrOp::Owner op = GrShadowRRectOp::Make(fContext,
+                                               ambientColor,
+                                               viewMatrix,
+                                               ambientRRect,
+                                               devSpaceAmbientBlur,
+                                               devSpaceInsetWidth);
         if (op) {
             this->addDrawOp(clip, std::move(op));
         }
@@ -1346,12 +1345,12 @@
 
         GrColor spotColor = SkColorToPremulGrColor(rec.fSpotColor);
 
-        std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
-                                                             spotColor,
-                                                             viewMatrix,
-                                                             spotShadowRRect,
-                                                             2.0f * devSpaceSpotBlur,
-                                                             insetWidth);
+        GrOp::Owner op = GrShadowRRectOp::Make(fContext,
+                                               spotColor,
+                                               viewMatrix,
+                                               spotShadowRRect,
+                                                 2.0f * devSpaceSpotBlur,
+                                               insetWidth);
         if (op) {
             this->addDrawOp(clip, std::move(op));
         }
@@ -1512,8 +1511,8 @@
     }
 
     GrAAType aaType = this->chooseAAType(GrAA::kNo);
-    std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(fContext, std::move(paint), viewMatrix, region,
-                                                    aaType, ss);
+    GrOp::Owner op = GrRegionOp::Make(fContext, std::move(paint), viewMatrix, region,
+                                      aaType, ss);
     this->addDrawOp(clip, std::move(op));
 }
 
@@ -1543,7 +1542,7 @@
 
     GrAAType aaType = this->chooseAAType(aa);
 
-    std::unique_ptr<GrDrawOp> op;
+    GrOp::Owner op;
     if (GrAAType::kCoverage == aaType && oval.width() > SK_ScalarNearlyZero &&
         oval.width() == oval.height() && viewMatrix.isSimilarity()) {
         // We don't draw true circles as round rects in coverage mode, because it can
@@ -1597,15 +1596,15 @@
     GrAAType aaType = this->chooseAAType(aa);
     if (GrAAType::kCoverage == aaType) {
         const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
-        std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(fContext,
-                                                                  std::move(paint),
-                                                                  viewMatrix,
-                                                                  oval,
-                                                                  startAngle,
-                                                                  sweepAngle,
-                                                                  useCenter,
-                                                                  style,
-                                                                  shaderCaps);
+        GrOp::Owner op = GrOvalOpFactory::MakeArcOp(fContext,
+                                                    std::move(paint),
+                                                    viewMatrix,
+                                                    oval,
+                                                    startAngle,
+                                                    sweepAngle,
+                                                    useCenter,
+                                                    style,
+                                                    shaderCaps);
         if (op) {
             this->addDrawOp(clip, std::move(op));
             return;
@@ -1633,7 +1632,7 @@
 
     AutoCheckFlush acf(this->drawingManager());
 
-    std::unique_ptr<GrDrawOp> op =
+    GrOp::Owner op =
             GrLatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(view),
                                    alphaType, std::move(csxf), filter, std::move(iter), dst);
     this->addDrawOp(clip, std::move(op));
@@ -1641,7 +1640,7 @@
 
 void GrRenderTargetContext::drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
                                          const SkRect& bounds) {
-    std::unique_ptr<GrOp> op(GrDrawableOp::Make(fContext, std::move(drawable), bounds));
+    GrOp::Owner op(GrDrawableOp::Make(fContext, std::move(drawable), bounds));
     SkASSERT(op);
     this->addOp(std::move(op));
 }
@@ -1739,7 +1738,7 @@
             SkRect rects[2];
             if (shape.asNestedRects(rects)) {
                 // Concave AA paths are expensive - try to avoid them for special cases
-                std::unique_ptr<GrDrawOp> op = GrStrokeRectOp::MakeNested(
+                GrOp::Owner op = GrStrokeRectOp::MakeNested(
                                 fContext, std::move(paint), viewMatrix, rects);
                 if (op) {
                     this->addDrawOp(clip, std::move(op));
@@ -1963,30 +1962,28 @@
     }
 }
 
-void GrRenderTargetContext::addOp(std::unique_ptr<GrOp> op) {
+void GrRenderTargetContext::addOp(GrOp::Owner op) {
     GrDrawingManager* drawingMgr = this->drawingManager();
     this->getOpsTask()->addOp(drawingMgr,
             std::move(op), GrTextureResolveManager(drawingMgr), *this->caps());
 }
 
-void GrRenderTargetContext::addDrawOp(const GrClip* clip, std::unique_ptr<GrDrawOp> op,
+void GrRenderTargetContext::addDrawOp(const GrClip* clip, GrOp::Owner op,
                                       const std::function<WillAddOpFn>& willAddFn) {
     ASSERT_SINGLE_OWNER
     if (fContext->abandoned()) {
-        #if !defined(GR_OP_ALLOCATE_USE_NEW)
-            fContext->priv().opMemoryPool()->release(std::move(op));
-        #endif
         return;
     }
+    GrDrawOp* drawOp = (GrDrawOp*)op.get();
     SkDEBUGCODE(this->validate();)
-    SkDEBUGCODE(op->fAddDrawOpCalled = true;)
+    SkDEBUGCODE(drawOp->fAddDrawOpCalled = true;)
     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "addDrawOp", fContext);
 
     // Setup clip
     SkRect bounds;
     op_bounds(&bounds, op.get());
     GrAppliedClip appliedClip(this->dimensions(), this->asSurfaceProxy()->backingStoreDimensions());
-    GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
+    GrDrawOp::FixedFunctionFlags fixedFunctionFlags = drawOp->fixedFunctionFlags();
     bool usesHWAA = fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA;
     bool usesUserStencilBits = fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil;
 
@@ -2008,9 +2005,6 @@
     }
 
     if (skipDraw) {
-        #if !defined(GR_OP_ALLOCATE_USE_NEW)
-            fContext->priv().opMemoryPool()->release(std::move(op));
-        #endif
         return;
     }
 
@@ -2026,7 +2020,7 @@
              this->asRenderTargetProxy()->canUseMixedSamples(*this->caps()));
 
     GrClampType clampType = GrColorTypeClampType(this->colorInfo().colorType());
-    GrProcessorSet::Analysis analysis = op->finalize(
+    GrProcessorSet::Analysis analysis = drawOp->finalize(
             *this->caps(), &appliedClip, hasMixedSampledCoverage, clampType);
 
     // Must be called before setDstProxyView so that it sees the final bounds of the op.
@@ -2035,9 +2029,6 @@
     GrXferProcessor::DstProxyView dstProxyView;
     if (analysis.requiresDstTexture()) {
         if (!this->setupDstProxyView(*op, &dstProxyView)) {
-            #if !defined(GR_OP_ALLOCATE_USE_NEW)
-                fContext->priv().opMemoryPool()->release(std::move(op));
-            #endif
             return;
         }
     }
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index ac40a45..5b2b7a4 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -683,7 +683,7 @@
     void drawShapeUsingPathRenderer(const GrClip*, GrPaint&&, GrAA, const SkMatrix&,
                                     const GrStyledShape&, bool attemptShapeFallback = true);
 
-    void addOp(std::unique_ptr<GrOp>);
+    void addOp(GrOp::Owner);
 
     // Allows caller of addDrawOp to know which op list an op will be added to.
     using WillAddOpFn = void(GrOp*, uint32_t opsTaskID);
@@ -693,7 +693,7 @@
     // another op after the function is called (either before addDrawOp returns or some time later).
     //
     // If the clip pointer is null, no clipping will be performed.
-    void addDrawOp(const GrClip*, std::unique_ptr<GrDrawOp>,
+    void addDrawOp(const GrClip*, GrOp::Owner,
                    const std::function<WillAddOpFn>& = std::function<WillAddOpFn>());
 
     // Makes a copy of the proxy if it is necessary for the draw and places the texture that should
diff --git a/src/gpu/GrRenderTargetContextPriv.h b/src/gpu/GrRenderTargetContextPriv.h
index 474f0fc..c4c4fdb 100644
--- a/src/gpu/GrRenderTargetContextPriv.h
+++ b/src/gpu/GrRenderTargetContextPriv.h
@@ -97,8 +97,8 @@
     uint32_t testingOnly_getOpsTaskID();
 
     using WillAddOpFn = GrRenderTargetContext::WillAddOpFn;
-    void testingOnly_addDrawOp(std::unique_ptr<GrDrawOp>);
-    void testingOnly_addDrawOp(const GrClip*, std::unique_ptr<GrDrawOp>,
+    void testingOnly_addDrawOp(GrOp::Owner);
+    void testingOnly_addDrawOp(const GrClip*, GrOp::Owner ,
                                const std::function<WillAddOpFn>& = std::function<WillAddOpFn>());
 
     SkGlyphRunListPainter* testingOnly_glyphRunPainter() {
@@ -109,7 +109,7 @@
         return fRenderTargetContext->asRenderTargetProxy()->refsWrappedObjects();
     }
 
-    void addDrawOp(const GrClip* clip, std::unique_ptr<GrDrawOp> op) {
+    void addDrawOp(const GrClip* clip, GrOp::Owner op) {
         fRenderTargetContext->addDrawOp(clip, std::move(op));
     }
 
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
index 9ff8123..a7c8046 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
@@ -25,7 +25,7 @@
     return false;
 }
 
-std::unique_ptr<GrCCDrawPathsOp> GrCCDrawPathsOp::Make(
+GrOp::Owner GrCCDrawPathsOp::Make(
         GrRecordingContext* context, const SkIRect& clipIBounds, const SkMatrix& m,
         const GrStyledShape& shape, GrPaint&& paint) {
     SkRect conservativeDevBounds;
@@ -74,7 +74,7 @@
                         std::move(paint));
 }
 
-std::unique_ptr<GrCCDrawPathsOp> GrCCDrawPathsOp::InternalMake(
+GrOp::Owner GrCCDrawPathsOp::InternalMake(
         GrRecordingContext* context, const SkIRect& clipIBounds, const SkMatrix& m,
         const GrStyledShape& shape, float strokeDevWidth, const SkRect& conservativeDevBounds,
         GrPaint&& paint) {
@@ -92,9 +92,8 @@
         return nullptr;
     }
 
-    GrOpMemoryPool* pool = context->priv().opMemoryPool();
-    return pool->allocate<GrCCDrawPathsOp>(m, shape, strokeDevWidth, shapeConservativeIBounds,
-                                           maskDevIBounds, conservativeDevBounds, std::move(paint));
+    return GrOp::Make<GrCCDrawPathsOp>(context, m, shape, strokeDevWidth, shapeConservativeIBounds,
+                                       maskDevIBounds, conservativeDevBounds, std::move(paint));
 }
 
 GrCCDrawPathsOp::GrCCDrawPathsOp(const SkMatrix& m, const GrStyledShape& shape,
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.h b/src/gpu/ccpr/GrCCDrawPathsOp.h
index 011f717..d123374 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.h
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.h
@@ -29,8 +29,8 @@
     DEFINE_OP_CLASS_ID
     SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrCCDrawPathsOp);
 
-    static std::unique_ptr<GrCCDrawPathsOp> Make(GrRecordingContext*, const SkIRect& clipIBounds,
-                                                 const SkMatrix&, const GrStyledShape&, GrPaint&&);
+    static GrOp::Owner Make(GrRecordingContext*, const SkIRect& clipIBounds,
+                            const SkMatrix&, const GrStyledShape&, GrPaint&&);
     ~GrCCDrawPathsOp() override;
 
     const char* name() const override { return "GrCCDrawPathsOp"; }
@@ -77,14 +77,14 @@
                       const GrXferProcessor::DstProxyView&,
                       GrXferBarrierFlags renderPassXferBarriers) override {}
 
-    friend class GrOpMemoryPool;
+    friend class GrOp;
 
-    static std::unique_ptr<GrCCDrawPathsOp> InternalMake(GrRecordingContext*,
-                                                         const SkIRect& clipIBounds,
-                                                         const SkMatrix&, const GrStyledShape&,
-                                                         float strokeDevWidth,
-                                                         const SkRect& conservativeDevBounds,
-                                                         GrPaint&&);
+    static GrOp::Owner InternalMake(GrRecordingContext*,
+                                    const SkIRect& clipIBounds,
+                                    const SkMatrix&, const GrStyledShape&,
+                                    float strokeDevWidth,
+                                    const SkRect& conservativeDevBounds,
+                                    GrPaint&&);
 
     GrCCDrawPathsOp(const SkMatrix&, const GrStyledShape&, float strokeDevWidth,
                     const SkIRect& shapeConservativeIBounds, const SkIRect& maskDevIBounds,
diff --git a/src/gpu/ccpr/GrCCPerFlushResources.cpp b/src/gpu/ccpr/GrCCPerFlushResources.cpp
index a549f48..0c34605 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.cpp
+++ b/src/gpu/ccpr/GrCCPerFlushResources.cpp
@@ -70,14 +70,13 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(
+    static GrOp::Owner Make(
             GrRecordingContext* context, sk_sp<const GrCCPerFlushResources> resources,
             sk_sp<GrTextureProxy> copyProxy, int baseInstance, int endInstance,
             const SkISize& drawBounds) {
-        GrOpMemoryPool* pool = context->priv().opMemoryPool();
-
-        return pool->allocate<CopyAtlasOp>(std::move(resources), std::move(copyProxy), baseInstance,
-                                           endInstance, drawBounds);
+        return GrOp::Make<CopyAtlasOp>(
+                context, std::move(resources), std::move(copyProxy), baseInstance,
+                endInstance, drawBounds);
     }
 
     const char* name() const override { return "CopyAtlasOp (CCPR)"; }
@@ -107,7 +106,7 @@
     }
 
 private:
-    friend class ::GrOpMemoryPool; // for ctor
+    friend class ::GrOp; // for ctor
 
     CopyAtlasOp(sk_sp<const GrCCPerFlushResources> resources, sk_sp<GrTextureProxy> srcProxy,
                 int baseInstance, int endInstance, const SkISize& drawBounds)
@@ -126,12 +125,10 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(
+    static GrOp::Owner Make(
             GrRecordingContext* context, sk_sp<const GrCCPerFlushResources> resources,
             FillBatchID fillBatchID, StrokeBatchID strokeBatchID, const SkISize& drawBounds) {
-        GrOpMemoryPool* pool = context->priv().opMemoryPool();
-
-        return pool->allocate<RenderAtlasOp>(
+        return GrOp::Make<RenderAtlasOp>(context,
                 std::move(resources), fillBatchID, strokeBatchID, drawBounds);
     }
 
@@ -147,7 +144,7 @@
     }
 
 private:
-    friend class ::GrOpMemoryPool; // for ctor
+    friend class ::GrOp; // for ctor
 
     RenderAtlasOp(sk_sp<const GrCCPerFlushResources> resources, FillBatchID fillBatchID,
                   StrokeBatchID strokeBatchID, const SkISize& drawBounds)
@@ -567,7 +564,7 @@
         }
 
         if (auto rtc = atlas.instantiate(onFlushRP, std::move(backingTexture))) {
-            std::unique_ptr<GrDrawOp> op;
+            GrOp::Owner op;
             if (CoverageType::kA8_Multisample == fRenderedAtlasStack.coverageType()) {
                 op = GrStencilAtlasOp::Make(
                         rtc->surfPriv().getContext(), sk_ref_sp(this), atlas.getFillBatchID(),
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index 159230a..473bbe1 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -173,7 +173,7 @@
     return true;
 }
 
-void GrCoverageCountingPathRenderer::recordOp(std::unique_ptr<GrCCDrawPathsOp> op,
+void GrCoverageCountingPathRenderer::recordOp(GrOp::Owner op,
                                               const DrawPathArgs& args) {
     if (op) {
         auto addToOwningPerOpsTaskPaths = [this](GrOp* op, uint32_t opsTaskID) {
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.h b/src/gpu/ccpr/GrCoverageCountingPathRenderer.h
index ac26008..5e4d2ba 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.h
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.h
@@ -99,7 +99,7 @@
     bool onDrawPath(const DrawPathArgs&) override;
 
     GrCCPerOpsTaskPaths* lookupPendingPaths(uint32_t opsTaskID);
-    void recordOp(std::unique_ptr<GrCCDrawPathsOp>, const DrawPathArgs&);
+    void recordOp(GrOp::Owner, const DrawPathArgs&);
 
     const CoverageType fCoverageType;
 
diff --git a/src/gpu/ccpr/GrStencilAtlasOp.cpp b/src/gpu/ccpr/GrStencilAtlasOp.cpp
index ba6c88e..35303c4 100644
--- a/src/gpu/ccpr/GrStencilAtlasOp.cpp
+++ b/src/gpu/ccpr/GrStencilAtlasOp.cpp
@@ -67,14 +67,13 @@
 
 }  // namespace
 
-std::unique_ptr<GrDrawOp> GrStencilAtlasOp::Make(
+GrOp::Owner GrStencilAtlasOp::Make(
         GrRecordingContext* context, sk_sp<const GrCCPerFlushResources> resources,
         FillBatchID fillBatchID, StrokeBatchID strokeBatchID, int baseStencilResolveInstance,
         int endStencilResolveInstance, const SkISize& drawBounds) {
-    GrOpMemoryPool* pool = context->priv().opMemoryPool();
 
-    return pool->allocate<GrStencilAtlasOp>(
-            std::move(resources), fillBatchID, strokeBatchID, baseStencilResolveInstance,
+    return GrOp::Make<GrStencilAtlasOp>(
+            context, std::move(resources), fillBatchID, strokeBatchID, baseStencilResolveInstance,
             endStencilResolveInstance, drawBounds);
 }
 
diff --git a/src/gpu/ccpr/GrStencilAtlasOp.h b/src/gpu/ccpr/GrStencilAtlasOp.h
index 72ab6b3..132623d 100644
--- a/src/gpu/ccpr/GrStencilAtlasOp.h
+++ b/src/gpu/ccpr/GrStencilAtlasOp.h
@@ -47,7 +47,7 @@
         return CombineResult::kCannotCombine;
     }
 
-    static std::unique_ptr<GrDrawOp> Make(
+    static GrOp::Owner Make(
             GrRecordingContext*, sk_sp<const GrCCPerFlushResources>, FillBatchID, StrokeBatchID,
             int baseStencilResolveInstance, int endStencilResolveInstance,
             const SkISize& drawBounds);
@@ -63,7 +63,7 @@
     void drawResolve(GrOpFlushState*, const GrPipeline&, const GrUserStencilSettings*,
                      const GrPrimitiveProcessor&, const SkIRect& drawBounds) const;
 
-    friend class ::GrOpMemoryPool; // for ctor
+    friend class ::GrOp; // for ctor
 
     GrStencilAtlasOp(sk_sp<const GrCCPerFlushResources> resources, FillBatchID fillBatchID,
                      StrokeBatchID strokeBatchID, int baseStencilResolveInstance,
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index 2a5c4de..56e0e12 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -697,19 +697,19 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          const SkPath& path,
-                                          const GrUserStencilSettings* stencilSettings) {
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            const SkMatrix& viewMatrix,
+                            const SkPath& path,
+                            const GrUserStencilSettings* stencilSettings) {
         return Helper::FactoryHelper<AAConvexPathOp>(context, std::move(paint), viewMatrix, path,
                                                      stencilSettings);
     }
 
-    AAConvexPathOp(const Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
+    AAConvexPathOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
                    const SkMatrix& viewMatrix, const SkPath& path,
                    const GrUserStencilSettings* stencilSettings)
-            : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage, stencilSettings) {
+            : INHERITED(ClassID()), fHelper(processorSet, GrAAType::kCoverage, stencilSettings) {
         fPaths.emplace_back(PathData{viewMatrix, path, color});
         this->setTransformedBounds(path.getBounds(), viewMatrix, HasAABloat::kYes,
                                    IsHairline::kNo);
@@ -914,9 +914,9 @@
     SkPath path;
     args.fShape->asPath(&path);
 
-    std::unique_ptr<GrDrawOp> op = AAConvexPathOp::Make(args.fContext, std::move(args.fPaint),
-                                                        *args.fViewMatrix,
-                                                        path, args.fUserStencilSettings);
+    GrOp::Owner op = AAConvexPathOp::Make(args.fContext, std::move(args.fPaint),
+                                          *args.fViewMatrix,
+                                          path, args.fUserStencilSettings);
     args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
     return true;
 }
diff --git a/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
index 202cb37..96462ec 100644
--- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
@@ -800,13 +800,13 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          const SkPath& path,
-                                          const GrStyle& style,
-                                          const SkIRect& devClipBounds,
-                                          const GrUserStencilSettings* stencilSettings) {
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            const SkMatrix& viewMatrix,
+                            const SkPath& path,
+                            const GrStyle& style,
+                            const SkIRect& devClipBounds,
+                            const GrUserStencilSettings* stencilSettings) {
         SkScalar hairlineCoverage;
         uint8_t newCoverage = 0xff;
         if (GrPathRenderer::IsStrokeHairlineOrEquivalent(style, viewMatrix, &hairlineCoverage)) {
@@ -821,7 +821,7 @@
                                                    devClipBounds, capLength, stencilSettings);
     }
 
-    AAHairlineOp(const Helper::MakeArgs& helperArgs,
+    AAHairlineOp(GrProcessorSet* processorSet,
                  const SkPMColor4f& color,
                  uint8_t coverage,
                  const SkMatrix& viewMatrix,
@@ -830,7 +830,7 @@
                  SkScalar capLength,
                  const GrUserStencilSettings* stencilSettings)
             : INHERITED(ClassID())
-            , fHelper(helperArgs, GrAAType::kCoverage, stencilSettings)
+            , fHelper(processorSet, GrAAType::kCoverage, stencilSettings)
             , fColor(color)
             , fCoverage(coverage) {
         fPaths.emplace_back(PathData{viewMatrix, path, devClipBounds, capLength});
@@ -1306,7 +1306,7 @@
 
     SkPath path;
     args.fShape->asPath(&path);
-    std::unique_ptr<GrDrawOp> op =
+    GrOp::Owner op =
             AAHairlineOp::Make(args.fContext, std::move(args.fPaint), *args.fViewMatrix, path,
                                args.fShape->style(), *args.fClipConservativeBounds,
                                args.fUserStencilSettings);
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index 9f8bc51..9b0ef32 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -132,22 +132,23 @@
 
 public:
     DEFINE_OP_CLASS_ID
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          const SkPath& path,
-                                          SkScalar strokeWidth,
-                                          SkStrokeRec::Style style,
-                                          SkPaint::Join join,
-                                          SkScalar miterLimit,
-                                          const GrUserStencilSettings* stencilSettings) {
+
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            const SkMatrix& viewMatrix,
+                            const SkPath& path,
+                            SkScalar strokeWidth,
+                            SkStrokeRec::Style style,
+                            SkPaint::Join join,
+                            SkScalar miterLimit,
+                            const GrUserStencilSettings* stencilSettings) {
         return Helper::FactoryHelper<AAFlatteningConvexPathOp>(context, std::move(paint),
                                                                viewMatrix, path,
                                                                strokeWidth, style, join, miterLimit,
                                                                stencilSettings);
     }
 
-    AAFlatteningConvexPathOp(const Helper::MakeArgs& helperArgs,
+    AAFlatteningConvexPathOp(GrProcessorSet* processorSet,
                              const SkPMColor4f& color,
                              const SkMatrix& viewMatrix,
                              const SkPath& path,
@@ -156,7 +157,7 @@
                              SkPaint::Join join,
                              SkScalar miterLimit,
                              const GrUserStencilSettings* stencilSettings)
-            : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage, stencilSettings) {
+            : INHERITED(ClassID()), fHelper(processorSet, GrAAType::kCoverage, stencilSettings) {
         fPaths.emplace_back(
                 PathData{viewMatrix, path, color, strokeWidth, miterLimit, style, join});
 
@@ -402,7 +403,7 @@
     SkPaint::Join join = fill ? SkPaint::Join::kMiter_Join : stroke.getJoin();
     SkScalar miterLimit = stroke.getMiter();
 
-    std::unique_ptr<GrDrawOp> op = AAFlatteningConvexPathOp::Make(
+    GrOp::Owner op = AAFlatteningConvexPathOp::Make(
             args.fContext, std::move(args.fPaint), *args.fViewMatrix, path, strokeWidth,
             stroke.getStyle(), join, miterLimit, args.fUserStencilSettings);
     args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index 3d5b801..b89e6c2 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -456,13 +456,14 @@
 }
 
 #if GR_TEST_UTILS
-std::unique_ptr<GrDrawOp> GrAtlasTextOp::CreateOpTestingOnly(GrRenderTargetContext* rtc,
-                                                             const SkPaint& skPaint,
-                                                             const SkFont& font,
-                                                             const SkMatrixProvider& mtxProvider,
-                                                             const char* text,
-                                                             int x,
-                                                             int y) {
+
+GrOp::Owner GrAtlasTextOp::CreateOpTestingOnly(GrRenderTargetContext* rtc,
+                                               const SkPaint& skPaint,
+                                               const SkFont& font,
+                                               const SkMatrixProvider& mtxProvider,
+                                               const char* text,
+                                               int x,
+                                               int y) {
     size_t textLen = (int)strlen(text);
 
     const SkMatrix& drawMatrix(mtxProvider.localToDevice());
@@ -491,7 +492,7 @@
     }
 
     GrAtlasSubRun* subRun = static_cast<GrAtlasSubRun*>(blob->subRunList().head());
-    std::unique_ptr<GrDrawOp> op;
+    GrOp::Owner op;
     std::tie(std::ignore, op) = subRun->makeAtlasTextOp(nullptr, mtxProvider, glyphRunList, rtc);
     return op;
 }
diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h
index 0db4ac7..35d6110 100644
--- a/src/gpu/ops/GrAtlasTextOp.h
+++ b/src/gpu/ops/GrAtlasTextOp.h
@@ -61,17 +61,17 @@
     MaskType maskType() const { return fMaskType; }
 
 #if GR_TEST_UTILS
-    static std::unique_ptr<GrDrawOp> CreateOpTestingOnly(GrRenderTargetContext* rtc,
-                                                         const SkPaint& skPaint,
-                                                         const SkFont& font,
-                                                         const SkMatrixProvider& mtxProvider,
-                                                         const char* text,
-                                                         int x,
-                                                         int y);
+    static GrOp::Owner CreateOpTestingOnly(GrRenderTargetContext* rtc,
+                                           const SkPaint& skPaint,
+                                           const SkFont& font,
+                                           const SkMatrixProvider& mtxProvider,
+                                           const char* text,
+                                           int x,
+                                           int y);
 #endif
 
 private:
-    friend class GrOpMemoryPool; // for ctor
+    friend class GrOp; // 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 821bdaa..da5e47a 100644
--- a/src/gpu/ops/GrClearOp.cpp
+++ b/src/gpu/ops/GrClearOp.cpp
@@ -18,18 +18,16 @@
     return !a.enabled() || (b.enabled() && a.rect().contains(b.rect()));
 }
 
-std::unique_ptr<GrClearOp> GrClearOp::MakeColor(GrRecordingContext* context,
-                                                const GrScissorState& scissor,
-                                                const SkPMColor4f& color) {
-    GrOpMemoryPool* pool = context->priv().opMemoryPool();
-    return pool->allocate<GrClearOp>(Buffer::kColor, scissor, color, false);
+GrOp::Owner GrClearOp::MakeColor(GrRecordingContext* context,
+                                 const GrScissorState& scissor,
+                                 const SkPMColor4f& color) {
+    return GrOp::Make<GrClearOp>(context, Buffer::kColor, scissor, color, false);
 }
 
-std::unique_ptr<GrClearOp> GrClearOp::MakeStencilClip(GrRecordingContext* context,
-                                                      const GrScissorState& scissor,
-                                                      bool insideMask) {
-    GrOpMemoryPool* pool = context->priv().opMemoryPool();
-    return pool->allocate<GrClearOp>(Buffer::kStencilClip, scissor, SkPMColor4f(), insideMask);
+GrOp::Owner GrClearOp::MakeStencilClip(GrRecordingContext* context,
+                                       const GrScissorState& scissor,
+                                       bool insideMask) {
+    return GrOp::Make<GrClearOp>(context, Buffer::kStencilClip, scissor, SkPMColor4f(), insideMask);
 }
 
 GrClearOp::GrClearOp(Buffer buffer, const GrScissorState& scissor,
diff --git a/src/gpu/ops/GrClearOp.h b/src/gpu/ops/GrClearOp.h
index 6e4846b..fa5f935 100644
--- a/src/gpu/ops/GrClearOp.h
+++ b/src/gpu/ops/GrClearOp.h
@@ -20,18 +20,18 @@
     DEFINE_OP_CLASS_ID
 
     // A fullscreen or scissored clear, depending on the clip and proxy dimensions
-    static std::unique_ptr<GrClearOp> MakeColor(GrRecordingContext* context,
-                                                const GrScissorState& scissor,
-                                                const SkPMColor4f& color);
+    static GrOp::Owner MakeColor(GrRecordingContext* context,
+                                 const GrScissorState& scissor,
+                                 const SkPMColor4f& color);
 
-    static std::unique_ptr<GrClearOp> MakeStencilClip(GrRecordingContext* context,
-                                                      const GrScissorState& scissor,
-                                                      bool insideMask);
+    static GrOp::Owner MakeStencilClip(GrRecordingContext* context,
+                                       const GrScissorState& scissor,
+                                       bool insideMask);
 
     const char* name() const override { return "Clear"; }
 
 private:
-    friend class GrOpMemoryPool; // for ctors
+    friend class GrOp; // for ctors
 
     enum class Buffer {
         kColor       = 0b01,
diff --git a/src/gpu/ops/GrDashLinePathRenderer.cpp b/src/gpu/ops/GrDashLinePathRenderer.cpp
index e5cf9e4..0b079cc 100644
--- a/src/gpu/ops/GrDashLinePathRenderer.cpp
+++ b/src/gpu/ops/GrDashLinePathRenderer.cpp
@@ -47,7 +47,7 @@
     }
     SkPoint pts[2];
     SkAssertResult(args.fShape->asLine(pts, nullptr));
-    std::unique_ptr<GrDrawOp> op =
+    GrOp::Owner op =
             GrDashOp::MakeDashLineOp(args.fContext, std::move(args.fPaint), *args.fViewMatrix, pts,
                                      aaMode, args.fShape->style(), args.fUserStencilSettings);
     if (!op) {
diff --git a/src/gpu/ops/GrDashOp.cpp b/src/gpu/ops/GrDashOp.cpp
index 08846f0..cf45035 100644
--- a/src/gpu/ops/GrDashOp.cpp
+++ b/src/gpu/ops/GrDashOp.cpp
@@ -222,16 +222,14 @@
         SkScalar fPerpendicularScale;
     };
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const LineData& geometry,
-                                          SkPaint::Cap cap,
-                                          AAMode aaMode, bool fullDash,
-                                          const GrUserStencilSettings* stencilSettings) {
-        GrOpMemoryPool* pool = context->priv().opMemoryPool();
-
-        return pool->allocate<DashOp>(std::move(paint), geometry, cap,
-                                      aaMode, fullDash, stencilSettings);
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            const LineData& geometry,
+                            SkPaint::Cap cap,
+                            AAMode aaMode, bool fullDash,
+                            const GrUserStencilSettings* stencilSettings) {
+        return GrOp::Make<DashOp>(context, std::move(paint), geometry, cap,
+                                  aaMode, fullDash, stencilSettings);
     }
 
     const char* name() const override { return "DashOp"; }
@@ -267,7 +265,7 @@
     }
 
 private:
-    friend class GrOpMemoryPool; // for ctor
+    friend class GrOp; // for ctor
 
     DashOp(GrPaint&& paint, const LineData& geometry, SkPaint::Cap cap, AAMode aaMode,
            bool fullDash, const GrUserStencilSettings* stencilSettings)
@@ -740,13 +738,13 @@
     using INHERITED = GrMeshDrawOp;
 };
 
-std::unique_ptr<GrDrawOp> GrDashOp::MakeDashLineOp(GrRecordingContext* context,
-                                                   GrPaint&& paint,
-                                                   const SkMatrix& viewMatrix,
-                                                   const SkPoint pts[2],
-                                                   AAMode aaMode,
-                                                   const GrStyle& style,
-                                                   const GrUserStencilSettings* stencilSettings) {
+GrOp::Owner GrDashOp::MakeDashLineOp(GrRecordingContext* context,
+                                     GrPaint&& paint,
+                                     const SkMatrix& viewMatrix,
+                                     const SkPoint pts[2],
+                                     AAMode aaMode,
+                                     const GrStyle& style,
+                                     const GrUserStencilSettings* stencilSettings) {
     SkASSERT(GrDashOp::CanDrawDashLine(pts, style, viewMatrix));
     const SkScalar* intervals = style.dashIntervals();
     SkScalar phase = style.dashPhase();
diff --git a/src/gpu/ops/GrDashOp.h b/src/gpu/ops/GrDashOp.h
index 22fc48b..addd9e1 100644
--- a/src/gpu/ops/GrDashOp.h
+++ b/src/gpu/ops/GrDashOp.h
@@ -10,6 +10,7 @@
 
 #include "include/core/SkPathEffect.h"
 #include "include/gpu/GrTypes.h"
+#include "src/gpu/ops/GrOp.h"
 
 class GrDrawOp;
 class GrPaint;
@@ -25,13 +26,13 @@
 };
 static const int kAAModeCnt = static_cast<int>(AAMode::kCoverageWithMSAA) + 1;
 
-std::unique_ptr<GrDrawOp> MakeDashLineOp(GrRecordingContext*,
-                                         GrPaint&&,
-                                         const SkMatrix& viewMatrix,
-                                         const SkPoint pts[2],
-                                         AAMode,
-                                         const GrStyle& style,
-                                         const GrUserStencilSettings*);
+GrOp::Owner MakeDashLineOp(GrRecordingContext*,
+                           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);
 }  // namespace GrDashOp
 
diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp
index 95802c8..3f8113f 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -344,16 +344,16 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkPath& path,
-                                          SkScalar tolerance,
-                                          uint8_t coverage,
-                                          const SkMatrix& viewMatrix,
-                                          bool isHairline,
-                                          GrAAType aaType,
-                                          const SkRect& devBounds,
-                                          const GrUserStencilSettings* stencilSettings) {
+    static GrOp::Owner Make(GrRecordingContext* 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>(context, std::move(paint), path, tolerance,
                                                     coverage, viewMatrix, isHairline, aaType,
                                                     devBounds, stencilSettings);
@@ -369,12 +369,12 @@
         }
     }
 
-    DefaultPathOp(const Helper::MakeArgs& helperArgs, const SkPMColor4f& color, const SkPath& path,
+    DefaultPathOp(GrProcessorSet* processorSet, const SkPMColor4f& color, const SkPath& path,
                   SkScalar tolerance, uint8_t coverage, const SkMatrix& viewMatrix, bool isHairline,
                   GrAAType aaType, const SkRect& devBounds,
                   const GrUserStencilSettings* stencilSettings)
             : INHERITED(ClassID())
-            , fHelper(helperArgs, aaType, stencilSettings)
+            , fHelper(processorSet, aaType, stencilSettings)
             , fColor(color)
             , fCoverage(coverage)
             , fViewMatrix(viewMatrix)
@@ -661,7 +661,7 @@
                     GrAA(aaType == GrAAType::kMSAA), viewM, bounds, &localMatrix);
         } else {
             bool stencilPass = stencilOnly || passCount > 1;
-            std::unique_ptr<GrDrawOp> op;
+            GrOp::Owner op;
             if (stencilPass) {
                 GrPaint stencilPaint;
                 stencilPaint.setXPFactory(GrDisableColorXPFactory::Get());
diff --git a/src/gpu/ops/GrDrawAtlasOp.cpp b/src/gpu/ops/GrDrawAtlasOp.cpp
index bc19a1a..90cda27 100644
--- a/src/gpu/ops/GrDrawAtlasOp.cpp
+++ b/src/gpu/ops/GrDrawAtlasOp.cpp
@@ -30,7 +30,7 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    DrawAtlasOp(const Helper::MakeArgs&, const SkPMColor4f& color,
+    DrawAtlasOp(GrProcessorSet*, const SkPMColor4f& color,
                 const SkMatrix& viewMatrix, GrAAType, int spriteCount, const SkRSXform* xforms,
                 const SkRect* rects, const SkColor* colors);
 
@@ -104,10 +104,10 @@
                                          LocalCoords::kHasExplicit_Type, viewMatrix);
 }
 
-DrawAtlasOp::DrawAtlasOp(const Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
+DrawAtlasOp::DrawAtlasOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
                          const SkMatrix& viewMatrix, GrAAType aaType, int spriteCount,
                          const SkRSXform* xforms, const SkRect* rects, const SkColor* colors)
-        : INHERITED(ClassID()), fHelper(helperArgs, aaType), fColor(color) {
+        : INHERITED(ClassID()), fHelper(processorSet, aaType), fColor(color) {
     SkASSERT(xforms);
     SkASSERT(rects);
 
@@ -303,14 +303,14 @@
 
 } // anonymous namespace
 
-std::unique_ptr<GrDrawOp> GrDrawAtlasOp::Make(GrRecordingContext* context,
-                                              GrPaint&& paint,
-                                              const SkMatrix& viewMatrix,
-                                              GrAAType aaType,
-                                              int spriteCount,
-                                              const SkRSXform* xforms,
-                                              const SkRect* rects,
-                                              const SkColor* colors) {
+GrOp::Owner GrDrawAtlasOp::Make(GrRecordingContext* context,
+                                GrPaint&& paint,
+                                const SkMatrix& viewMatrix,
+                                GrAAType aaType,
+                                int spriteCount,
+                                const SkRSXform* xforms,
+                                const SkRect* rects,
+                                const SkColor* colors) {
     return GrSimpleMeshDrawOpHelper::FactoryHelper<DrawAtlasOp>(context, std::move(paint),
                                                                 viewMatrix, aaType,
                                                                 spriteCount, xforms,
diff --git a/src/gpu/ops/GrDrawAtlasOp.h b/src/gpu/ops/GrDrawAtlasOp.h
index f607f4e..f035e90 100644
--- a/src/gpu/ops/GrDrawAtlasOp.h
+++ b/src/gpu/ops/GrDrawAtlasOp.h
@@ -10,6 +10,7 @@
 
 #include "include/core/SkRefCnt.h"
 #include "include/private/GrTypesPriv.h"
+#include "src/gpu/ops/GrOp.h"
 
 class GrDrawOp;
 class GrPaint;
@@ -17,14 +18,14 @@
 class SkMatrix;
 
 namespace GrDrawAtlasOp {
-    std::unique_ptr<GrDrawOp> Make(GrRecordingContext*,
-                                   GrPaint&&,
-                                   const SkMatrix& viewMatrix,
-                                   GrAAType,
-                                   int spriteCount,
-                                   const SkRSXform* xforms,
-                                   const SkRect* rects,
-                                   const SkColor* colors);
+GrOp::Owner Make(GrRecordingContext*,
+                 GrPaint&&,
+                 const SkMatrix& viewMatrix,
+                 GrAAType,
+                 int spriteCount,
+                 const SkRSXform* xforms,
+                 const SkRect* rects,
+                 const SkColor* colors);
 }  // namespace GrDrawAtlasOp
 
 #endif
diff --git a/src/gpu/ops/GrDrawPathOp.cpp b/src/gpu/ops/GrDrawPathOp.cpp
index f56f2ed..936ef82 100644
--- a/src/gpu/ops/GrDrawPathOp.cpp
+++ b/src/gpu/ops/GrDrawPathOp.cpp
@@ -65,14 +65,12 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-std::unique_ptr<GrDrawOp> GrDrawPathOp::Make(GrRecordingContext* context,
-                                             const SkMatrix& viewMatrix,
-                                             GrPaint&& paint,
-                                             GrAA aa,
-                                             sk_sp<const GrPath> path) {
-    GrOpMemoryPool* pool = context->priv().opMemoryPool();
-
-    return pool->allocate<GrDrawPathOp>(viewMatrix, std::move(paint), aa, std::move(path));
+GrOp::Owner GrDrawPathOp::Make(GrRecordingContext* context,
+                               const SkMatrix& viewMatrix,
+                               GrPaint&& paint,
+                               GrAA aa,
+                               sk_sp<const GrPath> path) {
+    return GrOp::Make<GrDrawPathOp>(context, viewMatrix, std::move(paint), aa, std::move(path));
 }
 
 void GrDrawPathOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
diff --git a/src/gpu/ops/GrDrawPathOp.h b/src/gpu/ops/GrDrawPathOp.h
index 178969f..366c99a 100644
--- a/src/gpu/ops/GrDrawPathOp.h
+++ b/src/gpu/ops/GrDrawPathOp.h
@@ -76,13 +76,13 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(
+    static GrOp::Owner Make(
             GrRecordingContext*, const SkMatrix& viewMatrix, GrPaint&&, GrAA, sk_sp<const GrPath>);
 
     const char* name() const override { return "DrawPath"; }
 
 private:
-    friend class GrOpMemoryPool; // for ctor
+    friend class GrOp; // for ctor
 
     GrDrawPathOp(const SkMatrix& viewMatrix, GrPaint&& paint, GrAA aa, sk_sp<const GrPath> path)
             : GrDrawPathOpBase(
diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp
index 0a80e67..c99f150 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -441,7 +441,7 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    DrawVerticesOp(const Helper::MakeArgs&, const SkPMColor4f&, sk_sp<SkVertices>,
+    DrawVerticesOp(GrProcessorSet*, const SkPMColor4f&, sk_sp<SkVertices>,
                    GrPrimitiveType, GrAAType, sk_sp<GrColorSpaceXform>, const SkMatrixProvider&,
                    const SkRuntimeEffect*);
 
@@ -537,7 +537,7 @@
     using INHERITED = GrMeshDrawOp;
 };
 
-DrawVerticesOp::DrawVerticesOp(const Helper::MakeArgs& helperArgs,
+DrawVerticesOp::DrawVerticesOp(GrProcessorSet* processorSet,
                                const SkPMColor4f& color,
                                sk_sp<SkVertices> vertices,
                                GrPrimitiveType primitiveType,
@@ -546,7 +546,7 @@
                                const SkMatrixProvider& matrixProvider,
                                const SkRuntimeEffect* effect)
         : INHERITED(ClassID())
-        , fHelper(helperArgs, aaType)
+        , fHelper(processorSet, aaType)
         , fPrimitiveType(primitiveType)
         , fMultipleViewMatrices(false)
         , fColorSpaceXform(std::move(colorSpaceXform)) {
@@ -845,14 +845,14 @@
     SK_ABORT("Invalid mode");
 }
 
-std::unique_ptr<GrDrawOp> GrDrawVerticesOp::Make(GrRecordingContext* context,
-                                                 GrPaint&& paint,
-                                                 sk_sp<SkVertices> vertices,
-                                                 const SkMatrixProvider& matrixProvider,
-                                                 GrAAType aaType,
-                                                 sk_sp<GrColorSpaceXform> colorSpaceXform,
-                                                 GrPrimitiveType* overridePrimType,
-                                                 const SkRuntimeEffect* effect) {
+GrOp::Owner GrDrawVerticesOp::Make(GrRecordingContext* context,
+                                   GrPaint&& paint,
+                                   sk_sp<SkVertices> vertices,
+                                   const SkMatrixProvider& matrixProvider,
+                                   GrAAType aaType,
+                                   sk_sp<GrColorSpaceXform> colorSpaceXform,
+                                   GrPrimitiveType* overridePrimType,
+                                   const SkRuntimeEffect* effect) {
     SkASSERT(vertices);
     GrPrimitiveType primType = overridePrimType
                                        ? *overridePrimType
diff --git a/src/gpu/ops/GrDrawVerticesOp.h b/src/gpu/ops/GrDrawVerticesOp.h
index 6dedacd..bd5cfa3 100644
--- a/src/gpu/ops/GrDrawVerticesOp.h
+++ b/src/gpu/ops/GrDrawVerticesOp.h
@@ -27,14 +27,14 @@
      * specified. If an SkRuntimeEffect is provided, it may expect some number of input varyings,
      * which should match the number of extra per-vertex values in the SkVertices.
      */
-    std::unique_ptr<GrDrawOp> Make(GrRecordingContext*,
-                                   GrPaint&&,
-                                   sk_sp<SkVertices>,
-                                   const SkMatrixProvider&,
-                                   GrAAType,
-                                   sk_sp<GrColorSpaceXform>,
-                                   GrPrimitiveType* overridePrimType,
-                                   const SkRuntimeEffect*);
+    GrOp::Owner Make(GrRecordingContext*,
+                     GrPaint&&,
+                     sk_sp<SkVertices>,
+                     const SkMatrixProvider&,
+                     GrAAType,
+                     sk_sp<GrColorSpaceXform>,
+                     GrPrimitiveType* overridePrimType,
+                     const SkRuntimeEffect*);
 
 }  // namespace GrDrawVerticesOp
 
diff --git a/src/gpu/ops/GrDrawableOp.cpp b/src/gpu/ops/GrDrawableOp.cpp
index a8ba547..4756606 100644
--- a/src/gpu/ops/GrDrawableOp.cpp
+++ b/src/gpu/ops/GrDrawableOp.cpp
@@ -14,11 +14,10 @@
 #include "src/gpu/GrOpsRenderPass.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 
-std::unique_ptr<GrDrawableOp> GrDrawableOp::Make(
+GrOp::Owner GrDrawableOp::Make(
         GrRecordingContext* context, std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
         const SkRect& bounds) {
-    GrOpMemoryPool* pool = context->priv().opMemoryPool();
-    return pool->allocate<GrDrawableOp>(std::move(drawable), bounds);
+    return GrOp::Make<GrDrawableOp>(context, std::move(drawable), bounds);
 }
 
 GrDrawableOp::GrDrawableOp(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
diff --git a/src/gpu/ops/GrDrawableOp.h b/src/gpu/ops/GrDrawableOp.h
index 7be5648..ff2e51f 100644
--- a/src/gpu/ops/GrDrawableOp.h
+++ b/src/gpu/ops/GrDrawableOp.h
@@ -20,14 +20,14 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawableOp> Make(GrRecordingContext*,
-                                              std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
-                                              const SkRect& bounds);
+    static GrOp::Owner Make(GrRecordingContext*,
+                            std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
+                            const SkRect& bounds);
 
     const char* name() const override { return "Drawable"; }
 
 private:
-    friend class GrOpMemoryPool; // for ctor
+    friend class GrOp; // for ctor
 
     GrDrawableOp(std::unique_ptr<SkDrawable::GpuDrawHandler>, const SkRect& bounds);
 
diff --git a/src/gpu/ops/GrFillRRectOp.cpp b/src/gpu/ops/GrFillRRectOp.cpp
index a8c4aca..b55e679 100644
--- a/src/gpu/ops/GrFillRRectOp.cpp
+++ b/src/gpu/ops/GrFillRRectOp.cpp
@@ -31,11 +31,11 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext*,
-                                          GrPaint&&,
-                                          const SkMatrix& viewMatrix,
-                                          const SkRRect&,
-                                          GrAAType);
+    static GrOp::Owner Make(GrRecordingContext*,
+                            GrPaint&&,
+                            const SkMatrix& viewMatrix,
+                            const SkRRect&,
+                            GrAAType);
 
     const char* name() const final { return "GrFillRRectOp"; }
 
@@ -59,7 +59,7 @@
 
 private:
     friend class ::GrSimpleMeshDrawOpHelper; // for access to ctor
-    friend class ::GrOpMemoryPool;         // for access to ctor
+    friend class ::GrOp;         // for access to ctor
 
     enum class ProcessorFlags {
         kNone             = 0,
@@ -73,7 +73,7 @@
 
     class Processor;
 
-    FillRRectOp(const Helper::MakeArgs&,
+    FillRRectOp(GrProcessorSet*,
                 const SkPMColor4f& paintColor,
                 const SkMatrix& totalShapeMatrix,
                 const SkRRect&,
@@ -137,11 +137,11 @@
                                                  const SkMatrix&,
                                                  const SkRRect&);
 
-std::unique_ptr<GrDrawOp> FillRRectOp::Make(GrRecordingContext* ctx,
-                                            GrPaint&& paint,
-                                            const SkMatrix& viewMatrix,
-                                            const SkRRect& rrect,
-                                            GrAAType aaType) {
+GrOp::Owner FillRRectOp::Make(GrRecordingContext* ctx,
+                              GrPaint&& paint,
+                              const SkMatrix& viewMatrix,
+                              const SkRRect& rrect,
+                              GrAAType aaType) {
     using Helper = GrSimpleMeshDrawOpHelper;
 
     const GrCaps* caps = ctx->priv().caps();
@@ -212,7 +212,7 @@
                                               flags, devBounds);
 }
 
-FillRRectOp::FillRRectOp(const GrSimpleMeshDrawOpHelper::MakeArgs& helperArgs,
+FillRRectOp::FillRRectOp(GrProcessorSet* processorSet,
                          const SkPMColor4f& paintColor,
                          const SkMatrix& totalShapeMatrix,
                          const SkRRect& rrect,
@@ -220,7 +220,7 @@
                          ProcessorFlags processorFlags,
                          const SkRect& devBounds)
         : INHERITED(ClassID())
-        , fHelper(helperArgs, aaType)
+        , fHelper(processorSet, aaType)
         , fColor(paintColor)
         , fLocalRect(rrect.rect())
         , fProcessorFlags(processorFlags & ~(ProcessorFlags::kHasLocalCoords |
@@ -943,11 +943,11 @@
 } // anonymous namespace
 
 
-std::unique_ptr<GrDrawOp> GrFillRRectOp::Make(GrRecordingContext* ctx,
-                                              GrPaint&& paint,
-                                              const SkMatrix& viewMatrix,
-                                              const SkRRect& rrect,
-                                              GrAAType aaType) {
+GrOp::Owner GrFillRRectOp::Make(GrRecordingContext* ctx,
+                                GrPaint&& paint,
+                                const SkMatrix& viewMatrix,
+                                const SkRRect& rrect,
+                                GrAAType aaType) {
     return FillRRectOp::Make(ctx, std::move(paint), viewMatrix, rrect, aaType);
 }
 
diff --git a/src/gpu/ops/GrFillRRectOp.h b/src/gpu/ops/GrFillRRectOp.h
index 3d0949a..c544c80f 100644
--- a/src/gpu/ops/GrFillRRectOp.h
+++ b/src/gpu/ops/GrFillRRectOp.h
@@ -9,6 +9,7 @@
 #define GrFillRRectOp_DEFINED
 
 #include "include/private/GrTypesPriv.h"
+#include "src/gpu/ops/GrOp.h"
 
 class GrCaps;
 class GrDrawOp;
@@ -18,11 +19,11 @@
 class SkRRect;
 
 namespace GrFillRRectOp {
-    std::unique_ptr<GrDrawOp> Make(GrRecordingContext*,
-                                   GrPaint&&,
-                                   const SkMatrix& viewMatrix,
-                                   const SkRRect&,
-                                   GrAAType);
+    GrOp::Owner Make(GrRecordingContext*,
+                     GrPaint&&,
+                     const SkMatrix& viewMatrix,
+                     const SkRRect&,
+                     GrAAType);
 }  // namespace GrFillRRectOp
 
 #endif
diff --git a/src/gpu/ops/GrFillRectOp.cpp b/src/gpu/ops/GrFillRectOp.cpp
index c966a41..d722af4 100644
--- a/src/gpu/ops/GrFillRectOp.cpp
+++ b/src/gpu/ops/GrFillRectOp.cpp
@@ -62,12 +62,12 @@
     using Helper = GrSimpleMeshDrawOpHelperWithStencil;
 
 public:
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          GrAAType aaType,
-                                          DrawQuad* quad,
-                                          const GrUserStencilSettings* stencilSettings,
-                                          Helper::InputFlags inputFlags) {
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            GrAAType aaType,
+                            DrawQuad* quad,
+                            const GrUserStencilSettings* stencilSettings,
+                            Helper::InputFlags inputFlags) {
         // Clean up deviations between aaType and edgeAA
         GrQuadUtils::ResolveAAType(aaType, quad->fEdgeFlags, quad->fDevice,
                                    &aaType, &quad->fEdgeFlags);
@@ -77,10 +77,10 @@
 
     // aaType is passed to Helper in the initializer list, so incongruities between aaType and
     // edgeFlags must be resolved prior to calling this constructor.
-    FillRectOp(Helper::MakeArgs args, SkPMColor4f paintColor, GrAAType aaType,
+    FillRectOp(GrProcessorSet* processorSet, SkPMColor4f paintColor, GrAAType aaType,
                DrawQuad* quad, const GrUserStencilSettings* stencil, Helper::InputFlags inputFlags)
             : INHERITED(ClassID())
-            , fHelper(args, aaType, stencil, inputFlags)
+            , fHelper(processorSet, aaType, stencil, inputFlags)
             , fQuads(1, !fHelper.isTrivial()) {
         // Set bounds before clipping so we don't have to worry about unioning the bounds of
         // the two potential quads (GrQuad::bounds() is perspective-safe).
@@ -457,34 +457,34 @@
 
 } // anonymous namespace
 
-std::unique_ptr<GrDrawOp> GrFillRectOp::Make(GrRecordingContext* context,
-                                             GrPaint&& paint,
-                                             GrAAType aaType,
-                                             DrawQuad* quad,
-                                             const GrUserStencilSettings* stencil,
-                                             InputFlags inputFlags) {
+GrOp::Owner GrFillRectOp::Make(GrRecordingContext* context,
+                               GrPaint&& paint,
+                               GrAAType aaType,
+                               DrawQuad* quad,
+                               const GrUserStencilSettings* stencil,
+                               InputFlags inputFlags) {
     return FillRectOp::Make(context, std::move(paint), aaType, std::move(quad), stencil,
                             inputFlags);
 }
 
-std::unique_ptr<GrDrawOp> GrFillRectOp::MakeNonAARect(GrRecordingContext* context,
-                                                      GrPaint&& paint,
-                                                      const SkMatrix& view,
-                                                      const SkRect& rect,
-                                                      const GrUserStencilSettings* stencil) {
+GrOp::Owner GrFillRectOp::MakeNonAARect(GrRecordingContext* context,
+                                        GrPaint&& paint,
+                                        const SkMatrix& view,
+                                        const SkRect& rect,
+                                        const GrUserStencilSettings* stencil) {
     DrawQuad quad{GrQuad::MakeFromRect(rect, view), GrQuad(rect), GrQuadAAFlags::kNone};
     return FillRectOp::Make(context, std::move(paint), GrAAType::kNone, &quad, stencil,
                             InputFlags::kNone);
 }
 
-std::unique_ptr<GrDrawOp> GrFillRectOp::MakeOp(GrRecordingContext* context,
-                                               GrPaint&& paint,
-                                               GrAAType aaType,
-                                               const SkMatrix& viewMatrix,
-                                               const GrRenderTargetContext::QuadSetEntry quads[],
-                                               int cnt,
-                                               const GrUserStencilSettings* stencilSettings,
-                                               int* numConsumed) {
+GrOp::Owner GrFillRectOp::MakeOp(GrRecordingContext* context,
+                                 GrPaint&& paint,
+                                 GrAAType aaType,
+                                 const SkMatrix& viewMatrix,
+                                 const GrRenderTargetContext::QuadSetEntry quads[],
+                                 int cnt,
+                                 const GrUserStencilSettings* stencilSettings,
+                                 int* numConsumed) {
     // First make a draw op for the first quad in the set
     SkASSERT(cnt > 0);
 
@@ -492,8 +492,8 @@
                   GrQuad::MakeFromRect(quads[0].fRect, quads[0].fLocalMatrix),
                   quads[0].fAAFlags};
     paint.setColor4f(quads[0].fColor);
-    std::unique_ptr<GrDrawOp> op = FillRectOp::Make(context, std::move(paint), aaType,
-                                                    &quad, stencilSettings, InputFlags::kNone);
+    GrOp::Owner op = FillRectOp::Make(context, std::move(paint), aaType,
+                                      &quad, stencilSettings, InputFlags::kNone);
     FillRectOp* fillRects = op->cast<FillRectOp>();
 
     *numConsumed = 1;
@@ -532,9 +532,9 @@
     while (numLeft) {
         int numConsumed = 0;
 
-        std::unique_ptr<GrDrawOp> op = MakeOp(context, GrPaint::Clone(paint), aaType, viewMatrix,
-                                              &quads[offset], numLeft, stencilSettings,
-                                              &numConsumed);
+        GrOp::Owner op = MakeOp(context, GrPaint::Clone(paint), aaType, viewMatrix,
+                                &quads[offset], numLeft, stencilSettings,
+                                &numConsumed);
 
         offset += numConsumed;
         numLeft -= numConsumed;
diff --git a/src/gpu/ops/GrFillRectOp.h b/src/gpu/ops/GrFillRectOp.h
index 4a8f211..8710861 100644
--- a/src/gpu/ops/GrFillRectOp.h
+++ b/src/gpu/ops/GrFillRectOp.h
@@ -30,21 +30,21 @@
 public:
     using InputFlags = GrSimpleMeshDrawOpHelper::InputFlags;
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          GrAAType aaType,
-                                          DrawQuad* quad,
-                                          const GrUserStencilSettings* stencil = nullptr,
-                                          InputFlags = InputFlags::kNone);
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            GrAAType aaType,
+                            DrawQuad* quad,
+                            const GrUserStencilSettings* stencil = nullptr,
+                            InputFlags = InputFlags::kNone);
 
     // Utility function to create a non-AA rect transformed by view. This is used commonly enough
     // in testing and GMs that manage ops without going through GrRTC that it's worth the
     // convenience.
-    static std::unique_ptr<GrDrawOp> MakeNonAARect(GrRecordingContext* context,
-                                                   GrPaint&& paint,
-                                                   const SkMatrix& view,
-                                                   const SkRect& rect,
-                                                   const GrUserStencilSettings* stencil = nullptr);
+    static GrOp::Owner MakeNonAARect(GrRecordingContext* context,
+                                     GrPaint&& paint,
+                                     const SkMatrix& view,
+                                     const SkRect& rect,
+                                     const GrUserStencilSettings* stencil = nullptr);
 
     // Bulk API for drawing quads with a single op
     // TODO(michaelludwig) - remove if the bulk API is not useful for SkiaRenderer
@@ -65,14 +65,14 @@
 private:
     // Create a GrFillRectOp that uses as many quads as possible from 'quads' w/o exceeding
     // any index buffer size limits.
-    static std::unique_ptr<GrDrawOp> MakeOp(GrRecordingContext*,
-                                            GrPaint&&,
-                                            GrAAType,
-                                            const SkMatrix& viewMatrix,
-                                            const GrRenderTargetContext::QuadSetEntry quads[],
-                                            int quadCount,
-                                            const GrUserStencilSettings*,
-                                            int* numConsumed);
+    static GrOp::Owner MakeOp(GrRecordingContext*,
+                              GrPaint&&,
+                              GrAAType,
+                              const SkMatrix& viewMatrix,
+                              const GrRenderTargetContext::QuadSetEntry quads[],
+                              int quadCount,
+                              const GrUserStencilSettings*,
+                              int* numConsumed);
 };
 
 #endif // GrFillRectOp_DEFINED
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 773e8d9..77e92b7 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -125,15 +125,15 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          GrSurfaceProxyView view,
-                                          SkAlphaType alphaType,
-                                          sk_sp<GrColorSpaceXform> colorSpaceXForm,
-                                          GrSamplerState::Filter filter,
-                                          std::unique_ptr<SkLatticeIter> iter,
-                                          const SkRect& dst) {
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            const SkMatrix& viewMatrix,
+                            GrSurfaceProxyView view,
+                            SkAlphaType alphaType,
+                            sk_sp<GrColorSpaceXform> colorSpaceXForm,
+                            GrSamplerState::Filter filter,
+                            std::unique_ptr<SkLatticeIter> iter,
+                            const SkRect& dst) {
         SkASSERT(view.proxy());
         return Helper::FactoryHelper<NonAALatticeOp>(context, std::move(paint), viewMatrix,
                                                      std::move(view), alphaType,
@@ -141,13 +141,13 @@
                                                      std::move(iter), dst);
     }
 
-    NonAALatticeOp(Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
+    NonAALatticeOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
                    const SkMatrix& viewMatrix, GrSurfaceProxyView view,
                    SkAlphaType alphaType, sk_sp<GrColorSpaceXform> colorSpaceXform,
                    GrSamplerState::Filter filter, std::unique_ptr<SkLatticeIter> iter,
                    const SkRect& dst)
             : INHERITED(ClassID())
-            , fHelper(helperArgs, GrAAType::kNone)
+            , fHelper(processorSet, GrAAType::kNone)
             , fView(std::move(view))
             , fAlphaType(alphaType)
             , fColorSpaceXform(std::move(colorSpaceXform))
@@ -366,15 +366,15 @@
 }  // anonymous namespace
 
 namespace GrLatticeOp {
-std::unique_ptr<GrDrawOp> MakeNonAA(GrRecordingContext* context,
-                                    GrPaint&& paint,
-                                    const SkMatrix& viewMatrix,
-                                    GrSurfaceProxyView view,
-                                    SkAlphaType alphaType,
-                                    sk_sp<GrColorSpaceXform> colorSpaceXform,
-                                    GrSamplerState::Filter filter,
-                                    std::unique_ptr<SkLatticeIter> iter,
-                                    const SkRect& dst) {
+GrOp::Owner MakeNonAA(GrRecordingContext* context,
+                      GrPaint&& paint,
+                      const SkMatrix& viewMatrix,
+                      GrSurfaceProxyView view,
+                      SkAlphaType alphaType,
+                      sk_sp<GrColorSpaceXform> colorSpaceXform,
+                      GrSamplerState::Filter filter,
+                      std::unique_ptr<SkLatticeIter> iter,
+                      const SkRect& dst) {
     return NonAALatticeOp::Make(context, std::move(paint), viewMatrix, std::move(view), alphaType,
                                 std::move(colorSpaceXform), filter, std::move(iter), dst);
 }
diff --git a/src/gpu/ops/GrLatticeOp.h b/src/gpu/ops/GrLatticeOp.h
index f77021f..9bceccf 100644
--- a/src/gpu/ops/GrLatticeOp.h
+++ b/src/gpu/ops/GrLatticeOp.h
@@ -22,15 +22,15 @@
 struct SkRect;
 
 namespace GrLatticeOp {
-std::unique_ptr<GrDrawOp> MakeNonAA(GrRecordingContext*,
-                                    GrPaint&&,
-                                    const SkMatrix& viewMatrix,
-                                    GrSurfaceProxyView view,
-                                    SkAlphaType alphaType,
-                                    sk_sp<GrColorSpaceXform>,
-                                    GrSamplerState::Filter,
-                                    std::unique_ptr<SkLatticeIter>,
-                                    const SkRect& dst);
+GrOp::Owner MakeNonAA(GrRecordingContext*,
+                      GrPaint&&,
+                      const SkMatrix& viewMatrix,
+                      GrSurfaceProxyView view,
+                      SkAlphaType alphaType,
+                      sk_sp<GrColorSpaceXform>,
+                      GrSamplerState::Filter,
+                      std::unique_ptr<SkLatticeIter>,
+                      const SkRect& dst);
 }  // namespace GrLatticeOp
 
 #endif
diff --git a/src/gpu/ops/GrOp.cpp b/src/gpu/ops/GrOp.cpp
index ee2bd11..e635d81 100644
--- a/src/gpu/ops/GrOp.cpp
+++ b/src/gpu/ops/GrOp.cpp
@@ -10,6 +10,15 @@
 std::atomic<uint32_t> GrOp::gCurrOpClassID {GrOp::kIllegalOpID + 1};
 std::atomic<uint32_t> GrOp::gCurrOpUniqueID{GrOp::kIllegalOpID + 1};
 
+#if !defined(GR_OP_ALLOCATE_USE_NEW)
+    void GrOp::DeleteFromPool::operator() (GrOp* op) {
+        if (op != nullptr) {
+            op->~GrOp();
+            fPool->release(op);
+        }
+    }
+#endif
+
 #if !defined(GR_OP_ALLOCATE_USE_NEW) && defined(SK_DEBUG)
     void* GrOp::operator new(size_t size) {
         // All GrOp-derived class should be allocated in a GrMemoryPool
@@ -43,7 +52,7 @@
     return result;
 }
 
-void GrOp::chainConcat(std::unique_ptr<GrOp> next) {
+void GrOp::chainConcat(GrOp::Owner next) {
     SkASSERT(next);
     SkASSERT(this->classID() == next->classID());
     SkASSERT(this->isChainTail());
@@ -52,7 +61,7 @@
     fNextInChain->fPrevInChain = this;
 }
 
-std::unique_ptr<GrOp> GrOp::cutChain() {
+GrOp::Owner GrOp::cutChain() {
     if (fNextInChain) {
         fNextInChain->fPrevInChain = nullptr;
         return std::move(fNextInChain);
diff --git a/src/gpu/ops/GrOp.h b/src/gpu/ops/GrOp.h
index f1372e4..15f3bb4 100644
--- a/src/gpu/ops/GrOp.h
+++ b/src/gpu/ops/GrOp.h
@@ -13,6 +13,8 @@
 #include "include/core/SkString.h"
 #include "include/gpu/GrRecordingContext.h"
 #include "src/gpu/GrGpuResource.h"
+#include "src/gpu/GrMemoryPool.h"
+#include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrTracing.h"
 #include "src/gpu/GrXferProcessor.h"
 #include <atomic>
@@ -22,6 +24,7 @@
 class GrCaps;
 class GrOpFlushState;
 class GrOpsRenderPass;
+class GrPaint;
 
 /**
  * GrOp is the base class for all Ganesh deferred GPU operations. To facilitate reordering and to
@@ -65,6 +68,46 @@
 
 class GrOp : private SkNoncopyable {
 public:
+    #if defined(GR_OP_ALLOCATE_USE_NEW)
+        using Owner = std::unique_ptr<GrOp>;
+    #else
+        struct DeleteFromPool {
+            DeleteFromPool() : fPool{nullptr} {}
+            DeleteFromPool(GrOpMemoryPool* pool) : fPool{pool} {}
+            void operator() (GrOp* op);
+            GrOpMemoryPool* fPool;
+        };
+        using Owner =  std::unique_ptr<GrOp, DeleteFromPool>;
+    #endif
+
+    template<typename Op, typename... Args>
+    static Owner Make(GrRecordingContext* context, Args&&... args) {
+        return MakeWithExtraMemory<Op>(context, 0, std::forward<Args>(args)...);
+    }
+
+    template<typename Op, typename... Args>
+    static Owner MakeWithProcessorSet(
+            GrRecordingContext* context, const SkPMColor4f& color,
+            GrPaint&& paint, Args&&... args);
+
+    #if defined(GR_OP_ALLOCATE_USE_NEW)
+        template<typename Op, typename... Args>
+            static Owner MakeWithExtraMemory(
+                    GrRecordingContext* context, size_t extraSize, Args&&... args) {
+                void* bytes = ::operator new(sizeof(Op) + extraSize);
+                return Owner{new (bytes) Op(std::forward<Args>(args)...)};
+            }
+    #else
+        template<typename Op, typename... Args>
+        static Owner MakeWithExtraMemory(
+                GrRecordingContext* context, size_t extraSize, Args&&... args) {
+            GrOpMemoryPool* pool = context->priv().opMemoryPool();
+            void* mem = pool->allocate(sizeof(Op) + extraSize);
+            GrOp* op = new (mem) Op(std::forward<Args>(args)...);
+            return Owner{op, pool};
+        }
+    #endif
+
     virtual ~GrOp() = default;
 
     virtual const char* name() const = 0;
@@ -226,7 +269,7 @@
      * Concatenates two op chains. This op must be a tail and the passed op must be a head. The ops
      * must be of the same subclass.
      */
-    void chainConcat(std::unique_ptr<GrOp>);
+    void chainConcat(GrOp::Owner);
     /** Returns true if this is the head of a chain (including a length 1 chain). */
     bool isChainHead() const { return !fPrevInChain; }
     /** Returns true if this is the tail of a chain (including a length 1 chain). */
@@ -239,7 +282,7 @@
      * Cuts the chain after this op. The returned op is the op that was previously next in the
      * chain or null if this was already a tail.
      */
-    std::unique_ptr<GrOp> cutChain();
+    GrOp::Owner cutChain();
     SkDEBUGCODE(void validateChain(GrOp* expectedTail = nullptr) const);
 
 #ifdef SK_DEBUG
@@ -336,7 +379,7 @@
         SkDEBUGCODE(kUninitialized_BoundsFlag   = 0x4)
     };
 
-    std::unique_ptr<GrOp>               fNextInChain;
+    Owner                             fNextInChain{nullptr};
     GrOp*                               fPrevInChain = nullptr;
     const uint16_t                      fClassID;
     uint16_t                            fBoundsFlags;
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index 051906e..9e00222 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -989,13 +989,13 @@
         bool fUseCenter;
     };
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          SkPoint center,
-                                          SkScalar radius,
-                                          const GrStyle& style,
-                                          const ArcParams* arcParams = nullptr) {
+    static GrOp::Owner Make(GrRecordingContext* 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()) {
             return nullptr;
@@ -1031,11 +1031,11 @@
                                                radius, style, arcParams);
     }
 
-    CircleOp(const Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
+    CircleOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
              const SkMatrix& viewMatrix, SkPoint center, SkScalar radius, const GrStyle& style,
              const ArcParams* arcParams)
             : GrMeshDrawOp(ClassID())
-            , fHelper(helperArgs, GrAAType::kCoverage) {
+            , fHelper(processorSet, GrAAType::kCoverage) {
         const SkStrokeRec& stroke = style.strokeRec();
         SkStrokeRec::Style recStyle = stroke.getStyle();
 
@@ -1488,16 +1488,16 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          SkPoint center,
-                                          SkScalar radius,
-                                          SkScalar strokeWidth,
-                                          SkScalar startAngle,
-                                          SkScalar onAngle,
-                                          SkScalar offAngle,
-                                          SkScalar phaseAngle) {
+    static GrOp::Owner Make(GrRecordingContext* 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>(context, std::move(paint), viewMatrix,
@@ -1505,12 +1505,12 @@
                                                             onAngle, offAngle, phaseAngle);
     }
 
-    ButtCapDashedCircleOp(const Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
+    ButtCapDashedCircleOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
                           const SkMatrix& viewMatrix, SkPoint center, SkScalar radius,
                           SkScalar strokeWidth, SkScalar startAngle, SkScalar onAngle,
                           SkScalar offAngle, SkScalar phaseAngle)
             : GrMeshDrawOp(ClassID())
-            , fHelper(helperArgs, GrAAType::kCoverage) {
+            , fHelper(processorSet, GrAAType::kCoverage) {
         SkASSERT(circle_stays_circle(viewMatrix));
         viewMatrix.mapPoints(&center, 1);
         radius = viewMatrix.mapRadius(radius);
@@ -1808,11 +1808,11 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          const SkRect& ellipse,
-                                          const SkStrokeRec& stroke) {
+    static GrOp::Owner Make(GrRecordingContext* 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());
@@ -1885,11 +1885,11 @@
                                                 params, stroke);
     }
 
-    EllipseOp(const Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
+    EllipseOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
               const SkMatrix& viewMatrix, const DeviceSpaceParams& params,
               const SkStrokeRec& stroke)
             : INHERITED(ClassID())
-            , fHelper(helperArgs, GrAAType::kCoverage)
+            , fHelper(processorSet, GrAAType::kCoverage)
             , fUseScale(false) {
         SkStrokeRec::Style style = stroke.getStyle();
         bool isStrokeOnly =
@@ -2092,11 +2092,11 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          const SkRect& ellipse,
-                                          const SkStrokeRec& stroke) {
+    static GrOp::Owner Make(GrRecordingContext* 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());
@@ -2164,10 +2164,10 @@
         return Helper::FactoryHelper<DIEllipseOp>(context, std::move(paint), params, viewMatrix);
     }
 
-    DIEllipseOp(Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
+    DIEllipseOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
                 const DeviceSpaceParams& params, const SkMatrix& viewMatrix)
             : INHERITED(ClassID())
-            , fHelper(helperArgs, GrAAType::kCoverage)
+            , fHelper(processorSet, GrAAType::kCoverage)
             , fUseScale(false) {
         // This expands the outer rect so that after CTM we end up with a half-pixel border
         SkScalar a = viewMatrix[SkMatrix::kMScaleX];
@@ -2476,23 +2476,23 @@
 
     // 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(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          const SkRect& devRect,
-                                          float devRadius,
-                                          float devStrokeWidth,
-                                          bool strokeOnly) {
+    static GrOp::Owner Make(GrRecordingContext* 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, const SkPMColor4f& color,
+    CircularRRectOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
                     const SkMatrix& viewMatrix, const SkRect& devRect, float devRadius,
                     float devStrokeWidth, bool strokeOnly)
             : INHERITED(ClassID())
             , fViewMatrixIfUsingLocalCoords(viewMatrix)
-            , fHelper(helperArgs, GrAAType::kCoverage) {
+            , fHelper(processorSet, GrAAType::kCoverage) {
         SkRect bounds = devRect;
         SkASSERT(!(devStrokeWidth <= 0 && strokeOnly));
         SkScalar innerRadius = 0.0f;
@@ -2838,14 +2838,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(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          const SkRect& devRect,
-                                          float devXRadius,
-                                          float devYRadius,
-                                          SkVector devStrokeWidths,
-                                          bool strokeOnly) {
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            const SkMatrix& viewMatrix,
+                            const SkRect& devRect,
+                            float devXRadius,
+                            float devYRadius,
+                            SkVector devStrokeWidths,
+                            bool strokeOnly) {
         SkASSERT(devXRadius >= 0.5 || strokeOnly);
         SkASSERT(devYRadius >= 0.5 || strokeOnly);
         SkASSERT((devStrokeWidths.fX > 0) == (devStrokeWidths.fY > 0));
@@ -2880,11 +2880,11 @@
                                                         strokeOnly);
     }
 
-    EllipticalRRectOp(Helper::MakeArgs helperArgs, const SkPMColor4f& color,
+    EllipticalRRectOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
                       const SkMatrix& viewMatrix, const SkRect& devRect, float devXRadius,
                       float devYRadius, SkVector devStrokeHalfWidths, bool strokeOnly)
             : INHERITED(ClassID())
-            , fHelper(helperArgs, GrAAType::kCoverage)
+            , fHelper(processorSet, GrAAType::kCoverage)
             , fUseScale(false) {
         SkScalar innerXRadius = 0.0f;
         SkScalar innerYRadius = 0.0f;
@@ -3116,12 +3116,12 @@
     using INHERITED = GrMeshDrawOp;
 };
 
-std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeCircularRRectOp(GrRecordingContext* context,
-                                                               GrPaint&& paint,
-                                                               const SkMatrix& viewMatrix,
-                                                               const SkRRect& rrect,
-                                                               const SkStrokeRec& stroke,
-                                                               const GrShaderCaps* shaderCaps) {
+GrOp::Owner GrOvalOpFactory::MakeCircularRRectOp(GrRecordingContext* context,
+                                                 GrPaint&& paint,
+                                                 const SkMatrix& viewMatrix,
+                                                 const SkRRect& rrect,
+                                                 const SkStrokeRec& stroke,
+                                                 const GrShaderCaps* shaderCaps) {
     SkASSERT(viewMatrix.rectStaysRect());
     SkASSERT(viewMatrix.isSimilarity());
     SkASSERT(rrect.isSimple());
@@ -3169,11 +3169,11 @@
                                  scaledStroke, isStrokeOnly);
 }
 
-static std::unique_ptr<GrDrawOp> make_rrect_op(GrRecordingContext* context,
-                                               GrPaint&& paint,
-                                               const SkMatrix& viewMatrix,
-                                               const SkRRect& rrect,
-                                               const SkStrokeRec& stroke) {
+GrOp::Owner make_rrect_op(GrRecordingContext* context,
+                          GrPaint&& paint,
+                          const SkMatrix& viewMatrix,
+                          const SkRRect& rrect,
+                          const SkStrokeRec& stroke) {
     SkASSERT(viewMatrix.rectStaysRect());
     SkASSERT(rrect.isSimple());
     SkASSERT(!rrect.isOval());
@@ -3237,12 +3237,12 @@
                                    xRadius, yRadius, scaledStroke, isStrokeOnly);
 }
 
-std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeRRectOp(GrRecordingContext* context,
-                                                       GrPaint&& paint,
-                                                       const SkMatrix& viewMatrix,
-                                                       const SkRRect& rrect,
-                                                       const SkStrokeRec& stroke,
-                                                       const GrShaderCaps* shaderCaps) {
+GrOp::Owner GrOvalOpFactory::MakeRRectOp(GrRecordingContext* context,
+                                         GrPaint&& paint,
+                                         const SkMatrix& viewMatrix,
+                                         const SkRRect& rrect,
+                                         const SkStrokeRec& stroke,
+                                         const GrShaderCaps* shaderCaps) {
     if (rrect.isOval()) {
         return MakeOvalOp(context, std::move(paint), viewMatrix, rrect.getBounds(),
                           GrStyle(stroke, nullptr), shaderCaps);
@@ -3257,12 +3257,12 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeCircleOp(GrRecordingContext* context,
-                                                        GrPaint&& paint,
-                                                        const SkMatrix& viewMatrix,
-                                                        const SkRect& oval,
-                                                        const GrStyle& style,
-                                                        const GrShaderCaps* shaderCaps) {
+GrOp::Owner GrOvalOpFactory::MakeCircleOp(GrRecordingContext* context,
+                                          GrPaint&& paint,
+                                          const SkMatrix& viewMatrix,
+                                          const SkRect& oval,
+                                          const GrStyle& style,
+                                          const GrShaderCaps* shaderCaps) {
     SkScalar width = oval.width();
     SkASSERT(width > SK_ScalarNearlyZero && SkScalarNearlyEqual(width, oval.height()) &&
              circle_stays_circle(viewMatrix));
@@ -3299,12 +3299,12 @@
     return CircleOp::Make(context, std::move(paint), viewMatrix, center, r, style);
 }
 
-std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeOvalOp(GrRecordingContext* context,
-                                                      GrPaint&& paint,
-                                                      const SkMatrix& viewMatrix,
-                                                      const SkRect& oval,
-                                                      const GrStyle& style,
-                                                      const GrShaderCaps* shaderCaps) {
+GrOp::Owner GrOvalOpFactory::MakeOvalOp(GrRecordingContext* context,
+                                        GrPaint&& paint,
+                                        const SkMatrix& viewMatrix,
+                                        const SkRect& oval,
+                                        const GrStyle& style,
+                                        const GrShaderCaps* shaderCaps) {
     // we can draw circles
     SkScalar width = oval.width();
     if (width > SK_ScalarNearlyZero && SkScalarNearlyEqual(width, oval.height()) &&
@@ -3339,13 +3339,13 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeArcOp(GrRecordingContext* context,
-                                                     GrPaint&& paint,
-                                                     const SkMatrix& viewMatrix,
-                                                     const SkRect& oval, SkScalar startAngle,
-                                                     SkScalar sweepAngle, bool useCenter,
-                                                     const GrStyle& style,
-                                                     const GrShaderCaps* shaderCaps) {
+GrOp::Owner GrOvalOpFactory::MakeArcOp(GrRecordingContext* context,
+                                       GrPaint&& paint,
+                                       const SkMatrix& viewMatrix,
+                                       const SkRect& oval, SkScalar startAngle,
+                                       SkScalar sweepAngle, bool useCenter,
+                                       const GrStyle& style,
+                                       const GrShaderCaps* shaderCaps) {
     SkASSERT(!oval.isEmpty());
     SkASSERT(sweepAngle);
     SkScalar width = oval.width();
@@ -3391,9 +3391,9 @@
             arcParamsTmp.fUseCenter = random->nextBool();
             arcParams = &arcParamsTmp;
         }
-        std::unique_ptr<GrDrawOp> op = CircleOp::Make(context, std::move(paint), viewMatrix,
-                                                      center, radius,
-                                                      GrStyle(stroke, nullptr), arcParams);
+        GrOp::Owner op = CircleOp::Make(context, std::move(paint), viewMatrix,
+                                        center, radius,
+                                        GrStyle(stroke, nullptr), arcParams);
         if (op) {
             return op;
         }
@@ -3459,7 +3459,7 @@
         if (rrect.isOval()) {
             continue;
         }
-        std::unique_ptr<GrDrawOp> op =
+        GrOp::Owner op =
                 GrOvalOpFactory::MakeCircularRRectOp(context, std::move(paint), viewMatrix, rrect,
                                                      GrTest::TestStrokeRec(random), nullptr);
         if (op) {
diff --git a/src/gpu/ops/GrOvalOpFactory.h b/src/gpu/ops/GrOvalOpFactory.h
index de25fa1..047679e 100644
--- a/src/gpu/ops/GrOvalOpFactory.h
+++ b/src/gpu/ops/GrOvalOpFactory.h
@@ -26,43 +26,43 @@
  */
 class GrOvalOpFactory {
 public:
-    static std::unique_ptr<GrDrawOp> MakeCircleOp(GrRecordingContext*,
-                                                  GrPaint&&,
-                                                  const SkMatrix&,
-                                                  const SkRect& oval,
-                                                  const GrStyle& style,
-                                                  const GrShaderCaps*);
+    static GrOp::Owner MakeCircleOp(GrRecordingContext*,
+                                    GrPaint&&,
+                                    const SkMatrix&,
+                                    const SkRect& oval,
+                                    const GrStyle& style,
+                                    const GrShaderCaps*);
 
-    static std::unique_ptr<GrDrawOp> MakeOvalOp(GrRecordingContext*,
-                                                GrPaint&&,
-                                                const SkMatrix&,
-                                                const SkRect& oval,
-                                                const GrStyle& style,
-                                                const GrShaderCaps*);
+    static GrOp::Owner MakeOvalOp(GrRecordingContext*,
+                                  GrPaint&&,
+                                  const SkMatrix&,
+                                  const SkRect& oval,
+                                  const GrStyle& style,
+                                  const GrShaderCaps*);
 
-    static std::unique_ptr<GrDrawOp> MakeCircularRRectOp(GrRecordingContext*,
-                                                         GrPaint&&,
-                                                         const SkMatrix&,
-                                                         const SkRRect&,
-                                                         const SkStrokeRec&,
-                                                         const GrShaderCaps*);
+    static GrOp::Owner MakeCircularRRectOp(GrRecordingContext*,
+                                           GrPaint&&,
+                                           const SkMatrix&,
+                                           const SkRRect&,
+                                           const SkStrokeRec&,
+                                           const GrShaderCaps*);
 
-    static std::unique_ptr<GrDrawOp> MakeRRectOp(GrRecordingContext*,
-                                                 GrPaint&&,
-                                                 const SkMatrix&,
-                                                 const SkRRect&,
-                                                 const SkStrokeRec&,
-                                                 const GrShaderCaps*);
+    static GrOp::Owner MakeRRectOp(GrRecordingContext*,
+                                   GrPaint&&,
+                                   const SkMatrix&,
+                                   const SkRRect&,
+                                   const SkStrokeRec&,
+                                   const GrShaderCaps*);
 
-    static std::unique_ptr<GrDrawOp> MakeArcOp(GrRecordingContext*,
-                                               GrPaint&&,
-                                               const SkMatrix&,
-                                               const SkRect& oval,
-                                               SkScalar startAngle,
-                                               SkScalar sweepAngle,
-                                               bool useCenter,
-                                               const GrStyle&,
-                                               const GrShaderCaps*);
+    static GrOp::Owner MakeArcOp(GrRecordingContext*,
+                                 GrPaint&&,
+                                 const SkMatrix&,
+                                 const SkRect& oval,
+                                 SkScalar startAngle,
+                                 SkScalar sweepAngle,
+                                 bool useCenter,
+                                 const GrStyle&,
+                                 const GrShaderCaps*);
 };
 
 #endif  // GrOvalOpFactory_DEFINED
diff --git a/src/gpu/ops/GrRegionOp.cpp b/src/gpu/ops/GrRegionOp.cpp
index 91983ea..b5ee30e 100644
--- a/src/gpu/ops/GrRegionOp.cpp
+++ b/src/gpu/ops/GrRegionOp.cpp
@@ -38,21 +38,21 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          const SkRegion& region,
-                                          GrAAType aaType,
-                                          const GrUserStencilSettings* stencilSettings = nullptr) {
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            const SkMatrix& viewMatrix,
+                            const SkRegion& region,
+                            GrAAType aaType,
+                            const GrUserStencilSettings* stencilSettings = nullptr) {
         return Helper::FactoryHelper<RegionOp>(context, std::move(paint), viewMatrix, region,
                                                aaType, stencilSettings);
     }
 
-    RegionOp(const Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
+    RegionOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
              const SkMatrix& viewMatrix, const SkRegion& region, GrAAType aaType,
              const GrUserStencilSettings* stencilSettings)
             : INHERITED(ClassID())
-            , fHelper(helperArgs, aaType, stencilSettings)
+            , fHelper(processorSet, aaType, stencilSettings)
             , fViewMatrix(viewMatrix) {
         RegionInfo& info = fRegions.push_back();
         info.fColor = color;
@@ -201,12 +201,12 @@
 
 namespace GrRegionOp {
 
-std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                               GrPaint&& paint,
-                               const SkMatrix& viewMatrix,
-                               const SkRegion& region,
-                               GrAAType aaType,
-                               const GrUserStencilSettings* stencilSettings) {
+GrOp::Owner Make(GrRecordingContext* context,
+                 GrPaint&& paint,
+                 const SkMatrix& viewMatrix,
+                 const SkRegion& region,
+                 GrAAType aaType,
+                 const GrUserStencilSettings* stencilSettings) {
     if (aaType != GrAAType::kNone && aaType != GrAAType::kMSAA) {
         return nullptr;
     }
diff --git a/src/gpu/ops/GrRegionOp.h b/src/gpu/ops/GrRegionOp.h
index 2502d3e..0900a23 100644
--- a/src/gpu/ops/GrRegionOp.h
+++ b/src/gpu/ops/GrRegionOp.h
@@ -9,6 +9,7 @@
 #define GrRegionOp_DEFINED
 
 #include "include/private/GrTypesPriv.h"
+#include "src/gpu/ops/GrOp.h"
 
 class GrDrawOp;
 class GrRecordingContext;
@@ -19,12 +20,12 @@
 
 namespace GrRegionOp {
 /** GrAAType must be kNone or kMSAA. */
-std::unique_ptr<GrDrawOp> Make(GrRecordingContext*,
-                               GrPaint&&,
-                               const SkMatrix& viewMatrix,
-                               const SkRegion&,
-                               GrAAType,
-                               const GrUserStencilSettings* stencilSettings = nullptr);
+GrOp::Owner Make(GrRecordingContext*,
+                 GrPaint&&,
+                 const SkMatrix& viewMatrix,
+                 const SkRegion&,
+                 GrAAType,
+                 const GrUserStencilSettings* stencilSettings = nullptr);
 }  // namespace GrRegionOp
 
 #endif
diff --git a/src/gpu/ops/GrShadowRRectOp.cpp b/src/gpu/ops/GrShadowRRectOp.cpp
index 65ff5a2..e9910f6 100644
--- a/src/gpu/ops/GrShadowRRectOp.cpp
+++ b/src/gpu/ops/GrShadowRRectOp.cpp
@@ -703,12 +703,12 @@
 }
 
 
-std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                               GrColor color,
-                               const SkMatrix& viewMatrix,
-                               const SkRRect& rrect,
-                               SkScalar blurWidth,
-                               SkScalar insetWidth) {
+GrOp::Owner Make(GrRecordingContext* context,
+                 GrColor color,
+                 const SkMatrix& viewMatrix,
+                 const SkRRect& rrect,
+                 SkScalar blurWidth,
+                 SkScalar insetWidth) {
     // Shadow rrect ops only handle simple circular rrects.
     SkASSERT(viewMatrix.isSimilarity() && SkRRectPriv::EqualRadii(rrect));
 
@@ -732,14 +732,14 @@
         return nullptr;
     }
 
-    GrOpMemoryPool* pool = context->priv().opMemoryPool();
-
-    return pool->allocate<ShadowCircularRRectOp>(color, bounds,
-                                                 scaledRadius,
-                                                 rrect.isOval(),
-                                                 blurWidth,
-                                                 scaledInsetWidth,
-                                                 std::move(falloffView));
+    return GrOp::Make<ShadowCircularRRectOp>(context,
+                                             color,
+                                             bounds,
+                                             scaledRadius,
+                                             rrect.isOval(),
+                                             blurWidth,
+                                             scaledInsetWidth,
+                                             std::move(falloffView));
 }
 }  // namespace GrShadowRRectOp
 
diff --git a/src/gpu/ops/GrShadowRRectOp.h b/src/gpu/ops/GrShadowRRectOp.h
index 964c158..be5557c 100644
--- a/src/gpu/ops/GrShadowRRectOp.h
+++ b/src/gpu/ops/GrShadowRRectOp.h
@@ -10,6 +10,7 @@
 
 #include <memory>
 #include "src/gpu/GrColor.h"
+#include "src/gpu/ops/GrOp.h"
 
 class GrDrawOp;
 class GrRecordingContext;
@@ -19,12 +20,12 @@
 
 namespace GrShadowRRectOp {
 
-std::unique_ptr<GrDrawOp> Make(GrRecordingContext*,
-                               GrColor,
-                               const SkMatrix& viewMatrix,
-                               const SkRRect&,
-                               SkScalar blurWidth,
-                               SkScalar insetWidth);
+GrOp::Owner Make(GrRecordingContext*,
+                 GrColor,
+                 const SkMatrix& viewMatrix,
+                 const SkRRect&,
+                 SkScalar blurWidth,
+                 SkScalar insetWidth);
 }  // namespace GrShadowRRectOp
 
 #endif
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp b/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp
index 23bc438..d52f51e 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp
@@ -13,10 +13,10 @@
 #include "src/gpu/geometry/GrRect.h"
 #include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
 
-GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(const MakeArgs& args,
+GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(GrProcessorSet* processorSet,
                                                    GrAAType aaType,
                                                    InputFlags inputFlags)
-        : fProcessors(args.fProcessorSet)
+        : fProcessors(processorSet)
         , fPipelineFlags((GrPipeline::InputFlags)inputFlags)
         , fAAType((int)aaType)
         , fUsesLocalCoords(false)
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
index feabe94..b016050 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
@@ -14,6 +14,7 @@
 #include "src/gpu/GrPipeline.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/ops/GrMeshDrawOp.h"
+#include "src/gpu/ops/GrOp.h"
 #include <new>
 
 struct SkRect;
@@ -26,17 +27,14 @@
  */
 class GrSimpleMeshDrawOpHelper {
 public:
-    struct MakeArgs;
-
     /**
      * This can be used by a Op class to perform allocation and initialization such that a
      * GrProcessorSet (if required) is allocated as part of the the same allocation that as
      * the Op instance. It requires that Op implements a constructor of the form:
-     *      Op(MakeArgs, GrColor, OpArgs...)
-     * which is public or made accessible via 'friend'.
+     *      Op(ProcessorSet*, GrColor, OpArgs...).
      */
     template <typename Op, typename... OpArgs>
-    static std::unique_ptr<GrDrawOp> FactoryHelper(GrRecordingContext*, GrPaint&&, OpArgs&&...);
+    static GrOp::Owner FactoryHelper(GrRecordingContext*, GrPaint&&, OpArgs&&...);
 
     // Here we allow callers to specify a subset of the GrPipeline::InputFlags upon creation.
     enum class InputFlags : uint8_t {
@@ -46,7 +44,7 @@
     };
     GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(InputFlags);
 
-    GrSimpleMeshDrawOpHelper(const MakeArgs&, GrAAType, InputFlags = InputFlags::kNone);
+    GrSimpleMeshDrawOpHelper(GrProcessorSet*, GrAAType, InputFlags = InputFlags::kNone);
     ~GrSimpleMeshDrawOpHelper();
 
     GrSimpleMeshDrawOpHelper() = delete;
@@ -99,15 +97,6 @@
 
     bool compatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
 
-    struct MakeArgs {
-    private:
-        MakeArgs() = default;
-
-        GrProcessorSet* fProcessorSet;
-
-        friend class GrSimpleMeshDrawOpHelper;
-    };
-
     void visitProxies(const GrOp::VisitProxyFunc& func) const {
         if (fProcessors) {
             fProcessors->visitProxies(func);
@@ -200,33 +189,34 @@
     SkDEBUGCODE(unsigned fDidAnalysis : 1;)
 };
 
-template <typename Op, typename... OpArgs>
-std::unique_ptr<GrDrawOp> GrSimpleMeshDrawOpHelper::FactoryHelper(GrRecordingContext* context,
-                                                                  GrPaint&& paint,
-                                                                  OpArgs&&... opArgs) {
+template<typename Op, typename... Args>
+GrOp::Owner GrOp::MakeWithProcessorSet(
+        GrRecordingContext* context, const SkPMColor4f& color,
+        GrPaint&& paint, Args&&... args) {
+#if defined(GR_OP_ALLOCATE_USE_NEW)
+    char* bytes = (char*)::operator new(sizeof(Op) + sizeof(GrProcessorSet));
+    char* setMem = bytes + sizeof(Op);
+    GrProcessorSet* processorSet = new (setMem)  GrProcessorSet{std::move(paint)};
+    return Owner{new (bytes) Op(processorSet, color, std::forward<Args>(args)...)};
+#else
     GrOpMemoryPool* pool = context->priv().opMemoryPool();
+    char* bytes = (char*)pool->allocate(sizeof(Op) + sizeof(GrProcessorSet));
+    char* setMem = bytes + sizeof(Op);
+    GrProcessorSet* processorSet = new (setMem)  GrProcessorSet{std::move(paint)};
+    return Owner{new (bytes) Op(processorSet, color, std::forward<Args>(args)...), pool};
+#endif
+}
 
-    MakeArgs makeArgs;
-
+template <typename Op, typename... OpArgs>
+GrOp::Owner GrSimpleMeshDrawOpHelper::FactoryHelper(GrRecordingContext* context,
+                                                    GrPaint&& paint,
+                                                    OpArgs&& ... opArgs) {
+    auto color = paint.getColor4f();
     if (paint.isTrivial()) {
-        makeArgs.fProcessorSet = nullptr;
-        return pool->allocate<Op>(makeArgs, paint.getColor4f(), std::forward<OpArgs>(opArgs)...);
+        return GrOp::Make<Op>(context, nullptr, color, std::forward<OpArgs>(opArgs)...);
     } else {
-        #if defined(GR_OP_ALLOCATE_USE_NEW)
-            char* mem = (char*) ::operator new(sizeof(Op) + sizeof(GrProcessorSet));
-            char* setMem = mem + sizeof(Op);
-            auto color = paint.getColor4f();
-            makeArgs.fProcessorSet = new (setMem) GrProcessorSet(std::move(paint));
-            GrDrawOp* op = new (mem) Op(makeArgs, color, std::forward<OpArgs>(opArgs)...);
-            return std::unique_ptr<GrDrawOp>(op);
-        #else
-            char* mem = (char*) pool->allocate(sizeof(Op) + sizeof(GrProcessorSet));
-            char* setMem = mem + sizeof(Op);
-            auto color = paint.getColor4f();
-            makeArgs.fProcessorSet = new (setMem) GrProcessorSet(std::move(paint));
-            return std::unique_ptr<GrDrawOp>(new (mem) Op(makeArgs, color,
-                                                          std::forward<OpArgs>(opArgs)...));
-        #endif
+        return GrOp::MakeWithProcessorSet<Op>(
+                context, color, std::move(paint), std::forward<OpArgs>(opArgs)...);
     }
 }
 
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.cpp b/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.cpp
index bc8353f..0d3e8ed 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.cpp
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.cpp
@@ -8,11 +8,11 @@
 #include "src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.h"
 
 GrSimpleMeshDrawOpHelperWithStencil::GrSimpleMeshDrawOpHelperWithStencil(
-                                                    const MakeArgs& args,
+                                                    GrProcessorSet* processorSet,
                                                     GrAAType aaType,
                                                     const GrUserStencilSettings* stencilSettings,
                                                     InputFlags inputFlags)
-        : INHERITED(args, aaType, inputFlags)
+        : INHERITED(processorSet, aaType, inputFlags)
         , fStencilSettings(stencilSettings ? stencilSettings : &GrUserStencilSettings::kUnused) {}
 
 GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelperWithStencil::fixedFunctionFlags() const {
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.h b/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.h
index 2036ae8..c86ba14 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.h
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.h
@@ -17,7 +17,6 @@
  */
 class GrSimpleMeshDrawOpHelperWithStencil : private GrSimpleMeshDrawOpHelper {
 public:
-    using MakeArgs = GrSimpleMeshDrawOpHelper::MakeArgs;
     using InputFlags = GrSimpleMeshDrawOpHelper::InputFlags;
 
     using GrSimpleMeshDrawOpHelper::visitProxies;
@@ -34,13 +33,13 @@
 
     // 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(GrRecordingContext* context, GrPaint&& paint,
-                                                   OpArgs... opArgs) {
+    static GrOp::Owner FactoryHelper(GrRecordingContext* context, GrPaint&& paint,
+                                     OpArgs... opArgs) {
         return GrSimpleMeshDrawOpHelper::FactoryHelper<Op, OpArgs...>(
                 context, std::move(paint), std::forward<OpArgs>(opArgs)...);
     }
 
-    GrSimpleMeshDrawOpHelperWithStencil(const MakeArgs&, GrAAType, const GrUserStencilSettings*,
+    GrSimpleMeshDrawOpHelperWithStencil(GrProcessorSet*, GrAAType, const GrUserStencilSettings*,
                                         InputFlags = InputFlags::kNone);
 
     GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const;
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index e87cdd2..c0e4d93 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -97,21 +97,21 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const GrStyledShape& shape,
-                                          const SkMatrix& viewMatrix,
-                                          bool gammaCorrect,
-                                          const GrUserStencilSettings* stencilSettings) {
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            const GrStyledShape& shape,
+                            const SkMatrix& viewMatrix,
+                            bool gammaCorrect,
+                            const GrUserStencilSettings* stencilSettings) {
         return Helper::FactoryHelper<SmallPathOp>(context, std::move(paint), shape, viewMatrix,
                                                   gammaCorrect, stencilSettings);
     }
 
-    SmallPathOp(Helper::MakeArgs helperArgs, const SkPMColor4f& color, const GrStyledShape& shape,
+    SmallPathOp(GrProcessorSet* processorSet, const SkPMColor4f& color, const GrStyledShape& shape,
                 const SkMatrix& viewMatrix, bool gammaCorrect,
                 const GrUserStencilSettings* stencilSettings)
             : INHERITED(ClassID())
-            , fHelper(helperArgs, GrAAType::kCoverage, stencilSettings) {
+            , fHelper(processorSet, GrAAType::kCoverage, stencilSettings) {
         SkASSERT(shape.hasUnstyledKey());
         // Compute bounds
         this->setTransformedBounds(shape.bounds(), viewMatrix, HasAABloat::kYes, IsHairline::kNo);
@@ -694,7 +694,7 @@
     SkASSERT(!args.fShape->isEmpty());
     SkASSERT(args.fShape->hasUnstyledKey());
 
-    std::unique_ptr<GrDrawOp> op = SmallPathOp::Make(
+    GrOp::Owner op = SmallPathOp::Make(
             args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix,
             args.fGammaCorrect, args.fUserStencilSettings);
     args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
@@ -705,14 +705,14 @@
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #if GR_TEST_UTILS
-std::unique_ptr<GrDrawOp> GrSmallPathRenderer::createOp_TestingOnly(
-                                                        GrRecordingContext* context,
-                                                        GrPaint&& paint,
-                                                        const GrStyledShape& shape,
-                                                        const SkMatrix& viewMatrix,
-                                                        bool gammaCorrect,
-                                                        const GrUserStencilSettings* stencil) {
 
+GrOp::Owner GrSmallPathRenderer::createOp_TestingOnly(
+        GrRecordingContext* context,
+        GrPaint&& paint,
+        const GrStyledShape& shape,
+        const SkMatrix& viewMatrix,
+        bool gammaCorrect,
+        const GrUserStencilSettings* stencil) {
     return GrSmallPathRenderer::SmallPathOp::Make(context, std::move(paint), shape, viewMatrix,
                                                   gammaCorrect, stencil);
 }
diff --git a/src/gpu/ops/GrSmallPathRenderer.h b/src/gpu/ops/GrSmallPathRenderer.h
index fdbdc6f..0d8615b 100644
--- a/src/gpu/ops/GrSmallPathRenderer.h
+++ b/src/gpu/ops/GrSmallPathRenderer.h
@@ -9,6 +9,7 @@
 #define GrSmallPathRenderer_DEFINED
 
 #include "src/gpu/GrPathRenderer.h"
+#include "src/gpu/ops/GrOp.h"
 
 class GrDrawOp;
 class GrRecordingContext;
@@ -21,12 +22,12 @@
 
     const char* name() const final { return "Small"; }
 
-    static std::unique_ptr<GrDrawOp> createOp_TestingOnly(GrRecordingContext*,
-                                                          GrPaint&&,
-                                                          const GrStyledShape&,
-                                                          const SkMatrix& viewMatrix,
-                                                          bool gammaCorrect,
-                                                          const GrUserStencilSettings*);
+    static GrOp::Owner createOp_TestingOnly(GrRecordingContext*,
+                                            GrPaint&&,
+                                            const GrStyledShape&,
+                                            const SkMatrix& viewMatrix,
+                                            bool gammaCorrect,
+                                            const GrUserStencilSettings*);
 
 private:
     class SmallPathOp;
diff --git a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
index 517bf29..a5fe212 100644
--- a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
@@ -179,7 +179,7 @@
                     coverMatrix, coverBounds, &localMatrix);
         }
     } else {
-        std::unique_ptr<GrDrawOp> op = GrDrawPathOp::Make(
+        GrOp::Owner op = GrDrawPathOp::Make(
                 args.fContext, viewMatrix, std::move(args.fPaint),
                 GrAA(stencilAAType == GrAAType::kMSAA), std::move(path));
         args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
diff --git a/src/gpu/ops/GrStencilPathOp.cpp b/src/gpu/ops/GrStencilPathOp.cpp
index 4567af5..39c7c1b 100644
--- a/src/gpu/ops/GrStencilPathOp.cpp
+++ b/src/gpu/ops/GrStencilPathOp.cpp
@@ -14,16 +14,14 @@
 #include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrRenderTarget.h"
 
-std::unique_ptr<GrOp> GrStencilPathOp::Make(GrRecordingContext* context,
-                                            const SkMatrix& viewMatrix,
-                                            bool useHWAA,
-                                            bool hasStencilClip,
-                                            const GrScissorState& scissor,
-                                            sk_sp<const GrPath> path) {
-    GrOpMemoryPool* pool = context->priv().opMemoryPool();
-
-    return pool->allocate<GrStencilPathOp>(viewMatrix, useHWAA,
-                                           hasStencilClip, scissor, std::move(path));
+GrOp::Owner GrStencilPathOp::Make(GrRecordingContext* context,
+                                  const SkMatrix& viewMatrix,
+                                  bool useHWAA,
+                                  bool hasStencilClip,
+                                  const GrScissorState& scissor,
+                                  sk_sp<const GrPath> path) {
+    return GrOp::Make<GrStencilPathOp>(context, viewMatrix, useHWAA,
+                                       hasStencilClip, scissor, std::move(path));
 }
 
 void GrStencilPathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
diff --git a/src/gpu/ops/GrStencilPathOp.h b/src/gpu/ops/GrStencilPathOp.h
index dca6866..b7c680f 100644
--- a/src/gpu/ops/GrStencilPathOp.h
+++ b/src/gpu/ops/GrStencilPathOp.h
@@ -21,17 +21,17 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrOp> Make(GrRecordingContext* context,
-                                      const SkMatrix& viewMatrix,
-                                      bool useHWAA,
-                                      bool hasStencilClip,
-                                      const GrScissorState& scissor,
-                                      sk_sp<const GrPath> path);
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            const SkMatrix& viewMatrix,
+                            bool useHWAA,
+                            bool hasStencilClip,
+                            const GrScissorState& scissor,
+                            sk_sp<const GrPath> path);
 
     const char* name() const override { return "StencilPathOp"; }
 
 private:
-    friend class GrOpMemoryPool; // for ctor
+    friend class GrOp; // for ctor
 
     GrStencilPathOp(const SkMatrix& viewMatrix,
                     bool useHWAA,
diff --git a/src/gpu/ops/GrStrokeRectOp.cpp b/src/gpu/ops/GrStrokeRectOp.cpp
index e7a5ba8..2dc2097 100644
--- a/src/gpu/ops/GrStrokeRectOp.cpp
+++ b/src/gpu/ops/GrStrokeRectOp.cpp
@@ -99,12 +99,12 @@
         }
     }
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          const SkRect& rect,
-                                          const SkStrokeRec& stroke,
-                                          GrAAType aaType) {
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            const SkMatrix& viewMatrix,
+                            const SkRect& rect,
+                            const SkStrokeRec& stroke,
+                            GrAAType aaType) {
         bool isMiter;
         if (!allowed_stroke(stroke, GrAA::kNo, &isMiter)) {
             return nullptr;
@@ -121,11 +121,11 @@
                                                         stroke, aaType);
     }
 
-    NonAAStrokeRectOp(const Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
+    NonAAStrokeRectOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
                       Helper::InputFlags inputFlags, const SkMatrix& viewMatrix, const SkRect& rect,
                       const SkStrokeRec& stroke, GrAAType aaType)
             : INHERITED(ClassID())
-            , fHelper(helperArgs, aaType, inputFlags) {
+            , fHelper(processorSet, aaType, inputFlags) {
         fColor = color;
         fViewMatrix = viewMatrix;
         fRect = rect;
@@ -355,21 +355,21 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          const SkRect& devOutside,
-                                          const SkRect& devInside,
-                                          const SkVector& devHalfStrokeSize) {
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            const SkMatrix& viewMatrix,
+                            const SkRect& devOutside,
+                            const SkRect& devInside,
+                            const SkVector& devHalfStrokeSize) {
         return Helper::FactoryHelper<AAStrokeRectOp>(context, std::move(paint), viewMatrix,
                                                      devOutside, devInside, devHalfStrokeSize);
     }
 
-    AAStrokeRectOp(const Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
+    AAStrokeRectOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
                    const SkMatrix& viewMatrix, const SkRect& devOutside, const SkRect& devInside,
                    const SkVector& devHalfStrokeSize)
             : INHERITED(ClassID())
-            , fHelper(helperArgs, GrAAType::kCoverage)
+            , fHelper(processorSet, GrAAType::kCoverage)
             , fViewMatrix(viewMatrix) {
         SkASSERT(!devOutside.isEmpty());
         SkASSERT(!devInside.isEmpty());
@@ -379,11 +379,11 @@
         fMiterStroke = true;
     }
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const SkMatrix& viewMatrix,
-                                          const SkRect& rect,
-                                          const SkStrokeRec& stroke) {
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            const SkMatrix& viewMatrix,
+                            const SkRect& rect,
+                            const SkStrokeRec& stroke) {
         bool isMiter;
         if (!allowed_stroke(stroke, GrAA::kYes, &isMiter)) {
             return nullptr;
@@ -392,11 +392,11 @@
                                                      stroke, isMiter);
     }
 
-    AAStrokeRectOp(const Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
+    AAStrokeRectOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
                    const SkMatrix& viewMatrix, const SkRect& rect, const SkStrokeRec& stroke,
                    bool isMiter)
             : INHERITED(ClassID())
-            , fHelper(helperArgs, GrAAType::kCoverage)
+            , fHelper(processorSet, GrAAType::kCoverage)
             , fViewMatrix(viewMatrix) {
         fMiterStroke = isMiter;
         RectInfo& info = fRects.push_back();
@@ -825,12 +825,12 @@
 
 namespace GrStrokeRectOp {
 
-std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                               GrPaint&& paint,
-                               GrAAType aaType,
-                               const SkMatrix& viewMatrix,
-                               const SkRect& rect,
-                               const SkStrokeRec& stroke) {
+GrOp::Owner Make(GrRecordingContext* context,
+                 GrPaint&& paint,
+                 GrAAType aaType,
+                 const SkMatrix& viewMatrix,
+                 const SkRect& rect,
+                 const SkStrokeRec& stroke) {
     if (aaType == GrAAType::kCoverage) {
         // The AA op only supports axis-aligned rectangles
         if (!viewMatrix.rectStaysRect()) {
@@ -842,10 +842,10 @@
     }
 }
 
-std::unique_ptr<GrDrawOp> MakeNested(GrRecordingContext* context,
-                                     GrPaint&& paint,
-                                     const SkMatrix& viewMatrix,
-                                     const SkRect rects[2]) {
+GrOp::Owner MakeNested(GrRecordingContext* context,
+                       GrPaint&& paint,
+                       const SkMatrix& viewMatrix,
+                       const SkRect rects[2]) {
     SkASSERT(viewMatrix.rectStaysRect());
     SkASSERT(!rects[0].isEmpty() && !rects[1].isEmpty());
 
diff --git a/src/gpu/ops/GrStrokeRectOp.h b/src/gpu/ops/GrStrokeRectOp.h
index 6f319cc..b3f1d8e 100644
--- a/src/gpu/ops/GrStrokeRectOp.h
+++ b/src/gpu/ops/GrStrokeRectOp.h
@@ -9,6 +9,7 @@
 #define GrStrokeRectOp_DEFINED
 
 #include "include/private/GrTypesPriv.h"
+#include "src/gpu/ops/GrOp.h"
 
 class GrDrawOp;
 class GrPaint;
@@ -25,20 +26,20 @@
  */
 namespace GrStrokeRectOp {
 
-std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                               GrPaint&& paint,
-                               GrAAType aaType,
-                               const SkMatrix& viewMatrix,
-                               const SkRect& rect,
-                               const SkStrokeRec& stroke);
+GrOp::Owner Make(GrRecordingContext* context,
+                 GrPaint&& paint,
+                 GrAAType aaType,
+                 const SkMatrix& viewMatrix,
+                 const SkRect& rect,
+                 const SkStrokeRec& stroke);
 
 // rects[0] == outer rectangle, rects[1] == inner rectangle. Null return means there is nothing to
 // draw rather than failure. The area between the rectangles will be filled by the paint, and it
 // will be anti-aliased with coverage AA. viewMatrix.rectStaysRect() must be true.
-std::unique_ptr<GrDrawOp> MakeNested(GrRecordingContext* context,
-                                     GrPaint&& paint,
-                                     const SkMatrix& viewMatrix,
-                                     const SkRect rects[2]);
+GrOp::Owner MakeNested(GrRecordingContext* context,
+                       GrPaint&& paint,
+                       const SkMatrix& viewMatrix,
+                       const SkRect rects[2]);
 
 }  // namespace GrStrokeRectOp
 
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 6120ea1..7d9852d 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -221,45 +221,38 @@
  */
 class TextureOp final : public GrMeshDrawOp {
 public:
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrSurfaceProxyView proxyView,
-                                          sk_sp<GrColorSpaceXform> textureXform,
-                                          GrSamplerState::Filter filter,
-                                          GrSamplerState::MipmapMode mm,
-                                          const SkPMColor4f& color,
-                                          GrTextureOp::Saturate saturate,
-                                          GrAAType aaType,
-                                          DrawQuad* quad,
-                                          const SkRect* subset) {
-        GrOpMemoryPool* pool = context->priv().opMemoryPool();
-        return pool->allocate<TextureOp>(std::move(proxyView), std::move(textureXform), filter, mm,
-                                         color, saturate, aaType, quad, subset);
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrSurfaceProxyView proxyView,
+                            sk_sp<GrColorSpaceXform> textureXform,
+                            GrSamplerState::Filter filter,
+                            GrSamplerState::MipmapMode mm,
+                            const SkPMColor4f& color,
+                            GrTextureOp::Saturate saturate,
+                            GrAAType aaType,
+                            DrawQuad* quad,
+                            const SkRect* subset) {
+
+        return GrOp::Make<TextureOp>(context, std::move(proxyView), std::move(textureXform),
+                                     filter, mm, color, saturate, aaType, quad, subset);
     }
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrRenderTargetContext::TextureSetEntry set[],
-                                          int cnt,
-                                          int proxyRunCnt,
-                                          GrSamplerState::Filter filter,
-                                          GrSamplerState::MipmapMode mm,
-                                          GrTextureOp::Saturate saturate,
-                                          GrAAType aaType,
-                                          SkCanvas::SrcRectConstraint constraint,
-                                          const SkMatrix& viewMatrix,
-                                          sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrRenderTargetContext::TextureSetEntry set[],
+                            int cnt,
+                            int proxyRunCnt,
+                            GrSamplerState::Filter filter,
+                            GrSamplerState::MipmapMode mm,
+                            GrTextureOp::Saturate saturate,
+                            GrAAType aaType,
+                            SkCanvas::SrcRectConstraint constraint,
+                            const SkMatrix& viewMatrix,
+                            sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
         // Allocate size based on proxyRunCnt, since that determines number of ViewCountPairs.
         SkASSERT(proxyRunCnt <= cnt);
-        size_t size = sizeof(TextureOp) + sizeof(ViewCountPair) * (proxyRunCnt - 1);
-        #if defined(GR_OP_ALLOCATE_USE_NEW)
-            void* mem = ::operator new(size);
-        #else
-            GrOpMemoryPool* pool = context->priv().opMemoryPool();
-            void* mem = pool->allocate(size);
-        #endif
-        return std::unique_ptr<GrDrawOp>(
-                new (mem) TextureOp(
-                        set, cnt, proxyRunCnt, filter, mm, saturate, aaType, constraint,
-                        viewMatrix, std::move(textureColorSpaceXform)));
+        return GrOp::MakeWithExtraMemory<TextureOp>(
+                context, sizeof(ViewCountPair) * (proxyRunCnt - 1),
+                set, cnt, proxyRunCnt, filter, mm, saturate, aaType, constraint,
+                viewMatrix, std::move(textureColorSpaceXform));
     }
 
     ~TextureOp() override {
@@ -314,7 +307,7 @@
     DEFINE_OP_CLASS_ID
 
 private:
-    friend class ::GrOpMemoryPool;
+    friend class ::GrOp;
 
     struct ColorSubsetAndAA {
         ColorSubsetAndAA(const SkPMColor4f& color, const SkRect& subsetRect, GrQuadAAFlags aaFlags)
@@ -1118,18 +1111,18 @@
 }
 #endif
 
-std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context,
-                                            GrSurfaceProxyView proxyView,
-                                            SkAlphaType alphaType,
-                                            sk_sp<GrColorSpaceXform> textureXform,
-                                            GrSamplerState::Filter filter,
-                                            GrSamplerState::MipmapMode mm,
-                                            const SkPMColor4f& color,
-                                            Saturate saturate,
-                                            SkBlendMode blendMode,
-                                            GrAAType aaType,
-                                            DrawQuad* quad,
-                                            const SkRect* subset) {
+GrOp::Owner GrTextureOp::Make(GrRecordingContext* context,
+                              GrSurfaceProxyView proxyView,
+                              SkAlphaType alphaType,
+                              sk_sp<GrColorSpaceXform> textureXform,
+                              GrSamplerState::Filter filter,
+                              GrSamplerState::MipmapMode mm,
+                              const SkPMColor4f& color,
+                              Saturate saturate,
+                              SkBlendMode blendMode,
+                              GrAAType aaType,
+                              DrawQuad* quad,
+                              const SkRect* subset) {
     // Apply optimizations that are valid whether or not using GrTextureOp or GrFillRectOp
     if (subset && subset->contains(proxyView.proxy()->backingStoreBoundsRect())) {
         // No need for a shader-based subset if hardware clamping achieves the same effect
@@ -1207,17 +1200,17 @@
                   int clumpSize,
                   GrAAType aaType) {
         int clumpProxyCount = proxy_run_count(&set[fNumClumped], clumpSize);
-        std::unique_ptr<GrDrawOp> op = TextureOp::Make(fContext,
-                                                       &set[fNumClumped],
-                                                       clumpSize,
-                                                       clumpProxyCount,
-                                                       fFilter,
-                                                       fMipmapMode,
-                                                       fSaturate,
-                                                       aaType,
-                                                       fConstraint,
-                                                       fViewMatrix,
-                                                       fTextureColorSpaceXform);
+        GrOp::Owner op = TextureOp::Make(fContext,
+                                         &set[fNumClumped],
+                                         clumpSize,
+                                         clumpProxyCount,
+                                         fFilter,
+                                         fMipmapMode,
+                                         fSaturate,
+                                         aaType,
+                                         fConstraint,
+                                         fViewMatrix,
+                                         fTextureColorSpaceXform);
         fRTC->addDrawOp(fClip, std::move(op));
 
         fNumLeft -= clumpSize;
diff --git a/src/gpu/ops/GrTextureOp.h b/src/gpu/ops/GrTextureOp.h
index 1af1a6f..aee32b0 100644
--- a/src/gpu/ops/GrTextureOp.h
+++ b/src/gpu/ops/GrTextureOp.h
@@ -40,18 +40,18 @@
      * deconstructed into the texture, filter, modulating color, and blend mode. When blend mode is
      * src over, this will return a GrFillRectOp with a paint that samples the proxy.
      */
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext*,
-                                          GrSurfaceProxyView,
-                                          SkAlphaType srcAlphaType,
-                                          sk_sp<GrColorSpaceXform>,
-                                          GrSamplerState::Filter,
-                                          GrSamplerState::MipmapMode,
-                                          const SkPMColor4f&,
-                                          Saturate,
-                                          SkBlendMode,
-                                          GrAAType,
-                                          DrawQuad*,
-                                          const SkRect* subset = nullptr);
+    static GrOp::Owner Make(GrRecordingContext*,
+                            GrSurfaceProxyView,
+                            SkAlphaType srcAlphaType,
+                            sk_sp<GrColorSpaceXform>,
+                            GrSamplerState::Filter,
+                            GrSamplerState::MipmapMode,
+                            const SkPMColor4f&,
+                            Saturate,
+                            SkBlendMode,
+                            GrAAType,
+                            DrawQuad*,
+                            const SkRect* subset = nullptr);
 
     // Automatically falls back to using one GrFillRectOp per entry if dynamic states are not
     // supported, or if the blend mode is not src-over. 'cnt' is the size of the entry array.
diff --git a/src/gpu/ops/GrTriangulatingPathRenderer.cpp b/src/gpu/ops/GrTriangulatingPathRenderer.cpp
index 196b54b..0d8ff25 100644
--- a/src/gpu/ops/GrTriangulatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTriangulatingPathRenderer.cpp
@@ -173,13 +173,13 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                                          GrPaint&& paint,
-                                          const GrStyledShape& shape,
-                                          const SkMatrix& viewMatrix,
-                                          SkIRect devClipBounds,
-                                          GrAAType aaType,
-                                          const GrUserStencilSettings* stencilSettings) {
+    static GrOp::Owner Make(GrRecordingContext* context,
+                            GrPaint&& paint,
+                            const GrStyledShape& shape,
+                            const SkMatrix& viewMatrix,
+                            SkIRect devClipBounds,
+                            GrAAType aaType,
+                            const GrUserStencilSettings* stencilSettings) {
         return Helper::FactoryHelper<TriangulatingPathOp>(context, std::move(paint), shape,
                                                           viewMatrix, devClipBounds, aaType,
                                                           stencilSettings);
@@ -195,7 +195,7 @@
         }
     }
 
-    TriangulatingPathOp(Helper::MakeArgs helperArgs,
+    TriangulatingPathOp(GrProcessorSet* processorSet,
                         const SkPMColor4f& color,
                         const GrStyledShape& shape,
                         const SkMatrix& viewMatrix,
@@ -203,7 +203,7 @@
                         GrAAType aaType,
                         const GrUserStencilSettings* stencilSettings)
             : INHERITED(ClassID())
-            , fHelper(helperArgs, aaType, stencilSettings)
+            , fHelper(processorSet, aaType, stencilSettings)
             , fColor(color)
             , fShape(shape)
             , fViewMatrix(viewMatrix)
@@ -467,7 +467,7 @@
     GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
                               "GrTriangulatingPathRenderer::onDrawPath");
 
-    std::unique_ptr<GrDrawOp> op = TriangulatingPathOp::Make(
+    GrOp::Owner op = TriangulatingPathOp::Make(
             args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix,
             *args.fClipConservativeBounds, args.fAAType, args.fUserStencilSettings);
     args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
diff --git a/src/gpu/tessellate/GrPathTessellateOp.h b/src/gpu/tessellate/GrPathTessellateOp.h
index 1ab4a62..7e8a933 100644
--- a/src/gpu/tessellate/GrPathTessellateOp.h
+++ b/src/gpu/tessellate/GrPathTessellateOp.h
@@ -195,7 +195,7 @@
     int fIndirectDrawCount;
     sk_sp<const GrBuffer> fIndirectIndexBuffer;
 
-    friend class GrOpMemoryPool;  // For ctor.
+    friend class GrOp;  // For ctor.
 
 public:
     // This serves as a base class for benchmarking individual methods on GrPathTessellateOp.
diff --git a/src/gpu/tessellate/GrStrokeTessellateOp.h b/src/gpu/tessellate/GrStrokeTessellateOp.h
index 757edbe..7bec3bb 100644
--- a/src/gpu/tessellate/GrStrokeTessellateOp.h
+++ b/src/gpu/tessellate/GrStrokeTessellateOp.h
@@ -65,7 +65,7 @@
     // S=1 because we will almost always fit everything into one single chunk.
     SkSTArray<1, GrStrokePatchBuilder::PatchChunk> fPatchChunks;
 
-    friend class GrOpMemoryPool;  // For ctor.
+    friend class GrOp;  // For ctor.
 };
 
 #endif
diff --git a/src/gpu/tessellate/GrTessellationPathRenderer.cpp b/src/gpu/tessellate/GrTessellationPathRenderer.cpp
index 829c69b..ba6b052 100644
--- a/src/gpu/tessellate/GrTessellationPathRenderer.cpp
+++ b/src/gpu/tessellate/GrTessellationPathRenderer.cpp
@@ -161,7 +161,6 @@
 
 bool GrTessellationPathRenderer::onDrawPath(const DrawPathArgs& args) {
     GrRenderTargetContext* renderTargetContext = args.fRenderTargetContext;
-    GrOpMemoryPool* pool = args.fContext->priv().opMemoryPool();
     const GrShaderCaps& shaderCaps = *args.fContext->priv().caps()->shaderCaps();
 
     SkPath path;
@@ -194,7 +193,7 @@
             SkASSERT(worstCaseNumSegments <= shaderCaps.maxTessellationSegments());
         }
 #endif
-        auto op = pool->allocate<GrDrawAtlasPathOp>(
+        auto op = GrOp::Make<GrDrawAtlasPathOp>(args.fContext,
                 renderTargetContext->numSamples(), sk_ref_sp(fAtlas.textureProxy()),
                 devIBounds, locationInAtlas, transposedInAtlas, *args.fViewMatrix,
                 std::move(args.fPaint));
@@ -259,8 +258,9 @@
         path.transform(*args.fViewMatrix, &devPath);
         SkStrokeRec devStroke = args.fShape->style().strokeRec();
         devStroke.setStrokeStyle(1);
-        auto op = pool->allocate<GrStrokeTessellateOp>(args.fAAType, SkMatrix::I(), devStroke,
-                                                       devPath, std::move(args.fPaint));
+        auto op = GrOp::Make<GrStrokeTessellateOp>(
+                args.fContext, args.fAAType, SkMatrix::I(), devStroke,
+                devPath, std::move(args.fPaint));
         renderTargetContext->addDrawOp(args.fClip, std::move(op));
         return true;
     }
@@ -268,8 +268,9 @@
     if (!args.fShape->style().isSimpleFill()) {
         const SkStrokeRec& stroke = args.fShape->style().strokeRec();
         SkASSERT(stroke.getStyle() == SkStrokeRec::kStroke_Style);
-        auto op = pool->allocate<GrStrokeTessellateOp>(args.fAAType, *args.fViewMatrix, stroke,
-                                                       path, std::move(args.fPaint));
+        auto op = GrOp::Make<GrStrokeTessellateOp>(
+                args.fContext, args.fAAType, *args.fViewMatrix, stroke,
+                path, std::move(args.fPaint));
         renderTargetContext->addDrawOp(args.fClip, std::move(op));
         return true;
     }
@@ -282,8 +283,9 @@
         drawPathFlags |= OpFlags::kDisableHWTessellation;
     }
 
-    auto op = pool->allocate<GrPathTessellateOp>(*args.fViewMatrix, path, std::move(args.fPaint),
-                                                 args.fAAType, drawPathFlags);
+    auto op = GrOp::Make<GrPathTessellateOp>(
+            args.fContext, *args.fViewMatrix, path, std::move(args.fPaint),
+            args.fAAType, drawPathFlags);
     renderTargetContext->addDrawOp(args.fClip, std::move(op));
     return true;
 }
@@ -353,8 +355,8 @@
 
     GrAAType aaType = (GrAA::kYes == args.fDoStencilMSAA) ? GrAAType::kMSAA : GrAAType::kNone;
 
-    auto op = args.fContext->priv().opMemoryPool()->allocate<GrPathTessellateOp>(
-            *args.fViewMatrix, path, GrPaint(), aaType, OpFlags::kStencilOnly);
+    auto op = GrOp::Make<GrPathTessellateOp>(
+            args.fContext, *args.fViewMatrix, path, GrPaint(), aaType, OpFlags::kStencilOnly);
     args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
 }
 
@@ -402,7 +404,7 @@
             }
             uberPath->setFillType(fillType);
             GrAAType aaType = (antialias) ? GrAAType::kMSAA : GrAAType::kNone;
-            auto op = onFlushRP->opMemoryPool()->allocate<GrPathTessellateOp>(
+            auto op = GrOp::Make<GrPathTessellateOp>(onFlushRP->recordingContext(),
                     SkMatrix::I(), *uberPath, GrPaint(), aaType, fStencilAtlasFlags);
             rtc->addDrawOp(nullptr, std::move(op));
         }
diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp
index 934783c..9b30649 100644
--- a/src/gpu/text/GrTextBlob.cpp
+++ b/src/gpu/text/GrTextBlob.cpp
@@ -537,7 +537,7 @@
     return fGlyphs.glyphs().count();
 }
 
-std::tuple<const GrClip*, std::unique_ptr<GrDrawOp>>
+std::tuple<const GrClip*, GrOp::Owner>
 GrDirectMaskSubRun::makeAtlasTextOp(const GrClip* clip, const SkMatrixProvider& viewMatrix,
                                     const SkGlyphRunList& glyphRunList,
                                     GrRenderTargetContext* rtc) const {
@@ -589,13 +589,14 @@
             drawingColor
     };
 
-    GrOpMemoryPool* const pool = rtc->priv().recordingContext()->priv().opMemoryPool();
-    std::unique_ptr<GrDrawOp> op = pool->allocate<GrAtlasTextOp>(op_mask_type(fMaskFormat),
-                                                                 false,
-                                                                 this->glyphCount(),
-                                                                 subRunBounds,
-                                                                 geometry,
-                                                                 std::move(grPaint));
+    GrRecordingContext* const context = rtc->priv().recordingContext();
+    GrOp::Owner op = GrOp::Make<GrAtlasTextOp>(context,
+                                               op_mask_type(fMaskFormat),
+                                               false,
+                                               this->glyphCount(),
+                                               subRunBounds,
+                                               geometry,
+                                               std::move(grPaint));
 
     return {clip, std::move(op)};
 }
@@ -723,7 +724,7 @@
     return true;
 }
 
-std::tuple<const GrClip*, std::unique_ptr<GrDrawOp>>
+std::tuple<const GrClip*, GrOp::Owner>
 GrTransformedMaskSubRun::makeAtlasTextOp(const GrClip* clip,
                                          const SkMatrixProvider& viewMatrix,
                                          const SkGlyphRunList& glyphRunList,
@@ -733,7 +734,6 @@
     SkPoint drawOrigin = glyphRunList.origin();
     const SkPaint& drawPaint = glyphRunList.paint();
     const SkMatrix& drawMatrix = viewMatrix.localToDevice();
-    GrOpMemoryPool* pool = rtc->priv().recordingContext()->priv().opMemoryPool();
 
     GrPaint grPaint;
     SkPMColor4f drawingColor = calculate_colors(rtc, drawPaint, viewMatrix, fMaskFormat, &grPaint);
@@ -749,7 +749,9 @@
             drawingColor
     };
 
-    std::unique_ptr<GrDrawOp> op = pool->allocate<GrAtlasTextOp>(
+    GrRecordingContext* context = rtc->priv().recordingContext();
+    GrOp::Owner op = GrOp::Make<GrAtlasTextOp>(
+            context,
             op_mask_type(fMaskFormat),
             true,
             this->glyphCount(),
@@ -905,7 +907,7 @@
             runFont.hasSomeAntiAliasing());
 }
 
-std::tuple<const GrClip*, std::unique_ptr<GrDrawOp> >
+std::tuple<const GrClip*, GrOp::Owner >
 GrSDFTSubRun::makeAtlasTextOp(const GrClip* clip,
                               const SkMatrixProvider& viewMatrix,
                               const SkGlyphRunList& glyphRunList,
@@ -915,7 +917,6 @@
     SkPoint drawOrigin = glyphRunList.origin();
     const SkPaint& drawPaint = glyphRunList.paint();
     const SkMatrix& drawMatrix = viewMatrix.localToDevice();
-    GrOpMemoryPool* pool = rtc->priv().recordingContext()->priv().opMemoryPool();
 
     GrPaint grPaint;
     SkPMColor4f drawingColor = calculate_colors(rtc, drawPaint, viewMatrix, fMaskFormat, &grPaint);
@@ -953,7 +954,9 @@
             drawingColor
     };
 
-    std::unique_ptr<GrDrawOp> op = pool->allocate<GrAtlasTextOp>(
+    GrRecordingContext* context = rtc->priv().recordingContext();
+    GrOp::Owner op = GrOp::Make<GrAtlasTextOp>(
+            context,
             maskType,
             true,
             this->glyphCount(),
diff --git a/src/gpu/text/GrTextBlob.h b/src/gpu/text/GrTextBlob.h
index af5fd72..a1568a5 100644
--- a/src/gpu/text/GrTextBlob.h
+++ b/src/gpu/text/GrTextBlob.h
@@ -219,7 +219,7 @@
     virtual size_t vertexStride() const = 0;
     virtual int glyphCount() const = 0;
 
-    virtual std::tuple<const GrClip*, std::unique_ptr<GrDrawOp>>
+    virtual std::tuple<const GrClip*, GrOp::Owner>
     makeAtlasTextOp(const GrClip* clip,
                     const SkMatrixProvider& viewMatrix,
                     const SkGlyphRunList& glyphRunList,
@@ -305,7 +305,7 @@
 
     int glyphCount() const override;
 
-    std::tuple<const GrClip*, std::unique_ptr<GrDrawOp>>
+    std::tuple<const GrClip*, GrOp::Owner>
     makeAtlasTextOp(const GrClip* clip,
                     const SkMatrixProvider& viewMatrix,
                     const SkGlyphRunList& glyphRunList,
@@ -367,7 +367,7 @@
 
     bool canReuse(const SkPaint& paint, const SkMatrix& drawMatrix) override;
 
-    std::tuple<const GrClip*, std::unique_ptr<GrDrawOp>>
+    std::tuple<const GrClip*, GrOp::Owner>
     makeAtlasTextOp(const GrClip* clip,
                     const SkMatrixProvider& viewMatrix,
                     const SkGlyphRunList& glyphRunList,
@@ -434,7 +434,7 @@
 
     bool canReuse(const SkPaint& paint, const SkMatrix& drawMatrix) override;
 
-    std::tuple<const GrClip*, std::unique_ptr<GrDrawOp>>
+    std::tuple<const GrClip*, GrOp::Owner>
     makeAtlasTextOp(const GrClip* clip,
                     const SkMatrixProvider& viewMatrix,
                     const SkGlyphRunList& glyphRunList,