Index: src/gpu/GrTessellator.cpp |
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp |
index 5fb008dad5047a1f5c5db7a3977d13b171b44471..25d1bb3a2418e5dda1c576896faee6626a9d4052 100644 |
--- a/src/gpu/GrTessellator.cpp |
+++ b/src/gpu/GrTessellator.cpp |
@@ -249,7 +249,11 @@ struct Edge { |
, fPrevEdgeBelow(nullptr) |
, fNextEdgeBelow(nullptr) |
, fLeftPoly(nullptr) |
- , fRightPoly(nullptr) { |
+ , fRightPoly(nullptr) |
+ , fLeftPolyPrev(nullptr) |
+ , fLeftPolyNext(nullptr) |
+ , fRightPolyPrev(nullptr) |
+ , fRightPolyNext(nullptr) { |
recompute(); |
} |
int fWinding; // 1 == edge goes downward; -1 = edge goes upward. |
@@ -263,6 +267,10 @@ struct Edge { |
Edge* fNextEdgeBelow; // " |
Poly* fLeftPoly; // The Poly to the left of this edge, if any. |
Poly* fRightPoly; // The Poly to the right of this edge, if any. |
+ Edge* fLeftPolyPrev; |
+ Edge* fLeftPolyNext; |
+ Edge* fRightPolyPrev; |
+ Edge* fRightPolyNext; |
double fDX; // The line equation for this edge, in implicit form. |
double fDY; // fDY * x + fDX * y + fC = 0, for point (x, y) on the line. |
double fC; |
@@ -316,11 +324,11 @@ struct Edge { |
/***************************************************************************************/ |
struct Poly { |
- Poly(int winding) |
- : fWinding(winding) |
+ Poly(Vertex* v, int winding) |
+ : fFirstVertex(v) |
+ , fWinding(winding) |
, fHead(nullptr) |
, fTail(nullptr) |
- , fActive(nullptr) |
, fNext(nullptr) |
, fPartner(nullptr) |
, fCount(0) |
@@ -331,36 +339,49 @@ struct Poly { |
LOG("*** created Poly %d\n", fID); |
#endif |
} |
- typedef enum { kNeither_Side, kLeft_Side, kRight_Side } Side; |
+ typedef enum { kLeft_Side, kRight_Side } Side; |
struct MonotonePoly { |
- MonotonePoly() |
- : fSide(kNeither_Side) |
+ MonotonePoly(Edge* edge, Side side) |
+ : fSide(side) |
+ , fFirstEdge(nullptr) |
+ , fLastEdge(nullptr) |
, fPrev(nullptr) |
- , fNext(nullptr) {} |
+ , fNext(nullptr) { |
+ this->addEdge(edge); |
+ } |
Side fSide; |
- VertexList fVertices; |
+ Edge* fFirstEdge; |
+ Edge* fLastEdge; |
MonotonePoly* fPrev; |
MonotonePoly* fNext; |
- bool addVertex(Vertex* v, Side side, SkChunkAlloc& alloc) { |
- Vertex* newV = ALLOC_NEW(Vertex, (v->fPoint), alloc); |
- bool done = false; |
- if (fSide == kNeither_Side) { |
- fSide = side; |
- } else { |
- done = side != fSide; |
- } |
+ void addEdge(Edge* edge) { |
if (fSide == kRight_Side) { |
- fVertices.append(newV); |
+ list_insert<Edge, &Edge::fRightPolyPrev, &Edge::fRightPolyNext>( |
+ edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge); |
} else { |
- fVertices.prepend(newV); |
+ list_insert<Edge, &Edge::fLeftPolyPrev, &Edge::fLeftPolyNext>( |
+ edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge); |
} |
- return done; |
} |
SkPoint* emit(SkPoint* data) { |
- Vertex* first = fVertices.fHead; |
+ Edge* e = fFirstEdge; |
+ e->fTop->fPrev = e->fTop->fNext = nullptr; |
+ VertexList vertices; |
+ vertices.append(e->fTop); |
+ while (e != nullptr) { |
+ e->fBottom->fPrev = e->fBottom->fNext = nullptr; |
+ if (kRight_Side == fSide) { |
+ vertices.append(e->fBottom); |
+ e = e->fRightPolyNext; |
+ } else { |
+ vertices.prepend(e->fBottom); |
+ e = e->fLeftPolyNext; |
+ } |
+ } |
+ Vertex* first = vertices.fHead; |
Vertex* v = first->fNext; |
- while (v != fVertices.fTail) { |
+ while (v != vertices.fTail) { |
SkASSERT(v && v->fPrev && v->fNext); |
Vertex* prev = v->fPrev; |
Vertex* curr = v; |
@@ -385,46 +406,41 @@ struct Poly { |
return data; |
} |
}; |
- Poly* addVertex(Vertex* v, Side side, SkChunkAlloc& alloc) { |
- LOG("addVertex() to %d at %g (%g, %g), %s side\n", fID, v->fID, v->fPoint.fX, v->fPoint.fY, |
- side == kLeft_Side ? "left" : side == kRight_Side ? "right" : "neither"); |
+ Poly* addEdge(Edge* e, Side side, SkChunkAlloc& alloc) { |
+ LOG("addEdge (%g,%g)-(%g,%g) to poly %d, %s side\n", |
+ e->fTop->fPoint.fX, e->fTop->fPoint.fY, e->fBottom->fPoint.fX, e->fBottom->fPoint.fY, |
+ fID, side == kLeft_Side ? "left" : "right"); |
Poly* partner = fPartner; |
Poly* poly = this; |
if (partner) { |
fPartner = partner->fPartner = nullptr; |
} |
- if (!fActive) { |
- fActive = ALLOC_NEW(MonotonePoly, (), alloc); |
- } |
- if (fActive->addVertex(v, side, alloc)) { |
- if (fTail) { |
- fActive->fPrev = fTail; |
- fTail->fNext = fActive; |
- fTail = fActive; |
- } else { |
- fHead = fTail = fActive; |
+ if (!fTail) { |
+ fHead = fTail = ALLOC_NEW(MonotonePoly, (e, side), alloc); |
+ fCount += 2; |
+ } else if (side == fTail->fSide) { |
+ fTail->addEdge(e); |
+ fCount++; |
+ } else { |
+ if (e->fBottom == fTail->fLastEdge->fBottom) { |
+ return poly; |
} |
+ e = ALLOC_NEW(Edge, (fTail->fLastEdge->fBottom, e->fBottom, 1), alloc); |
+ fTail->addEdge(e); |
+ fCount++; |
if (partner) { |
- partner->addVertex(v, side, alloc); |
+ partner->addEdge(e, side, alloc); |
poly = partner; |
} else { |
- Vertex* prev = fActive->fSide == Poly::kLeft_Side ? |
- fActive->fVertices.fHead->fNext : fActive->fVertices.fTail->fPrev; |
- fActive = ALLOC_NEW(MonotonePoly, , alloc); |
- fActive->addVertex(prev, Poly::kNeither_Side, alloc); |
- fActive->addVertex(v, side, alloc); |
+ MonotonePoly* m = ALLOC_NEW(MonotonePoly, (e, side), alloc); |
+ m->fPrev = fTail; |
+ fTail->fNext = m; |
+ fTail = m; |
+ fCount += 2; |
} |
} |
- fCount++; |
return poly; |
} |
- void end(Vertex* v, SkChunkAlloc& alloc) { |
- LOG("end() %d at %g, %g\n", fID, v->fPoint.fX, v->fPoint.fY); |
- if (fPartner) { |
- fPartner = fPartner->fPartner = nullptr; |
- } |
- addVertex(v, fActive->fSide == kLeft_Side ? kRight_Side : kLeft_Side, alloc); |
- } |
SkPoint* emit(SkPoint *data) { |
if (fCount < 3) { |
return data; |
@@ -435,10 +451,11 @@ struct Poly { |
} |
return data; |
} |
+ Vertex* lastVertex() const { return fTail ? fTail->fLastEdge->fBottom : fFirstVertex; } |
+ Vertex* fFirstVertex; |
int fWinding; |
MonotonePoly* fHead; |
MonotonePoly* fTail; |
- MonotonePoly* fActive; |
Poly* fNext; |
Poly* fPartner; |
int fCount; |
@@ -454,8 +471,7 @@ bool coincident(const SkPoint& a, const SkPoint& b) { |
} |
Poly* new_poly(Poly** head, Vertex* v, int winding, SkChunkAlloc& alloc) { |
- Poly* poly = ALLOC_NEW(Poly, (winding), alloc); |
- poly->addVertex(v, Poly::kNeither_Side, alloc); |
+ Poly* poly = ALLOC_NEW(Poly, (v, winding), alloc); |
poly->fNext = *head; |
*head = poly; |
return poly; |
@@ -1196,10 +1212,10 @@ Poly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) { |
#endif |
if (v->fFirstEdgeAbove) { |
if (leftPoly) { |
- leftPoly = leftPoly->addVertex(v, Poly::kRight_Side, alloc); |
+ leftPoly = leftPoly->addEdge(v->fFirstEdgeAbove, Poly::kRight_Side, alloc); |
} |
if (rightPoly) { |
- rightPoly = rightPoly->addVertex(v, Poly::kLeft_Side, alloc); |
+ rightPoly = rightPoly->addEdge(v->fLastEdgeAbove, Poly::kLeft_Side, alloc); |
} |
for (Edge* e = v->fFirstEdgeAbove; e != v->fLastEdgeAbove; e = e->fNextEdgeAbove) { |
Edge* leftEdge = e; |
@@ -1207,10 +1223,10 @@ Poly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) { |
SkASSERT(rightEdge->isRightOf(leftEdge->fTop)); |
remove_edge(leftEdge, &activeEdges); |
if (leftEdge->fRightPoly) { |
- leftEdge->fRightPoly->end(v, alloc); |
+ leftEdge->fRightPoly->addEdge(e, Poly::kLeft_Side, alloc); |
} |
- if (rightEdge->fLeftPoly && rightEdge->fLeftPoly != leftEdge->fRightPoly) { |
- rightEdge->fLeftPoly->end(v, alloc); |
+ if (rightEdge->fLeftPoly) { |
+ rightEdge->fLeftPoly->addEdge(e, Poly::kRight_Side, alloc); |
} |
} |
remove_edge(v->fLastEdgeAbove, &activeEdges); |
@@ -1224,28 +1240,21 @@ Poly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) { |
} |
if (v->fFirstEdgeBelow) { |
if (!v->fFirstEdgeAbove) { |
- if (leftPoly && leftPoly == rightPoly) { |
- // Split the poly. |
- if (leftPoly->fActive->fSide == Poly::kLeft_Side) { |
- leftPoly = new_poly(&polys, leftEnclosingEdge->fTop, leftPoly->fWinding, |
- alloc); |
- leftPoly->addVertex(v, Poly::kRight_Side, alloc); |
- rightPoly->addVertex(v, Poly::kLeft_Side, alloc); |
- leftEnclosingEdge->fRightPoly = leftPoly; |
- } else { |
- rightPoly = new_poly(&polys, rightEnclosingEdge->fTop, rightPoly->fWinding, |
- alloc); |
- rightPoly->addVertex(v, Poly::kLeft_Side, alloc); |
- leftPoly->addVertex(v, Poly::kRight_Side, alloc); |
- rightEnclosingEdge->fLeftPoly = rightPoly; |
- } |
- } else { |
- if (leftPoly) { |
- leftPoly = leftPoly->addVertex(v, Poly::kRight_Side, alloc); |
- } |
- if (rightPoly) { |
- rightPoly = rightPoly->addVertex(v, Poly::kLeft_Side, alloc); |
+ if (leftPoly) { |
+ if (leftPoly == rightPoly) { |
+ if (leftPoly->fTail && leftPoly->fTail->fSide == Poly::kLeft_Side) { |
+ leftPoly = new_poly(&polys, leftPoly->lastVertex(), |
+ leftPoly->fWinding, alloc); |
+ leftEnclosingEdge->fRightPoly = leftPoly; |
+ } else { |
+ rightPoly = new_poly(&polys, rightPoly->lastVertex(), |
+ rightPoly->fWinding, alloc); |
+ rightEnclosingEdge->fLeftPoly = rightPoly; |
+ } |
} |
+ 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); |
} |
} |
Edge* leftEdge = v->fFirstEdgeBelow; |