Index: src/gpu/GrAAConvexPathRenderer.cpp |
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp |
index a0e72e5e6e676fcfd1860fbaeb77f99f41a94e6b..fc6cae68c62298fc26430154ae6c9090f47f2bf7 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; |
} |