Move GrTessellator::VertexAllocator to GrEagerVertexAllocator
Moves the interface up to Ganesh level and starts using it from other
locations.
Change-Id: I939d2b357d3ae8551976d0d71b877b72da403712
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/266063
Reviewed-by: Stephen White <senorblanco@chromium.org>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index a2e3839..0dcd690 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -89,6 +89,7 @@
"$_src/gpu/GrDrawOpTest.cpp",
"$_src/gpu/GrDrawOpTest.h",
"$_src/gpu/GrDriverBugWorkarounds.cpp",
+ "$_src/gpu/GrEagerVertexAllocator.h",
"$_src/gpu/GrFixedClip.cpp",
"$_src/gpu/GrFixedClip.h",
"$_src/gpu/GrFragmentProcessor.cpp",
diff --git a/src/gpu/GrEagerVertexAllocator.h b/src/gpu/GrEagerVertexAllocator.h
new file mode 100644
index 0000000..2bf23d0
--- /dev/null
+++ b/src/gpu/GrEagerVertexAllocator.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrEagerVertexAllocator_DEFINED
+#define GrEagerVertexAllocator_DEFINED
+
+#include "src/gpu/ops/GrMeshDrawOp.h"
+
+// This interface is used to allocate and map GPU vertex data before the exact number of required
+// vertices is known. Usage pattern:
+//
+// 1. Call lock(eagerCount) with an upper bound on the number of required vertices.
+// 2. Compute and write vertex data to the returned pointer (if not null).
+// 3. Call unlock(actualCount) and provide the actual number of vertices written during step #2.
+//
+// On step #3, the implementation will attempt to shrink the underlying GPU memory slot to fit the
+// actual vertex count.
+class GrEagerVertexAllocator {
+public:
+ template<typename T> T* lock(int eagerCount) {
+ return static_cast<T*>(this->lock(sizeof(T), eagerCount));
+ }
+ virtual void* lock(size_t stride, int eagerCount) = 0;
+
+ virtual void unlock(int actualCount) = 0;
+
+ virtual ~GrEagerVertexAllocator() {}
+};
+
+// GrEagerVertexAllocator implementation that uses GrMeshDrawOp::Target::makeVertexSpace and
+// GrMeshDrawOp::Target::putBackVertices.
+class GrEagerDynamicVertexAllocator : public GrEagerVertexAllocator {
+public:
+ GrEagerDynamicVertexAllocator(GrMeshDrawOp::Target* target,
+ sk_sp<const GrBuffer>* vertexBuffer, int* baseVertex)
+ : fTarget(target)
+ , fVertexBuffer(vertexBuffer)
+ , fBaseVertex(baseVertex) {
+ }
+
+#ifdef SK_DEBUG
+ ~GrEagerDynamicVertexAllocator() override {
+ SkASSERT(!fLockCount);
+ }
+#endif
+
+ void* lock(size_t stride, int eagerCount) override {
+ SkASSERT(!fLockCount);
+ SkASSERT(eagerCount);
+ if (void* data = fTarget->makeVertexSpace(stride, eagerCount, fVertexBuffer, fBaseVertex)) {
+ fLockStride = stride;
+ fLockCount = eagerCount;
+ return data;
+ }
+ fVertexBuffer->reset();
+ *fBaseVertex = 0;
+ return nullptr;
+ }
+
+ void unlock(int actualCount) override {
+ SkASSERT(fLockCount);
+ SkASSERT(actualCount <= fLockCount);
+ fTarget->putBackVertices(fLockCount - actualCount, fLockStride);
+ if (!actualCount) {
+ fVertexBuffer->reset();
+ *fBaseVertex = 0;
+ }
+ fLockCount = 0;
+ }
+
+private:
+ GrMeshDrawOp::Target* const fTarget;
+ sk_sp<const GrBuffer>* const fVertexBuffer;
+ int* const fBaseVertex;
+
+ size_t fLockStride;
+ int fLockCount = 0;
+};
+
+#endif
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp
index d6149af..40b73c9 100644
--- a/src/gpu/GrTessellator.cpp
+++ b/src/gpu/GrTessellator.cpp
@@ -8,6 +8,7 @@
#include "src/gpu/GrTessellator.h"
#include "src/gpu/GrDefaultGeoProcFactory.h"
+#include "src/gpu/GrEagerVertexAllocator.h"
#include "src/gpu/GrVertexWriter.h"
#include "src/gpu/geometry/GrPathUtils.h"
@@ -2358,7 +2359,7 @@
// Stage 6: Triangulate the monotone polygons into a vertex buffer.
int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
- VertexAllocator* vertexAllocator, bool antialias, bool* isLinear) {
+ GrEagerVertexAllocator* vertexAllocator, bool antialias, bool* isLinear) {
int contourCnt = get_contour_count(path, tolerance);
if (contourCnt <= 0) {
*isLinear = true;
@@ -2378,7 +2379,8 @@
}
int count = count64;
- void* verts = vertexAllocator->lock(count);
+ size_t vertexStride = GetVertexStride(antialias);
+ void* verts = vertexAllocator->lock(vertexStride, count);
if (!verts) {
SkDebugf("Could not allocate vertices\n");
return 0;
@@ -2389,7 +2391,7 @@
end = outer_mesh_to_triangles(outerMesh, true, end);
int actualCount = static_cast<int>((static_cast<uint8_t*>(end) - static_cast<uint8_t*>(verts))
- / vertexAllocator->stride());
+ / vertexStride);
SkASSERT(actualCount <= count);
vertexAllocator->unlock(actualCount);
return actualCount;
diff --git a/src/gpu/GrTessellator.h b/src/gpu/GrTessellator.h
index e892a19..6e89698 100644
--- a/src/gpu/GrTessellator.h
+++ b/src/gpu/GrTessellator.h
@@ -12,6 +12,7 @@
#include "include/private/SkColorData.h"
#include "src/gpu/GrColor.h"
+class GrEagerVertexAllocator;
class SkPath;
struct SkRect;
@@ -23,17 +24,6 @@
namespace GrTessellator {
-class VertexAllocator {
-public:
- VertexAllocator(size_t stride) : fStride(stride) {}
- virtual ~VertexAllocator() {}
- virtual void* lock(int vertexCount) = 0;
- virtual void unlock(int actualCount) = 0;
- size_t stride() const { return fStride; }
-private:
- size_t fStride;
-};
-
struct WindingVertex {
SkPoint fPos;
int fWinding;
@@ -46,8 +36,12 @@
int PathToVertices(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
WindingVertex** verts);
+constexpr size_t GetVertexStride(bool antialias) {
+ return sizeof(SkPoint) + ((antialias) ? sizeof(float) : 0);
+}
+
int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
- VertexAllocator*, bool antialias, bool *isLinear);
+ GrEagerVertexAllocator*, bool antialias, bool *isLinear);
}
#endif
diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp
index ee4d91d..49f677b 100644
--- a/src/gpu/ops/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp
@@ -13,6 +13,7 @@
#include "src/gpu/GrClip.h"
#include "src/gpu/GrDefaultGeoProcFactory.h"
#include "src/gpu/GrDrawOpTest.h"
+#include "src/gpu/GrEagerVertexAllocator.h"
#include "src/gpu/GrMesh.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrResourceCache.h"
@@ -68,16 +69,22 @@
return false;
}
-class StaticVertexAllocator : public GrTessellator::VertexAllocator {
+class StaticVertexAllocator : public GrEagerVertexAllocator {
public:
- StaticVertexAllocator(size_t stride, GrResourceProvider* resourceProvider, bool canMapVB)
- : VertexAllocator(stride)
- , fResourceProvider(resourceProvider)
+ StaticVertexAllocator(GrResourceProvider* resourceProvider, bool canMapVB)
+ : fResourceProvider(resourceProvider)
, fCanMapVB(canMapVB)
, fVertices(nullptr) {
}
- void* lock(int vertexCount) override {
- size_t size = vertexCount * stride();
+#ifdef SK_DEBUG
+ ~StaticVertexAllocator() override {
+ SkASSERT(!fLockStride);
+ }
+#endif
+ void* lock(size_t stride, int eagerCount) override {
+ SkASSERT(!fLockStride);
+ SkASSERT(stride);
+ size_t size = eagerCount * stride;
fVertexBuffer = fResourceProvider->createBuffer(size, GrGpuBufferType::kVertex,
kStatic_GrAccessPattern);
if (!fVertexBuffer.get()) {
@@ -86,18 +93,21 @@
if (fCanMapVB) {
fVertices = fVertexBuffer->map();
} else {
- fVertices = sk_malloc_throw(vertexCount * stride());
+ fVertices = sk_malloc_throw(eagerCount * stride);
}
+ fLockStride = stride;
return fVertices;
}
void unlock(int actualCount) override {
+ SkASSERT(fLockStride);
if (fCanMapVB) {
fVertexBuffer->unmap();
} else {
- fVertexBuffer->updateData(fVertices, actualCount * stride());
+ fVertexBuffer->updateData(fVertices, actualCount * fLockStride);
sk_free(fVertices);
}
fVertices = nullptr;
+ fLockStride = 0;
}
sk_sp<GrGpuBuffer> detachVertexBuffer() { return std::move(fVertexBuffer); }
@@ -106,33 +116,7 @@
GrResourceProvider* fResourceProvider;
bool fCanMapVB;
void* fVertices;
-};
-
-class DynamicVertexAllocator : public GrTessellator::VertexAllocator {
-public:
- DynamicVertexAllocator(size_t stride, GrMeshDrawOp::Target* target)
- : VertexAllocator(stride)
- , fTarget(target)
- , fVertexBuffer(nullptr)
- , fVertices(nullptr) {}
- void* lock(int vertexCount) override {
- fVertexCount = vertexCount;
- fVertices = fTarget->makeVertexSpace(stride(), vertexCount, &fVertexBuffer, &fFirstVertex);
- return fVertices;
- }
- void unlock(int actualCount) override {
- fTarget->putBackVertices(fVertexCount - actualCount, stride());
- fVertices = nullptr;
- }
- sk_sp<const GrBuffer> detachVertexBuffer() const { return std::move(fVertexBuffer); }
- int firstVertex() const { return fFirstVertex; }
-
-private:
- GrMeshDrawOp::Target* fTarget;
- sk_sp<const GrBuffer> fVertexBuffer;
- int fVertexCount;
- int fFirstVertex;
- void* fVertices;
+ size_t fLockStride = 0;
};
} // namespace
@@ -255,7 +239,7 @@
return path;
}
- void draw(Target* target, const GrGeometryProcessor* gp, size_t vertexStride) {
+ void draw(Target* target, const GrGeometryProcessor* gp) {
SkASSERT(!fAntiAlias);
GrResourceProvider* rp = target->resourceProvider();
bool inverseFill = fShape.inverseFilled();
@@ -292,7 +276,7 @@
vmi.mapRect(&clipBounds);
bool isLinear;
bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags();
- StaticVertexAllocator allocator(vertexStride, rp, canMapVB);
+ StaticVertexAllocator allocator(rp, canMapVB);
int count = GrTessellator::PathToTriangles(getPath(), tol, clipBounds, &allocator, false,
&isLinear);
if (count == 0) {
@@ -309,7 +293,7 @@
this->drawVertices(target, gp, std::move(vb), 0, count);
}
- void drawAA(Target* target, const GrGeometryProcessor* gp, size_t vertexStride) {
+ void drawAA(Target* target, const GrGeometryProcessor* gp) {
SkASSERT(fAntiAlias);
SkPath path = getPath();
if (path.isEmpty()) {
@@ -318,15 +302,16 @@
SkRect clipBounds = SkRect::Make(fDevClipBounds);
path.transform(fViewMatrix);
SkScalar tol = GrPathUtils::kDefaultTolerance;
+ sk_sp<const GrBuffer> vertexBuffer;
+ int firstVertex;
bool isLinear;
- DynamicVertexAllocator allocator(vertexStride, target);
+ GrEagerDynamicVertexAllocator allocator(target, &vertexBuffer, &firstVertex);
int count = GrTessellator::PathToTriangles(path, tol, clipBounds, &allocator, true,
&isLinear);
if (count == 0) {
return;
}
- this->drawVertices(target, gp, allocator.detachVertexBuffer(),
- allocator.firstVertex(), count);
+ this->drawVertices(target, gp, std::move(vertexBuffer), firstVertex, count);
}
void onPrepareDraws(Target* target) override {
@@ -362,11 +347,11 @@
if (!gp) {
return;
}
- size_t vertexStride = gp->vertexStride();
+ SkASSERT(GrTessellator::GetVertexStride(fAntiAlias) == gp->vertexStride());
if (fAntiAlias) {
- this->drawAA(target, gp, vertexStride);
+ this->drawAA(target, gp);
} else {
- this->draw(target, gp, vertexStride);
+ this->draw(target, gp);
}
}
diff --git a/src/gpu/tessellate/GrPathParser.cpp b/src/gpu/tessellate/GrPathParser.cpp
index c6c61ac..a660a0d 100644
--- a/src/gpu/tessellate/GrPathParser.cpp
+++ b/src/gpu/tessellate/GrPathParser.cpp
@@ -9,6 +9,7 @@
#include "include/private/SkTArray.h"
#include "src/core/SkPathPriv.h"
+#include "src/gpu/GrEagerVertexAllocator.h"
static SkPoint lerp(const SkPoint& a, const SkPoint& b, float T) {
SkASSERT(1 != T); // The below does not guarantee lerp(a, b, 1) === b.
@@ -76,7 +77,19 @@
int fMidpointWeight;
};
-int GrPathParser::EmitCenterWedgePatches(const SkPath& path, SkPoint* patchData) {
+constexpr int max_wedge_vertex_count(int numPathVerbs) {
+ // No initial moveTo, one wedge per verb, plus an implicit close at the end.
+ // Each wedge has 5 vertices.
+ return (numPathVerbs + 1) * 5;
+}
+
+int GrPathParser::EmitCenterWedgePatches(const SkPath& path, GrEagerVertexAllocator* vertexAlloc) {
+ int maxVertices = max_wedge_vertex_count(path.countVerbs());
+ auto* vertexData = vertexAlloc->lock<SkPoint>(maxVertices);
+ if (!vertexData) {
+ return 0;
+ }
+
int vertexCount = 0;
MidpointContourParser parser(path);
while (parser.parseNextContour()) {
@@ -88,7 +101,7 @@
case SkPathVerb::kDone:
if (parser.startPoint() != lastPoint) {
lastPoint = write_line_as_cubic(
- patchData + vertexCount, lastPoint, parser.startPoint());
+ vertexData + vertexCount, lastPoint, parser.startPoint());
break;
} // fallthru
default:
@@ -99,29 +112,29 @@
continue;
case SkPathVerb::kLine:
- lastPoint = write_line_as_cubic(patchData + vertexCount, lastPoint,
+ lastPoint = write_line_as_cubic(vertexData + vertexCount, lastPoint,
parser.atPoint(ptsIdx));
++ptsIdx;
break;
case SkPathVerb::kQuad:
- lastPoint = write_quadratic_as_cubic(patchData + vertexCount, lastPoint,
+ lastPoint = write_quadratic_as_cubic(vertexData + vertexCount, lastPoint,
parser.atPoint(ptsIdx),
parser.atPoint(ptsIdx + 1));
ptsIdx += 2;
break;
case SkPathVerb::kCubic:
- lastPoint = write_cubic(patchData + vertexCount, lastPoint,
+ lastPoint = write_cubic(vertexData + vertexCount, lastPoint,
parser.atPoint(ptsIdx), parser.atPoint(ptsIdx + 1),
parser.atPoint(ptsIdx + 2));
ptsIdx += 3;
break;
}
- patchData[vertexCount + 4] = parser.midpoint();
+ vertexData[vertexCount + 4] = parser.midpoint();
vertexCount += 5;
}
}
- SkASSERT(vertexCount <= MaxWedgeVertices(path));
+ vertexAlloc->unlock(vertexCount);
return vertexCount;
}
@@ -147,8 +160,9 @@
class InnerPolygonContourParser : public SkTPathContourParser<InnerPolygonContourParser> {
public:
- InnerPolygonContourParser(const SkPath& path) : SkTPathContourParser(path) {
- fPolyPoints.reserve(GrPathParser::MaxInnerPolygonVertices(path));
+ InnerPolygonContourParser(const SkPath& path, int vertexReserveCount)
+ : SkTPathContourParser(path)
+ , fPolyPoints(vertexReserveCount) {
}
int emitInnerPolygon(SkPoint* vertexData) {
@@ -197,36 +211,51 @@
int fNumCurves;
};
-int GrPathParser::EmitInnerPolygonTriangles(const SkPath& path, SkPoint* vertexData,
- int* numCurves) {
- *numCurves = 0;
- int vertexCount = 0;
- InnerPolygonContourParser parser(path);
- while (parser.parseNextContour()) {
- vertexCount += parser.emitInnerPolygon(vertexData + vertexCount);
- *numCurves += parser.numCurves();
+constexpr int max_inner_poly_vertex_count(int numPathVerbs) {
+ // No initial moveTo, plus an implicit close at the end; n-2 trianles fill an n-gon.
+ // Each triangle has 3 vertices.
+ return (numPathVerbs - 1) * 3;
+}
+
+int GrPathParser::EmitInnerPolygonTriangles(const SkPath& path,
+ GrEagerVertexAllocator* vertexAlloc) {
+ int maxVertices = max_inner_poly_vertex_count(path.countVerbs());
+ InnerPolygonContourParser parser(path, maxVertices);
+ auto* vertexData = vertexAlloc->lock<SkPoint>(maxVertices);
+ if (!vertexData) {
+ return 0;
}
- SkASSERT(vertexCount <= MaxInnerPolygonVertices(path));
+ int vertexCount = 0;
+ while (parser.parseNextContour()) {
+ vertexCount += parser.emitInnerPolygon(vertexData + vertexCount);
+ }
+
+ vertexAlloc->unlock(vertexCount);
return vertexCount;
}
-int GrPathParser::EmitCubicInstances(const SkPath& path, SkPoint* vertexData) {
+int GrPathParser::EmitCubicInstances(const SkPath& path, GrEagerVertexAllocator* vertexAlloc) {
+ auto* instanceData = vertexAlloc->lock<std::array<SkPoint, 4>>(path.countVerbs());
+ if (!instanceData) {
+ return 0;
+ }
+
int instanceCount = 0;
SkPath::Iter iter(path, false);
SkPath::Verb verb;
SkPoint pts[4];
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
if (SkPath::kQuad_Verb == verb) {
- write_quadratic_as_cubic(vertexData + (instanceCount * 4), pts[0], pts[1], pts[2]);
- ++instanceCount;
+ write_quadratic_as_cubic(instanceData[instanceCount++].data(), pts[0], pts[1], pts[2]);
continue;
}
if (SkPath::kCubic_Verb == verb) {
- write_cubic(vertexData + (instanceCount * 4), pts[0], pts[1], pts[2], pts[3]);
- ++instanceCount;
+ instanceData[instanceCount++] = {pts[0], pts[1], pts[2], pts[3]};
continue;
}
}
+
+ vertexAlloc->unlock(instanceCount);
return instanceCount;
}
diff --git a/src/gpu/tessellate/GrPathParser.h b/src/gpu/tessellate/GrPathParser.h
index 76f61cf..61c1128 100644
--- a/src/gpu/tessellate/GrPathParser.h
+++ b/src/gpu/tessellate/GrPathParser.h
@@ -10,48 +10,35 @@
#include "include/core/SkPath.h"
+class GrEagerVertexAllocator;
+
namespace GrPathParser {
-// Returns the maximum number of vertices that can be written by EmitCenterWedges() for the given
-// path.
-inline int MaxWedgeVertices(const SkPath& path) {
- // No initial moveTo, one wedge per verb, plus an implicit close at the end.
- // Each wedge has 5 vertices.
- return (path.countVerbs() + 1) * 5;
-}
-
// Writes an array of cubic "wedges" from an SkPath, converting any lines or quadratics to cubics.
-// These wedges can then be fed into GrTessellateWedgeShader to stencil the path. A wedge is a
-// 5-point tessellation patch consisting of 4 cubic control points, plus an anchor point fanning
-// from the center of the curve's resident contour.
+// These wedges can then be fed into GrStencilWedgeShader to stencil the path. A wedge is a 5-point
+// tessellation patch consisting of 4 cubic control points, plus an anchor point fanning from the
+// center of the curve's resident contour.
//
// TODO: Eventually we want to use rational cubic wedges in order to support conics.
//
// Returns the number of vertices written to the array.
-//
-// The incoming patchData array must have at least MaxWedgeVertices() elements.
-int EmitCenterWedgePatches(const SkPath&, SkPoint* patchData);
+int EmitCenterWedgePatches(const SkPath&, GrEagerVertexAllocator*);
-// Returns the maximum number of vertices required to triangulate the given path's inner polygon(s).
-inline int MaxInnerPolygonVertices(const SkPath& path) {
- // No initial moveTo, plus an implicit close at the end; n-2 trianles fill an n-gon.
- // Each triangle has 3 vertices.
- return (path.countVerbs() - 1) * 3;
-}
-
-// Triangulates the path's inner polygon(s) and writes the result to "vertexData". The inner
-// polygons connect the endpoints of each verb. (i.e., they are the path that would result from
-// collapsing all curves to single lines.)
+// Triangulates and writes an SkPath's inner polygon(s). The inner polygons connect the endpoints of
+// each verb. (i.e., they are the path that would result from collapsing all curves to single
+// lines.)
//
// This method works by recursively subdividing the path rather than emitting a linear triangle fan
// or strip. This can reduce the load on the rasterizer by a great deal on complex paths.
//
// Returns the number of vertices written to the array.
-//
-// The incoming vertexData array must have at least MaxInnerPolygonVertices() elements.
-int EmitInnerPolygonTriangles(const SkPath&, SkPoint* vertexData, int* numCurves);
+int EmitInnerPolygonTriangles(const SkPath&, GrEagerVertexAllocator*);
-int EmitCubicInstances(const SkPath&, SkPoint* vertexData);
+// Writes out an array of cubics from an SkPath as 4-point instances, converting any quadratics to
+// cubics.
+//
+// Returns the number of *instances* written to the array.
+int EmitCubicInstances(const SkPath&, GrEagerVertexAllocator*);
} // namespace
diff --git a/src/gpu/tessellate/GrTessellatePathOp.cpp b/src/gpu/tessellate/GrTessellatePathOp.cpp
index 7b03923..a4ce3f1 100644
--- a/src/gpu/tessellate/GrTessellatePathOp.cpp
+++ b/src/gpu/tessellate/GrTessellatePathOp.cpp
@@ -7,6 +7,7 @@
#include "src/gpu/tessellate/GrTessellatePathOp.h"
+#include "src/gpu/GrEagerVertexAllocator.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrOpsRenderPass.h"
@@ -24,6 +25,10 @@
}
void GrTessellatePathOp::onPrepare(GrOpFlushState* state) {
+ GrEagerDynamicVertexAllocator pathVertexAllocator(state, &fPathVertexBuffer, &fBasePathVertex);
+ GrEagerDynamicVertexAllocator cubicInstanceAllocator(state, &fCubicInstanceBuffer,
+ &fBaseCubicInstance);
+
// First see if we should split up inner polygon triangles and curves, and triangulate the inner
// polygon(s) more efficiently. This causes greater CPU overhead due to the extra shaders and
// draw calls, but the better triangulation can reduce the rasterizer load by a great deal on
@@ -33,39 +38,15 @@
// Raster-edge work is 1-dimensional, so we sum height and width rather than multiplying them.
float rasterEdgeWork = (bounds.height() + bounds.width()) * scale * fPath.countVerbs();
if (rasterEdgeWork > 1000 * 1000) {
- int numCurves = 0;
- int maxVertexCount = GrPathParser::MaxInnerPolygonVertices(fPath);
- if (auto* triangleData = (SkPoint*)state->makeVertexSpace(
- sizeof(SkPoint), maxVertexCount, &fPathVertexBuffer, &fBasePathVertex)) {
- if ((fPathVertexCount =
- GrPathParser::EmitInnerPolygonTriangles(fPath, triangleData, &numCurves))) {
- fPathShader = state->allocator()->make<GrStencilTriangleShader>(fViewMatrix);
- } else {
- fPathVertexBuffer.reset();
- }
- state->putBackVertices(maxVertexCount - fPathVertexCount, sizeof(SkPoint));
- }
- if (numCurves) {
- if (auto* cubicData = (SkPoint*)state->makeVertexSpace(
- sizeof(SkPoint) * 4, numCurves, &fCubicInstanceBuffer, &fBaseCubicInstance)) {
- fCubicInstanceCount = GrPathParser::EmitCubicInstances(fPath, cubicData);
- SkASSERT(fCubicInstanceCount == numCurves);
- }
- }
+ fPathShader = state->allocator()->make<GrStencilTriangleShader>(fViewMatrix);
+ fPathVertexCount = GrPathParser::EmitInnerPolygonTriangles(fPath, &pathVertexAllocator);
+ fCubicInstanceCount = GrPathParser::EmitCubicInstances(fPath, &cubicInstanceAllocator);
return;
}
// Fastest CPU approach: emit one cubic wedge per verb, fanning out from the center.
- int maxVertexCount = GrPathParser::MaxWedgeVertices(fPath);
- if (auto* patchData = (SkPoint*)state->makeVertexSpace(
- sizeof(SkPoint), maxVertexCount, &fPathVertexBuffer, &fBasePathVertex)) {
- if ((fPathVertexCount = GrPathParser::EmitCenterWedgePatches(fPath, patchData))) {
- fPathShader = state->allocator()->make<GrStencilWedgeShader>(fViewMatrix);
- } else {
- fPathVertexBuffer.reset();
- }
- state->putBackVertices(maxVertexCount - fPathVertexCount, sizeof(SkPoint));
- }
+ fPathShader = state->allocator()->make<GrStencilWedgeShader>(fViewMatrix);
+ fPathVertexCount = GrPathParser::EmitCenterWedgePatches(fPath, &pathVertexAllocator);
}
void GrTessellatePathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
diff --git a/src/gpu/tessellate/GrTessellatePathOp.h b/src/gpu/tessellate/GrTessellatePathOp.h
index 0e17c41..cd0e37b 100644
--- a/src/gpu/tessellate/GrTessellatePathOp.h
+++ b/src/gpu/tessellate/GrTessellatePathOp.h
@@ -67,6 +67,9 @@
SkPMColor4f fColor;
GrProcessorSet fProcessors;
+ // The "path shader" draws the below path geometry.
+ GrStencilPathShader* fPathShader;
+
// The "path vertex buffer" is made up of either inner polygon triangles (see
// GrPathParser::EmitInnerPolygonTriangles) or cubic wedge patches (see
// GrPathParser::EmitCenterWedgePatches).
@@ -74,9 +77,6 @@
int fBasePathVertex;
int fPathVertexCount;
- // The "path shader" draws the above path geometry.
- GrStencilPathShader* fPathShader;
-
// The cubic instance buffer defines standalone cubics to tessellate into the stencil buffer, in
// addition to the above path geometry.
sk_sp<const GrBuffer> fCubicInstanceBuffer;