Add a factory to any GrOp-derived class that lacked one

All GrOp-derived classes are going to have allocate their memory in a GrMemoryPool.

Change-Id: Ifa410b05eecd9b68c39dcc15dd4298d617204c13
Reviewed-on: https://skia-review.googlesource.com/132828
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 110667d..65484c3 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -262,6 +262,7 @@
   "$_src/gpu/ops/GrDashOp.h",
   "$_src/gpu/ops/GrDefaultPathRenderer.cpp",
   "$_src/gpu/ops/GrDefaultPathRenderer.h",
+  "$_src/gpu/ops/GrDebugMarkerOp.cpp",
   "$_src/gpu/ops/GrDebugMarkerOp.h",
   "$_src/gpu/ops/GrDrawAtlasOp.cpp",
   "$_src/gpu/ops/GrDrawAtlasOp.h",
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index a79f9d1..a4c08f3 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -1409,7 +1409,7 @@
 }
 
 void GrRenderTargetContext::insertEventMarker(const SkString& str) {
-    std::unique_ptr<GrOp> op(GrDebugMarkerOp::Make(fRenderTargetProxy.get(), str));
+    std::unique_ptr<GrOp> op(GrDebugMarkerOp::Make(fContext, fRenderTargetProxy.get(), str));
     this->getRTOpList()->addOp(std::move(op), *this->caps());
 }
 
diff --git a/src/gpu/ccpr/GrCCAtlas.cpp b/src/gpu/ccpr/GrCCAtlas.cpp
index da4138f..afa82c4 100644
--- a/src/gpu/ccpr/GrCCAtlas.cpp
+++ b/src/gpu/ccpr/GrCCAtlas.cpp
@@ -9,6 +9,7 @@
 
 #include "GrClip.h"
 #include "GrOnFlushResourceProvider.h"
+#include "GrSurfaceContextPriv.h"
 #include "GrRectanizer_skyline.h"
 #include "GrRenderTargetContext.h"
 #include "GrTextureProxy.h"
@@ -54,14 +55,12 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    DrawCoverageCountOp(sk_sp<const GrCCPathParser> parser, CoverageCountBatchID batchID,
-                        const SkISize& drawBounds)
-            : INHERITED(ClassID())
-            , fParser(std::move(parser))
-            , fBatchID(batchID)
-            , fDrawBounds(drawBounds) {
-        this->setBounds(SkRect::MakeIWH(fDrawBounds.width(), fDrawBounds.height()),
-                        GrOp::HasAABloat::kNo, GrOp::IsZeroArea::kNo);
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          sk_sp<const GrCCPathParser> parser,
+                                          CoverageCountBatchID batchID,
+                                          const SkISize& drawBounds) {
+        return std::unique_ptr<GrDrawOp>(new DrawCoverageCountOp(std::move(parser),
+                                                                 batchID, drawBounds));
     }
 
     // GrDrawOp interface.
@@ -77,6 +76,16 @@
     }
 
 private:
+    DrawCoverageCountOp(sk_sp<const GrCCPathParser> parser, CoverageCountBatchID batchID,
+                        const SkISize& drawBounds)
+            : INHERITED(ClassID())
+            , fParser(std::move(parser))
+            , fBatchID(batchID)
+            , fDrawBounds(drawBounds) {
+        this->setBounds(SkRect::MakeIWH(fDrawBounds.width(), fDrawBounds.height()),
+                        GrOp::HasAABloat::kNo, GrOp::IsZeroArea::kNo);
+    }
+
     const sk_sp<const GrCCPathParser> fParser;
     const CoverageCountBatchID fBatchID;
     const SkISize fDrawBounds;
@@ -160,8 +169,12 @@
     SkIRect clearRect = SkIRect::MakeSize(fDrawBounds);
     rtc->clear(&clearRect, 0, GrRenderTargetContext::CanClearFullscreen::kYes);
 
-    auto op = skstd::make_unique<DrawCoverageCountOp>(std::move(parser), fCoverageCountBatchID,
-                                                      fDrawBounds);
+    GrContext* context = rtc->surfPriv().getContext();
+
+    std::unique_ptr<GrDrawOp> op = DrawCoverageCountOp::Make(context,
+                                                             std::move(parser),
+                                                             fCoverageCountBatchID,
+                                                             fDrawBounds);
     rtc->addDrawOp(GrNoClip(), std::move(op));
 
     fTextureProxy = sk_ref_sp(rtc->asTextureProxy());
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
index 39c1b26..c4be7c5 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
@@ -12,6 +12,15 @@
 #include "ccpr/GrCCPerFlushResources.h"
 #include "ccpr/GrCoverageCountingPathRenderer.h"
 
+GrCCDrawPathsOp* GrCCDrawPathsOp::Make(GrContext* context,
+                                       GrPaint&& paint,
+                                       const SkIRect& clipIBounds,
+                                       const SkMatrix& m,
+                                       const SkPath& path,
+                                       const SkRect& devBounds) {
+    return new GrCCDrawPathsOp(std::move(paint), clipIBounds, m, path, devBounds);
+}
+
 static bool has_coord_transforms(const GrPaint& paint) {
     GrFragmentProcessor::Iter iter(paint);
     while (const GrFragmentProcessor* fp = iter.next()) {
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.h b/src/gpu/ccpr/GrCCDrawPathsOp.h
index 9189e5a..f43ccd0 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.h
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.h
@@ -26,8 +26,13 @@
     DEFINE_OP_CLASS_ID
     SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrCCDrawPathsOp);
 
-    GrCCDrawPathsOp(GrPaint&&, const SkIRect& clipIBounds, const SkMatrix&, const SkPath&,
-                    const SkRect& devBounds);
+    static GrCCDrawPathsOp* Make(GrContext*,
+                                 GrPaint&&,
+                                 const SkIRect& clipIBounds,
+                                 const SkMatrix&,
+                                 const SkPath&,
+                                 const SkRect& devBounds);
+
     ~GrCCDrawPathsOp() override;
 
     const char* name() const override { return "GrCCDrawOp"; }
@@ -48,6 +53,9 @@
     void onExecute(GrOpFlushState*) override;
 
 private:
+    GrCCDrawPathsOp(GrPaint&&, const SkIRect& clipIBounds, const SkMatrix&, const SkPath&,
+                    const SkRect& devBounds);
+
     struct AtlasBatch {
         const GrCCAtlas* fAtlas;
         int fEndInstanceIdx;
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index c8fafeb..dcb9a58 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -127,19 +127,20 @@
     SkRect devBounds;
     args.fViewMatrix->mapRect(&devBounds, path.getBounds());
 
+    GrCCDrawPathsOp* op;
     if (SkTMax(devBounds.height(), devBounds.width()) > kPathCropThreshold) {
         // The path is too large. Crop it or analytic AA can run out of fp32 precision.
         SkPath croppedPath;
         path.transform(*args.fViewMatrix, &croppedPath);
         crop_path(croppedPath, clipIBounds, &croppedPath);
-        this->adoptAndRecordOp(new GrCCDrawPathsOp(std::move(args.fPaint), clipIBounds,
-                                                   SkMatrix::I(), croppedPath,
-                                                   croppedPath.getBounds()), args);
-        return true;
+        op = GrCCDrawPathsOp::Make(args.fContext, std::move(args.fPaint), clipIBounds,
+                                   SkMatrix::I(), croppedPath, croppedPath.getBounds());
+    } else {
+        op = GrCCDrawPathsOp::Make(args.fContext, std::move(args.fPaint), clipIBounds,
+                                   *args.fViewMatrix, path, devBounds);
     }
 
-    this->adoptAndRecordOp(new GrCCDrawPathsOp(std::move(args.fPaint), clipIBounds,
-                                               *args.fViewMatrix, path, devBounds), args);
+    this->adoptAndRecordOp(op, args);
     return true;
 }
 
diff --git a/src/gpu/ops/GrDebugMarkerOp.cpp b/src/gpu/ops/GrDebugMarkerOp.cpp
new file mode 100644
index 0000000..1b663ce
--- /dev/null
+++ b/src/gpu/ops/GrDebugMarkerOp.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrDebugMarkerOp.h"
+
+#include "GrCaps.h"
+#include "GrContext.h"
+#include "GrContextPriv.h"
+#include "GrGpuCommandBuffer.h"
+#include "GrOpFlushState.h"
+
+std::unique_ptr<GrOp> GrDebugMarkerOp::Make(GrContext* context,
+                                            GrRenderTargetProxy* proxy,
+                                            const SkString& str) {
+    return std::unique_ptr<GrOp>(new GrDebugMarkerOp(proxy, str));
+}
+
+void GrDebugMarkerOp::onExecute(GrOpFlushState* state) {
+    //SkDebugf("%s\n", fStr.c_str());
+    if (state->caps().gpuTracingSupport()) {
+        state->commandBuffer()->insertEventMarker(fStr.c_str());
+    }
+}
diff --git a/src/gpu/ops/GrDebugMarkerOp.h b/src/gpu/ops/GrDebugMarkerOp.h
index 1b02c62..931882e 100644
--- a/src/gpu/ops/GrDebugMarkerOp.h
+++ b/src/gpu/ops/GrDebugMarkerOp.h
@@ -8,18 +8,18 @@
 #ifndef GrDebugMarkerOp_DEFINED
 #define GrDebugMarkerOp_DEFINED
 
-#include "GrGpuCommandBuffer.h"
 #include "GrOp.h"
-#include "GrOpFlushState.h"
 #include "GrRenderTargetProxy.h"
 
+class GrOpFlushState;
+
 class GrDebugMarkerOp final : public GrOp {
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrOp> Make(GrRenderTargetProxy* proxy, const SkString& str) {
-        return std::unique_ptr<GrOp>(new GrDebugMarkerOp(proxy, str));
-    }
+    static std::unique_ptr<GrOp> Make(GrContext* context,
+                                      GrRenderTargetProxy* proxy,
+                                      const SkString& str);
 
     const char* name() const override { return "DebugMarker"; }
 
@@ -41,12 +41,7 @@
 
     void onPrepare(GrOpFlushState*) override {}
 
-    void onExecute(GrOpFlushState* state) override {
-        //SkDebugf("%s\n", fStr.c_str());
-        if (state->caps().gpuTracingSupport()) {
-            state->commandBuffer()->insertEventMarker(fStr.c_str());
-        }
-    }
+    void onExecute(GrOpFlushState* state) override;
 
     SkString fStr;
 
diff --git a/tests/GrMeshTest.cpp b/tests/GrMeshTest.cpp
index 1cdfe38..fb3579c 100644
--- a/tests/GrMeshTest.cpp
+++ b/tests/GrMeshTest.cpp
@@ -75,11 +75,12 @@
  * from the set (r,g,b) = (0,255)^3, so the GPU renderings ought to produce exact matches.
  */
 
-static void run_test(const char* testName, skiatest::Reporter*, const sk_sp<GrRenderTargetContext>&,
-                     const SkBitmap& gold, std::function<void(DrawMeshHelper*)> testFn);
+static void run_test(GrContext* context, const char* testName, skiatest::Reporter*,
+                     const sk_sp<GrRenderTargetContext>&, const SkBitmap& gold,
+                     std::function<void(DrawMeshHelper*)> testFn);
 
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrMeshTest, reporter, ctxInfo) {
-    GrContext* const context = ctxInfo.grContext();
+    GrContext* context = ctxInfo.grContext();
 
     sk_sp<GrRenderTargetContext> rtc(context->contextPriv().makeDeferredRenderTargetContext(
                                                  SkBackingFit::kExact, kImageWidth, kImageHeight,
@@ -136,26 +137,27 @@
         return; \
     }
 
-    run_test("setNonIndexedNonInstanced", reporter, rtc, gold, [&](DrawMeshHelper* helper) {
-        SkTArray<Box> expandedVertexData;
-        for (int i = 0; i < kBoxCount; ++i) {
-            for (int j = 0; j < 6; ++j) {
-                expandedVertexData.push_back(vertexData[i][kIndexPattern[j]]);
-            }
-        }
+    run_test(context, "setNonIndexedNonInstanced", reporter, rtc, gold,
+             [&](DrawMeshHelper* helper) {
+                 SkTArray<Box> expandedVertexData;
+                 for (int i = 0; i < kBoxCount; ++i) {
+                     for (int j = 0; j < 6; ++j) {
+                         expandedVertexData.push_back(vertexData[i][kIndexPattern[j]]);
+                     }
+                 }
 
-        // Draw boxes one line at a time to exercise base vertex.
-        auto vbuff = helper->makeVertexBuffer(expandedVertexData);
-        VALIDATE(vbuff);
-        for (int y = 0; y < kBoxCountY; ++y) {
-            GrMesh mesh(GrPrimitiveType::kTriangles);
-            mesh.setNonIndexedNonInstanced(kBoxCountX * 6);
-            mesh.setVertexData(vbuff.get(), y * kBoxCountX * 6);
-            helper->drawMesh(mesh);
-        }
-    });
+                 // Draw boxes one line at a time to exercise base vertex.
+                 auto vbuff = helper->makeVertexBuffer(expandedVertexData);
+                 VALIDATE(vbuff);
+                 for (int y = 0; y < kBoxCountY; ++y) {
+                     GrMesh mesh(GrPrimitiveType::kTriangles);
+                     mesh.setNonIndexedNonInstanced(kBoxCountX * 6);
+                     mesh.setVertexData(vbuff.get(), y * kBoxCountX * 6);
+                     helper->drawMesh(mesh);
+                 }
+             });
 
-    run_test("setIndexed", reporter, rtc, gold, [&](DrawMeshHelper* helper) {
+    run_test(context, "setIndexed", reporter, rtc, gold, [&](DrawMeshHelper* helper) {
         auto ibuff = helper->getIndexBuffer();
         VALIDATE(ibuff);
         auto vbuff = helper->makeVertexBuffer(vertexData);
@@ -179,7 +181,7 @@
         }
     });
 
-    run_test("setIndexedPatterned", reporter, rtc, gold, [&](DrawMeshHelper* helper) {
+    run_test(context, "setIndexedPatterned", reporter, rtc, gold, [&](DrawMeshHelper* helper) {
         auto ibuff = helper->getIndexBuffer();
         VALIDATE(ibuff);
         auto vbuff = helper->makeVertexBuffer(vertexData);
@@ -200,7 +202,7 @@
             break;
         }
 
-        run_test(indexed ? "setIndexedInstanced" : "setInstanced",
+        run_test(context, indexed ? "setIndexedInstanced" : "setInstanced",
                  reporter, rtc, gold, [&](DrawMeshHelper* helper) {
             auto idxbuff = indexed ? helper->getIndexBuffer() : nullptr;
             auto instbuff = helper->makeVertexBuffer(boxes);
@@ -252,6 +254,12 @@
 public:
     DEFINE_OP_CLASS_ID
 
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          std::function<void(DrawMeshHelper*)> testFn) {
+        return std::unique_ptr<GrDrawOp>(new GrMeshTestOp(testFn));
+    }
+
+private:
     GrMeshTestOp(std::function<void(DrawMeshHelper*)> testFn)
         : INHERITED(ClassID())
         , fTestFn(testFn) {
@@ -259,7 +267,6 @@
                         HasAABloat::kNo, IsZeroArea::kNo);
     }
 
-private:
     const char* name() const override { return "GrMeshTestOp"; }
     FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
     RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
@@ -374,7 +381,7 @@
                                     SkRect::MakeIWH(kImageWidth, kImageHeight));
 }
 
-static void run_test(const char* testName, skiatest::Reporter* reporter,
+static void run_test(GrContext* context, const char* testName, skiatest::Reporter* reporter,
                      const sk_sp<GrRenderTargetContext>& rtc, const SkBitmap& gold,
                      std::function<void(DrawMeshHelper*)> testFn) {
     const int w = gold.width(), h = gold.height(), rowBytes = gold.rowBytes();
@@ -390,7 +397,7 @@
 
     SkAutoSTMalloc<kImageHeight * kImageWidth, uint32_t> resultPx(h * rowBytes);
     rtc->clear(nullptr, 0xbaaaaaad, GrRenderTargetContext::CanClearFullscreen::kYes);
-    rtc->priv().testingOnly_addDrawOp(skstd::make_unique<GrMeshTestOp>(testFn));
+    rtc->priv().testingOnly_addDrawOp(GrMeshTestOp::Make(context, testFn));
     rtc->readPixels(gold.info(), resultPx, rowBytes, 0, 0, 0);
     for (int y = 0; y < h; ++y) {
         for (int x = 0; x < w; ++x) {
diff --git a/tests/GrPipelineDynamicStateTest.cpp b/tests/GrPipelineDynamicStateTest.cpp
index b6ca8f0..227fd7c 100644
--- a/tests/GrPipelineDynamicStateTest.cpp
+++ b/tests/GrPipelineDynamicStateTest.cpp
@@ -105,6 +105,14 @@
 public:
     DEFINE_OP_CLASS_ID
 
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          ScissorState scissorState,
+                                          sk_sp<const GrBuffer> vbuff) {
+        return std::unique_ptr<GrDrawOp>(new GrPipelineDynamicStateTestOp(scissorState,
+                                                                          std::move(vbuff)));
+    }
+
+private:
     GrPipelineDynamicStateTestOp(ScissorState scissorState, sk_sp<const GrBuffer> vbuff)
         : INHERITED(ClassID())
         , fScissorState(scissorState)
@@ -113,7 +121,6 @@
                         HasAABloat::kNo, IsZeroArea::kNo);
     }
 
-private:
     const char* name() const override { return "GrPipelineDynamicStateTestOp"; }
     FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
     RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
@@ -143,7 +150,7 @@
 };
 
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrPipelineDynamicStateTest, reporter, ctxInfo) {
-    GrContext* const context = ctxInfo.grContext();
+    GrContext* context = ctxInfo.grContext();
     GrResourceProvider* rp = context->contextPriv().resourceProvider();
 
     sk_sp<GrRenderTargetContext> rtc(context->contextPriv().makeDeferredRenderTargetContext(
@@ -192,7 +199,7 @@
     for (ScissorState scissorState : {ScissorState::kEnabled, ScissorState::kDisabled}) {
         rtc->clear(nullptr, 0xbaaaaaad, GrRenderTargetContext::CanClearFullscreen::kYes);
         rtc->priv().testingOnly_addDrawOp(
-            skstd::make_unique<GrPipelineDynamicStateTestOp>(scissorState, vbuff));
+            GrPipelineDynamicStateTestOp::Make(context, scissorState, vbuff));
         rtc->readPixels(SkImageInfo::Make(kScreenSize, kScreenSize,
                                           kRGBA_8888_SkColorType, kPremul_SkAlphaType),
                         resultPx, 4 * kScreenSize, 0, 0, 0);
diff --git a/tests/LazyProxyTest.cpp b/tests/LazyProxyTest.cpp
index 28ba817..901cd29 100644
--- a/tests/LazyProxyTest.cpp
+++ b/tests/LazyProxyTest.cpp
@@ -54,6 +54,23 @@
     public:
         DEFINE_OP_CLASS_ID
 
+        static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                              GrProxyProvider* proxyProvider,
+                                              LazyProxyTest* test,
+                                              bool nullTexture) {
+            return std::unique_ptr<GrDrawOp>(new Op(proxyProvider, test, nullTexture));
+        }
+
+        void visitProxies(const VisitProxyFunc& func) const override {
+            func(fProxy.get());
+        }
+
+        void onExecute(GrOpFlushState*) override {
+            REPORTER_ASSERT(fTest->fReporter, fTest->fHasOpTexture);
+            REPORTER_ASSERT(fTest->fReporter, fTest->fHasClipTexture);
+        }
+
+    private:
         Op(GrProxyProvider* proxyProvider, LazyProxyTest* test, bool nullTexture)
                     : GrDrawOp(ClassID()), fTest(test) {
             fProxy = proxyProvider->createFullyLazyProxy([this, nullTexture](
@@ -78,16 +95,6 @@
             this->setBounds(SkRectPriv::MakeLargest(), GrOp::HasAABloat::kNo, GrOp::IsZeroArea::kNo);
         }
 
-        void visitProxies(const VisitProxyFunc& func) const override {
-            func(fProxy.get());
-        }
-
-        void onExecute(GrOpFlushState*) override {
-            REPORTER_ASSERT(fTest->fReporter, fTest->fHasOpTexture);
-            REPORTER_ASSERT(fTest->fReporter, fTest->fHasClipTexture);
-        }
-
-    private:
         const char* name() const override { return "LazyProxyTest::Op"; }
         FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
         RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
@@ -194,7 +201,7 @@
                                                      kAlpha_half_GrPixelConfig, nullptr);
         REPORTER_ASSERT(reporter, mockAtlas);
         rtc->priv().testingOnly_addDrawOp(LazyProxyTest::Clip(&test, mockAtlas->asTextureProxy()),
-                        skstd::make_unique<LazyProxyTest::Op>(proxyProvider, &test, nullTexture));
+                        LazyProxyTest::Op::Make(ctx.get(), proxyProvider, &test, nullTexture));
         ctx->contextPriv().testingOnly_flushAndRemoveOnFlushCallbackObject(&test);
     }
 }
@@ -256,6 +263,19 @@
 public:
     DEFINE_OP_CLASS_ID
 
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context,
+                                          GrProxyProvider* proxyProvider,
+                                          int* testExecuteValue,
+                                          bool shouldFailInstantiation) {
+        return std::unique_ptr<GrDrawOp>(new LazyFailedInstantiationTestOp(
+            proxyProvider, testExecuteValue, shouldFailInstantiation));
+    }
+
+    void visitProxies(const VisitProxyFunc& func) const override {
+        func(fLazyProxy.get());
+    }
+
+private:
     LazyFailedInstantiationTestOp(GrProxyProvider* proxyProvider, int* testExecuteValue,
                                   bool shouldFailInstantiation)
             : INHERITED(ClassID())
@@ -285,11 +305,6 @@
                         HasAABloat::kNo, IsZeroArea::kNo);
     }
 
-    void visitProxies(const VisitProxyFunc& func) const override {
-        func(fLazyProxy.get());
-    }
-
-private:
     const char* name() const override { return "LazyFailedInstantiationTestOp"; }
     FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
     RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
@@ -324,9 +339,8 @@
         rtc->clear(nullptr, 0xbaaaaaad, GrRenderTargetContext::CanClearFullscreen::kYes);
 
         int executeTestValue = 0;
-        rtc->priv().testingOnly_addDrawOp(
-                skstd::make_unique<LazyFailedInstantiationTestOp>(proxyProvider, &executeTestValue,
-                                                                  failInstantiation));
+        rtc->priv().testingOnly_addDrawOp(LazyFailedInstantiationTestOp::Make(
+                ctx.get(), proxyProvider, &executeTestValue, failInstantiation));
         ctx->flush();
 
         if (failInstantiation) {
@@ -347,12 +361,8 @@
 public:
     DEFINE_OP_CLASS_ID
 
-    LazyUninstantiateTestOp(sk_sp<GrTextureProxy> proxy)
-            : INHERITED(ClassID())
-            , fLazyProxy(std::move(proxy)) {
-
-        this->setBounds(SkRect::MakeIWH(kSize, kSize),
-                        HasAABloat::kNo, IsZeroArea::kNo);
+    static std::unique_ptr<GrDrawOp> Make(GrContext* context, sk_sp<GrTextureProxy> proxy) {
+        return std::unique_ptr<GrDrawOp>(new LazyUninstantiateTestOp(std::move(proxy)));
     }
 
     void visitProxies(const VisitProxyFunc& func) const override {
@@ -360,6 +370,12 @@
     }
 
 private:
+    LazyUninstantiateTestOp(sk_sp<GrTextureProxy> proxy)
+            : INHERITED(ClassID())
+            , fLazyProxy(std::move(proxy)) {
+        this->setBounds(SkRect::MakeIWH(kSize, kSize), HasAABloat::kNo, IsZeroArea::kNo);
+    }
+
     const char* name() const override { return "LazyUninstantiateTestOp"; }
     FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
     RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
@@ -431,7 +447,7 @@
         // need to manually call setDoesNotSupportMipMaps.
         lazyProxy->texPriv().setDoesNotSupportMipMaps();
 
-        rtc->priv().testingOnly_addDrawOp(skstd::make_unique<LazyUninstantiateTestOp>(lazyProxy));
+        rtc->priv().testingOnly_addDrawOp(LazyUninstantiateTestOp::Make(ctx.get(), lazyProxy));
 
         ctx->flush();
 
@@ -444,9 +460,9 @@
 
         // This should cause the uninstantiate proxies to be instantiated again but have no effect
         // on the others
-        rtc->priv().testingOnly_addDrawOp(skstd::make_unique<LazyUninstantiateTestOp>(lazyProxy));
+        rtc->priv().testingOnly_addDrawOp(LazyUninstantiateTestOp::Make(ctx.get(), lazyProxy));
         // Add a second op to make sure we only instantiate once.
-        rtc->priv().testingOnly_addDrawOp(skstd::make_unique<LazyUninstantiateTestOp>(lazyProxy));
+        rtc->priv().testingOnly_addDrawOp(LazyUninstantiateTestOp::Make(ctx.get(), lazyProxy));
         ctx->flush();
 
         if (LazyType::kUninstantiate == lazyType) {