| 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 "GrBatchFlushState.h" | 10 #include "GrBatchFlushState.h" |
| (...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1330 for (Poly* poly = polys; poly; poly = poly->fNext) { | 1330 for (Poly* poly = polys; poly; poly = poly->fNext) { |
| 1331 if (apply_fill_type(fillType, poly->fWinding)) { | 1331 if (apply_fill_type(fillType, poly->fWinding)) { |
| 1332 d = poly->emit(d); | 1332 d = poly->emit(d); |
| 1333 } | 1333 } |
| 1334 } | 1334 } |
| 1335 return d; | 1335 return d; |
| 1336 } | 1336 } |
| 1337 | 1337 |
| 1338 struct TessInfo { | 1338 struct TessInfo { |
| 1339 SkScalar fTolerance; | 1339 SkScalar fTolerance; |
| 1340 int fVertexCount; | 1340 int fCount; |
| 1341 }; | 1341 }; |
| 1342 | 1342 |
| 1343 bool cache_match(GrVertexBuffer* vertexBuffer, SkScalar tol, int* vertexCount) { | 1343 bool cache_match(GrVertexBuffer* vertexBuffer, SkScalar tol, int* actualCount) { |
| 1344 if (!vertexBuffer) { | 1344 if (!vertexBuffer) { |
| 1345 return false; | 1345 return false; |
| 1346 } | 1346 } |
| 1347 const SkData* data = vertexBuffer->getUniqueKey().getCustomData(); | 1347 const SkData* data = vertexBuffer->getUniqueKey().getCustomData(); |
| 1348 SkASSERT(data); | 1348 SkASSERT(data); |
| 1349 const TessInfo* info = static_cast<const TessInfo*>(data->data()); | 1349 const TessInfo* info = static_cast<const TessInfo*>(data->data()); |
| 1350 if (info->fTolerance == 0 || info->fTolerance < 3.0f * tol) { | 1350 if (info->fTolerance == 0 || info->fTolerance < 3.0f * tol) { |
| 1351 *vertexCount = info->fVertexCount; | 1351 *actualCount = info->fCount; |
| 1352 return true; | 1352 return true; |
| 1353 } | 1353 } |
| 1354 return false; | 1354 return false; |
| 1355 } | 1355 } |
| 1356 | 1356 |
| 1357 }; | 1357 }; |
| 1358 | 1358 |
| 1359 GrTessellatingPathRenderer::GrTessellatingPathRenderer() { | 1359 GrTessellatingPathRenderer::GrTessellatingPathRenderer() { |
| 1360 } | 1360 } |
| 1361 | 1361 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1464 | 1464 |
| 1465 // For the initial size of the chunk allocator, estimate based on the po
int count: | 1465 // For the initial size of the chunk allocator, estimate based on the po
int count: |
| 1466 // one vertex per point for the initial passes, plus two for the vertice
s in the | 1466 // one vertex per point for the initial passes, plus two for the vertice
s in the |
| 1467 // resulting Polys, since the same point may end up in two Polys. Assum
e minimal | 1467 // resulting Polys, since the same point may end up in two Polys. Assum
e minimal |
| 1468 // connectivity of one Edge per Vertex (will grow for intersections). | 1468 // connectivity of one Edge per Vertex (will grow for intersections). |
| 1469 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); | 1469 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); |
| 1470 bool isLinear; | 1470 bool isLinear; |
| 1471 path_to_contours(path, tol, fClipBounds, contours.get(), alloc, &isLinea
r); | 1471 path_to_contours(path, tol, fClipBounds, contours.get(), alloc, &isLinea
r); |
| 1472 Poly* polys; | 1472 Poly* polys; |
| 1473 polys = contours_to_polys(contours.get(), contourCnt, c, alloc); | 1473 polys = contours_to_polys(contours.get(), contourCnt, c, alloc); |
| 1474 int vertexCount = 0; | 1474 int count = 0; |
| 1475 for (Poly* poly = polys; poly; poly = poly->fNext) { | 1475 for (Poly* poly = polys; poly; poly = poly->fNext) { |
| 1476 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3)
{ | 1476 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3)
{ |
| 1477 vertexCount += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); | 1477 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); |
| 1478 } | 1478 } |
| 1479 } | 1479 } |
| 1480 if (0 == vertexCount) { | 1480 if (0 == count) { |
| 1481 return 0; | 1481 return 0; |
| 1482 } | 1482 } |
| 1483 | 1483 |
| 1484 size_t size = vertexCount * sizeof(SkPoint); | 1484 size_t size = count * sizeof(SkPoint); |
| 1485 if (!vertexBuffer.get() || vertexBuffer->gpuMemorySize() < size) { | 1485 if (!vertexBuffer.get() || vertexBuffer->gpuMemorySize() < size) { |
| 1486 vertexBuffer.reset(resourceProvider->createVertexBuffer( | 1486 vertexBuffer.reset(resourceProvider->createVertexBuffer( |
| 1487 size, GrResourceProvider::kStatic_BufferUsage, 0)); | 1487 size, GrResourceProvider::kStatic_BufferUsage, 0)); |
| 1488 } | 1488 } |
| 1489 if (!vertexBuffer.get()) { | 1489 if (!vertexBuffer.get()) { |
| 1490 SkDebugf("Could not allocate vertices\n"); | 1490 SkDebugf("Could not allocate vertices\n"); |
| 1491 return 0; | 1491 return 0; |
| 1492 } | 1492 } |
| 1493 SkPoint* verts; | 1493 SkPoint* verts; |
| 1494 if (canMapVB) { | 1494 if (canMapVB) { |
| 1495 verts = static_cast<SkPoint*>(vertexBuffer->map()); | 1495 verts = static_cast<SkPoint*>(vertexBuffer->map()); |
| 1496 } else { | 1496 } else { |
| 1497 verts = new SkPoint[vertexCount]; | 1497 verts = new SkPoint[count]; |
| 1498 } | 1498 } |
| 1499 SkDEBUGCODE(SkPoint* end = ) polys_to_triangles(polys, fillType, verts); | 1499 SkPoint* end = polys_to_triangles(polys, fillType, verts); |
| 1500 SkASSERT(static_cast<int>(end - verts) == vertexCount); | 1500 int actualCount = static_cast<int>(end - verts); |
| 1501 LOG("vertex count: %d\n", vertexCount); | 1501 LOG("actual count: %d\n", actualCount); |
| 1502 SkASSERT(actualCount <= count); |
| 1502 if (canMapVB) { | 1503 if (canMapVB) { |
| 1503 vertexBuffer->unmap(); | 1504 vertexBuffer->unmap(); |
| 1504 } else { | 1505 } else { |
| 1505 vertexBuffer->updateData(verts, vertexCount * sizeof(SkPoint)); | 1506 vertexBuffer->updateData(verts, actualCount * sizeof(SkPoint)); |
| 1506 delete[] verts; | 1507 delete[] verts; |
| 1507 } | 1508 } |
| 1508 | 1509 |
| 1509 | 1510 |
| 1510 if (!fPath.isVolatile()) { | 1511 if (!fPath.isVolatile()) { |
| 1511 TessInfo info; | 1512 TessInfo info; |
| 1512 info.fTolerance = isLinear ? 0 : tol; | 1513 info.fTolerance = isLinear ? 0 : tol; |
| 1513 info.fVertexCount = vertexCount; | 1514 info.fCount = actualCount; |
| 1514 SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info))); | 1515 SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info))); |
| 1515 key->setCustomData(data.get()); | 1516 key->setCustomData(data.get()); |
| 1516 resourceProvider->assignUniqueKeyToResource(*key, vertexBuffer.get()
); | 1517 resourceProvider->assignUniqueKeyToResource(*key, vertexBuffer.get()
); |
| 1517 SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(*key))
; | 1518 SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(*key))
; |
| 1518 } | 1519 } |
| 1519 return vertexCount; | 1520 return actualCount; |
| 1520 } | 1521 } |
| 1521 | 1522 |
| 1522 void onPrepareDraws(Target* target) override { | 1523 void onPrepareDraws(Target* target) override { |
| 1523 // construct a cache key from the path's genID and the view matrix | 1524 // construct a cache key from the path's genID and the view matrix |
| 1524 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain()
; | 1525 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain()
; |
| 1525 GrUniqueKey key; | 1526 GrUniqueKey key; |
| 1526 int clipBoundsSize32 = | 1527 int clipBoundsSize32 = |
| 1527 fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) :
0; | 1528 fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) :
0; |
| 1528 int strokeDataSize32 = fStroke.computeUniqueKeyFragmentData32Cnt(); | 1529 int strokeDataSize32 = fStroke.computeUniqueKeyFragmentData32Cnt(); |
| 1529 GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsSize32 + strok
eDataSize32); | 1530 GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsSize32 + strok
eDataSize32); |
| 1530 builder[0] = fPath.getGenerationID(); | 1531 builder[0] = fPath.getGenerationID(); |
| 1531 builder[1] = fPath.getFillType(); | 1532 builder[1] = fPath.getFillType(); |
| 1532 // For inverse fills, the tessellation is dependent on clip bounds. | 1533 // For inverse fills, the tessellation is dependent on clip bounds. |
| 1533 if (fPath.isInverseFillType()) { | 1534 if (fPath.isInverseFillType()) { |
| 1534 memcpy(&builder[2], &fClipBounds, sizeof(fClipBounds)); | 1535 memcpy(&builder[2], &fClipBounds, sizeof(fClipBounds)); |
| 1535 } | 1536 } |
| 1536 fStroke.asUniqueKeyFragment(&builder[2 + clipBoundsSize32]); | 1537 fStroke.asUniqueKeyFragment(&builder[2 + clipBoundsSize32]); |
| 1537 builder.finish(); | 1538 builder.finish(); |
| 1538 GrResourceProvider* rp = target->resourceProvider(); | 1539 GrResourceProvider* rp = target->resourceProvider(); |
| 1539 SkAutoTUnref<GrVertexBuffer> vertexBuffer(rp->findAndRefTByUniqueKey<GrV
ertexBuffer>(key)); | 1540 SkAutoTUnref<GrVertexBuffer> vertexBuffer(rp->findAndRefTByUniqueKey<GrV
ertexBuffer>(key)); |
| 1540 int vertexCount; | 1541 int actualCount; |
| 1541 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; | 1542 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; |
| 1542 SkScalar tol = GrPathUtils::scaleToleranceToSrc( | 1543 SkScalar tol = GrPathUtils::scaleToleranceToSrc( |
| 1543 screenSpaceTol, fViewMatrix, fPath.getBounds()); | 1544 screenSpaceTol, fViewMatrix, fPath.getBounds()); |
| 1544 if (!cache_match(vertexBuffer.get(), tol, &vertexCount)) { | 1545 if (!cache_match(vertexBuffer.get(), tol, &actualCount)) { |
| 1545 bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFl
ags(); | 1546 bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFl
ags(); |
| 1546 vertexCount = tessellate(&key, rp, vertexBuffer, canMapVB); | 1547 actualCount = tessellate(&key, rp, vertexBuffer, canMapVB); |
| 1547 } | 1548 } |
| 1548 | 1549 |
| 1549 if (vertexCount == 0) { | 1550 if (actualCount == 0) { |
| 1550 return; | 1551 return; |
| 1551 } | 1552 } |
| 1552 | 1553 |
| 1553 SkAutoTUnref<const GrGeometryProcessor> gp; | 1554 SkAutoTUnref<const GrGeometryProcessor> gp; |
| 1554 { | 1555 { |
| 1555 using namespace GrDefaultGeoProcFactory; | 1556 using namespace GrDefaultGeoProcFactory; |
| 1556 | 1557 |
| 1557 Color color(fColor); | 1558 Color color(fColor); |
| 1558 LocalCoords localCoords(fPipelineInfo.readsLocalCoords() ? | 1559 LocalCoords localCoords(fPipelineInfo.readsLocalCoords() ? |
| 1559 LocalCoords::kUsePosition_Type : | 1560 LocalCoords::kUsePosition_Type : |
| 1560 LocalCoords::kUnused_Type); | 1561 LocalCoords::kUnused_Type); |
| 1561 Coverage::Type coverageType; | 1562 Coverage::Type coverageType; |
| 1562 if (fPipelineInfo.readsCoverage()) { | 1563 if (fPipelineInfo.readsCoverage()) { |
| 1563 coverageType = Coverage::kSolid_Type; | 1564 coverageType = Coverage::kSolid_Type; |
| 1564 } else { | 1565 } else { |
| 1565 coverageType = Coverage::kNone_Type; | 1566 coverageType = Coverage::kNone_Type; |
| 1566 } | 1567 } |
| 1567 Coverage coverage(coverageType); | 1568 Coverage coverage(coverageType); |
| 1568 gp.reset(GrDefaultGeoProcFactory::Create(color, coverage, localCoord
s, | 1569 gp.reset(GrDefaultGeoProcFactory::Create(color, coverage, localCoord
s, |
| 1569 fViewMatrix)); | 1570 fViewMatrix)); |
| 1570 } | 1571 } |
| 1571 | 1572 |
| 1572 target->initDraw(gp, this->pipeline()); | 1573 target->initDraw(gp, this->pipeline()); |
| 1573 SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); | 1574 SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); |
| 1574 | 1575 |
| 1575 GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType | 1576 GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType |
| 1576 : kTriangles_GrPrimitiveType; | 1577 : kTriangles_GrPrimitiveType; |
| 1577 GrVertices vertices; | 1578 GrVertices vertices; |
| 1578 vertices.init(primitiveType, vertexBuffer.get(), 0, vertexCount); | 1579 vertices.init(primitiveType, vertexBuffer.get(), 0, actualCount); |
| 1579 target->draw(vertices); | 1580 target->draw(vertices); |
| 1580 } | 1581 } |
| 1581 | 1582 |
| 1582 bool onCombineIfPossible(GrBatch*, const GrCaps&) override { return false; } | 1583 bool onCombineIfPossible(GrBatch*, const GrCaps&) override { return false; } |
| 1583 | 1584 |
| 1584 TessellatingPathBatch(const GrColor& color, | 1585 TessellatingPathBatch(const GrColor& color, |
| 1585 const SkPath& path, | 1586 const SkPath& path, |
| 1586 const GrStrokeInfo& stroke, | 1587 const GrStrokeInfo& stroke, |
| 1587 const SkMatrix& viewMatrix, | 1588 const SkMatrix& viewMatrix, |
| 1588 const SkRect& clipBounds) | 1589 const SkRect& clipBounds) |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1651 bool result = viewMatrix.invert(&vmi); | 1652 bool result = viewMatrix.invert(&vmi); |
| 1652 if (!result) { | 1653 if (!result) { |
| 1653 SkFAIL("Cannot invert matrix\n"); | 1654 SkFAIL("Cannot invert matrix\n"); |
| 1654 } | 1655 } |
| 1655 vmi.mapRect(&clipBounds); | 1656 vmi.mapRect(&clipBounds); |
| 1656 GrStrokeInfo strokeInfo = GrTest::TestStrokeInfo(random); | 1657 GrStrokeInfo strokeInfo = GrTest::TestStrokeInfo(random); |
| 1657 return TessellatingPathBatch::Create(color, path, strokeInfo, viewMatrix, cl
ipBounds); | 1658 return TessellatingPathBatch::Create(color, path, strokeInfo, viewMatrix, cl
ipBounds); |
| 1658 } | 1659 } |
| 1659 | 1660 |
| 1660 #endif | 1661 #endif |
| OLD | NEW |