| 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" | 
|  | 11 #include "GrBatchTarget.h" | 
| 10 #include "GrDefaultGeoProcFactory.h" | 12 #include "GrDefaultGeoProcFactory.h" | 
| 11 #include "GrPathUtils.h" | 13 #include "GrPathUtils.h" | 
| 12 #include "SkChunkAlloc.h" | 14 #include "SkChunkAlloc.h" | 
| 13 #include "SkGeometry.h" | 15 #include "SkGeometry.h" | 
| 14 | 16 | 
| 15 #include <stdio.h> | 17 #include <stdio.h> | 
| 16 | 18 | 
| 17 /* | 19 /* | 
| 18  * This path renderer tessellates the path into triangles, uploads the triangles
       to a | 20  * This path renderer tessellates the path into triangles, uploads the triangles
       to a | 
| 19  * vertex buffer, and renders them with a single draw call. It does not currentl
      y do | 21  * vertex buffer, and renders them with a single draw call. It does not currentl
      y do | 
| (...skipping 1409 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1429                                              const GrPipelineBuilder* pipelineBu
      ilder, | 1431                                              const GrPipelineBuilder* pipelineBu
      ilder, | 
| 1430                                              const SkMatrix& viewMatrix, | 1432                                              const SkMatrix& viewMatrix, | 
| 1431                                              const SkPath& path, | 1433                                              const SkPath& path, | 
| 1432                                              const SkStrokeRec& stroke, | 1434                                              const SkStrokeRec& stroke, | 
| 1433                                              bool antiAlias) const { | 1435                                              bool antiAlias) const { | 
| 1434     // This path renderer can draw all fill styles, but does not do antialiasing
      . It can do convex | 1436     // This path renderer can draw all fill styles, but does not do antialiasing
      . It can do convex | 
| 1435     // and concave paths, but we'll leave the convex ones to simpler algorithms. | 1437     // and concave paths, but we'll leave the convex ones to simpler algorithms. | 
| 1436     return stroke.isFillStyle() && !antiAlias && !path.isConvex(); | 1438     return stroke.isFillStyle() && !antiAlias && !path.isConvex(); | 
| 1437 } | 1439 } | 
| 1438 | 1440 | 
|  | 1441 class TessellatingPathBatch : public GrBatch { | 
|  | 1442 public: | 
|  | 1443 | 
|  | 1444     static GrBatch* Create(const GrColor& color, | 
|  | 1445                            const SkPath& path, | 
|  | 1446                            const SkMatrix& viewMatrix, | 
|  | 1447                            SkRect clipBounds) { | 
|  | 1448         return SkNEW_ARGS(TessellatingPathBatch, (color, path, viewMatrix, clipB
      ounds)); | 
|  | 1449     } | 
|  | 1450 | 
|  | 1451     const char* name() const SK_OVERRIDE { return "TessellatingPathBatch"; } | 
|  | 1452 | 
|  | 1453     void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE { | 
|  | 1454         out->setKnownFourComponents(fColor); | 
|  | 1455     } | 
|  | 1456 | 
|  | 1457     void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRID
      E { | 
|  | 1458         out->setUnknownSingleComponent(); | 
|  | 1459     } | 
|  | 1460 | 
|  | 1461     void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE { | 
|  | 1462         // Handle any color overrides | 
|  | 1463         if (init.fColorIgnored) { | 
|  | 1464             fColor = GrColor_ILLEGAL; | 
|  | 1465         } else if (GrColor_ILLEGAL != init.fOverrideColor) { | 
|  | 1466             fColor = init.fOverrideColor; | 
|  | 1467         } | 
|  | 1468         fPipelineInfo = init; | 
|  | 1469     } | 
|  | 1470 | 
|  | 1471     void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline
      ) SK_OVERRIDE { | 
|  | 1472         SkScalar tol = GrPathUtils::scaleToleranceToSrc(SK_Scalar1, fViewMatrix,
       fPath.getBounds()); | 
|  | 1473         int contourCnt; | 
|  | 1474         int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol); | 
|  | 1475         if (maxPts <= 0) { | 
|  | 1476             return; | 
|  | 1477         } | 
|  | 1478         if (maxPts > ((int)SK_MaxU16 + 1)) { | 
|  | 1479             SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); | 
|  | 1480             return; | 
|  | 1481         } | 
|  | 1482         SkPath::FillType fillType = fPath.getFillType(); | 
|  | 1483         if (SkPath::IsInverseFillType(fillType)) { | 
|  | 1484             contourCnt++; | 
|  | 1485         } | 
|  | 1486 | 
|  | 1487         LOG("got %d pts, %d contours\n", maxPts, contourCnt); | 
|  | 1488         uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType; | 
|  | 1489         SkAutoTUnref<const GrGeometryProcessor> gp( | 
|  | 1490             GrDefaultGeoProcFactory::Create(flags, fColor, fViewMatrix, SkMatrix
      ::I())); | 
|  | 1491         batchTarget->initDraw(gp, pipeline); | 
|  | 1492         gp->initBatchTracker(batchTarget->currentBatchTracker(), fPipelineInfo); | 
|  | 1493 | 
|  | 1494         SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt)); | 
|  | 1495 | 
|  | 1496         // For the initial size of the chunk allocator, estimate based on the po
      int count: | 
|  | 1497         // one vertex per point for the initial passes, plus two for the vertice
      s in the | 
|  | 1498         // resulting Polys, since the same point may end up in two Polys.  Assum
      e minimal | 
|  | 1499         // connectivity of one Edge per Vertex (will grow for intersections). | 
|  | 1500         SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); | 
|  | 1501         path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc); | 
|  | 1502         Poly* polys; | 
|  | 1503         polys = contours_to_polys(contours.get(), contourCnt, alloc); | 
|  | 1504         int count = 0; | 
|  | 1505         for (Poly* poly = polys; poly; poly = poly->fNext) { | 
|  | 1506             if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) 
      { | 
|  | 1507                 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); | 
|  | 1508             } | 
|  | 1509         } | 
|  | 1510 | 
|  | 1511         size_t stride = gp->getVertexStride(); | 
|  | 1512         const GrVertexBuffer* vertexBuffer; | 
|  | 1513         int firstVertex; | 
|  | 1514         void* vertices = batchTarget->vertexPool()->makeSpace(stride, | 
|  | 1515                                                               count, | 
|  | 1516                                                               &vertexBuffer, | 
|  | 1517                                                               &firstVertex); | 
|  | 1518         LOG("emitting %d verts\n", count); | 
|  | 1519         void* end = polys_to_triangles(polys, fillType, vertices); | 
|  | 1520         int actualCount = static_cast<int>( | 
|  | 1521             (static_cast<char*>(end) - static_cast<char*>(vertices)) / stride); | 
|  | 1522         LOG("actual count: %d\n", actualCount); | 
|  | 1523         SkASSERT(actualCount <= count); | 
|  | 1524 | 
|  | 1525         GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType | 
|  | 1526                                                   : kTriangles_GrPrimitiveType; | 
|  | 1527         GrDrawTarget::DrawInfo drawInfo; | 
|  | 1528         drawInfo.setPrimitiveType(primitiveType); | 
|  | 1529         drawInfo.setVertexBuffer(vertexBuffer); | 
|  | 1530         drawInfo.setStartVertex(firstVertex); | 
|  | 1531         drawInfo.setVertexCount(actualCount); | 
|  | 1532         drawInfo.setStartIndex(0); | 
|  | 1533         drawInfo.setIndexCount(0); | 
|  | 1534         batchTarget->draw(drawInfo); | 
|  | 1535 | 
|  | 1536         batchTarget->putBackVertices((size_t)(count - actualCount), stride); | 
|  | 1537         return; | 
|  | 1538     } | 
|  | 1539 | 
|  | 1540     bool onCombineIfPossible(GrBatch*) SK_OVERRIDE { | 
|  | 1541         return false; | 
|  | 1542     } | 
|  | 1543 | 
|  | 1544 private: | 
|  | 1545     TessellatingPathBatch(const GrColor& color, | 
|  | 1546                           const SkPath& path, | 
|  | 1547                           const SkMatrix& viewMatrix, | 
|  | 1548                           const SkRect& clipBounds) | 
|  | 1549       : fColor(color) | 
|  | 1550       , fPath(path) | 
|  | 1551       , fViewMatrix(viewMatrix) | 
|  | 1552       , fClipBounds(clipBounds) { | 
|  | 1553         this->initClassID<TessellatingPathBatch>(); | 
|  | 1554     } | 
|  | 1555 | 
|  | 1556     GrColor        fColor; | 
|  | 1557     SkPath         fPath; | 
|  | 1558     SkMatrix       fViewMatrix; | 
|  | 1559     SkRect         fClipBounds; // in source space | 
|  | 1560     GrPipelineInfo fPipelineInfo; | 
|  | 1561 }; | 
|  | 1562 | 
| 1439 bool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target, | 1563 bool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target, | 
| 1440                                             GrPipelineBuilder* pipelineBuilder, | 1564                                             GrPipelineBuilder* pipelineBuilder, | 
| 1441                                             GrColor color, | 1565                                             GrColor color, | 
| 1442                                             const SkMatrix& viewM, | 1566                                             const SkMatrix& viewM, | 
| 1443                                             const SkPath& path, | 1567                                             const SkPath& path, | 
| 1444                                             const SkStrokeRec& stroke, | 1568                                             const SkStrokeRec& stroke, | 
| 1445                                             bool antiAlias) { | 1569                                             bool antiAlias) { | 
| 1446     SkASSERT(!antiAlias); | 1570     SkASSERT(!antiAlias); | 
| 1447     const GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); | 1571     const GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); | 
| 1448     if (NULL == rt) { | 1572     if (NULL == rt) { | 
| 1449         return false; | 1573         return false; | 
| 1450     } | 1574     } | 
| 1451 | 1575 | 
| 1452     SkScalar tol = GrPathUtils::scaleToleranceToSrc(SK_Scalar1, viewM, path.getB
      ounds()); |  | 
| 1453 |  | 
| 1454     int contourCnt; |  | 
| 1455     int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, tol); |  | 
| 1456     if (maxPts <= 0) { |  | 
| 1457         return false; |  | 
| 1458     } |  | 
| 1459     if (maxPts > ((int)SK_MaxU16 + 1)) { |  | 
| 1460         SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); |  | 
| 1461         return false; |  | 
| 1462     } |  | 
| 1463     SkPath::FillType fillType = path.getFillType(); |  | 
| 1464     if (SkPath::IsInverseFillType(fillType)) { |  | 
| 1465         contourCnt++; |  | 
| 1466     } |  | 
| 1467 |  | 
| 1468     LOG("got %d pts, %d contours\n", maxPts, contourCnt); |  | 
| 1469 |  | 
| 1470     SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt)); |  | 
| 1471 |  | 
| 1472     // For the initial size of the chunk allocator, estimate based on the point 
      count: |  | 
| 1473     // one vertex per point for the initial passes, plus two for the vertices in
       the |  | 
| 1474     // resulting Polys, since the same point may end up in two Polys.  Assume mi
      nimal |  | 
| 1475     // connectivity of one Edge per Vertex (will grow for intersections). |  | 
| 1476     SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); |  | 
| 1477     SkIRect clipBoundsI; | 1576     SkIRect clipBoundsI; | 
| 1478     pipelineBuilder->clip().getConservativeBounds(rt, &clipBoundsI); | 1577     pipelineBuilder->clip().getConservativeBounds(rt, &clipBoundsI); | 
| 1479     SkRect clipBounds = SkRect::Make(clipBoundsI); | 1578     SkRect clipBounds = SkRect::Make(clipBoundsI); | 
| 1480     SkMatrix vmi; | 1579     SkMatrix vmi; | 
| 1481     if (!viewM.invert(&vmi)) { | 1580     if (!viewM.invert(&vmi)) { | 
| 1482         return false; | 1581         return false; | 
| 1483     } | 1582     } | 
| 1484     vmi.mapRect(&clipBounds); | 1583     vmi.mapRect(&clipBounds); | 
| 1485     path_to_contours(path, tol, clipBounds, contours.get(), alloc); | 1584     SkAutoTUnref<GrBatch> batch(TessellatingPathBatch::Create(color, path, viewM
      , clipBounds)); | 
| 1486     Poly* polys; | 1585     target->drawBatch(pipelineBuilder, batch); | 
| 1487     uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType; |  | 
| 1488     polys = contours_to_polys(contours.get(), contourCnt, alloc); |  | 
| 1489     SkAutoTUnref<const GrGeometryProcessor> gp( |  | 
| 1490         GrDefaultGeoProcFactory::Create(flags, color, viewM, SkMatrix::I())); |  | 
| 1491     int count = 0; |  | 
| 1492     for (Poly* poly = polys; poly; poly = poly->fNext) { |  | 
| 1493         if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) { |  | 
| 1494             count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); |  | 
| 1495         } |  | 
| 1496     } |  | 
| 1497 |  | 
| 1498     size_t stride = gp->getVertexStride(); |  | 
| 1499     GrDrawTarget::AutoReleaseGeometry arg; |  | 
| 1500     if (!arg.set(target, count, stride, 0)) { |  | 
| 1501         return false; |  | 
| 1502     } |  | 
| 1503     LOG("emitting %d verts\n", count); |  | 
| 1504     void* end = polys_to_triangles(polys, fillType, arg.vertices()); |  | 
| 1505     int actualCount = static_cast<int>((static_cast<char*>(end) - static_cast<ch
      ar*>(arg.vertices())) / stride); |  | 
| 1506     LOG("actual count: %d\n", actualCount); |  | 
| 1507     SkASSERT(actualCount <= count); |  | 
| 1508 |  | 
| 1509     GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType |  | 
| 1510                                               : kTriangles_GrPrimitiveType; |  | 
| 1511     target->drawNonIndexed(pipelineBuilder, gp, primitiveType, 0, actualCount); |  | 
| 1512 | 1586 | 
| 1513     return true; | 1587     return true; | 
| 1514 } | 1588 } | 
| OLD | NEW | 
|---|