aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar senorblanco <senorblanco@chromium.org>2015-03-05 07:13:42 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-03-05 07:13:42 -0800
commit9ba3972ed93321ee606e2974e00a926cd871ddcc (patch)
treef994aa76c96956b44ddfe2f8fffe9b07be421a3e
parent71b03e468d941984f600d6bca4e26e00e2af7756 (diff)
Batchify the tessellated path renderer.
-rw-r--r--src/gpu/GrTessellatingPathRenderer.cpp178
1 files changed, 126 insertions, 52 deletions
diff --git a/src/gpu/GrTessellatingPathRenderer.cpp b/src/gpu/GrTessellatingPathRenderer.cpp
index a9ae6fa4e1..955e6c12e2 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;
}