Index: src/gpu/batches/GrTessellatingPathRenderer.cpp |
diff --git a/src/gpu/batches/GrTessellatingPathRenderer.cpp b/src/gpu/batches/GrTessellatingPathRenderer.cpp |
index a312db654c4b89df48d27160021d34ad43fd5a6b..85c2ca0738b5e6bc1e8fb18f12d1caf98ddeb496 100644 |
--- a/src/gpu/batches/GrTessellatingPathRenderer.cpp |
+++ b/src/gpu/batches/GrTessellatingPathRenderer.cpp |
@@ -59,6 +59,48 @@ bool cache_match(GrVertexBuffer* vertexBuffer, SkScalar tol, int* actualCount) { |
return false; |
} |
+class StaticVertexAllocator : public GrTessellator::VertexAllocator { |
+public: |
+ StaticVertexAllocator(SkAutoTUnref<GrVertexBuffer>& vertexBuffer, |
+ GrResourceProvider* resourceProvider, |
+ bool canMapVB) |
+ : fVertexBuffer(vertexBuffer) |
+ , fResourceProvider(resourceProvider) |
+ , fCanMapVB(canMapVB) |
+ , fVertices(nullptr) { |
+ } |
+ SkPoint* lock(int vertexCount) override { |
+ size_t size = vertexCount * sizeof(SkPoint); |
+ if (!fVertexBuffer.get() || fVertexBuffer->gpuMemorySize() < size) { |
+ fVertexBuffer.reset(fResourceProvider->createVertexBuffer( |
+ size, GrResourceProvider::kStatic_BufferUsage, 0)); |
+ } |
+ if (!fVertexBuffer.get()) { |
+ return nullptr; |
+ } |
+ if (fCanMapVB) { |
+ fVertices = static_cast<SkPoint*>(fVertexBuffer->map()); |
+ } else { |
+ fVertices = new SkPoint[vertexCount]; |
+ } |
+ return fVertices; |
+ } |
+ void unlock(int actualCount) override { |
+ if (fCanMapVB) { |
+ fVertexBuffer->unmap(); |
+ } else { |
+ fVertexBuffer->updateData(fVertices, actualCount * sizeof(SkPoint)); |
+ delete[] fVertices; |
+ } |
+ fVertices = nullptr; |
+ } |
+private: |
+ SkAutoTUnref<GrVertexBuffer>& fVertexBuffer; |
+ GrResourceProvider* fResourceProvider; |
+ bool fCanMapVB; |
+ SkPoint* fVertices; |
+}; |
+ |
} // namespace |
GrTessellatingPathRenderer::GrTessellatingPathRenderer() { |
@@ -103,46 +145,7 @@ private: |
fPipelineInfo = overrides; |
} |
- int tessellate(GrUniqueKey* key, |
- GrResourceProvider* resourceProvider, |
- SkAutoTUnref<GrVertexBuffer>& vertexBuffer, |
- bool canMapVB) const { |
- SkPath path; |
- GrStrokeInfo stroke(fStroke); |
- if (stroke.isDashed()) { |
- if (!stroke.applyDashToPath(&path, &stroke, fPath)) { |
- return 0; |
- } |
- } else { |
- path = fPath; |
- } |
- if (!stroke.isFillStyle()) { |
- stroke.setResScale(SkScalarAbs(fViewMatrix.getMaxScale())); |
- if (!stroke.applyToPath(&path, path)) { |
- return 0; |
- } |
- stroke.setFillStyle(); |
- } |
- SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; |
- SkRect pathBounds = path.getBounds(); |
- SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMatrix, pathBounds); |
- |
- bool isLinear; |
- int count = GrTessellator::PathToTriangles(path, tol, fClipBounds, resourceProvider, |
- vertexBuffer, canMapVB, &isLinear); |
- if (!fPath.isVolatile()) { |
- TessInfo info; |
- info.fTolerance = isLinear ? 0 : tol; |
- info.fCount = count; |
- SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info))); |
- key->setCustomData(data.get()); |
- resourceProvider->assignUniqueKeyToResource(*key, vertexBuffer.get()); |
- SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(*key)); |
- } |
- return count; |
- } |
- |
- void onPrepareDraws(Target* target) const override { |
+ void draw(Target* target, const GrGeometryProcessor* gp) const { |
// construct a cache key from the path's genID and the view matrix |
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); |
GrUniqueKey key; |
@@ -164,15 +167,47 @@ private: |
SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; |
SkScalar tol = GrPathUtils::scaleToleranceToSrc( |
screenSpaceTol, fViewMatrix, fPath.getBounds()); |
- if (!cache_match(vertexBuffer.get(), tol, &actualCount)) { |
- bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags(); |
- actualCount = this->tessellate(&key, rp, vertexBuffer, canMapVB); |
+ if (cache_match(vertexBuffer.get(), tol, &actualCount)) { |
+ this->drawVertices(target, gp, vertexBuffer.get(), 0, actualCount); |
+ return; |
} |
- if (actualCount == 0) { |
+ SkPath path; |
+ GrStrokeInfo stroke(fStroke); |
+ if (stroke.isDashed()) { |
+ if (!stroke.applyDashToPath(&path, &stroke, fPath)) { |
+ return; |
+ } |
+ } else { |
+ path = fPath; |
+ } |
+ if (!stroke.isFillStyle()) { |
+ stroke.setResScale(SkScalarAbs(fViewMatrix.getMaxScale())); |
+ if (!stroke.applyToPath(&path, path)) { |
+ return; |
+ } |
+ stroke.setFillStyle(); |
+ } |
+ bool isLinear; |
+ bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags(); |
+ StaticVertexAllocator allocator(vertexBuffer, target->resourceProvider(), canMapVB); |
+ int count = GrTessellator::PathToTriangles(path, tol, fClipBounds, &allocator, &isLinear); |
+ if (count == 0) { |
return; |
} |
+ this->drawVertices(target, gp, vertexBuffer.get(), 0, count); |
+ if (!fPath.isVolatile()) { |
+ TessInfo info; |
+ info.fTolerance = isLinear ? 0 : tol; |
+ info.fCount = count; |
+ SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info))); |
+ key.setCustomData(data.get()); |
+ target->resourceProvider()->assignUniqueKeyToResource(key, vertexBuffer.get()); |
+ SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(key)); |
+ } |
+ } |
+ void onPrepareDraws(Target* target) const override { |
SkAutoTUnref<const GrGeometryProcessor> gp; |
{ |
using namespace GrDefaultGeoProcFactory; |
@@ -191,14 +226,18 @@ private: |
gp.reset(GrDefaultGeoProcFactory::Create(color, coverage, localCoords, |
fViewMatrix)); |
} |
+ this->draw(target, gp.get()); |
+ } |
+ void drawVertices(Target* target, const GrGeometryProcessor* gp, const GrVertexBuffer* vb, |
+ int firstVertex, int count) const { |
target->initDraw(gp, this->pipeline()); |
SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); |
GrPrimitiveType primitiveType = TESSELLATOR_WIREFRAME ? kLines_GrPrimitiveType |
: kTriangles_GrPrimitiveType; |
GrVertices vertices; |
- vertices.init(primitiveType, vertexBuffer.get(), 0, actualCount); |
+ vertices.init(primitiveType, vb, firstVertex, count); |
target->draw(vertices); |
} |