Add onPrePrepare to GrFillRRectOp

As the first real op to be updated this required the plumbing of the DstProxyView and the de-constification of the GrAppliedClip.

Bug: skia:9455
Change-Id: Ieaa16adfa1d114021b2ad60d0ef8ecbe31d9cc82
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/255136
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/ops/GrFillRRectOp.cpp b/src/gpu/ops/GrFillRRectOp.cpp
index 27b8f54..c0ba65b 100644
--- a/src/gpu/ops/GrFillRRectOp.cpp
+++ b/src/gpu/ops/GrFillRRectOp.cpp
@@ -94,9 +94,9 @@
     return pool->allocate<GrFillRRectOp>(aaType, rrect, flags, m, std::move(paint), devBounds);
 }
 
-GrFillRRectOp::GrFillRRectOp(
-        GrAAType aaType, const SkRRect& rrect, Flags flags,
-        const SkMatrix& totalShapeMatrix, GrPaint&& paint, const SkRect& devBounds)
+GrFillRRectOp::GrFillRRectOp(GrAAType aaType, const SkRRect& rrect, Flags flags,
+                             const SkMatrix& totalShapeMatrix, GrPaint&& paint,
+                             const SkRect& devBounds)
         : GrDrawOp(ClassID())
         , fAAType(aaType)
         , fOriginalColor(paint.getColor4f())
@@ -135,7 +135,6 @@
 
     SkPMColor4f overrideColor;
     const GrProcessorSet::Analysis& analysis = fProcessors.finalize(
-
             fOriginalColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
             &GrUserStencilSettings::kUnused, hasMixedSampledCoverage, caps, clampType,
             &overrideColor);
@@ -179,13 +178,13 @@
         return arena->make<Processor>(aaType, flags);
     }
 
-    const char* name() const override { return "GrFillRRectOp::Processor"; }
+    const char* name() const final { return "GrFillRRectOp::Processor"; }
 
-    void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
+    void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const final {
         b->add32(((uint32_t)fFlags << 16) | (uint32_t)fAAType);
     }
 
-    GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
+    GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
 
 private:
     friend class ::SkArenaAlloc; // for access to ctor
@@ -450,6 +449,20 @@
 
 GR_DECLARE_STATIC_UNIQUE_KEY(gMSAAIndexBufferKey);
 
+void GrFillRRectOp::onPrePrepare(GrRecordingContext* context,
+                                 const GrSurfaceProxyView* dstView,
+                                 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();
+
+    // TODO: need to also give this to the recording context
+    fProgramInfo = this->createProgramInfo(context->priv().caps(), arena, dstView,
+                                           std::move(appliedClip), dstProxyView);
+}
+
 void GrFillRRectOp::onPrepare(GrOpFlushState* flushState) {
     if (void* instanceData = flushState->makeVertexSpace(fInstanceStride, fInstanceCount,
                                                          &fInstanceBuffer, &fBaseInstance)) {
@@ -738,49 +751,66 @@
     return new CoverageImpl();
 }
 
-void GrFillRRectOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
-    if (!fInstanceBuffer || !fIndexBuffer || !fVertexBuffer) {
-        return;  // Setup failed.
-    }
-
-    Processor* proc = flushState->allocator()->make<Processor>(fAAType, fFlags);
-    SkASSERT(proc->instanceStride() == (size_t)fInstanceStride);
+GrProgramInfo* GrFillRRectOp::createProgramInfo(const GrCaps* caps,
+                                                SkArenaAlloc* arena,
+                                                const GrSurfaceProxyView* dstView,
+                                                GrAppliedClip&& appliedClip,
+                                                const GrXferProcessor::DstProxyView& dstProxyView) {
+    GrGeometryProcessor* geomProc = Processor::Make(arena, fAAType, fFlags);
+    SkASSERT(geomProc->instanceStride() == (size_t)fInstanceStride);
 
     GrPipeline::InitArgs initArgs;
     if (GrAAType::kMSAA == fAAType) {
         initArgs.fInputFlags = GrPipeline::InputFlags::kHWAntialias;
     }
-    initArgs.fCaps = &flushState->caps();
-    initArgs.fDstProxyView = flushState->drawOpArgs().dstProxyView();
-    initArgs.fOutputSwizzle = flushState->drawOpArgs().outputSwizzle();
-    auto clip = flushState->detachAppliedClip();
+    initArgs.fCaps = caps;
+    initArgs.fDstProxyView = dstProxyView;
+    initArgs.fOutputSwizzle = dstView->swizzle();
+
     GrPipeline::FixedDynamicState* fixedDynamicState = nullptr;
 
-    if (clip.scissorState().enabled()) {
-        fixedDynamicState = flushState->allocator()->make<GrPipeline::FixedDynamicState>(
-                                                                    clip.scissorState().rect());
+    if (appliedClip.scissorState().enabled()) {
+        fixedDynamicState = arena->make<GrPipeline::FixedDynamicState>(
+                                                        appliedClip.scissorState().rect());
     }
 
-    GrPipeline* pipeline = flushState->allocator()->make<GrPipeline>(initArgs,
-                                                                     std::move(fProcessors),
-                                                                     std::move(clip));
+    GrPipeline* pipeline = arena->make<GrPipeline>(initArgs,
+                                                   std::move(fProcessors),
+                                                   std::move(appliedClip));
 
-    GrProgramInfo programInfo(flushState->proxy()->numSamples(),
-                              flushState->proxy()->numStencilSamples(),
-                              flushState->drawOpArgs().origin(),
-                              pipeline,
-                              proc,
-                              fixedDynamicState,
-                              nullptr, 0,
-                              GrPrimitiveType::kTriangles);
+    GrRenderTargetProxy* dstProxy = dstView->asRenderTargetProxy();
+    return arena->make<GrProgramInfo>(dstProxy->numSamples(),
+                                      dstProxy->numStencilSamples(),
+                                      dstView->origin(),
+                                      pipeline,
+                                      geomProc,
+                                      fixedDynamicState,
+                                      nullptr, 0,
+                                      GrPrimitiveType::kTriangles);
+}
+
+void GrFillRRectOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
+    if (!fInstanceBuffer || !fIndexBuffer || !fVertexBuffer) {
+        return;  // Setup failed.
+    }
+
+    if (!fProgramInfo) {
+        const GrSurfaceProxyView* dstView = flushState->view();
+
+        fProgramInfo = this->createProgramInfo(&flushState->caps(),
+                                               flushState->allocator(),
+                                               dstView,
+                                               flushState->detachAppliedClip(),
+                                               flushState->dstProxyView());
+    }
 
     GrMesh* mesh = flushState->allocator()->make<GrMesh>(GrPrimitiveType::kTriangles);
-    mesh->setIndexedInstanced(
-            std::move(fIndexBuffer), fIndexCount, std::move(fInstanceBuffer), fInstanceCount,
-            fBaseInstance, GrPrimitiveRestart::kNo);
+    mesh->setIndexedInstanced(std::move(fIndexBuffer), fIndexCount,
+                              std::move(fInstanceBuffer), fInstanceCount,
+                              fBaseInstance, GrPrimitiveRestart::kNo);
     mesh->setVertexData(std::move(fVertexBuffer));
-    flushState->opsRenderPass()->draw(programInfo, mesh, 1, this->bounds());
-    fIndexCount = 0;
+
+    flushState->opsRenderPass()->draw(*fProgramInfo, mesh, 1, this->bounds());
 }
 
 // Will the given corner look good if we use HW derivatives?
diff --git a/src/gpu/ops/GrFillRRectOp.h b/src/gpu/ops/GrFillRRectOp.h
index c3e7599..c6ad1e2 100644
--- a/src/gpu/ops/GrFillRRectOp.h
+++ b/src/gpu/ops/GrFillRRectOp.h
@@ -8,6 +8,7 @@
 #ifndef GrFillRRectOp_DEFINED
 #define GrFillRRectOp_DEFINED
 
+#include "src/gpu/GrProgramInfo.h"
 #include "src/gpu/ops/GrDrawOp.h"
 
 class GrRecordingContext;
@@ -20,21 +21,29 @@
             GrRecordingContext*, GrAAType, const SkMatrix& viewMatrix, const SkRRect&,
             const GrCaps&, GrPaint&&);
 
-    const char* name() const override { return "GrFillRRectOp"; }
-    FixedFunctionFlags fixedFunctionFlags() const override {
-        return (GrAAType::kMSAA == fAAType)
-                ? FixedFunctionFlags::kUsesHWAA
-                : FixedFunctionFlags::kNone;
+    const char* name() const final { return "GrFillRRectOp"; }
+
+    FixedFunctionFlags fixedFunctionFlags() const final {
+        return (GrAAType::kMSAA == fAAType) ? FixedFunctionFlags::kUsesHWAA
+                                            : FixedFunctionFlags::kNone;
     }
     GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
-                                      bool hasMixedSampledCoverage, GrClampType) override;
-    CombineResult onCombineIfPossible(GrOp*, const GrCaps&) override;
+                                      bool hasMixedSampledCoverage, GrClampType) final;
+    CombineResult onCombineIfPossible(GrOp*, const GrCaps&) final;
     void visitProxies(const VisitProxyFunc& fn) const override {
-        fProcessors.visitProxies(fn);
+        if (fProgramInfo) {
+            fProgramInfo->visitProxies(fn);
+        } else {
+            fProcessors.visitProxies(fn);
+        }
     }
-    void onPrepare(GrOpFlushState*) override;
 
-    void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
+    void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView*, GrAppliedClip*,
+                      const GrXferProcessor::DstProxyView&) final;
+
+    void onPrepare(GrOpFlushState*) final;
+
+    void onExecute(GrOpFlushState*, const SkRect& chainBounds) final;
 
 private:
     enum class Flags {
@@ -68,6 +77,13 @@
 
     void writeInstanceData() {}  // Halt condition.
 
+    // Create a GrProgramInfo object in the provided arena
+    GrProgramInfo* createProgramInfo(const GrCaps*,
+                                     SkArenaAlloc*,
+                                     const GrSurfaceProxyView* dstView,
+                                     GrAppliedClip&&,
+                                     const GrXferProcessor::DstProxyView&);
+
     const GrAAType fAAType;
     const SkPMColor4f fOriginalColor;
     const SkRect fLocalRect;
@@ -81,9 +97,13 @@
     sk_sp<const GrBuffer> fInstanceBuffer;
     sk_sp<const GrBuffer> fVertexBuffer;
     sk_sp<const GrBuffer> fIndexBuffer;
-    int fBaseInstance;
+    int fBaseInstance = 0;
     int fIndexCount = 0;
 
+    // If this op is prePrepared the created programInfo will be stored here from use in
+    // onExecute. In the prePrepared case it will have been stored in the record-time arena.
+    GrProgramInfo* fProgramInfo = nullptr;
+
     friend class GrOpMemoryPool;
 };
 
diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h
index cf259c7..7ba78db 100644
--- a/src/gpu/ops/GrMeshDrawOp.h
+++ b/src/gpu/ops/GrMeshDrawOp.h
@@ -89,15 +89,17 @@
 private:
     void onPrePrepare(GrRecordingContext* context,
                       const GrSurfaceProxyView* dstView,
-                      const GrAppliedClip* clip) final {
-        this->onPrePrepareDraws(context, dstView, clip);
+                      GrAppliedClip* clip,
+                      const GrXferProcessor::DstProxyView& dstProxyView) final {
+        this->onPrePrepareDraws(context, dstView, clip, dstProxyView);
     }
     void onPrepare(GrOpFlushState* state) final;
 
     // Only the GrTextureOp currently overrides this virtual
     virtual void onPrePrepareDraws(GrRecordingContext*,
                                    const GrSurfaceProxyView*,
-                                   const GrAppliedClip*) {}
+                                   GrAppliedClip*,
+                                   const GrXferProcessor::DstProxyView&) {}
 
     virtual void onPrepareDraws(Target*) = 0;
     typedef GrDrawOp INHERITED;
@@ -186,7 +188,7 @@
 
     virtual GrRenderTargetProxy* proxy() const = 0;
 
-    virtual const GrAppliedClip* appliedClip() = 0;
+    virtual const GrAppliedClip* appliedClip() const = 0;
     virtual GrAppliedClip detachAppliedClip() = 0;
 
     virtual const GrXferProcessor::DstProxyView& dstProxyView() const = 0;
diff --git a/src/gpu/ops/GrOp.h b/src/gpu/ops/GrOp.h
index 7dfa7bc..4d58666 100644
--- a/src/gpu/ops/GrOp.h
+++ b/src/gpu/ops/GrOp.h
@@ -159,8 +159,9 @@
      * onPrePrepare must be prepared to handle both cases (when onPrePrepare has been called
      * ahead of time and when it has not been called).
      */
-    void prePrepare(GrRecordingContext* context, GrSurfaceProxyView* dstView, GrAppliedClip* clip) {
-        this->onPrePrepare(context, dstView, clip);
+    void prePrepare(GrRecordingContext* context, GrSurfaceProxyView* dstView, GrAppliedClip* clip,
+                    const GrXferProcessor::DstProxyView& dstProxyView) {
+        this->onPrePrepare(context, dstView, clip, dstProxyView);
     }
 
     /**
@@ -291,9 +292,11 @@
         return CombineResult::kCannotCombine;
     }
 
-    // Only GrMeshDrawOp currently overrides this virtual
-    virtual void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView*,
-                              const GrAppliedClip*) {}
+    // TODO: the parameters to onPrePrepare mirror GrOpFlushState::OpArgs - fuse the two?
+    virtual void onPrePrepare(GrRecordingContext*,
+                              const GrSurfaceProxyView*,
+                              GrAppliedClip*,
+                              const GrXferProcessor::DstProxyView&) {}
     virtual void onPrepare(GrOpFlushState*) = 0;
     // If this op is chained then chainBounds is the union of the bounds of all ops in the chain.
     // Otherwise, this op's bounds.
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index d61d968..23f140b 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -516,7 +516,8 @@
 
     void onPrePrepareDraws(GrRecordingContext* context,
                            const GrSurfaceProxyView* dstView,
-                           const GrAppliedClip* clip) override {
+                           GrAppliedClip* clip,
+                           const GrXferProcessor::DstProxyView& dstProxyView) override {
         TRACE_EVENT0("skia.gpu", TRACE_FUNC);
 
         SkDEBUGCODE(this->validate();)