Add onPrePrepareDraws to GrFillRectOp
In DDL-mode, this pulls the tessellation of the GrFillRectOp's vertices forward to record time.
Bug: skia:9601
Change-Id: I1a505845cc20f795d6f171b4c19d779475fdd240
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/257685
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/ops/GrFillRectOp.cpp b/src/gpu/ops/GrFillRectOp.cpp
index 050a461..ab5c833 100644
--- a/src/gpu/ops/GrFillRectOp.cpp
+++ b/src/gpu/ops/GrFillRectOp.cpp
@@ -185,24 +185,62 @@
int numQuads() const final { return fQuads.count(); }
#endif
- void onPrepareDraws(Target* target) override {
- TRACE_EVENT0("skia.gpu", TRACE_FUNC);
-
- using Domain = GrQuadPerEdgeAA::Domain;
- static constexpr SkRect kEmptyDomain = SkRect::MakeEmpty();
-
+ VertexSpec vertexSpec() const {
auto indexBufferOption = GrQuadPerEdgeAA::CalcIndexBufferOption(fHelper.aaType(),
fQuads.count());
- VertexSpec vertexSpec(fQuads.deviceQuadType(), fColorType, fQuads.localQuadType(),
- fHelper.usesLocalCoords(), Domain::kNo, fHelper.aaType(),
- fHelper.compatibleWithCoverageAsAlpha(), indexBufferOption);
+ return VertexSpec(fQuads.deviceQuadType(), fColorType, fQuads.localQuadType(),
+ fHelper.usesLocalCoords(), GrQuadPerEdgeAA::Domain::kNo,
+ fHelper.aaType(),
+ fHelper.compatibleWithCoverageAsAlpha(), indexBufferOption);
+ }
+
+ void onPrePrepareDraws(GrRecordingContext* context,
+ const GrSurfaceProxyView*,
+ GrAppliedClip*,
+ const GrXferProcessor::DstProxyView&) override {
+ TRACE_EVENT0("skia.gpu", TRACE_FUNC);
+
+ SkASSERT(!fPrePreparedVertices);
+
+ SkArenaAlloc* arena = context->priv().recordTimeAllocator();
+
+ const VertexSpec vertexSpec = this->vertexSpec();
+
+ const int totalNumVertices = fQuads.count() * vertexSpec.verticesPerQuad();
+ const size_t totalVertexSizeInBytes = vertexSpec.vertexSize() * totalNumVertices;
+
+ fPrePreparedVertices = arena->makeArrayDefault<char>(totalVertexSizeInBytes);
+
+ this->tessellate(vertexSpec, fPrePreparedVertices);
+ }
+
+ void tessellate(const VertexSpec& vertexSpec, char* dst) const {
+ static constexpr SkRect kEmptyDomain = SkRect::MakeEmpty();
+
+ GrQuadPerEdgeAA::Tessellator tessellator(vertexSpec, dst);
+ auto iter = fQuads.iterator();
+ while (iter.next()) {
+ // All entries should have local coords, or no entries should have local coords,
+ // matching !helper.isTrivial() (which is more conservative than helper.usesLocalCoords)
+ SkASSERT(iter.isLocalValid() != fHelper.isTrivial());
+ auto info = iter.metadata();
+ tessellator.append(iter.deviceQuad(), iter.localQuad(),
+ info.fColor, kEmptyDomain, info.fAAFlags);
+ }
+ }
+
+ void onPrepareDraws(Target* target) override {
+ TRACE_EVENT0("skia.gpu", TRACE_FUNC);
+
+ const VertexSpec vertexSpec = this->vertexSpec();
+
// Make sure that if the op thought it was a solid color, the vertex spec does not use
// local coords.
SkASSERT(!fHelper.isTrivial() || !fHelper.usesLocalCoords());
GrGeometryProcessor* gp = GrQuadPerEdgeAA::MakeProcessor(target->allocator(), vertexSpec);
- size_t vertexSize = gp->vertexStride();
+ SkASSERT(gp->vertexStride() == vertexSpec.vertexSize());
sk_sp<const GrBuffer> vertexBuffer;
int vertexOffsetInBuffer = 0;
@@ -210,22 +248,19 @@
const int totalNumVertices = fQuads.count() * vertexSpec.verticesPerQuad();
// Fill the allocated vertex data
- void* vdata = target->makeVertexSpace(vertexSize, totalNumVertices,
+ void* vdata = target->makeVertexSpace(vertexSpec.vertexSize(), totalNumVertices,
&vertexBuffer, &vertexOffsetInBuffer);
if (!vdata) {
SkDebugf("Could not allocate vertices\n");
return;
}
- GrQuadPerEdgeAA::Tessellator tessellator(vertexSpec, (char*) vdata);
- auto iter = fQuads.iterator();
- while(iter.next()) {
- // All entries should have local coords, or no entries should have local coords,
- // matching !helper.isTrivial() (which is more conservative than helper.usesLocalCoords)
- SkASSERT(iter.isLocalValid() != fHelper.isTrivial());
- auto info = iter.metadata();
- tessellator.append(iter.deviceQuad(), iter.localQuad(),
- info.fColor, kEmptyDomain, info.fAAFlags);
+ if (fPrePreparedVertices) {
+ const size_t totalVertexSizeInBytes = vertexSpec.vertexSize() * totalNumVertices;
+
+ memcpy(vdata, fPrePreparedVertices, totalVertexSizeInBytes);
+ } else {
+ this->tessellate(vertexSpec, (char*) vdata);
}
sk_sp<const GrBuffer> indexBuffer;
@@ -336,6 +371,7 @@
Helper fHelper;
GrQuadBuffer<ColorAndAA> fQuads;
+ char* fPrePreparedVertices = nullptr;
ColorType fColorType;