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