Index: src/gpu/GrTessellatingPathRenderer.cpp |
diff --git a/src/gpu/GrTessellatingPathRenderer.cpp b/src/gpu/GrTessellatingPathRenderer.cpp |
index a9ae6fa4e13dee3e473c2498378a81cc9e82922e..955e6c12e2ee76c7da96baf53784d3b9e85699e9 100644 |
--- a/src/gpu/GrTessellatingPathRenderer.cpp |
+++ b/src/gpu/GrTessellatingPathRenderer.cpp |
@@ -7,6 +7,8 @@ |
#include "GrTessellatingPathRenderer.h" |
+#include "GrBatch.h" |
+#include "GrBatchTarget.h" |
#include "GrDefaultGeoProcFactory.h" |
#include "GrPathUtils.h" |
#include "SkChunkAlloc.h" |
@@ -1436,6 +1438,128 @@ bool GrTessellatingPathRenderer::canDrawPath(const GrDrawTarget* target, |
return stroke.isFillStyle() && !antiAlias && !path.isConvex(); |
} |
+class TessellatingPathBatch : public GrBatch { |
+public: |
+ |
+ static GrBatch* Create(const GrColor& color, |
+ const SkPath& path, |
+ const SkMatrix& viewMatrix, |
+ SkRect clipBounds) { |
+ return SkNEW_ARGS(TessellatingPathBatch, (color, path, viewMatrix, clipBounds)); |
+ } |
+ |
+ const char* name() const SK_OVERRIDE { return "TessellatingPathBatch"; } |
+ |
+ void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE { |
+ out->setKnownFourComponents(fColor); |
+ } |
+ |
+ void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE { |
+ out->setUnknownSingleComponent(); |
+ } |
+ |
+ void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE { |
+ // Handle any color overrides |
+ if (init.fColorIgnored) { |
+ fColor = GrColor_ILLEGAL; |
+ } else if (GrColor_ILLEGAL != init.fOverrideColor) { |
+ fColor = init.fOverrideColor; |
+ } |
+ fPipelineInfo = init; |
+ } |
+ |
+ void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) SK_OVERRIDE { |
+ SkScalar tol = GrPathUtils::scaleToleranceToSrc(SK_Scalar1, fViewMatrix, fPath.getBounds()); |
+ int contourCnt; |
+ int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol); |
+ if (maxPts <= 0) { |
+ return; |
+ } |
+ if (maxPts > ((int)SK_MaxU16 + 1)) { |
+ SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); |
+ return; |
+ } |
+ SkPath::FillType fillType = fPath.getFillType(); |
+ if (SkPath::IsInverseFillType(fillType)) { |
+ contourCnt++; |
+ } |
+ |
+ LOG("got %d pts, %d contours\n", maxPts, contourCnt); |
+ uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType; |
+ SkAutoTUnref<const GrGeometryProcessor> gp( |
+ GrDefaultGeoProcFactory::Create(flags, fColor, fViewMatrix, SkMatrix::I())); |
+ batchTarget->initDraw(gp, pipeline); |
+ gp->initBatchTracker(batchTarget->currentBatchTracker(), fPipelineInfo); |
+ |
+ SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt)); |
+ |
+ // For the initial size of the chunk allocator, estimate based on the point count: |
+ // one vertex per point for the initial passes, plus two for the vertices in the |
+ // resulting Polys, since the same point may end up in two Polys. Assume minimal |
+ // connectivity of one Edge per Vertex (will grow for intersections). |
+ SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); |
+ path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc); |
+ Poly* polys; |
+ polys = contours_to_polys(contours.get(), contourCnt, alloc); |
+ int count = 0; |
+ for (Poly* poly = polys; poly; poly = poly->fNext) { |
+ if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) { |
+ count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); |
+ } |
+ } |
+ |
+ size_t stride = gp->getVertexStride(); |
+ const GrVertexBuffer* vertexBuffer; |
+ int firstVertex; |
+ void* vertices = batchTarget->vertexPool()->makeSpace(stride, |
+ count, |
+ &vertexBuffer, |
+ &firstVertex); |
+ LOG("emitting %d verts\n", count); |
+ void* end = polys_to_triangles(polys, fillType, vertices); |
+ int actualCount = static_cast<int>( |
+ (static_cast<char*>(end) - static_cast<char*>(vertices)) / stride); |
+ LOG("actual count: %d\n", actualCount); |
+ SkASSERT(actualCount <= count); |
+ |
+ GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType |
+ : kTriangles_GrPrimitiveType; |
+ GrDrawTarget::DrawInfo drawInfo; |
+ drawInfo.setPrimitiveType(primitiveType); |
+ drawInfo.setVertexBuffer(vertexBuffer); |
+ drawInfo.setStartVertex(firstVertex); |
+ drawInfo.setVertexCount(actualCount); |
+ drawInfo.setStartIndex(0); |
+ drawInfo.setIndexCount(0); |
+ batchTarget->draw(drawInfo); |
+ |
+ batchTarget->putBackVertices((size_t)(count - actualCount), stride); |
+ return; |
+ } |
+ |
+ bool onCombineIfPossible(GrBatch*) SK_OVERRIDE { |
+ return false; |
+ } |
+ |
+private: |
+ TessellatingPathBatch(const GrColor& color, |
+ const SkPath& path, |
+ const SkMatrix& viewMatrix, |
+ const SkRect& clipBounds) |
+ : fColor(color) |
+ , fPath(path) |
+ , fViewMatrix(viewMatrix) |
+ , fClipBounds(clipBounds) { |
+ this->initClassID<TessellatingPathBatch>(); |
+ } |
+ |
+ GrColor fColor; |
+ SkPath fPath; |
+ SkMatrix fViewMatrix; |
+ SkRect fClipBounds; // in source space |
+ GrPipelineInfo fPipelineInfo; |
+}; |
+ |
bool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target, |
GrPipelineBuilder* pipelineBuilder, |
GrColor color, |
@@ -1449,31 +1573,6 @@ bool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target, |
return false; |
} |
- SkScalar tol = GrPathUtils::scaleToleranceToSrc(SK_Scalar1, viewM, path.getBounds()); |
- |
- int contourCnt; |
- int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, tol); |
- if (maxPts <= 0) { |
- return false; |
- } |
- if (maxPts > ((int)SK_MaxU16 + 1)) { |
- SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); |
- return false; |
- } |
- SkPath::FillType fillType = path.getFillType(); |
- if (SkPath::IsInverseFillType(fillType)) { |
- contourCnt++; |
- } |
- |
- LOG("got %d pts, %d contours\n", maxPts, contourCnt); |
- |
- SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt)); |
- |
- // For the initial size of the chunk allocator, estimate based on the point count: |
- // one vertex per point for the initial passes, plus two for the vertices in the |
- // resulting Polys, since the same point may end up in two Polys. Assume minimal |
- // connectivity of one Edge per Vertex (will grow for intersections). |
- SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); |
SkIRect clipBoundsI; |
pipelineBuilder->clip().getConservativeBounds(rt, &clipBoundsI); |
SkRect clipBounds = SkRect::Make(clipBoundsI); |
@@ -1482,33 +1581,8 @@ bool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target, |
return false; |
} |
vmi.mapRect(&clipBounds); |
- path_to_contours(path, tol, clipBounds, contours.get(), alloc); |
- Poly* polys; |
- uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType; |
- polys = contours_to_polys(contours.get(), contourCnt, alloc); |
- SkAutoTUnref<const GrGeometryProcessor> gp( |
- GrDefaultGeoProcFactory::Create(flags, color, viewM, SkMatrix::I())); |
- int count = 0; |
- for (Poly* poly = polys; poly; poly = poly->fNext) { |
- if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) { |
- count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); |
- } |
- } |
- |
- size_t stride = gp->getVertexStride(); |
- GrDrawTarget::AutoReleaseGeometry arg; |
- if (!arg.set(target, count, stride, 0)) { |
- return false; |
- } |
- LOG("emitting %d verts\n", count); |
- void* end = polys_to_triangles(polys, fillType, arg.vertices()); |
- int actualCount = static_cast<int>((static_cast<char*>(end) - static_cast<char*>(arg.vertices())) / stride); |
- LOG("actual count: %d\n", actualCount); |
- SkASSERT(actualCount <= count); |
- |
- GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType |
- : kTriangles_GrPrimitiveType; |
- target->drawNonIndexed(pipelineBuilder, gp, primitiveType, 0, actualCount); |
+ SkAutoTUnref<GrBatch> batch(TessellatingPathBatch::Create(color, path, viewM, clipBounds)); |
+ target->drawBatch(pipelineBuilder, batch); |
return true; |
} |