Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Unified Diff: src/gpu/GrTessellator.cpp

Issue 2299683002: Revert of Screenspace AA tessellated path rendering. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/GrTessellator.h ('k') | src/gpu/batches/GrTessellatingPathRenderer.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrTessellator.cpp
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp
index 9ce1a739df8dff27b24d3364da825fa35928ca24..ccffa9ffbeed21b29156e96c8d8e4cffe82e06c7 100644
--- a/src/gpu/GrTessellator.cpp
+++ b/src/gpu/GrTessellator.cpp
@@ -7,7 +7,6 @@
#include "GrTessellator.h"
-#include "GrDefaultGeoProcFactory.h"
#include "GrPathUtils.h"
#include "SkChunkAlloc.h"
@@ -17,7 +16,7 @@
#include <stdio.h>
/*
- * There are six stages to the basic algorithm:
+ * There are six stages to the algorithm:
*
* 1) Linearize the path contours into piecewise linear segments (path_to_contours()).
* 2) Build a mesh of edges connecting the vertices (build_edges()).
@@ -25,16 +24,6 @@
* 4) Simplify the mesh by inserting new vertices at intersecting edges (simplify()).
* 5) Tessellate the simplified mesh into monotone polygons (tessellate()).
* 6) Triangulate the monotone polygons directly into a vertex buffer (polys_to_triangles()).
- *
- * For screenspace antialiasing, the algorithm is modified as follows:
- *
- * Run steps 1-5 above to produce polygons.
- * 5b) Apply fill rules to extract boundary contours from the polygons (extract_boundaries()).
- * 5c) Simplify boundaries to remove "pointy" vertices which cause inversions (simplify_boundary()).
- * 5d) Displace edges by half a pixel inward and outward along their normals. Intersect to find
- * new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a new
- * antialiased mesh from those vertices (boundary_to_aa_mesh()).
- * Run steps 3-6 above on the new mesh, and produce antialiased triangles.
*
* The vertex sorting in step (3) is a merge sort, since it plays well with the linked list
* of vertices (and the necessity of inserting new vertices on intersection).
@@ -141,12 +130,11 @@
*/
struct Vertex {
- Vertex(const SkPoint& point, uint8_t alpha)
+ Vertex(const SkPoint& point)
: fPoint(point), fPrev(nullptr), fNext(nullptr)
, fFirstEdgeAbove(nullptr), fLastEdgeAbove(nullptr)
, fFirstEdgeBelow(nullptr), fLastEdgeBelow(nullptr)
, fProcessed(false)
- , fAlpha(alpha)
#if LOGGING_ENABLED
, fID (-1.0f)
#endif
@@ -159,7 +147,6 @@
Edge* fFirstEdgeBelow; // Linked list of edges below this vertex.
Edge* fLastEdgeBelow; // "
bool fProcessed; // Has this vertex been seen in simplify()?
- uint8_t fAlpha;
#if LOGGING_ENABLED
float fID; // Identifier used for logging.
#endif
@@ -167,11 +154,6 @@
/***************************************************************************************/
-struct AAParams {
- bool fTweakAlpha;
- GrColor fColor;
-};
-
typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b);
struct Comparator {
@@ -195,42 +177,32 @@
return a.fY == b.fY ? a.fX > b.fX : a.fY > b.fY;
}
-inline void* emit_vertex(Vertex* v, const AAParams* aaParams, void* data) {
- if (!aaParams) {
- SkPoint* d = static_cast<SkPoint*>(data);
- *d++ = v->fPoint;
- return d;
- }
- if (aaParams->fTweakAlpha) {
- auto d = static_cast<GrDefaultGeoProcFactory::PositionColorAttr*>(data);
- d->fPosition = v->fPoint;
- d->fColor = SkAlphaMulQ(aaParams->fColor, v->fAlpha);
- d++;
- return d;
- }
- auto d = static_cast<GrDefaultGeoProcFactory::PositionColorCoverageAttr*>(data);
- d->fPosition = v->fPoint;
- d->fColor = aaParams->fColor;
- d->fCoverage = GrNormalizeByteToFloat(v->fAlpha);
- d++;
- return d;
-}
-
-void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, const AAParams* aaParams, void* data) {
-#if TESSELLATOR_WIREFRAME
- data = emit_vertex(v0, aaParams, data);
- data = emit_vertex(v1, aaParams, data);
- data = emit_vertex(v1, aaParams, data);
- data = emit_vertex(v2, aaParams, data);
- data = emit_vertex(v2, aaParams, data);
- data = emit_vertex(v0, aaParams, data);
+inline SkPoint* emit_vertex(Vertex* v, SkPoint* data) {
+ *data++ = v->fPoint;
+ return data;
+}
+
+SkPoint* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, SkPoint* data) {
+#if WIREFRAME
+ data = emit_vertex(v0, data);
+ data = emit_vertex(v1, data);
+ data = emit_vertex(v1, data);
+ data = emit_vertex(v2, data);
+ data = emit_vertex(v2, data);
+ data = emit_vertex(v0, data);
#else
- data = emit_vertex(v0, aaParams, data);
- data = emit_vertex(v1, aaParams, data);
- data = emit_vertex(v2, aaParams, data);
+ data = emit_vertex(v0, data);
+ data = emit_vertex(v1, data);
+ data = emit_vertex(v2, data);
#endif
return data;
}
+
+struct EdgeList {
+ EdgeList() : fHead(nullptr), fTail(nullptr) {}
+ Edge* fHead;
+ Edge* fTail;
+};
struct VertexList {
VertexList() : fHead(nullptr), fTail(nullptr) {}
@@ -245,20 +217,7 @@
void prepend(Vertex* v) {
insert(v, nullptr, fHead);
}
- void close() {
- if (fHead && fTail) {
- fTail->fNext = fHead;
- fHead->fPrev = fTail;
- }
- }
};
-
-// Round to nearest quarter-pixel. This is used for screenspace tessellation.
-
-inline void round(SkPoint* p) {
- p->fX = SkScalarRoundToScalar(p->fX * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f);
- p->fY = SkScalarRoundToScalar(p->fY * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f);
-}
/**
* An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and
@@ -361,33 +320,8 @@
p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fDY);
return true;
}
-};
-
-struct EdgeList {
- EdgeList() : fHead(nullptr), fTail(nullptr), fNext(nullptr), fCount(0) {}
- Edge* fHead;
- Edge* fTail;
- EdgeList* fNext;
- int fCount;
- void insert(Edge* edge, Edge* prev, Edge* next) {
- list_insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &fHead, &fTail);
- fCount++;
- }
- void append(Edge* e) {
- insert(e, fTail, nullptr);
- }
- void remove(Edge* edge) {
- list_remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &fHead, &fTail);
- fCount--;
- }
- void close() {
- if (fHead && fTail) {
- fTail->fRight = fHead;
- fHead->fLeft = fTail;
- }
- }
- bool contains(Edge* edge) const {
- return edge->fLeft || edge->fRight || fHead == edge;
+ bool isActive(EdgeList* activeEdges) const {
+ return activeEdges && (fLeft || fRight || activeEdges->fHead == this);
}
};
@@ -438,7 +372,7 @@
}
}
- void* emit(const AAParams* aaParams, void* data) {
+ SkPoint* emit(SkPoint* data) {
Edge* e = fFirstEdge;
e->fTop->fPrev = e->fTop->fNext = nullptr;
VertexList vertices;
@@ -465,7 +399,7 @@
double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint.fX;
double by = static_cast<double>(next->fPoint.fY) - curr->fPoint.fY;
if (ax * by - ay * bx >= 0.0) {
- data = emit_triangle(prev, curr, next, aaParams, data);
+ data = emit_triangle(prev, curr, next, data);
v->fPrev->fNext = v->fNext;
v->fNext->fPrev = v->fPrev;
if (v->fPrev == first) {
@@ -521,13 +455,13 @@
}
return poly;
}
- void* emit(const AAParams* aaParams, void *data) {
+ SkPoint* emit(SkPoint *data) {
if (fCount < 3) {
return data;
}
LOG("emit() %d, size %d\n", fID, fCount);
for (MonotonePoly* m = fHead; m != nullptr; m = m->fNext) {
- data = m->emit(aaParams, data);
+ data = m->emit(data);
}
return data;
}
@@ -557,16 +491,9 @@
return poly;
}
-EdgeList* new_contour(EdgeList** head, SkChunkAlloc& alloc) {
- EdgeList* contour = ALLOC_NEW(EdgeList, (), alloc);
- contour->fNext = *head;
- *head = contour;
- return contour;
-}
-
Vertex* append_point_to_contour(const SkPoint& p, Vertex* prev, Vertex** head,
SkChunkAlloc& alloc) {
- Vertex* v = ALLOC_NEW(Vertex, (p, 255), alloc);
+ Vertex* v = ALLOC_NEW(Vertex, (p), alloc);
#if LOGGING_ENABLED
static float gID = 0.0f;
v->fID = gID++;
@@ -651,7 +578,7 @@
if (path.isInverseFillType()) {
SkPoint quad[4];
clipBounds.toQuad(quad);
- for (int i = 0; i < 4; i++) {
+ for (int i = 3; i >= 0; i--) {
prev = append_point_to_contour(quad[i], prev, &head, alloc);
}
head->fPrev = prev;
@@ -722,18 +649,14 @@
}
}
-inline bool apply_fill_type(SkPath::FillType fillType, Poly* poly) {
- if (!poly) {
- return false;
- }
- int winding = poly->fWinding;
+inline bool apply_fill_type(SkPath::FillType fillType, int winding) {
switch (fillType) {
case SkPath::kWinding_FillType:
return winding != 0;
case SkPath::kEvenOdd_FillType:
return (winding & 1) != 0;
case SkPath::kInverseWinding_FillType:
- return winding == -1;
+ return winding == 1;
case SkPath::kInverseEvenOdd_FillType:
return (winding & 1) == 1;
default:
@@ -742,9 +665,8 @@
}
}
-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;
+Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator& c) {
+ int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
Vertex* top = winding < 0 ? next : prev;
Vertex* bottom = winding < 0 ? prev : next;
return ALLOC_NEW(Edge, (top, bottom, winding), alloc);
@@ -752,15 +674,15 @@
void remove_edge(Edge* edge, EdgeList* edges) {
LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
- SkASSERT(edges->contains(edge));
- edges->remove(edge);
+ SkASSERT(edge->isActive(edges));
+ list_remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &edges->fHead, &edges->fTail);
}
void insert_edge(Edge* edge, Edge* prev, EdgeList* edges) {
LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
- SkASSERT(!edges->contains(edge));
+ SkASSERT(!edge->isActive(edges));
Edge* next = prev ? prev->fRight : edges->fHead;
- edges->insert(edge, prev, next);
+ list_insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &edges->fHead, &edges->fTail);
}
void find_enclosing_edges(Vertex* v, EdgeList* edges, Edge** left, Edge** right) {
@@ -800,7 +722,7 @@
}
void fix_active_state(Edge* edge, EdgeList* activeEdges, Comparator& c) {
- if (activeEdges && activeEdges->contains(edge)) {
+ if (edge->isActive(activeEdges)) {
if (edge->fBottom->fProcessed || !edge->fTop->fProcessed) {
remove_edge(edge, activeEdges);
}
@@ -869,7 +791,7 @@
LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID);
remove_edge_above(edge);
remove_edge_below(edge);
- if (edges && edges->contains(edge)) {
+ if (edge->isActive(edges)) {
remove_edge(edge, edges);
}
}
@@ -1006,24 +928,9 @@
}
}
-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);
- } else {
- insert_edge_below(edge, next, c);
- insert_edge_above(edge, prev, c);
- }
- merge_collinear_edges(edge, nullptr, c);
- return edge;
-}
-
void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, Comparator& c, SkChunkAlloc& alloc) {
LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX, src->fPoint.fY,
src->fID, dst->fID);
- dst->fAlpha = SkTMax(src->fAlpha, dst->fAlpha);
for (Edge* edge = src->fFirstEdgeAbove; edge;) {
Edge* next = edge->fNextEdgeAbove;
set_bottom(edge, dst, nullptr, c);
@@ -1035,11 +942,6 @@
edge = next;
}
list_remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(src, head, nullptr);
-}
-
-uint8_t max_edge_alpha(Edge* a, Edge* b) {
- 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,
@@ -1077,8 +979,7 @@
} else if (coincident(nextV->fPoint, p)) {
v = nextV;
} else {
- uint8_t alpha = max_edge_alpha(edge, other);
- v = ALLOC_NEW(Vertex, (p, alpha), alloc);
+ v = ALLOC_NEW(Vertex, (p), alloc);
LOG("inserting between %g (%g, %g) and %g (%g, %g)\n",
prevV->fID, prevV->fPoint.fX, prevV->fPoint.fY,
nextV->fID, nextV->fPoint.fX, nextV->fPoint.fY);
@@ -1098,13 +999,10 @@
return nullptr;
}
-void sanitize_contours(Vertex** contours, int contourCnt, bool approximate) {
+void sanitize_contours(Vertex** contours, int contourCnt) {
for (int i = 0; i < contourCnt; ++i) {
SkASSERT(contours[i]);
for (Vertex* v = contours[i];;) {
- if (approximate) {
- round(&v->fPoint);
- }
if (coincident(v->fPrev->fPoint, v->fPoint)) {
LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoint.fY);
if (v->fPrev == v) {
@@ -1144,7 +1042,15 @@
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* edge = new_edge(v->fPrev, v, alloc, c);
+ if (edge->fWinding > 0) {
+ insert_edge_below(edge, v->fPrev, c);
+ insert_edge_above(edge, v, c);
+ } else {
+ insert_edge_below(edge, v, c);
+ insert_edge_above(edge, v->fPrev, c);
+ }
+ merge_collinear_edges(edge, nullptr, c);
if (prev) {
prev->fNext = v;
v->fPrev = prev;
@@ -1239,7 +1145,7 @@
continue;
}
#if LOGGING_ENABLED
- LOG("\nvertex %g: (%g,%g), alpha %d\n", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
+ LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
#endif
Edge* leftEnclosingEdge = nullptr;
Edge* rightEnclosingEdge = nullptr;
@@ -1269,12 +1175,6 @@
}
} while (restartChecks);
- if (v->fAlpha == 0) {
- if ((leftEnclosingEdge && leftEnclosingEdge->fWinding < 0) &&
- (rightEnclosingEdge && rightEnclosingEdge->fWinding > 0)) {
- v->fAlpha = max_edge_alpha(leftEnclosingEdge, rightEnclosingEdge);
- }
- }
for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
remove_edge(e, &activeEdges);
}
@@ -1298,7 +1198,7 @@
continue;
}
#if LOGGING_ENABLED
- LOG("\nvertex %g: (%g,%g), alpha %d\n", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
+ LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
#endif
Edge* leftEnclosingEdge = nullptr;
Edge* rightEnclosingEdge = nullptr;
@@ -1398,255 +1298,9 @@
return polys;
}
-bool is_boundary_edge(Edge* edge, SkPath::FillType fillType) {
- return apply_fill_type(fillType, edge->fLeftPoly) !=
- apply_fill_type(fillType, edge->fRightPoly);
-}
-
-bool is_boundary_start(Edge* edge, SkPath::FillType fillType) {
- return !apply_fill_type(fillType, edge->fLeftPoly) &&
- apply_fill_type(fillType, edge->fRightPoly);
-}
-
-Vertex* remove_non_boundary_edges(Vertex* vertices, SkPath::FillType fillType,
- SkChunkAlloc& alloc) {
- for (Vertex* v = vertices; v != nullptr; v = v->fNext) {
- for (Edge* e = v->fFirstEdgeBelow; e != nullptr;) {
- Edge* next = e->fNextEdgeBelow;
- if (!is_boundary_edge(e, fillType)) {
- remove_edge_above(e);
- remove_edge_below(e);
- }
- e = next;
- }
- }
- return vertices;
-}
-
-// This is different from Edge::intersect, in that it intersects lines, not line segments.
-bool intersect(const Edge& a, const Edge& b, SkPoint* point) {
- double denom = a.fDX * b.fDY - a.fDY * b.fDX;
- if (denom == 0.0) {
- return false;
- }
- double scale = 1.0f / denom;
- point->fX = SkDoubleToScalar((b.fDX * a.fC - a.fDX * b.fC) * scale);
- point->fY = SkDoubleToScalar((b.fDY * a.fC - a.fDY * b.fC) * scale);
- round(point);
- return true;
-}
-
-void get_edge_normal(const Edge* e, SkVector* normal) {
- normal->setNormalize(SkDoubleToScalar(e->fDX) * e->fWinding,
- SkDoubleToScalar(e->fDY) * e->fWinding);
-}
-
-// Stage 5c: detect and remove "pointy" vertices whose edge normals point in opposite directions
-// and whose adjacent vertices are less than a quarter pixel from an edge. These are guaranteed to
-// invert on stroking.
-
-void simplify_boundary(EdgeList* boundary, Comparator& c, SkChunkAlloc& alloc) {
- Edge* prevEdge = boundary->fTail;
- SkVector prevNormal;
- get_edge_normal(prevEdge, &prevNormal);
- for (Edge* e = boundary->fHead; e != nullptr;) {
- Vertex* prev = prevEdge->fWinding == 1 ? prevEdge->fTop : prevEdge->fBottom;
- Vertex* next = e->fWinding == 1 ? e->fBottom : e->fTop;
- double dist = e->dist(prev->fPoint);
- SkVector normal;
- get_edge_normal(e, &normal);
- float denom = 0.25f * static_cast<float>(e->fDX * e->fDX + e->fDY * e->fDY);
- if (prevNormal.dot(normal) < 0.0 && (dist * dist) <= denom) {
- Edge* join = new_edge(prev, next, alloc, c);
- insert_edge(join, e, boundary);
- remove_edge(prevEdge, boundary);
- remove_edge(e, boundary);
- if (join->fLeft && join->fRight) {
- prevEdge = join->fLeft;
- e = join;
- } else {
- prevEdge = boundary->fTail;
- e = boundary->fHead; // join->fLeft ? join->fLeft : join;
- }
- get_edge_normal(prevEdge, &prevNormal);
- } else {
- prevEdge = e;
- prevNormal = normal;
- e = e->fRight;
- }
- }
-}
-
-// Stage 5d: Displace edges by half a pixel inward and outward along their normals. Intersect to
-// find new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a
-// new antialiased mesh from those vertices.
-
-void boundary_to_aa_mesh(EdgeList* boundary, VertexList* mesh, Comparator& c, SkChunkAlloc& alloc) {
- EdgeList outerContour;
- Edge* prevEdge = boundary->fTail;
- float radius = 0.5f;
- double offset = radius * sqrt(prevEdge->fDX * prevEdge->fDX + prevEdge->fDY * prevEdge->fDY)
- * prevEdge->fWinding;
- Edge prevInner(prevEdge->fTop, prevEdge->fBottom, prevEdge->fWinding);
- prevInner.fC -= offset;
- Edge prevOuter(prevEdge->fTop, prevEdge->fBottom, prevEdge->fWinding);
- prevOuter.fC += offset;
- VertexList innerVertices;
- VertexList outerVertices;
- SkScalar innerCount = SK_Scalar1, outerCount = SK_Scalar1;
- for (Edge* e = boundary->fHead; e != nullptr; e = e->fRight) {
- double offset = radius * sqrt(e->fDX * e->fDX + e->fDY * e->fDY) * e->fWinding;
- Edge inner(e->fTop, e->fBottom, e->fWinding);
- inner.fC -= offset;
- Edge outer(e->fTop, e->fBottom, e->fWinding);
- outer.fC += offset;
- SkPoint innerPoint, outerPoint;
- if (intersect(prevInner, inner, &innerPoint) &&
- intersect(prevOuter, outer, &outerPoint)) {
- 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 outerEdge(outerVertices.fTail, outerVertex, 1);
- SkVector innerNormal;
- get_edge_normal(&innerEdge, &innerNormal);
- SkVector outerNormal;
- get_edge_normal(&outerEdge, &outerNormal);
- SkVector normal;
- get_edge_normal(prevEdge, &normal);
- if (normal.dot(innerNormal) < 0) {
- innerPoint += innerVertices.fTail->fPoint * innerCount;
- innerCount++;
- innerPoint *= SkScalarInvert(innerCount);
- innerVertices.fTail->fPoint = innerVertex->fPoint = innerPoint;
- } else {
- innerCount = SK_Scalar1;
- }
- if (normal.dot(outerNormal) < 0) {
- outerPoint += outerVertices.fTail->fPoint * outerCount;
- outerCount++;
- outerPoint *= SkScalarInvert(outerCount);
- outerVertices.fTail->fPoint = outerVertex->fPoint = outerPoint;
- } else {
- outerCount = SK_Scalar1;
- }
- }
- innerVertices.append(innerVertex);
- outerVertices.append(outerVertex);
- prevEdge = e;
- }
- prevInner = inner;
- prevOuter = outer;
- }
- innerVertices.close();
- outerVertices.close();
-
- Vertex* innerVertex = innerVertices.fHead;
- Vertex* outerVertex = outerVertices.fHead;
- // Alternate clockwise and counterclockwise polys, so the tesselator
- // doesn't cancel out the interior edges.
- if (!innerVertex || !outerVertex) {
- return;
- }
- do {
- 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);
- mesh->append(outerVertex);
- innerVertex = innerNext;
- outerVertex = outerNext;
- } while (innerVertex != innerVertices.fHead && outerVertex != outerVertices.fHead);
-}
-
-void extract_boundary(EdgeList* boundary, Edge* e, SkPath::FillType fillType, SkChunkAlloc& alloc) {
- bool down = is_boundary_start(e, fillType);
- while (e) {
- e->fWinding = down ? 1 : -1;
- Edge* next;
- boundary->append(e);
- if (down) {
- // Find outgoing edge, in clockwise order.
- if ((next = e->fNextEdgeAbove)) {
- down = false;
- } else if ((next = e->fBottom->fLastEdgeBelow)) {
- down = true;
- } else if ((next = e->fPrevEdgeAbove)) {
- down = false;
- }
- } else {
- // Find outgoing edge, in counter-clockwise order.
- if ((next = e->fPrevEdgeBelow)) {
- down = true;
- } else if ((next = e->fTop->fFirstEdgeAbove)) {
- down = false;
- } else if ((next = e->fNextEdgeBelow)) {
- down = true;
- }
- }
- remove_edge_above(e);
- remove_edge_below(e);
- e = next;
- }
-}
-
-// Stage 5b: Extract boundary edges.
-
-EdgeList* extract_boundaries(Vertex* vertices, SkPath::FillType fillType, SkChunkAlloc& alloc) {
- LOG("extracting boundaries\n");
- vertices = remove_non_boundary_edges(vertices, fillType, alloc);
- EdgeList* boundaries = nullptr;
- for (Vertex* v = vertices; v != nullptr; v = v->fNext) {
- while (v->fFirstEdgeBelow) {
- EdgeList* boundary = new_contour(&boundaries, alloc);
- extract_boundary(boundary, v->fFirstEdgeBelow, fillType, alloc);
- }
- }
- return boundaries;
-}
-
// This is a driver function which calls stages 2-5 in turn.
-Vertex* contours_to_mesh(Vertex** contours, int contourCnt, bool antialias,
- Comparator& c, SkChunkAlloc& alloc) {
-#if LOGGING_ENABLED
- for (int i = 0; i < contourCnt; ++i) {
- Vertex* v = contours[i];
- SkASSERT(v);
- LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
- for (v = v->fNext; v != contours[i]; v = v->fNext) {
- LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
- }
- }
-#endif
- sanitize_contours(contours, contourCnt, antialias);
- return build_edges(contours, contourCnt, c, alloc);
-}
-
-Poly* mesh_to_polys(Vertex** vertices, SkPath::FillType fillType, Comparator& c,
- SkChunkAlloc& alloc) {
- if (!vertices || !*vertices) {
- return nullptr;
- }
-
- // Sort vertices in Y (secondarily in X).
- merge_sort(vertices, c);
- merge_coincident_vertices(vertices, c, alloc);
-#if LOGGING_ENABLED
- for (Vertex* v = *vertices; v != nullptr; v = v->fNext) {
- static float gID = 0.0f;
- v->fID = gID++;
- }
-#endif
- simplify(*vertices, c, alloc);
- return tessellate(*vertices, alloc);
-}
-
-Poly* contours_to_polys(Vertex** contours, int contourCnt, SkPath::FillType fillType,
- const SkRect& pathBounds, bool antialias,
+Poly* contours_to_polys(Vertex** contours, int contourCnt, const SkRect& pathBounds,
SkChunkAlloc& alloc) {
Comparator c;
if (pathBounds.width() > pathBounds.height()) {
@@ -1656,35 +1310,37 @@
c.sweep_lt = sweep_lt_vert;
c.sweep_gt = sweep_gt_vert;
}
- Vertex* mesh = contours_to_mesh(contours, contourCnt, antialias, c, alloc);
- Poly* polys = mesh_to_polys(&mesh, fillType, c, alloc);
- if (antialias) {
- EdgeList* boundaries = extract_boundaries(mesh, fillType, alloc);
- VertexList aaMesh;
- for (EdgeList* boundary = boundaries; boundary != nullptr; boundary = boundary->fNext) {
- simplify_boundary(boundary, c, alloc);
- if (boundary->fCount > 2) {
- boundary_to_aa_mesh(boundary, &aaMesh, c, alloc);
- }
- }
- return mesh_to_polys(&aaMesh.fHead, SkPath::kWinding_FillType, c, alloc);
- }
- return polys;
-}
-
-// Stage 6: Triangulate the monotone polygons into a vertex buffer.
-void* polys_to_triangles(Poly* polys, SkPath::FillType fillType, const AAParams* aaParams,
- void* data) {
- for (Poly* poly = polys; poly; poly = poly->fNext) {
- if (apply_fill_type(fillType, poly)) {
- data = poly->emit(aaParams, data);
- }
- }
- return data;
+#if LOGGING_ENABLED
+ for (int i = 0; i < contourCnt; ++i) {
+ Vertex* v = contours[i];
+ SkASSERT(v);
+ LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
+ for (v = v->fNext; v != contours[i]; v = v->fNext) {
+ LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
+ }
+ }
+#endif
+ sanitize_contours(contours, contourCnt);
+ Vertex* vertices = build_edges(contours, contourCnt, c, alloc);
+ if (!vertices) {
+ return nullptr;
+ }
+
+ // Sort vertices in Y (secondarily in X).
+ merge_sort(&vertices, c);
+ merge_coincident_vertices(&vertices, c, alloc);
+#if LOGGING_ENABLED
+ for (Vertex* v = vertices; v != nullptr; v = v->fNext) {
+ static float gID = 0.0f;
+ v->fID = gID++;
+ }
+#endif
+ simplify(vertices, c, alloc);
+ return tessellate(vertices, alloc);
}
Poly* path_to_polys(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
- int contourCnt, SkChunkAlloc& alloc, bool antialias, bool* isLinear) {
+ int contourCnt, SkChunkAlloc& alloc, bool* isLinear) {
SkPath::FillType fillType = path.getFillType();
if (SkPath::IsInverseFillType(fillType)) {
contourCnt++;
@@ -1692,8 +1348,7 @@
SkAutoTDeleteArray<Vertex*> contours(new Vertex* [contourCnt]);
path_to_contours(path, tolerance, clipBounds, contours.get(), alloc, isLinear);
- return contours_to_polys(contours.get(), contourCnt, path.getFillType(), path.getBounds(),
- antialias, alloc);
+ return contours_to_polys(contours.get(), contourCnt, path.getBounds(), alloc);
}
void get_contour_count_and_size_estimate(const SkPath& path, SkScalar tolerance, int* contourCnt,
@@ -1718,7 +1373,7 @@
int count_points(Poly* polys, SkPath::FillType fillType) {
int count = 0;
for (Poly* poly = polys; poly; poly = poly->fNext) {
- if (apply_fill_type(fillType, poly) && poly->fCount >= 3) {
+ if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) {
count += (poly->fCount - 2) * (TESSELLATOR_WIREFRAME ? 6 : 3);
}
}
@@ -1732,8 +1387,7 @@
// Stage 6: Triangulate the monotone polygons into a vertex buffer.
int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
- VertexAllocator* vertexAllocator, bool antialias, const GrColor& color,
- bool canTweakAlphaForCoverage, bool* isLinear) {
+ VertexAllocator* vertexAllocator, bool* isLinear) {
int contourCnt;
int sizeEstimate;
get_contour_count_and_size_estimate(path, tolerance, &contourCnt, &sizeEstimate);
@@ -1742,28 +1396,26 @@
return 0;
}
SkChunkAlloc alloc(sizeEstimate);
- Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, antialias,
- isLinear);
+ Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, isLinear);
SkPath::FillType fillType = path.getFillType();
int count = count_points(polys, fillType);
if (0 == count) {
return 0;
}
- void* verts = vertexAllocator->lock(count);
+ SkPoint* verts = vertexAllocator->lock(count);
if (!verts) {
SkDebugf("Could not allocate vertices\n");
return 0;
}
-
- LOG("emitting %d verts\n", count);
- AAParams aaParams;
- aaParams.fTweakAlpha = canTweakAlphaForCoverage;
- aaParams.fColor = color;
-
- void* end = polys_to_triangles(polys, fillType, antialias ? &aaParams : nullptr, verts);
- int actualCount = static_cast<int>((static_cast<uint8_t*>(end) - static_cast<uint8_t*>(verts))
- / vertexAllocator->stride());
+ SkPoint* end = verts;
+ for (Poly* poly = polys; poly; poly = poly->fNext) {
+ if (apply_fill_type(fillType, poly->fWinding)) {
+ end = poly->emit(end);
+ }
+ }
+ int actualCount = static_cast<int>(end - verts);
+ LOG("actual count: %d\n", actualCount);
SkASSERT(actualCount <= count);
vertexAllocator->unlock(actualCount);
return actualCount;
@@ -1779,7 +1431,7 @@
}
SkChunkAlloc alloc(sizeEstimate);
bool isLinear;
- Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, false, &isLinear);
+ Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, &isLinear);
SkPath::FillType fillType = path.getFillType();
int count = count_points(polys, fillType);
if (0 == count) {
@@ -1792,9 +1444,9 @@
SkPoint* points = new SkPoint[count];
SkPoint* pointsEnd = points;
for (Poly* poly = polys; poly; poly = poly->fNext) {
- if (apply_fill_type(fillType, poly)) {
+ if (apply_fill_type(fillType, poly->fWinding)) {
SkPoint* start = pointsEnd;
- pointsEnd = static_cast<SkPoint*>(poly->emit(nullptr, pointsEnd));
+ pointsEnd = poly->emit(pointsEnd);
while (start != pointsEnd) {
vertsEnd->fPos = *start;
vertsEnd->fWinding = poly->fWinding;
« no previous file with comments | « src/gpu/GrTessellator.h ('k') | src/gpu/batches/GrTessellatingPathRenderer.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698