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

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

Issue 1275553002: Implement caching of stroked paths in the tessellating path renderer. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 4 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" 10 #include "GrBatch.h"
(...skipping 1366 matching lines...) Expand 10 before | Expand all | Expand 10 after
1377 GrUniqueKeyInvalidatedMessage fMsg; 1377 GrUniqueKeyInvalidatedMessage fMsg;
1378 1378
1379 void onChange() override { 1379 void onChange() override {
1380 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); 1380 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
1381 } 1381 }
1382 }; 1382 };
1383 1383
1384 } // namespace 1384 } // namespace
1385 1385
1386 bool GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) cons t { 1386 bool GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) cons t {
1387 // This path renderer can draw all fill styles, but does not do antialiasing . It can do convex 1387 // This path renderer can draw all fill styles, all stroke styles except hai rlines, but does
1388 // and concave paths, but we'll leave the convex ones to simpler algorithms. 1388 // not do antialiasing. It can do convex and concave paths, but we'll leave the convex ones to
1389 return args.fStroke->isFillStyle() && !args.fAntiAlias && !args.fPath->isCon vex(); 1389 // simpler algorithms.
1390 return !args.fStroke->isHairlineStyle() && !args.fAntiAlias && !args.fPath-> isConvex();
1390 } 1391 }
1391 1392
1392 class TessellatingPathBatch : public GrBatch { 1393 class TessellatingPathBatch : public GrBatch {
1393 public: 1394 public:
1394 1395
1395 static GrBatch* Create(const GrColor& color, 1396 static GrBatch* Create(const GrColor& color,
1396 const SkPath& path, 1397 const SkPath& path,
1398 const GrStrokeInfo& stroke,
1397 const SkMatrix& viewMatrix, 1399 const SkMatrix& viewMatrix,
1398 SkRect clipBounds) { 1400 SkRect clipBounds) {
1399 return SkNEW_ARGS(TessellatingPathBatch, (color, path, viewMatrix, clipB ounds)); 1401 return SkNEW_ARGS(TessellatingPathBatch, (color, path, stroke, viewMatri x, clipBounds));
1400 } 1402 }
1401 1403
1402 const char* name() const override { return "TessellatingPathBatch"; } 1404 const char* name() const override { return "TessellatingPathBatch"; }
1403 1405
1404 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { 1406 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
1405 out->setKnownFourComponents(fColor); 1407 out->setKnownFourComponents(fColor);
1406 } 1408 }
1407 1409
1408 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { 1410 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
1409 out->setUnknownSingleComponent(); 1411 out->setUnknownSingleComponent();
1410 } 1412 }
1411 1413
1412 void initBatchTracker(const GrPipelineInfo& init) override { 1414 void initBatchTracker(const GrPipelineInfo& init) override {
1413 // Handle any color overrides 1415 // Handle any color overrides
1414 if (!init.readsColor()) { 1416 if (!init.readsColor()) {
1415 fColor = GrColor_ILLEGAL; 1417 fColor = GrColor_ILLEGAL;
1416 } 1418 }
1417 init.getOverrideColorIfSet(&fColor); 1419 init.getOverrideColorIfSet(&fColor);
1418 fPipelineInfo = init; 1420 fPipelineInfo = init;
1419 } 1421 }
1420 1422
1421 int tessellate(GrUniqueKey* key, 1423 int tessellate(GrUniqueKey* key,
1422 GrResourceProvider* resourceProvider, 1424 GrResourceProvider* resourceProvider,
1423 SkAutoTUnref<GrVertexBuffer>& vertexBuffer) { 1425 SkAutoTUnref<GrVertexBuffer>& vertexBuffer) {
1424 SkRect pathBounds = fPath.getBounds(); 1426 SkPath path;
1427 GrStrokeInfo stroke(fStroke);
1428 if (stroke.isDashed()) {
1429 if (!stroke.applyDashToPath(&path, &stroke, fPath)) {
1430 return 0;
1431 }
1432 } else {
1433 path = fPath;
1434 }
1435 if (!stroke.isFillStyle()) {
1436 stroke.setResScale(SkScalarAbs(fViewMatrix.getMaxScale()));
1437 if (!stroke.applyToPath(&path, path)) {
1438 return 0;
1439 }
1440 stroke.setFillStyle();
1441 }
1442 SkRect pathBounds = path.getBounds();
1425 Comparator c; 1443 Comparator c;
1426 if (pathBounds.width() > pathBounds.height()) { 1444 if (pathBounds.width() > pathBounds.height()) {
1427 c.sweep_lt = sweep_lt_horiz; 1445 c.sweep_lt = sweep_lt_horiz;
1428 c.sweep_gt = sweep_gt_horiz; 1446 c.sweep_gt = sweep_gt_horiz;
1429 } else { 1447 } else {
1430 c.sweep_lt = sweep_lt_vert; 1448 c.sweep_lt = sweep_lt_vert;
1431 c.sweep_gt = sweep_gt_vert; 1449 c.sweep_gt = sweep_gt_vert;
1432 } 1450 }
1433 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; 1451 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance;
1434 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat rix, pathBounds); 1452 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat rix, pathBounds);
1435 int contourCnt; 1453 int contourCnt;
1436 int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol); 1454 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, tol);
1437 if (maxPts <= 0) { 1455 if (maxPts <= 0) {
1438 return 0; 1456 return 0;
1439 } 1457 }
1440 if (maxPts > ((int)SK_MaxU16 + 1)) { 1458 if (maxPts > ((int)SK_MaxU16 + 1)) {
1441 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); 1459 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts);
1442 return 0; 1460 return 0;
1443 } 1461 }
1444 SkPath::FillType fillType = fPath.getFillType(); 1462 SkPath::FillType fillType = path.getFillType();
1445 if (SkPath::IsInverseFillType(fillType)) { 1463 if (SkPath::IsInverseFillType(fillType)) {
1446 contourCnt++; 1464 contourCnt++;
1447 } 1465 }
1448 1466
1449 LOG("got %d pts, %d contours\n", maxPts, contourCnt); 1467 LOG("got %d pts, %d contours\n", maxPts, contourCnt);
1450 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt)); 1468 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt));
1451 1469
1452 // For the initial size of the chunk allocator, estimate based on the po int count: 1470 // For the initial size of the chunk allocator, estimate based on the po int count:
1453 // one vertex per point for the initial passes, plus two for the vertice s in the 1471 // one vertex per point for the initial passes, plus two for the vertice s in the
1454 // resulting Polys, since the same point may end up in two Polys. Assum e minimal 1472 // resulting Polys, since the same point may end up in two Polys. Assum e minimal
1455 // connectivity of one Edge per Vertex (will grow for intersections). 1473 // connectivity of one Edge per Vertex (will grow for intersections).
1456 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); 1474 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge)));
1457 bool isLinear; 1475 bool isLinear;
1458 path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc, &isLine ar); 1476 path_to_contours(path, tol, fClipBounds, contours.get(), alloc, &isLinea r);
1459 Poly* polys; 1477 Poly* polys;
1460 polys = contours_to_polys(contours.get(), contourCnt, c, alloc); 1478 polys = contours_to_polys(contours.get(), contourCnt, c, alloc);
1461 int count = 0; 1479 int count = 0;
1462 for (Poly* poly = polys; poly; poly = poly->fNext) { 1480 for (Poly* poly = polys; poly; poly = poly->fNext) {
1463 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) { 1481 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) {
1464 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); 1482 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3);
1465 } 1483 }
1466 } 1484 }
1467 if (0 == count) { 1485 if (0 == count) {
1468 return 0; 1486 return 0;
(...skipping 27 matching lines...) Expand all
1496 } 1514 }
1497 return actualCount; 1515 return actualCount;
1498 } 1516 }
1499 1517
1500 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) override { 1518 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) override {
1501 // construct a cache key from the path's genID and the view matrix 1519 // construct a cache key from the path's genID and the view matrix
1502 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain() ; 1520 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain() ;
1503 GrUniqueKey key; 1521 GrUniqueKey key;
1504 int clipBoundsSize32 = 1522 int clipBoundsSize32 =
1505 fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) : 0; 1523 fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) : 0;
1506 GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsSize32); 1524 int strokeDataSize32 = fStroke.computeUniqueKeyFragmentData32Cnt();
1525 GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsSize32 + strok eDataSize32);
1507 builder[0] = fPath.getGenerationID(); 1526 builder[0] = fPath.getGenerationID();
1508 builder[1] = fPath.getFillType(); 1527 builder[1] = fPath.getFillType();
1509 // For inverse fills, the tessellation is dependent on clip bounds. 1528 // For inverse fills, the tessellation is dependent on clip bounds.
1510 if (fPath.isInverseFillType()) { 1529 if (fPath.isInverseFillType()) {
1511 memcpy(&builder[2], &fClipBounds, sizeof(fClipBounds)); 1530 memcpy(&builder[2], &fClipBounds, sizeof(fClipBounds));
1512 } 1531 }
1532 fStroke.asUniqueKeyFragment(&builder[2 + clipBoundsSize32]);
1513 builder.finish(); 1533 builder.finish();
1514 GrResourceProvider* rp = batchTarget->resourceProvider(); 1534 GrResourceProvider* rp = batchTarget->resourceProvider();
1515 SkAutoTUnref<GrVertexBuffer> vertexBuffer(rp->findAndRefTByUniqueKey<GrV ertexBuffer>(key)); 1535 SkAutoTUnref<GrVertexBuffer> vertexBuffer(rp->findAndRefTByUniqueKey<GrV ertexBuffer>(key));
1516 int actualCount; 1536 int actualCount;
1517 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; 1537 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance;
1518 SkScalar tol = GrPathUtils::scaleToleranceToSrc( 1538 SkScalar tol = GrPathUtils::scaleToleranceToSrc(
1519 screenSpaceTol, fViewMatrix, fPath.getBounds()); 1539 screenSpaceTol, fViewMatrix, fPath.getBounds());
1520 if (!cache_match(vertexBuffer.get(), tol, &actualCount)) { 1540 if (!cache_match(vertexBuffer.get(), tol, &actualCount)) {
1521 actualCount = tessellate(&key, rp, vertexBuffer); 1541 actualCount = tessellate(&key, rp, vertexBuffer);
1522 } 1542 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1554 batchTarget->draw(vertices); 1574 batchTarget->draw(vertices);
1555 } 1575 }
1556 1576
1557 bool onCombineIfPossible(GrBatch*) override { 1577 bool onCombineIfPossible(GrBatch*) override {
1558 return false; 1578 return false;
1559 } 1579 }
1560 1580
1561 private: 1581 private:
1562 TessellatingPathBatch(const GrColor& color, 1582 TessellatingPathBatch(const GrColor& color,
1563 const SkPath& path, 1583 const SkPath& path,
1584 const GrStrokeInfo& stroke,
1564 const SkMatrix& viewMatrix, 1585 const SkMatrix& viewMatrix,
1565 const SkRect& clipBounds) 1586 const SkRect& clipBounds)
1566 : fColor(color) 1587 : fColor(color)
1567 , fPath(path) 1588 , fPath(path)
1589 , fStroke(stroke)
1568 , fViewMatrix(viewMatrix) 1590 , fViewMatrix(viewMatrix)
1569 , fClipBounds(clipBounds) { 1591 , fClipBounds(clipBounds) {
1570 this->initClassID<TessellatingPathBatch>(); 1592 this->initClassID<TessellatingPathBatch>();
1571 1593
1572 fBounds = path.getBounds(); 1594 fBounds = path.getBounds();
1573 viewMatrix.mapRect(&fBounds); 1595 viewMatrix.mapRect(&fBounds);
1574 } 1596 }
1575 1597
1576 GrColor fColor; 1598 GrColor fColor;
1577 SkPath fPath; 1599 SkPath fPath;
1600 GrStrokeInfo fStroke;
1578 SkMatrix fViewMatrix; 1601 SkMatrix fViewMatrix;
1579 SkRect fClipBounds; // in source space 1602 SkRect fClipBounds; // in source space
1580 GrPipelineInfo fPipelineInfo; 1603 GrPipelineInfo fPipelineInfo;
1581 }; 1604 };
1582 1605
1583 bool GrTessellatingPathRenderer::onDrawPath(const DrawPathArgs& args) { 1606 bool GrTessellatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
1584 SkASSERT(!args.fAntiAlias); 1607 SkASSERT(!args.fAntiAlias);
1585 const GrRenderTarget* rt = args.fPipelineBuilder->getRenderTarget(); 1608 const GrRenderTarget* rt = args.fPipelineBuilder->getRenderTarget();
1586 if (NULL == rt) { 1609 if (NULL == rt) {
1587 return false; 1610 return false;
1588 } 1611 }
1589 1612
1590 SkIRect clipBoundsI; 1613 SkIRect clipBoundsI;
1591 args.fPipelineBuilder->clip().getConservativeBounds(rt, &clipBoundsI); 1614 args.fPipelineBuilder->clip().getConservativeBounds(rt, &clipBoundsI);
1592 SkRect clipBounds = SkRect::Make(clipBoundsI); 1615 SkRect clipBounds = SkRect::Make(clipBoundsI);
1593 SkMatrix vmi; 1616 SkMatrix vmi;
1594 if (!args.fViewMatrix->invert(&vmi)) { 1617 if (!args.fViewMatrix->invert(&vmi)) {
1595 return false; 1618 return false;
1596 } 1619 }
1597 vmi.mapRect(&clipBounds); 1620 vmi.mapRect(&clipBounds);
1598 SkAutoTUnref<GrBatch> batch(TessellatingPathBatch::Create(args.fColor, *args .fPath, 1621 SkAutoTUnref<GrBatch> batch(TessellatingPathBatch::Create(args.fColor, *args .fPath,
1599 *args.fViewMatrix, clipBounds)); 1622 *args.fStroke, *ar gs.fViewMatrix,
1623 clipBounds));
1600 args.fTarget->drawBatch(*args.fPipelineBuilder, batch); 1624 args.fTarget->drawBatch(*args.fPipelineBuilder, batch);
1601 1625
1602 return true; 1626 return true;
1603 } 1627 }
1604 1628
1605 //////////////////////////////////////////////////////////////////////////////// /////////////////// 1629 //////////////////////////////////////////////////////////////////////////////// ///////////////////
1606 1630
1607 #ifdef GR_TEST_UTILS 1631 #ifdef GR_TEST_UTILS
1608 1632
1609 BATCH_TEST_DEFINE(TesselatingPathBatch) { 1633 BATCH_TEST_DEFINE(TesselatingPathBatch) {
1610 GrColor color = GrRandomColor(random); 1634 GrColor color = GrRandomColor(random);
1611 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); 1635 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
1612 SkPath path = GrTest::TestPath(random); 1636 SkPath path = GrTest::TestPath(random);
1613 SkRect clipBounds = GrTest::TestRect(random); 1637 SkRect clipBounds = GrTest::TestRect(random);
1614 SkMatrix vmi; 1638 SkMatrix vmi;
1615 bool result = viewMatrix.invert(&vmi); 1639 bool result = viewMatrix.invert(&vmi);
1616 if (!result) { 1640 if (!result) {
1617 SkFAIL("Cannot invert matrix\n"); 1641 SkFAIL("Cannot invert matrix\n");
1618 } 1642 }
1619 vmi.mapRect(&clipBounds); 1643 vmi.mapRect(&clipBounds);
1620 return TessellatingPathBatch::Create(color, path, viewMatrix, clipBounds); 1644 SkPaint strokePaint;
bsalomon 2015/08/05 18:53:51 This doesn't look like it is actually initialized
Stephen White 2015/08/05 18:57:39 True.. I was looking for something that would gene
1645 GrStrokeInfo stroke(strokePaint);
1646 return TessellatingPathBatch::Create(color, path, stroke, viewMatrix, clipBo unds);
1621 } 1647 }
1622 1648
1623 #endif 1649 #endif
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