More programInfo cleanup

This CL moves the boiler-plate implementation of onPrePrepareDraws up to GrMeshDrawOp. This, unfortunately, required the addition of a 'programInfo' virtual but that may go away in the future.


The only GrMeshDrawOp-derived classes left are:
  AAHairlineOp - which has 3 programInfos
  AAFlatteningConvexPathOp - which has >=1 mesh (but just 1 programInfo)
  GrAtlasTextOp - which has inline uploads
  SmallPathOp - which, maybe, has inline uploads
  TextureOp - which has chaining

Bug: skia:9455
Change-Id: Id10f70e764054134751545ad38b99f0a0778de76
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/276642
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/bench/VertexColorSpaceBench.cpp b/bench/VertexColorSpaceBench.cpp
index c8ea9c6..6856445 100644
--- a/bench/VertexColorSpaceBench.cpp
+++ b/bench/VertexColorSpaceBench.cpp
@@ -169,6 +169,8 @@
 private:
     friend class ::GrOpMemoryPool;
 
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -187,21 +189,6 @@
                                                                    GrPipeline::InputFlags::kNone);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         if (!fProgramInfo) {
             this->createProgramInfo(target);
diff --git a/gm/beziereffects.cpp b/gm/beziereffects.cpp
index 2359727..61fe200 100644
--- a/gm/beziereffects.cpp
+++ b/gm/beziereffects.cpp
@@ -85,6 +85,8 @@
 
     virtual GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) = 0;
 
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -105,21 +107,6 @@
                                                                    flags);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) final {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) final {
         if (!fProgramInfo) {
             this->createProgramInfo(flushState);
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index 986055d..0048d84 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -739,6 +739,8 @@
     }
 
 private:
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -759,21 +761,6 @@
                                                             GrPrimitiveType::kTriangles);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         int instanceCount = fPaths.count();
 
diff --git a/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
index a8dbbce..020dbba 100644
--- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
@@ -859,6 +859,13 @@
                                      const SkMatrix* geometryProcessorViewM,
                                      const SkMatrix* geometryProcessorLocalM);
 
+    GrProgramInfo* programInfo() override {
+        // This Op has 3 programInfos and implements its own onPrePrepareDraws so this entry point
+        // should really never be called.
+        SkASSERT(0);
+        return nullptr;
+    }
+
     void onCreateProgramInfo(const GrCaps*,
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* outputView,
@@ -867,6 +874,13 @@
         // TODO [PI]: implement
     }
 
+    void onPrePrepareDraws(GrRecordingContext*,
+                           const GrSurfaceProxyView* outputView,
+                           GrAppliedClip*,
+                           const GrXferProcessor::DstProxyView&) override {
+        // TODO [PI]: implement
+    }
+
     void onPrepareDraws(Target*) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
 
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index f1dac6a..38331c5 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -198,6 +198,11 @@
     }
 
 private:
+    GrProgramInfo* programInfo() override {
+        // TODO [PI]: implement
+        return nullptr;
+    }
+
     void onCreateProgramInfo(const GrCaps*,
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* outputView,
@@ -206,6 +211,13 @@
         // TODO [PI]: implement
     }
 
+    void onPrePrepareDraws(GrRecordingContext*,
+                           const GrSurfaceProxyView* outputView,
+                           GrAppliedClip*,
+                           const GrXferProcessor::DstProxyView&) override {
+        // TODO [PI]: implement
+    }
+
     void recordDraw(Target* target, const GrGeometryProcessor* gp, int vertexCount,
                     size_t vertexStride, void* vertices, int indexCount, uint16_t* indices) const {
         if (vertexCount == 0 || indexCount == 0) {
diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h
index 89cd642..bc6cfa1 100644
--- a/src/gpu/ops/GrAtlasTextOp.h
+++ b/src/gpu/ops/GrAtlasTextOp.h
@@ -111,6 +111,11 @@
         int fNumDraws = 0;
     };
 
+    GrProgramInfo* programInfo() override {
+        // TODO [PI]: implement
+        return nullptr;
+    }
+
     void onCreateProgramInfo(const GrCaps*,
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* outputView,
@@ -119,6 +124,13 @@
         // TODO [PI]: implement
     }
 
+    void onPrePrepareDraws(GrRecordingContext*,
+                           const GrSurfaceProxyView* outputView,
+                           GrAppliedClip*,
+                           const GrXferProcessor::DstProxyView&) override {
+        // TODO [PI]: implement
+    }
+
     void onPrepareDraws(Target*) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
 
diff --git a/src/gpu/ops/GrDashOp.cpp b/src/gpu/ops/GrDashOp.cpp
index c7f18b3..f7fc1b3 100644
--- a/src/gpu/ops/GrDashOp.cpp
+++ b/src/gpu/ops/GrDashOp.cpp
@@ -326,6 +326,8 @@
         bool fHasEndRect;
     };
 
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -373,21 +375,6 @@
                                                                    fStencilSettings);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         int instanceCount = fLines.count();
         SkPaint::Cap cap = this->cap();
diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp
index eb57608..65a66e4 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -426,6 +426,8 @@
         return GrPrimitiveType::kTriangles;
     }
 
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -453,21 +455,6 @@
 
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         PathGeoBuilder pathGeoBuilder(this->primType(), target, &fMeshes);
 
diff --git a/src/gpu/ops/GrDrawAtlasOp.cpp b/src/gpu/ops/GrDrawAtlasOp.cpp
index 88f646d..7e17115 100644
--- a/src/gpu/ops/GrDrawAtlasOp.cpp
+++ b/src/gpu/ops/GrDrawAtlasOp.cpp
@@ -53,17 +53,14 @@
                                       bool hasMixedSampledCoverage, GrClampType) override;
 
 private:
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps*,
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* outputView,
                              GrAppliedClip&&,
                              const GrXferProcessor::DstProxyView&) override;
 
-    void onPrePrepareDraws(GrRecordingContext*,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip*,
-                           const GrXferProcessor::DstProxyView&) override;
-
     void onPrepareDraws(Target*) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
 
@@ -216,21 +213,6 @@
                                              dstProxyView, gp, GrPrimitiveType::kTriangles);
 }
 
-void DrawAtlasOp::onPrePrepareDraws(GrRecordingContext* context,
-                       const GrSurfaceProxyView* outputView,
-                       GrAppliedClip* clip,
-                       const GrXferProcessor::DstProxyView& dstProxyView) {
-    SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-    // This is equivalent to a GrOpFlushState::detachAppliedClip
-    GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-    this->createProgramInfo(context->priv().caps(), arena, outputView,
-                            std::move(appliedClip), dstProxyView);
-
-    context->priv().recordProgramInfo(fProgramInfo);
-}
-
 void DrawAtlasOp::onPrepareDraws(Target* target) {
     if (!fProgramInfo) {
         this->createProgramInfo(target);
diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp
index 597e05b..611c065 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -52,16 +52,14 @@
         kSkColor,
     };
 
-   void onCreateProgramInfo(const GrCaps*,
-                            SkArenaAlloc*,
-                            const GrSurfaceProxyView* outputView,
-                            GrAppliedClip&&,
-                            const GrXferProcessor::DstProxyView&) override;
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
 
-    void onPrePrepareDraws(GrRecordingContext*,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip*,
-                           const GrXferProcessor::DstProxyView&) override;
+    void onCreateProgramInfo(const GrCaps*,
+                             SkArenaAlloc*,
+                             const GrSurfaceProxyView* outputView,
+                             GrAppliedClip&&,
+                             const GrXferProcessor::DstProxyView&) override;
+
     void onPrepareDraws(Target*) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
 
@@ -268,21 +266,6 @@
                                              dstProxyView, gp, this->primitiveType());
 }
 
-void DrawVerticesOp::onPrePrepareDraws(GrRecordingContext* context,
-                                       const GrSurfaceProxyView* outputView,
-                                       GrAppliedClip* clip,
-                                       const GrXferProcessor::DstProxyView& dstProxyView) {
-    SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-    // This is equivalent to a GrOpFlushState::detachAppliedClip
-    GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-    this->createProgramInfo(context->priv().caps(), arena, outputView,
-                            std::move(appliedClip), dstProxyView);
-
-    context->priv().recordProgramInfo(fProgramInfo);
-}
-
 void DrawVerticesOp::onPrepareDraws(Target* target) {
     // Allocate buffers.
     size_t vertexStride = this->vertexStride();
diff --git a/src/gpu/ops/GrFillRectOp.cpp b/src/gpu/ops/GrFillRectOp.cpp
index 678e60a..e1b5fba 100644
--- a/src/gpu/ops/GrFillRectOp.cpp
+++ b/src/gpu/ops/GrFillRectOp.cpp
@@ -217,6 +217,12 @@
                           fHelper.compatibleWithCoverageAsAlpha(), indexBufferOption);
     }
 
+    GrProgramInfo* programInfo() override {
+        // This Op implements its own onPrePrepareDraws so this entry point should never be called.
+        SkASSERT(0);
+        return fProgramInfo;
+    }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 78fc2a3..9b90934 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -212,6 +212,8 @@
     }
 
 private:
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -238,21 +240,6 @@
                                                                    fixedDynamicState);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         if (!fProgramInfo) {
             this->createProgramInfo(target);
diff --git a/src/gpu/ops/GrMeshDrawOp.cpp b/src/gpu/ops/GrMeshDrawOp.cpp
index 375ce55..0cdc857 100644
--- a/src/gpu/ops/GrMeshDrawOp.cpp
+++ b/src/gpu/ops/GrMeshDrawOp.cpp
@@ -9,6 +9,7 @@
 
 #include "src/gpu/GrOpFlushState.h"
 #include "src/gpu/GrOpsRenderPass.h"
+#include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrResourceProvider.h"
 
 GrMeshDrawOp::GrMeshDrawOp(uint32_t classID) : INHERITED(classID) {}
@@ -23,6 +24,23 @@
                             target->dstProxyView());
 }
 
+// This onPrepareDraws implementation assumes the derived Op only has a single programInfo -
+// which is the majority of the cases.
+void GrMeshDrawOp::onPrePrepareDraws(GrRecordingContext* context,
+                                     const GrSurfaceProxyView* outputView,
+                                     GrAppliedClip* clip,
+                                     const GrXferProcessor::DstProxyView& dstProxyView) {
+    SkArenaAlloc* arena = context->priv().recordTimeAllocator();
+
+    // This is equivalent to a GrOpFlushState::detachAppliedClip
+    GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
+
+    this->createProgramInfo(context->priv().caps(), arena, outputView,
+                            std::move(appliedClip), dstProxyView);
+
+    context->priv().recordProgramInfo(this->programInfo());
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 GrMeshDrawOp::PatternHelper::PatternHelper(Target* target, GrPrimitiveType primitiveType,
diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h
index 8b2308f..5a8e65e 100644
--- a/src/gpu/ops/GrMeshDrawOp.h
+++ b/src/gpu/ops/GrMeshDrawOp.h
@@ -100,6 +100,7 @@
     }
 
 private:
+    virtual GrProgramInfo* programInfo() = 0;
     // This method is responsible for creating all the programInfos required
     // by this op.
     virtual void onCreateProgramInfo(const GrCaps*,
@@ -116,11 +117,10 @@
     }
     void onPrepare(GrOpFlushState* state) final;
 
-    // Only the GrTextureOp currently overrides this virtual
     virtual void onPrePrepareDraws(GrRecordingContext*,
                                    const GrSurfaceProxyView* outputView,
                                    GrAppliedClip*,
-                                   const GrXferProcessor::DstProxyView&) {}
+                                   const GrXferProcessor::DstProxyView&);
 
     virtual void onPrepareDraws(Target*) = 0;
     typedef GrDrawOp INHERITED;
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index efb1b82..7405dda 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -1273,6 +1273,7 @@
     FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
 
 private:
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
 
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
@@ -1293,21 +1294,6 @@
                                                  dstProxyView, gp, GrPrimitiveType::kTriangles);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         if (!fProgramInfo) {
             this->createProgramInfo(target);
@@ -1651,6 +1637,8 @@
     FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
 
 private:
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -1670,21 +1658,6 @@
                                                  dstProxyView, gp, GrPrimitiveType::kTriangles);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         if (!fProgramInfo) {
             this->createProgramInfo(target);
@@ -1995,6 +1968,8 @@
     FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
 
 private:
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -2012,21 +1987,6 @@
                                                  dstProxyView, gp, GrPrimitiveType::kTriangles);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         if (!fProgramInfo) {
             this->createProgramInfo(target);
@@ -2284,6 +2244,8 @@
     FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
 
 private:
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -2297,21 +2259,6 @@
                                                  dstProxyView, gp, GrPrimitiveType::kTriangles);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         if (!fProgramInfo) {
             this->createProgramInfo(target);
@@ -2694,6 +2641,8 @@
                     outerRadius, innerRadius);
     }
 
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -2713,22 +2662,6 @@
                                                  dstProxyView, gp, GrPrimitiveType::kTriangles);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
-
     void onPrepareDraws(Target* target) override {
         if (!fProgramInfo) {
             this->createProgramInfo(target);
@@ -3031,6 +2964,8 @@
     FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
 
 private:
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -3048,21 +2983,6 @@
                                                  dstProxyView, gp, GrPrimitiveType::kTriangles);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         if (!fProgramInfo) {
             this->createProgramInfo(target);
diff --git a/src/gpu/ops/GrRegionOp.cpp b/src/gpu/ops/GrRegionOp.cpp
index 74b264f..4a097a5 100644
--- a/src/gpu/ops/GrRegionOp.cpp
+++ b/src/gpu/ops/GrRegionOp.cpp
@@ -98,6 +98,8 @@
     }
 
 private:
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -114,21 +116,6 @@
                                                             gp, GrPrimitiveType::kTriangles);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         if (!fProgramInfo) {
             this->createProgramInfo(target);
diff --git a/src/gpu/ops/GrShadowRRectOp.cpp b/src/gpu/ops/GrShadowRRectOp.cpp
index 27824c6..cdc8eda 100644
--- a/src/gpu/ops/GrShadowRRectOp.cpp
+++ b/src/gpu/ops/GrShadowRRectOp.cpp
@@ -540,6 +540,8 @@
 
     }
 
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -563,21 +565,6 @@
                                                                    fixedDynamicState);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         int instanceCount = fGeoData.count();
 
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 4b95078..2dbbf37 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -311,6 +311,11 @@
         int fInstancesToFlush;
     };
 
+    GrProgramInfo* programInfo() override {
+        // TODO [PI]: implement
+        return nullptr;
+    }
+
     void onCreateProgramInfo(const GrCaps*,
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* outputView,
@@ -319,6 +324,13 @@
         // TODO [PI]: implement
     }
 
+    void onPrePrepareDraws(GrRecordingContext*,
+                           const GrSurfaceProxyView* outputView,
+                           GrAppliedClip*,
+                           const GrXferProcessor::DstProxyView&) override {
+        // TODO [PI]: implement
+    }
+
     void onPrepareDraws(Target* target) override {
         int instanceCount = fShapes.count();
 
diff --git a/src/gpu/ops/GrStrokeRectOp.cpp b/src/gpu/ops/GrStrokeRectOp.cpp
index a4f0433..639423e 100644
--- a/src/gpu/ops/GrStrokeRectOp.cpp
+++ b/src/gpu/ops/GrStrokeRectOp.cpp
@@ -181,6 +181,8 @@
     }
 
 private:
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -204,21 +206,6 @@
                                                  dstProxyView, gp, primType);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         if (!fProgramInfo) {
             this->createProgramInfo(target);
@@ -471,16 +458,14 @@
     }
 
 private:
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps*,
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* outputView,
                              GrAppliedClip&&,
                              const GrXferProcessor::DstProxyView&) override;
 
-    void onPrePrepareDraws(GrRecordingContext*,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip*,
-                           const GrXferProcessor::DstProxyView&) override;
     void onPrepareDraws(Target*) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
 
@@ -556,21 +541,6 @@
                                              GrPrimitiveType::kTriangles);
 }
 
-void AAStrokeRectOp::onPrePrepareDraws(GrRecordingContext* context,
-                                       const GrSurfaceProxyView* outputView,
-                                       GrAppliedClip* clip,
-                                       const GrXferProcessor::DstProxyView& dstProxyView) {
-    SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-    // This is equivalent to a GrOpFlushState::detachAppliedClip
-    GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-    this->createProgramInfo(context->priv().caps(), arena, outputView,
-                            std::move(appliedClip), dstProxyView);
-
-    context->priv().recordProgramInfo(fProgramInfo);
-}
-
 void AAStrokeRectOp::onPrepareDraws(Target* target) {
 
     if (!fProgramInfo) {
diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp
index 9fa75d2..97cdb87 100644
--- a/src/gpu/ops/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp
@@ -321,6 +321,8 @@
         this->createMesh(target, std::move(vertexBuffer), firstVertex, count);
     }
 
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -370,21 +372,6 @@
                                                              gp, primitiveType);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         if (fAntiAlias) {
             this->drawAA(target);
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 80cbb65..672e6ea 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -642,6 +642,12 @@
         return quadCount;
     }
 
+    GrProgramInfo* programInfo() override {
+        // This Op implements its own onPrePrepareDraws so this entry point should never be called.
+        SkASSERT(0);
+        return nullptr;
+    }
+
     void onCreateProgramInfo(const GrCaps*,
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* outputView,
diff --git a/tests/OnFlushCallbackTest.cpp b/tests/OnFlushCallbackTest.cpp
index a88a847..c639c6f 100644
--- a/tests/OnFlushCallbackTest.cpp
+++ b/tests/OnFlushCallbackTest.cpp
@@ -97,6 +97,8 @@
     SkRect      fRect;
 
 private:
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -120,21 +122,6 @@
                                                  dstProxyView, gp, GrPrimitiveType::kTriangles);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
 
         // The vertex attrib order is always pos, color, local coords.
diff --git a/tests/PrimitiveProcessorTest.cpp b/tests/PrimitiveProcessorTest.cpp
index 3327968..3990385 100644
--- a/tests/PrimitiveProcessorTest.cpp
+++ b/tests/PrimitiveProcessorTest.cpp
@@ -56,6 +56,8 @@
         this->setBounds(SkRect::MakeWH(1.f, 1.f), HasAABloat::kNo, IsHairline::kNo);
     }
 
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
+
     void onCreateProgramInfo(const GrCaps* caps,
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* outputView,
@@ -134,21 +136,6 @@
                                                                    GrPipeline::InputFlags::kNone);
     }
 
-    void onPrePrepareDraws(GrRecordingContext* context,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
-        SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-        // This is equivalent to a GrOpFlushState::detachAppliedClip
-        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-        this->createProgramInfo(context->priv().caps(), arena, outputView,
-                                std::move(appliedClip), dstProxyView);
-
-        context->priv().recordProgramInfo(fProgramInfo);
-    }
-
     void onPrepareDraws(Target* target) override {
         if (!fProgramInfo) {
             this->createProgramInfo(target);
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index 5121e91..bfbc1fe 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -64,11 +64,16 @@
         this->setBounds(SkRect::MakeWH(100, 100), HasAABloat::kNo, IsHairline::kNo);
     }
 
+    GrProgramInfo* programInfo() override { return nullptr; }
     void onCreateProgramInfo(const GrCaps*,
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* outputView,
                              GrAppliedClip&&,
                              const GrXferProcessor::DstProxyView&) override { return; }
+    void onPrePrepareDraws(GrRecordingContext*,
+                           const GrSurfaceProxyView* outputView,
+                           GrAppliedClip*,
+                           const GrXferProcessor::DstProxyView&) override { return; }
     void onPrepareDraws(Target* target) override { return; }
     void onExecute(GrOpFlushState*, const SkRect&) override { return; }
 
diff --git a/tools/gpu/TestOps.cpp b/tools/gpu/TestOps.cpp
index e18a4e7..9c926aa 100644
--- a/tools/gpu/TestOps.cpp
+++ b/tools/gpu/TestOps.cpp
@@ -102,16 +102,13 @@
                const SkRect& localRect,
                const SkMatrix& localMatrix);
 
+    GrProgramInfo* programInfo() override { return fProgramInfo; }
     void onCreateProgramInfo(const GrCaps*,
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* outputView,
                              GrAppliedClip&&,
                              const GrXferProcessor::DstProxyView&) override;
 
-    void onPrePrepareDraws(GrRecordingContext*,
-                           const GrSurfaceProxyView* outputView,
-                           GrAppliedClip*,
-                           const GrXferProcessor::DstProxyView&) final;
     void onPrepareDraws(Target*) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
 
@@ -182,21 +179,6 @@
                                                                GrPipeline::InputFlags::kNone);
 }
 
-void TestRectOp::onPrePrepareDraws(GrRecordingContext* context,
-                                   const GrSurfaceProxyView* outputView,
-                                   GrAppliedClip* clip,
-                                   const GrXferProcessor::DstProxyView& dstProxyView) {
-    SkArenaAlloc* arena = context->priv().recordTimeAllocator();
-
-    // This is equivalent to a GrOpFlushState::detachAppliedClip
-    GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
-
-    this->createProgramInfo(context->priv().caps(), arena, outputView,
-                            std::move(appliedClip), dstProxyView);
-
-    context->priv().recordProgramInfo(fProgramInfo);
-}
-
 void TestRectOp::onPrepareDraws(Target* target) {
     QuadHelper helper(target, fGP.vertexStride(), 1);
     GrVertexWriter writer{helper.vertices()};