diff options
-rw-r--r-- | gm/convexpaths.cpp | 20 | ||||
-rw-r--r-- | src/gpu/GrAAConvexPathRenderer.cpp | 230 |
2 files changed, 151 insertions, 99 deletions
diff --git a/gm/convexpaths.cpp b/gm/convexpaths.cpp index 2c4753d95a..a354bd4cef 100644 --- a/gm/convexpaths.cpp +++ b/gm/convexpaths.cpp @@ -120,12 +120,30 @@ protected: 20 * SK_Scalar1, 40 * SK_Scalar1, SkPath::kCCW_Direction); + // large number of points + enum { + kLength = 100, + kPtsPerSide = (1 << 12), + }; + fPaths.push_back().moveTo(0, 0); + for (int i = 1; i < kPtsPerSide; ++i) { // skip the first point due to moveTo. + fPaths.back().lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, 0); + } + for (int i = 0; i < kPtsPerSide; ++i) { + fPaths.back().lineTo(kLength, kLength * SkIntToScalar(i) / kPtsPerSide); + } + for (int i = kPtsPerSide; i > 0; --i) { + fPaths.back().lineTo(kLength * SkIntToScalar(i) / kPtsPerSide, kLength); + } + for (int i = kPtsPerSide; i > 0; --i) { + fPaths.back().lineTo(0, kLength * SkIntToScalar(i) / kPtsPerSide); + } + // shallow diagonals fPaths.push_back().lineTo(100 * SK_Scalar1, SK_Scalar1); fPaths.back().lineTo(98 * SK_Scalar1, 100 * SK_Scalar1); fPaths.back().lineTo(3 * SK_Scalar1, 96 * SK_Scalar1); - //It turns out arcTos are not automatically marked as convex and they //may in fact be ever so slightly concave. //fPaths.push_back().arcTo(SkRect::MakeXYWH(0, 0, diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index a0e72e5e6e..fc6cae68c6 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -128,7 +128,7 @@ void compute_vectors(SegmentArray* segments, *iCount = 0; // compute normals at all points for (int a = 0; a < count; ++a) { - const Segment& sega = (*segments)[a]; + Segment& sega = (*segments)[a]; int b = (a + 1) % count; Segment& segb = (*segments)[b]; @@ -304,12 +304,23 @@ struct QuadVertex { SkScalar fD1; }; +struct Draw { + Draw() : fVertexCnt(0), fIndexCnt(0) {} + int fVertexCnt; + int fIndexCnt; +}; + +typedef SkTArray<Draw, true> DrawArray; + void create_vertices(const SegmentArray& segments, const SkPoint& fanPt, + DrawArray* draws, QuadVertex* verts, uint16_t* idxs) { - int v = 0; - int i = 0; + Draw* draw = &draws->push_back(); + // alias just to make vert/index assignments easier to read. + int* v = &draw->fVertexCnt; + int* i = &draw->fIndexCnt; int count = segments.count(); for (int a = 0; a < count; ++a) { @@ -317,117 +328,133 @@ void create_vertices(const SegmentArray& segments, int b = (a + 1) % count; const Segment& segb = segments[b]; + // Check whether adding the verts for this segment to the current draw would cause index + // values to overflow. + int vCount = 4; + if (Segment::kLine == segb.fType) { + vCount += 5; + } else { + vCount += 6; + } + if (draw->fVertexCnt + vCount > (1 << 16)) { + verts += *v; + idxs += *i; + draw = &draws->push_back(); + v = &draw->fVertexCnt; + i = &draw->fIndexCnt; + } + // FIXME: These tris are inset in the 1 unit arc around the corner - verts[v + 0].fPos = sega.endPt(); - verts[v + 1].fPos = verts[v + 0].fPos + sega.endNorm(); - verts[v + 2].fPos = verts[v + 0].fPos + segb.fMid; - verts[v + 3].fPos = verts[v + 0].fPos + segb.fNorms[0]; - verts[v + 0].fUV.set(0,0); - verts[v + 1].fUV.set(0,-SK_Scalar1); - verts[v + 2].fUV.set(0,-SK_Scalar1); - verts[v + 3].fUV.set(0,-SK_Scalar1); - verts[v + 0].fD0 = verts[v + 0].fD1 = -SK_Scalar1; - verts[v + 1].fD0 = verts[v + 1].fD1 = -SK_Scalar1; - verts[v + 2].fD0 = verts[v + 2].fD1 = -SK_Scalar1; - verts[v + 3].fD0 = verts[v + 3].fD1 = -SK_Scalar1; - - idxs[i + 0] = v + 0; - idxs[i + 1] = v + 2; - idxs[i + 2] = v + 1; - idxs[i + 3] = v + 0; - idxs[i + 4] = v + 3; - idxs[i + 5] = v + 2; - - v += 4; - i += 6; + verts[*v + 0].fPos = sega.endPt(); + verts[*v + 1].fPos = verts[*v + 0].fPos + sega.endNorm(); + verts[*v + 2].fPos = verts[*v + 0].fPos + segb.fMid; + verts[*v + 3].fPos = verts[*v + 0].fPos + segb.fNorms[0]; + verts[*v + 0].fUV.set(0,0); + verts[*v + 1].fUV.set(0,-SK_Scalar1); + verts[*v + 2].fUV.set(0,-SK_Scalar1); + verts[*v + 3].fUV.set(0,-SK_Scalar1); + verts[*v + 0].fD0 = verts[*v + 0].fD1 = -SK_Scalar1; + verts[*v + 1].fD0 = verts[*v + 1].fD1 = -SK_Scalar1; + verts[*v + 2].fD0 = verts[*v + 2].fD1 = -SK_Scalar1; + verts[*v + 3].fD0 = verts[*v + 3].fD1 = -SK_Scalar1; + + idxs[*i + 0] = *v + 0; + idxs[*i + 1] = *v + 2; + idxs[*i + 2] = *v + 1; + idxs[*i + 3] = *v + 0; + idxs[*i + 4] = *v + 3; + idxs[*i + 5] = *v + 2; + + *v += 4; + *i += 6; if (Segment::kLine == segb.fType) { - verts[v + 0].fPos = fanPt; - verts[v + 1].fPos = sega.endPt(); - verts[v + 2].fPos = segb.fPts[0]; + verts[*v + 0].fPos = fanPt; + verts[*v + 1].fPos = sega.endPt(); + verts[*v + 2].fPos = segb.fPts[0]; - verts[v + 3].fPos = verts[v + 1].fPos + segb.fNorms[0]; - verts[v + 4].fPos = verts[v + 2].fPos + segb.fNorms[0]; + verts[*v + 3].fPos = verts[*v + 1].fPos + segb.fNorms[0]; + verts[*v + 4].fPos = verts[*v + 2].fPos + segb.fNorms[0]; // we draw the line edge as a degenerate quad (u is 0, v is the // signed distance to the edge) - SkScalar dist = fanPt.distanceToLineBetween(verts[v + 1].fPos, - verts[v + 2].fPos); - verts[v + 0].fUV.set(0, dist); - verts[v + 1].fUV.set(0, 0); - verts[v + 2].fUV.set(0, 0); - verts[v + 3].fUV.set(0, -SK_Scalar1); - verts[v + 4].fUV.set(0, -SK_Scalar1); - - verts[v + 0].fD0 = verts[v + 0].fD1 = -SK_Scalar1; - verts[v + 1].fD0 = verts[v + 1].fD1 = -SK_Scalar1; - verts[v + 2].fD0 = verts[v + 2].fD1 = -SK_Scalar1; - verts[v + 3].fD0 = verts[v + 3].fD1 = -SK_Scalar1; - verts[v + 4].fD0 = verts[v + 4].fD1 = -SK_Scalar1; - - idxs[i + 0] = v + 0; - idxs[i + 1] = v + 2; - idxs[i + 2] = v + 1; - - idxs[i + 3] = v + 3; - idxs[i + 4] = v + 1; - idxs[i + 5] = v + 2; - - idxs[i + 6] = v + 4; - idxs[i + 7] = v + 3; - idxs[i + 8] = v + 2; - - v += 5; - i += 9; + SkScalar dist = fanPt.distanceToLineBetween(verts[*v + 1].fPos, + verts[*v + 2].fPos); + verts[*v + 0].fUV.set(0, dist); + verts[*v + 1].fUV.set(0, 0); + verts[*v + 2].fUV.set(0, 0); + verts[*v + 3].fUV.set(0, -SK_Scalar1); + verts[*v + 4].fUV.set(0, -SK_Scalar1); + + verts[*v + 0].fD0 = verts[*v + 0].fD1 = -SK_Scalar1; + verts[*v + 1].fD0 = verts[*v + 1].fD1 = -SK_Scalar1; + verts[*v + 2].fD0 = verts[*v + 2].fD1 = -SK_Scalar1; + verts[*v + 3].fD0 = verts[*v + 3].fD1 = -SK_Scalar1; + verts[*v + 4].fD0 = verts[*v + 4].fD1 = -SK_Scalar1; + + idxs[*i + 0] = *v + 0; + idxs[*i + 1] = *v + 2; + idxs[*i + 2] = *v + 1; + + idxs[*i + 3] = *v + 3; + idxs[*i + 4] = *v + 1; + idxs[*i + 5] = *v + 2; + + idxs[*i + 6] = *v + 4; + idxs[*i + 7] = *v + 3; + idxs[*i + 8] = *v + 2; + + *v += 5; + *i += 9; } else { GrPoint qpts[] = {sega.endPt(), segb.fPts[0], segb.fPts[1]}; GrVec midVec = segb.fNorms[0] + segb.fNorms[1]; midVec.normalize(); - verts[v + 0].fPos = fanPt; - verts[v + 1].fPos = qpts[0]; - verts[v + 2].fPos = qpts[2]; - verts[v + 3].fPos = qpts[0] + segb.fNorms[0]; - verts[v + 4].fPos = qpts[2] + segb.fNorms[1]; - verts[v + 5].fPos = qpts[1] + midVec; + verts[*v + 0].fPos = fanPt; + verts[*v + 1].fPos = qpts[0]; + verts[*v + 2].fPos = qpts[2]; + verts[*v + 3].fPos = qpts[0] + segb.fNorms[0]; + verts[*v + 4].fPos = qpts[2] + segb.fNorms[1]; + verts[*v + 5].fPos = qpts[1] + midVec; SkScalar c = segb.fNorms[0].dot(qpts[0]); - verts[v + 0].fD0 = -segb.fNorms[0].dot(fanPt) + c; - verts[v + 1].fD0 = 0.f; - verts[v + 2].fD0 = -segb.fNorms[0].dot(qpts[2]) + c; - verts[v + 3].fD0 = -SK_ScalarMax/100; - verts[v + 4].fD0 = -SK_ScalarMax/100; - verts[v + 5].fD0 = -SK_ScalarMax/100; + verts[*v + 0].fD0 = -segb.fNorms[0].dot(fanPt) + c; + verts[*v + 1].fD0 = 0.f; + verts[*v + 2].fD0 = -segb.fNorms[0].dot(qpts[2]) + c; + verts[*v + 3].fD0 = -SK_ScalarMax/100; + verts[*v + 4].fD0 = -SK_ScalarMax/100; + verts[*v + 5].fD0 = -SK_ScalarMax/100; c = segb.fNorms[1].dot(qpts[2]); - verts[v + 0].fD1 = -segb.fNorms[1].dot(fanPt) + c; - verts[v + 1].fD1 = -segb.fNorms[1].dot(qpts[0]) + c; - verts[v + 2].fD1 = 0.f; - verts[v + 3].fD1 = -SK_ScalarMax/100; - verts[v + 4].fD1 = -SK_ScalarMax/100; - verts[v + 5].fD1 = -SK_ScalarMax/100; + verts[*v + 0].fD1 = -segb.fNorms[1].dot(fanPt) + c; + verts[*v + 1].fD1 = -segb.fNorms[1].dot(qpts[0]) + c; + verts[*v + 2].fD1 = 0.f; + verts[*v + 3].fD1 = -SK_ScalarMax/100; + verts[*v + 4].fD1 = -SK_ScalarMax/100; + verts[*v + 5].fD1 = -SK_ScalarMax/100; GrPathUtils::QuadUVMatrix toUV(qpts); - toUV.apply<6, sizeof(QuadVertex), sizeof(GrPoint)>(verts + v); + toUV.apply<6, sizeof(QuadVertex), sizeof(GrPoint)>(verts + *v); - idxs[i + 0] = v + 3; - idxs[i + 1] = v + 1; - idxs[i + 2] = v + 2; - idxs[i + 3] = v + 4; - idxs[i + 4] = v + 3; - idxs[i + 5] = v + 2; + idxs[*i + 0] = *v + 3; + idxs[*i + 1] = *v + 1; + idxs[*i + 2] = *v + 2; + idxs[*i + 3] = *v + 4; + idxs[*i + 4] = *v + 3; + idxs[*i + 5] = *v + 2; - idxs[i + 6] = v + 5; - idxs[i + 7] = v + 3; - idxs[i + 8] = v + 4; + idxs[*i + 6] = *v + 5; + idxs[*i + 7] = *v + 3; + idxs[*i + 8] = *v + 4; - idxs[i + 9] = v + 0; - idxs[i + 10] = v + 2; - idxs[i + 11] = v + 1; + idxs[*i + 9] = *v + 0; + idxs[*i + 10] = *v + 2; + idxs[*i + 11] = *v + 1; - v += 6; - i += 12; + *v += 6; + *i += 12; } } } @@ -601,6 +628,7 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, int iCount; enum { kPreallocSegmentCnt = 512 / sizeof(Segment), + kPreallocDrawCnt = 4, }; SkSTArray<kPreallocSegmentCnt, Segment, true> segments; SkPoint fanPt; @@ -629,13 +657,19 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, verts = reinterpret_cast<QuadVertex*>(arg.vertices()); idxs = reinterpret_cast<uint16_t*>(arg.indices()); - create_vertices(segments, fanPt, verts, idxs); - - target->drawIndexed(kTriangles_GrPrimitiveType, - 0, // start vertex - 0, // start index - vCount, - iCount); + SkSTArray<kPreallocDrawCnt, Draw, true> draws; + create_vertices(segments, fanPt, &draws, verts, idxs); + + int vOffset = 0; + for (int i = 0; i < draws.count(); ++i) { + const Draw& draw = draws[i]; + target->drawIndexed(kTriangles_GrPrimitiveType, + vOffset, // start vertex + 0, // start index + draw.fVertexCnt, + draw.fIndexCnt); + vOffset += draw.fVertexCnt; + } return true; } |