Add FwidthSquircleTestOp::onPrePrepare
This CL also introduces creating the geometryProcessor in the arena (which bypasses the GrProcessor memory pool).
Bug: skia:9455
Change-Id: Ia9d5c0d886ea918d9e4209078a1f7e8595234d0e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/254963
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/gm/fwidth_squircle.cpp b/gm/fwidth_squircle.cpp
index 7429664..f761783 100644
--- a/gm/fwidth_squircle.cpp
+++ b/gm/fwidth_squircle.cpp
@@ -65,19 +65,30 @@
class FwidthSquircleTestProcessor : public GrGeometryProcessor {
public:
+ static GrGeometryProcessor* Make(SkArenaAlloc* arena, const SkMatrix& viewMatrix) {
+ return arena->make<FwidthSquircleTestProcessor>(viewMatrix);
+ }
+
+ const char* name() const override { return "FwidthSquircleTestProcessor"; }
+
+ void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const final {}
+
+ GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
+
+private:
+ friend class ::SkArenaAlloc; // for access to ctor
+
FwidthSquircleTestProcessor(const SkMatrix& viewMatrix)
: GrGeometryProcessor(kFwidthSquircleTestProcessor_ClassID)
, fViewMatrix(viewMatrix) {
this->setVertexAttributes(&gVertex, 1);
}
- const char* name() const override { return "FwidthSquircleTestProcessor"; }
- void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const final {}
- GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
-private:
const SkMatrix fViewMatrix;
class Impl;
+
+ typedef GrGeometryProcessor INHERITED;
};
class FwidthSquircleTestProcessor::Impl : public GrGLSLGeometryProcessor {
@@ -153,11 +164,37 @@
const char* name() const override { return "FwidthSquircleTestOp"; }
FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
- GrProcessorSet::Analysis finalize(
- const GrCaps&, const GrAppliedClip*, bool hasMixedSampledCoverage, GrClampType) override {
+ GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
+ bool hasMixedSampledCoverage, GrClampType) override {
return GrProcessorSet::EmptySetAnalysis();
}
- void onPrepare(GrOpFlushState* flushState) override {
+
+ void onPrePrepare(GrRecordingContext* context,
+ const GrSurfaceProxyView* dstView,
+ const GrAppliedClip*) final {
+ // We're going to create the GrProgramInfo (and the GrPipeline and geometry processor
+ // it relies on) in the DDL-record-time arena.
+ SkArenaAlloc* arena = context->priv().recordTimeAllocator();
+
+ // Not POD! It has some sk_sp's buried inside it!
+ GrPipeline* pipeline = arena->make<GrPipeline>(GrScissorTest::kDisabled,
+ SkBlendMode::kSrcOver,
+ dstView->swizzle());
+
+ GrPrimitiveProcessor* geomProc = FwidthSquircleTestProcessor::Make(arena, fViewMatrix);
+
+ // The programInfo is POD
+ GrRenderTargetProxy* dstProxy = dstView->asRenderTargetProxy();
+ fProgramInfo = arena->make<GrProgramInfo>(dstProxy->numSamples(),
+ dstProxy->numStencilSamples(),
+ dstView->origin(),
+ pipeline,
+ geomProc,
+ nullptr, nullptr, 0,
+ GrPrimitiveType::kTriangleStrip);
+ }
+
+ void onPrepare(GrOpFlushState* flushState) final {
SkPoint vertices[4] = {
{-1, -1},
{+1, -1},
@@ -167,35 +204,58 @@
fVertexBuffer = flushState->resourceProvider()->createBuffer(
sizeof(vertices), GrGpuBufferType::kVertex, kStatic_GrAccessPattern, vertices);
}
- void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
+
+ void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) final {
if (!fVertexBuffer) {
return;
}
- GrPipeline pipeline(GrScissorTest::kDisabled, SkBlendMode::kSrcOver,
- flushState->drawOpArgs().outputSwizzle());
-
- FwidthSquircleTestProcessor primProc(fViewMatrix);
-
- GrProgramInfo programInfo(flushState->proxy()->numSamples(),
- flushState->proxy()->numStencilSamples(),
- flushState->drawOpArgs().origin(),
- &pipeline,
- &primProc,
- nullptr, nullptr, 0,
- GrPrimitiveType::kTriangleStrip);
GrMesh mesh(GrPrimitiveType::kTriangleStrip);
mesh.setNonIndexedNonInstanced(4);
mesh.setVertexData(std::move(fVertexBuffer));
- flushState->opsRenderPass()->draw(programInfo, &mesh, 1, SkRect::MakeIWH(kWidth, kHeight));
+
+ if (fProgramInfo) {
+ flushState->opsRenderPass()->draw(*fProgramInfo, &mesh, 1,
+ SkRect::MakeIWH(kWidth, kHeight));
+ } else {
+ const GrSurfaceProxyView* dstView = flushState->view();
+
+ GrPipeline pipeline(GrScissorTest::kDisabled,
+ SkBlendMode::kSrcOver,
+ dstView->swizzle());
+
+ GrGeometryProcessor* gp = FwidthSquircleTestProcessor::Make(flushState->allocator(),
+ fViewMatrix);
+
+ GrProgramInfo programInfo(dstView->asRenderTargetProxy()->numSamples(),
+ dstView->asRenderTargetProxy()->numStencilSamples(),
+ dstView->origin(),
+ &pipeline,
+ gp,
+ nullptr, nullptr, 0,
+ GrPrimitiveType::kTriangleStrip);
+
+ flushState->opsRenderPass()->draw(programInfo, &mesh, 1,
+ SkRect::MakeIWH(kWidth, kHeight));
+ }
}
- sk_sp<GrBuffer> fVertexBuffer;
- const SkMatrix fViewMatrix;
static const int kWidth = 200;
static const int kHeight = 200;
+ sk_sp<GrBuffer> fVertexBuffer;
+ const SkMatrix fViewMatrix;
+
+ // The program info (and both the GrPipeline and GrPrimitiveProcessor it relies on), when
+ // allocated, are allocated in the ddl-record-time arena. It is the arena's job to free up
+ // their memory so we just have a bare programInfo pointer here. We don't even store the
+ // GrPipeline and GrPrimitiveProcessor pointers here bc they are guaranteed to have the
+ // same lifetime as the program info.
+ GrProgramInfo* fProgramInfo = nullptr;
+
friend class ::GrOpMemoryPool; // for ctor
+
+ typedef GrDrawOp INHERITED;
};
////////////////////////////////////////////////////////////////////////////////////////////////////