Chromium Code Reviews| 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, 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |