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 |