From 021f927e4cb8293a56923b763682217067486878 Mon Sep 17 00:00:00 2001 From: Stephan White Date: Tue, 3 Jan 2017 21:06:16 +0000 Subject: [PATCH] Revert "Quality and performance fixes for AA tessellating path renderer." This reverts commit d4b21552481a6d313dfa9bc14b624c9ec94b56ce. Reason for revert: accidentally added some unwanted changes Original change's description: > Quality and performance fixes for AA tessellating path renderer. > > Use quads rather than triangles for the edge geometry. This allows > us to perform a simpler edge categorization (see below). It also > improves performance by reducing the number of edges processed during > the simplify and tessellate steps. > > Label AA edges as three types: inner, outer, and connector. This > results in correct alpha values for intersected edges, even when > the top or bottom vertex has been merged with a vertex on edges > of different types. > > Changed the "collinear edges" sample from the concavepaths GM for a > "fast-foward" shape, which more clearly shows the problem being fixed > here. (The collinearity from the "collinear edges" was actually being > removed earlier up the stack, causing the path to become convex and > not exercise the concave path renderers anyway.) > > NOTE: this will cause changes in the "concavepaths" GM results, and > minor pixel diffs in a number of other tests. > > BUG=660893 > > Change-Id: Ide49374d6d173404c7223f7316dd439df1435787 > Reviewed-on: https://skia-review.googlesource.com/6427 > Commit-Queue: Stephan White > Reviewed-by: Brian Salomon > TBR=bsalomon@google.com,senorblanco@chromium.org,reviews@skia.org BUG=660893 NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Change-Id: I06a36e397645bfc42442a5a9e7c27328f6048ab9 Reviewed-on: https://skia-review.googlesource.com/6428 Commit-Queue: Stephan White Reviewed-by: Stephan White --- gm/concavepaths.cpp | 15 ++--- src/gpu/GrPathRendererChain.cpp | 12 ++-- src/gpu/GrTessellator.cpp | 70 +++++++++------------- src/gpu/ops/GrTessellatingPathRenderer.cpp | 18 +++--- 4 files changed, 48 insertions(+), 67 deletions(-) diff --git a/gm/concavepaths.cpp b/gm/concavepaths.cpp index c68265b99f..ad87d255ca 100644 --- a/gm/concavepaths.cpp +++ b/gm/concavepaths.cpp @@ -80,18 +80,15 @@ void test_fish(SkCanvas* canvas, const SkPaint& paint) { canvas->restore(); } -// Overlapping "Fast-forward" icon: tests coincidence of inner and outer -// vertices generated by intersection. -void test_fast_forward(SkCanvas* canvas, const SkPaint& paint) { +// Collinear edges +void test_collinear_edges(SkCanvas* canvas, const SkPaint& paint) { SkPath path; canvas->save(); canvas->translate(100, 100); path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); - path.lineTo(SkIntToScalar(60), SkIntToScalar(50)); - path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); - path.moveTo(SkIntToScalar(40), SkIntToScalar(20)); - path.lineTo(SkIntToScalar(40), SkIntToScalar(80)); - path.lineTo(SkIntToScalar(80), SkIntToScalar(50)); + path.lineTo(SkIntToScalar(50), SkIntToScalar(20)); + path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); + path.lineTo(SkIntToScalar(50), SkIntToScalar(80)); canvas->drawPath(path, paint); canvas->restore(); } @@ -387,7 +384,7 @@ protected: test_bowtie(canvas, paint); test_fake_bowtie(canvas, paint); test_fish(canvas, paint); - test_fast_forward(canvas, paint); + test_collinear_edges(canvas, paint); test_hole(canvas, paint); test_star(canvas, paint); test_stairstep(canvas, paint); diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp index 233594b2e7..c0cac80dff 100644 --- a/src/gpu/GrPathRendererChain.cpp +++ b/src/gpu/GrPathRendererChain.cpp @@ -35,9 +35,9 @@ GrPathRendererChain::GrPathRendererChain(GrContext* context, const Options& opti this->addPathRenderer(pr)->unref(); } #ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK -// if (caps.sampleShadingSupport()) { -// this->addPathRenderer(new GrMSAAPathRenderer)->unref(); -// } + if (caps.sampleShadingSupport()) { + this->addPathRenderer(new GrMSAAPathRenderer)->unref(); + } #endif this->addPathRenderer(new GrAAHairLinePathRenderer)->unref(); this->addPathRenderer(new GrAAConvexPathRenderer)->unref(); @@ -45,9 +45,9 @@ GrPathRendererChain::GrPathRendererChain(GrContext* context, const Options& opti if (caps.shaderCaps()->plsPathRenderingSupport()) { this->addPathRenderer(new GrPLSPathRenderer)->unref(); } -// if (!options.fDisableDistanceFieldRenderer) { -// this->addPathRenderer(new GrAADistanceFieldPathRenderer)->unref(); -// } + if (!options.fDisableDistanceFieldRenderer) { + this->addPathRenderer(new GrAADistanceFieldPathRenderer)->unref(); + } this->addPathRenderer(new GrTessellatingPathRenderer)->unref(); this->addPathRenderer(new GrDefaultPathRenderer(caps.twoSidedStencilSupport(), caps.stencilWrapOpsSupport()))->unref(); diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp index 16f629ef64..e75e1bbd9f 100644 --- a/src/gpu/GrTessellator.cpp +++ b/src/gpu/GrTessellator.cpp @@ -309,12 +309,10 @@ struct Line { */ struct Edge { - enum class Type { kInner, kOuter, kConnector }; - Edge(Vertex* top, Vertex* bottom, int winding, Type type) + Edge(Vertex* top, Vertex* bottom, int winding) : fWinding(winding) , fTop(top) , fBottom(bottom) - , fType(type) , fLeft(nullptr) , fRight(nullptr) , fPrevEdgeAbove(nullptr) @@ -334,7 +332,6 @@ struct Edge { int fWinding; // 1 == edge goes downward; -1 = edge goes upward. Vertex* fTop; // The top vertex in vertex-sort-order (sweep_lt). Vertex* fBottom; // The bottom vertex in vertex-sort-order. - Type fType; Edge* fLeft; // The linked list of edges in the active edge list. Edge* fRight; // " Edge* fPrevEdgeAbove; // The linked list of edges in the bottom Vertex's "edges above". @@ -534,8 +531,7 @@ struct Poly { fTail->addEdge(e); fCount++; } else { - e = ALLOC_NEW(Edge, (fTail->fLastEdge->fBottom, e->fBottom, 1, Edge::Type::kInner), - alloc); + e = ALLOC_NEW(Edge, (fTail->fLastEdge->fBottom, e->fBottom, 1), alloc); fTail->addEdge(e); fCount++; if (partner) { @@ -771,11 +767,12 @@ inline bool apply_fill_type(SkPath::FillType fillType, Poly* poly) { } } -Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator& c, Edge::Type type) { - int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1; +Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator& c, + int winding_scale = 1) { + int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? winding_scale : -winding_scale; Vertex* top = winding < 0 ? next : prev; Vertex* bottom = winding < 0 ? prev : next; - return ALLOC_NEW(Edge, (top, bottom, winding, type), alloc); + return ALLOC_NEW(Edge, (top, bottom, winding), alloc); } void remove_edge(Edge* edge, EdgeList* edges) { @@ -828,10 +825,7 @@ void find_enclosing_edges(Edge* edge, EdgeList* edges, Comparator& c, Edge** lef } void fix_active_state(Edge* edge, EdgeList* activeEdges, Comparator& c) { - if (!activeEdges) { - return; - } - if (activeEdges->contains(edge)) { + if (activeEdges && activeEdges->contains(edge)) { if (edge->fBottom->fProcessed || !edge->fTop->fProcessed) { remove_edge(edge, activeEdges); } @@ -1027,7 +1021,7 @@ void split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c, SkC } else if (c.sweep_gt(v->fPoint, edge->fBottom->fPoint)) { set_bottom(edge, v, activeEdges, c); } else { - Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding, edge->fType), alloc); + Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), alloc); insert_edge_below(newEdge, v, c); insert_edge_above(newEdge, edge->fBottom, c); set_bottom(edge, v, activeEdges, c); @@ -1037,8 +1031,9 @@ void split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c, SkC } } -Edge* connect(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator c, Edge::Type type) { - Edge* edge = new_edge(prev, next, alloc, c, type); +Edge* connect(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator c, + int winding_scale = 1) { + Edge* edge = new_edge(prev, next, alloc, c, winding_scale); if (edge->fWinding > 0) { insert_edge_below(edge, prev, c); insert_edge_above(edge, next, c); @@ -1068,14 +1063,8 @@ void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, Comparator& c, SkCh } uint8_t max_edge_alpha(Edge* a, Edge* b) { - if (a->fType == Edge::Type::kInner && b->fType == Edge::Type::kInner) { - return 255; - } else if (a->fType == Edge::Type::kOuter && b->fType == Edge::Type::kOuter) { - return 0; - } else { - return SkTMax(SkTMax(a->fTop->fAlpha, a->fBottom->fAlpha), - SkTMax(b->fTop->fAlpha, b->fBottom->fAlpha)); - } + return SkTMax(SkTMax(a->fTop->fAlpha, a->fBottom->fAlpha), + SkTMax(b->fTop->fAlpha, b->fBottom->fAlpha)); } Vertex* check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Comparator& c, @@ -1180,7 +1169,7 @@ Vertex* build_edges(Vertex** contours, int contourCnt, Comparator& c, SkChunkAll for (int i = 0; i < contourCnt; ++i) { for (Vertex* v = contours[i]; v != nullptr;) { Vertex* vNext = v->fNext; - connect(v->fPrev, v, alloc, c, Edge::Type::kInner); + connect(v->fPrev, v, alloc, c); if (prev) { prev->fNext = v; v->fPrev = prev; @@ -1306,8 +1295,8 @@ void simplify(Vertex* vertices, Comparator& c, SkChunkAlloc& alloc) { } } while (restartChecks); if (v->fAlpha == 0) { - if ((leftEnclosingEdge && leftEnclosingEdge->fWinding > 0) && - (rightEnclosingEdge && rightEnclosingEdge->fWinding < 0)) { + if ((leftEnclosingEdge && leftEnclosingEdge->fWinding < 0) && + (rightEnclosingEdge && rightEnclosingEdge->fWinding > 0)) { v->fAlpha = max_edge_alpha(leftEnclosingEdge, rightEnclosingEdge); } } @@ -1402,8 +1391,7 @@ Poly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) { rightEnclosingEdge->fLeftPoly = rightPoly; } } - Edge* join = ALLOC_NEW(Edge, - (leftPoly->lastVertex(), v, 1, Edge::Type::kInner), alloc); + Edge* join = ALLOC_NEW(Edge, (leftPoly->lastVertex(), v, 1), alloc); leftPoly = leftPoly->addEdge(join, Poly::kRight_Side, alloc); rightPoly = rightPoly->addEdge(join, Poly::kLeft_Side, alloc); } @@ -1481,7 +1469,7 @@ void simplify_boundary(EdgeList* boundary, Comparator& c, SkChunkAlloc& alloc) { get_edge_normal(e, &normal); float denom = 0.25f * static_cast(e->fLine.magSq()); if (prevNormal.dot(normal) < 0.0 && (dist * dist) <= denom) { - Edge* join = new_edge(prev, next, alloc, c, Edge::Type::kInner); + Edge* join = new_edge(prev, next, alloc, c); insert_edge(join, e, boundary); remove_edge(prevEdge, boundary); remove_edge(e, boundary); @@ -1529,8 +1517,8 @@ void boundary_to_aa_mesh(EdgeList* boundary, VertexList* mesh, Comparator& c, Sk Vertex* innerVertex = ALLOC_NEW(Vertex, (innerPoint, 255), alloc); Vertex* outerVertex = ALLOC_NEW(Vertex, (outerPoint, 0), alloc); if (innerVertices.fTail && outerVertices.fTail) { - Edge innerEdge(innerVertices.fTail, innerVertex, 1, Edge::Type::kInner); - Edge outerEdge(outerVertices.fTail, outerVertex, 1, Edge::Type::kInner); + Edge innerEdge(innerVertices.fTail, innerVertex, 1); + Edge outerEdge(outerVertices.fTail, outerVertex, 1); SkVector innerNormal; get_edge_normal(&innerEdge, &innerNormal); SkVector outerNormal; @@ -1572,9 +1560,10 @@ void boundary_to_aa_mesh(EdgeList* boundary, VertexList* mesh, Comparator& c, Sk return; } do { - connect(outerVertex->fPrev, outerVertex, alloc, c, Edge::Type::kOuter); - connect(innerVertex->fPrev, innerVertex, alloc, c, Edge::Type::kInner); - connect(outerVertex, innerVertex, alloc, c, Edge::Type::kConnector)->fWinding = 0; + connect(outerVertex->fNext, outerVertex, alloc, c); + connect(innerVertex->fNext, innerVertex, alloc, c, 2); + connect(innerVertex, outerVertex->fNext, alloc, c, 2); + connect(outerVertex, innerVertex, alloc, c, 2); Vertex* innerNext = innerVertex->fNext; Vertex* outerNext = outerVertex->fNext; mesh->append(innerVertex); @@ -1648,9 +1637,9 @@ Vertex* contours_to_mesh(Vertex** contours, int contourCnt, bool antialias, return build_edges(contours, contourCnt, c, alloc); } -void sort_and_simplify(Vertex** vertices, Comparator& c, SkChunkAlloc& alloc) { +Poly* mesh_to_polys(Vertex** vertices, Comparator& c, SkChunkAlloc& alloc) { if (!vertices || !*vertices) { - return; + return nullptr; } // Sort vertices in Y (secondarily in X). @@ -1663,10 +1652,6 @@ void sort_and_simplify(Vertex** vertices, Comparator& c, SkChunkAlloc& alloc) { } #endif simplify(*vertices, c, alloc); -} - -Poly* mesh_to_polys(Vertex** vertices, Comparator& c, SkChunkAlloc& alloc) { - sort_and_simplify(vertices, c, alloc); return tessellate(*vertices, alloc); } @@ -1692,8 +1677,7 @@ Poly* contours_to_polys(Vertex** contours, int contourCnt, SkPath::FillType fill boundary_to_aa_mesh(boundary, &aaMesh, c, alloc); } } - sort_and_simplify(&aaMesh.fHead, c, alloc); - return tessellate(aaMesh.fHead, alloc); + return mesh_to_polys(&aaMesh.fHead, c, alloc); } return polys; } diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp index e61983452e..81a982ca20 100644 --- a/src/gpu/ops/GrTessellatingPathRenderer.cpp +++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp @@ -141,15 +141,15 @@ bool GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) cons return false; } if (GrAAType::kCoverage == args.fAAType) { -//#ifdef SK_DISABLE_SCREENSPACE_TESS_AA_PATH_RENDERER -// return false; -//#else -// SkPath path; -// args.fShape->asPath(&path); -// if (path.countVerbs() > 10) { -// return false; -// } -//#endif +#ifdef SK_DISABLE_SCREENSPACE_TESS_AA_PATH_RENDERER + return false; +#else + SkPath path; + args.fShape->asPath(&path); + if (path.countVerbs() > 10) { + return false; + } +#endif } else if (!args.fShape->hasUnstyledKey()) { return false; }