Chromium Code Reviews| Index: src/gpu/GrTessellator.cpp |
| diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp |
| index 5fb008dad5047a1f5c5db7a3977d13b171b44471..6b7b6c3bbcc56431d157399e3e467b9f5aaa2c7c 100644 |
| --- a/src/gpu/GrTessellator.cpp |
| +++ b/src/gpu/GrTessellator.cpp |
| @@ -204,21 +204,26 @@ struct EdgeList { |
| Edge* fTail; |
| }; |
| -struct VertexList { |
| - VertexList() : fHead(nullptr), fTail(nullptr) {} |
| - Vertex* fHead; |
| - Vertex* fTail; |
| - void insert(Vertex* v, Vertex* prev, Vertex* next) { |
| - list_insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, prev, next, &fHead, &fTail); |
| +template<class T> struct List { |
| + List() : fHead(nullptr), fTail(nullptr) {} |
| + T* fHead; |
| + T* fTail; |
| + void insert(T* t, T* prev, T* next) { |
| + list_insert<T, &T::fPrev, &T::fNext>(t, prev, next, &fHead, &fTail); |
| } |
| - void append(Vertex* v) { |
| - insert(v, fTail, nullptr); |
| + void append(T* t) { |
| + insert(t, fTail, nullptr); |
| } |
| - void prepend(Vertex* v) { |
| - insert(v, nullptr, fHead); |
| + void prepend(T* t) { |
| + insert(t, nullptr, fHead); |
| + } |
| + void remove(T* t) { |
| + list_remove<T, &T::fPrev, &T::fNext>(t, &fHead, &fTail); |
| } |
| }; |
| +typedef List<Vertex> VertexList; |
| + |
| /** |
| * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and |
| * "edge below" a vertex as well as for the active edge list is handled by isLeftOf()/isRightOf(). |
| @@ -249,7 +254,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 +272,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 +329,9 @@ struct Edge { |
| /***************************************************************************************/ |
| struct Poly { |
| - Poly(int winding) |
| - : fWinding(winding) |
| - , fHead(nullptr) |
| - , fTail(nullptr) |
| - , fActive(nullptr) |
| + Poly(Vertex* v, int winding) |
| + : fFirstVertex(v) |
| + , fWinding(winding) |
| , fNext(nullptr) |
| , fPartner(nullptr) |
| , fCount(0) |
| @@ -331,36 +342,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) { |
| + 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,60 +409,56 @@ 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"); |
| + void 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, |
|
robertphillips
2016/06/02 12:19:48
Does the "neither" case still make sense ?
Stephen White
2016/06/02 18:01:21
Good point. Removed.
|
| + fID, side == kLeft_Side ? "left" : side == kRight_Side ? "right" : "neither"); |
| 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 (!fMonotones.fTail) { |
| + fMonotones.append(ALLOC_NEW(MonotonePoly, (e, side), alloc)); |
| + fCount += 2; |
| + } else if (side == fMonotones.fTail->fSide) { |
| + fMonotones.fTail->addEdge(e); |
| + fCount++; |
| + } else { |
| + if (e->fBottom == fMonotones.fTail->fLastEdge->fBottom) { |
| + return; |
| } |
| + e = ALLOC_NEW(Edge, (fMonotones.fTail->fLastEdge->fBottom, e->fBottom, 1), alloc); |
| + fMonotones.fTail->addEdge(e); |
| + fCount++; |
| + MonotonePoly* m; |
| if (partner) { |
| - partner->addVertex(v, side, alloc); |
| - poly = partner; |
| + m = partner->fMonotones.fTail; |
| + m->addEdge(e); |
| + partner->fMonotones.remove(m); |
| } 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); |
| + m = ALLOC_NEW(MonotonePoly, (e, side), alloc); |
| } |
| + fCount += 2; |
| + fMonotones.append(m); |
| } |
| - 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; |
| } |
| LOG("emit() %d, size %d\n", fID, fCount); |
| - for (MonotonePoly* m = fHead; m != nullptr; m = m->fNext) { |
| + for (MonotonePoly* m = fMonotones.fHead; m != nullptr; m = m->fNext) { |
| data = m->emit(data); |
| } |
| return data; |
| } |
| + Vertex* lastVertex() const { |
| + return fMonotones.fTail ? fMonotones.fTail->fLastEdge->fBottom : fFirstVertex; |
| + } |
| + Vertex* fFirstVertex; |
| int fWinding; |
| - MonotonePoly* fHead; |
| - MonotonePoly* fTail; |
| - MonotonePoly* fActive; |
| + List<MonotonePoly> fMonotones; |
| Poly* fNext; |
| Poly* fPartner; |
| int fCount; |
| @@ -454,8 +474,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; |
| @@ -1195,25 +1214,15 @@ Poly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) { |
| } |
| #endif |
| if (v->fFirstEdgeAbove) { |
|
robertphillips
2016/06/02 12:19:48
Either "nullptr != e" or "e" ?
|
| - if (leftPoly) { |
| - leftPoly = leftPoly->addVertex(v, Poly::kRight_Side, alloc); |
| - } |
| - if (rightPoly) { |
| - rightPoly = rightPoly->addVertex(v, Poly::kLeft_Side, alloc); |
| - } |
| - for (Edge* e = v->fFirstEdgeAbove; e != v->fLastEdgeAbove; e = e->fNextEdgeAbove) { |
| - Edge* leftEdge = e; |
| - Edge* rightEdge = e->fNextEdgeAbove; |
| - SkASSERT(rightEdge->isRightOf(leftEdge->fTop)); |
| - remove_edge(leftEdge, &activeEdges); |
| - if (leftEdge->fRightPoly) { |
| - leftEdge->fRightPoly->end(v, alloc); |
| + for (Edge* e = v->fFirstEdgeAbove; e != nullptr; e = e->fNextEdgeAbove) { |
| + remove_edge(e, &activeEdges); |
| + if (e->fLeftPoly) { |
| + e->fLeftPoly->addEdge(e, Poly::kRight_Side, alloc); |
| } |
| - if (rightEdge->fLeftPoly && rightEdge->fLeftPoly != leftEdge->fRightPoly) { |
| - rightEdge->fLeftPoly->end(v, alloc); |
| + if (e->fRightPoly) { |
| + e->fRightPoly->addEdge(e, Poly::kLeft_Side, alloc); |
| } |
| } |
| - remove_edge(v->fLastEdgeAbove, &activeEdges); |
| if (!v->fFirstEdgeBelow) { |
| if (leftPoly && rightPoly && leftPoly != rightPoly) { |
| SkASSERT(leftPoly->fPartner == nullptr && rightPoly->fPartner == nullptr); |
| @@ -1224,28 +1233,22 @@ 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->fMonotones.fTail && |
| + leftPoly->fMonotones.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->addEdge(join, Poly::kRight_Side, alloc); |
| + rightPoly->addEdge(join, Poly::kLeft_Side, alloc); |
| } |
| } |
| Edge* leftEdge = v->fFirstEdgeBelow; |