Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: src/gpu/GrTessellatingPathRenderer.cpp

Issue 976103002: Batchify the tessellated path renderer. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Pass the GrPipelineInfo we got back to initBatchTracker() Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrTessellatingPathRenderer.h" 8 #include "GrTessellatingPathRenderer.h"
9 9
10 #include "GrBatch.h"
11 #include "GrBatchTarget.h"
10 #include "GrDefaultGeoProcFactory.h" 12 #include "GrDefaultGeoProcFactory.h"
11 #include "GrPathUtils.h" 13 #include "GrPathUtils.h"
12 #include "SkChunkAlloc.h" 14 #include "SkChunkAlloc.h"
13 #include "SkGeometry.h" 15 #include "SkGeometry.h"
14 16
15 #include <stdio.h> 17 #include <stdio.h>
16 18
17 /* 19 /*
18 * This path renderer tessellates the path into triangles, uploads the triangles to a 20 * This path renderer tessellates the path into triangles, uploads the triangles to a
19 * vertex buffer, and renders them with a single draw call. It does not currentl y do 21 * vertex buffer, and renders them with a single draw call. It does not currentl y do
(...skipping 1409 matching lines...) Expand 10 before | Expand all | Expand 10 after
1429 const GrPipelineBuilder* pipelineBu ilder, 1431 const GrPipelineBuilder* pipelineBu ilder,
1430 const SkMatrix& viewMatrix, 1432 const SkMatrix& viewMatrix,
1431 const SkPath& path, 1433 const SkPath& path,
1432 const SkStrokeRec& stroke, 1434 const SkStrokeRec& stroke,
1433 bool antiAlias) const { 1435 bool antiAlias) const {
1434 // This path renderer can draw all fill styles, but does not do antialiasing . It can do convex 1436 // This path renderer can draw all fill styles, but does not do antialiasing . It can do convex
1435 // and concave paths, but we'll leave the convex ones to simpler algorithms. 1437 // and concave paths, but we'll leave the convex ones to simpler algorithms.
1436 return stroke.isFillStyle() && !antiAlias && !path.isConvex(); 1438 return stroke.isFillStyle() && !antiAlias && !path.isConvex();
1437 } 1439 }
1438 1440
1441 class TessellatingPathBatch : public GrBatch {
1442 public:
1443
1444 static GrBatch* Create(const GrColor& color,
1445 const SkPath& path,
1446 const SkMatrix& viewMatrix,
1447 SkRect clipBounds) {
1448 return SkNEW_ARGS(TessellatingPathBatch, (color, path, viewMatrix, clipB ounds));
1449 }
1450
1451 const char* name() const SK_OVERRIDE { return "TessellatingPathBatch"; }
1452
1453 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE {
1454 out->setKnownFourComponents(fColor);
1455 }
1456
1457 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRID E {
1458 out->setUnknownSingleComponent();
1459 }
1460
1461 void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE {
1462 // Handle any color overrides
1463 if (init.fColorIgnored) {
1464 fColor = GrColor_ILLEGAL;
1465 } else if (GrColor_ILLEGAL != init.fOverrideColor) {
1466 fColor = init.fOverrideColor;
1467 }
1468 fPipelineInfo = init;
1469 }
1470
1471 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE {
1472 SkScalar tol = GrPathUtils::scaleToleranceToSrc(SK_Scalar1, fViewMatrix, fPath.getBounds());
1473 int contourCnt;
1474 int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol);
1475 if (maxPts <= 0) {
1476 return;
1477 }
1478 if (maxPts > ((int)SK_MaxU16 + 1)) {
1479 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts);
1480 return;
1481 }
1482 SkPath::FillType fillType = fPath.getFillType();
1483 if (SkPath::IsInverseFillType(fillType)) {
1484 contourCnt++;
1485 }
1486
1487 LOG("got %d pts, %d contours\n", maxPts, contourCnt);
1488 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType;
1489 SkAutoTUnref<const GrGeometryProcessor> gp(
1490 GrDefaultGeoProcFactory::Create(flags, fColor, fViewMatrix, SkMatrix ::I()));
1491 batchTarget->initDraw(gp, pipeline);
1492 gp->initBatchTracker(batchTarget->currentBatchTracker(), fPipelineInfo);
1493
1494 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt));
1495
1496 // For the initial size of the chunk allocator, estimate based on the po int count:
1497 // one vertex per point for the initial passes, plus two for the vertice s in the
1498 // resulting Polys, since the same point may end up in two Polys. Assum e minimal
1499 // connectivity of one Edge per Vertex (will grow for intersections).
1500 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge)));
1501 path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc);
1502 Poly* polys;
1503 polys = contours_to_polys(contours.get(), contourCnt, alloc);
1504 int count = 0;
1505 for (Poly* poly = polys; poly; poly = poly->fNext) {
1506 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) {
1507 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3);
1508 }
1509 }
1510
1511 size_t stride = gp->getVertexStride();
1512 const GrVertexBuffer* vertexBuffer;
1513 int firstVertex;
1514 void* vertices = batchTarget->vertexPool()->makeSpace(stride,
1515 count,
1516 &vertexBuffer,
1517 &firstVertex);
1518 LOG("emitting %d verts\n", count);
1519 void* end = polys_to_triangles(polys, fillType, vertices);
1520 int actualCount = static_cast<int>(
1521 (static_cast<char*>(end) - static_cast<char*>(vertices)) / stride);
1522 LOG("actual count: %d\n", actualCount);
1523 SkASSERT(actualCount <= count);
1524
1525 GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType
1526 : kTriangles_GrPrimitiveType;
1527 GrDrawTarget::DrawInfo drawInfo;
1528 drawInfo.setPrimitiveType(primitiveType);
1529 drawInfo.setVertexBuffer(vertexBuffer);
1530 drawInfo.setStartVertex(firstVertex);
1531 drawInfo.setVertexCount(actualCount);
1532 drawInfo.setStartIndex(0);
1533 drawInfo.setIndexCount(0);
1534 batchTarget->draw(drawInfo);
1535
1536 batchTarget->putBackVertices((size_t)(count - actualCount), stride);
1537 return;
1538 }
1539
1540 bool onCombineIfPossible(GrBatch*) SK_OVERRIDE {
1541 return false;
1542 }
1543
1544 private:
1545 TessellatingPathBatch(const GrColor& color,
1546 const SkPath& path,
1547 const SkMatrix& viewMatrix,
1548 const SkRect& clipBounds)
1549 : fColor(color)
1550 , fPath(path)
1551 , fViewMatrix(viewMatrix)
1552 , fClipBounds(clipBounds) {
1553 this->initClassID<TessellatingPathBatch>();
1554 }
1555
1556 GrColor fColor;
1557 SkPath fPath;
1558 SkMatrix fViewMatrix;
1559 SkRect fClipBounds; // in source space
1560 GrPipelineInfo fPipelineInfo;
1561 };
1562
1439 bool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target, 1563 bool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target,
1440 GrPipelineBuilder* pipelineBuilder, 1564 GrPipelineBuilder* pipelineBuilder,
1441 GrColor color, 1565 GrColor color,
1442 const SkMatrix& viewM, 1566 const SkMatrix& viewM,
1443 const SkPath& path, 1567 const SkPath& path,
1444 const SkStrokeRec& stroke, 1568 const SkStrokeRec& stroke,
1445 bool antiAlias) { 1569 bool antiAlias) {
1446 SkASSERT(!antiAlias); 1570 SkASSERT(!antiAlias);
1447 const GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 1571 const GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
1448 if (NULL == rt) { 1572 if (NULL == rt) {
1449 return false; 1573 return false;
1450 } 1574 }
1451 1575
1452 SkScalar tol = GrPathUtils::scaleToleranceToSrc(SK_Scalar1, viewM, path.getB ounds());
1453
1454 int contourCnt;
1455 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, tol);
1456 if (maxPts <= 0) {
1457 return false;
1458 }
1459 if (maxPts > ((int)SK_MaxU16 + 1)) {
1460 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts);
1461 return false;
1462 }
1463 SkPath::FillType fillType = path.getFillType();
1464 if (SkPath::IsInverseFillType(fillType)) {
1465 contourCnt++;
1466 }
1467
1468 LOG("got %d pts, %d contours\n", maxPts, contourCnt);
1469
1470 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt));
1471
1472 // For the initial size of the chunk allocator, estimate based on the point count:
1473 // one vertex per point for the initial passes, plus two for the vertices in the
1474 // resulting Polys, since the same point may end up in two Polys. Assume mi nimal
1475 // connectivity of one Edge per Vertex (will grow for intersections).
1476 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge)));
1477 SkIRect clipBoundsI; 1576 SkIRect clipBoundsI;
1478 pipelineBuilder->clip().getConservativeBounds(rt, &clipBoundsI); 1577 pipelineBuilder->clip().getConservativeBounds(rt, &clipBoundsI);
1479 SkRect clipBounds = SkRect::Make(clipBoundsI); 1578 SkRect clipBounds = SkRect::Make(clipBoundsI);
1480 SkMatrix vmi; 1579 SkMatrix vmi;
1481 if (!viewM.invert(&vmi)) { 1580 if (!viewM.invert(&vmi)) {
1482 return false; 1581 return false;
1483 } 1582 }
1484 vmi.mapRect(&clipBounds); 1583 vmi.mapRect(&clipBounds);
1485 path_to_contours(path, tol, clipBounds, contours.get(), alloc); 1584 SkAutoTUnref<GrBatch> batch(TessellatingPathBatch::Create(color, path, viewM , clipBounds));
1486 Poly* polys; 1585 target->drawBatch(pipelineBuilder, batch);
1487 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType;
1488 polys = contours_to_polys(contours.get(), contourCnt, alloc);
1489 SkAutoTUnref<const GrGeometryProcessor> gp(
1490 GrDefaultGeoProcFactory::Create(flags, color, viewM, SkMatrix::I()));
1491 int count = 0;
1492 for (Poly* poly = polys; poly; poly = poly->fNext) {
1493 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) {
1494 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3);
1495 }
1496 }
1497
1498 size_t stride = gp->getVertexStride();
1499 GrDrawTarget::AutoReleaseGeometry arg;
1500 if (!arg.set(target, count, stride, 0)) {
1501 return false;
1502 }
1503 LOG("emitting %d verts\n", count);
1504 void* end = polys_to_triangles(polys, fillType, arg.vertices());
1505 int actualCount = static_cast<int>((static_cast<char*>(end) - static_cast<ch ar*>(arg.vertices())) / stride);
1506 LOG("actual count: %d\n", actualCount);
1507 SkASSERT(actualCount <= count);
1508
1509 GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType
1510 : kTriangles_GrPrimitiveType;
1511 target->drawNonIndexed(pipelineBuilder, gp, primitiveType, 0, actualCount);
1512 1586
1513 return true; 1587 return true;
1514 } 1588 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698