Batch up draws into triangle fans as large as possible when drawing convex
edge AA polys, so we minimize state changes and GL calls. This requires
querying GL for the maximum number of fragment uniforms. It also makes the
shader generator produce custom shaders for the number of relevant edges.
This gives a ~5X speedup on the "Shapes" SampleApp.
Review URL: http://codereview.appspot.com/4536070/
git-svn-id: http://skia.googlecode.com/svn/trunk@1380 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrTesselatedPathRenderer.cpp b/gpu/src/GrTesselatedPathRenderer.cpp
index da6da5c..8a33012 100644
--- a/gpu/src/GrTesselatedPathRenderer.cpp
+++ b/gpu/src/GrTesselatedPathRenderer.cpp
@@ -85,19 +85,7 @@
GrTesselatedPathRenderer::GrTesselatedPathRenderer() {
}
-class Edge {
- public:
- Edge() {}
- Edge(float x, float y, float z) : fX(x), fY(y), fZ(z) {}
- GrPoint intersect(const Edge& other) {
- return GrPoint::Make(
- (fY * other.fZ - other.fY * fZ) / (fX * other.fY - other.fX * fY),
- (fX * other.fZ - other.fX * fZ) / (other.fX * fY - fX * other.fY));
- }
- float fX, fY, fZ;
-};
-
-typedef GrTDArray<Edge> EdgeArray;
+typedef GrTDArray<GrDrawTarget::Edge> EdgeArray;
bool isCCW(const GrPoint* pts)
{
@@ -121,15 +109,15 @@
GrVec tangent = GrVec::Make(p.fY - q.fY, q.fX - p.fX);
float scale = sign / tangent.length();
float cross2 = p.fX * q.fY - q.fX * p.fY;
- Edge edge(tangent.fX * scale,
+ GrDrawTarget::Edge edge(tangent.fX * scale,
tangent.fY * scale,
cross2 * scale + 0.5f);
*edges->append() = edge;
p = q;
}
- Edge prev_edge = *edges->back();
+ GrDrawTarget::Edge prev_edge = *edges->back();
for (size_t i = 0; i < edges->count(); ++i) {
- Edge edge = edges->at(i);
+ GrDrawTarget::Edge edge = edges->at(i);
vertices[i] = prev_edge.intersect(edge);
inverse.mapPoints(&vertices[i], 1);
prev_edge = edge;
@@ -262,29 +250,30 @@
if (subpathCnt == 1 && !inverted && path.isConvex()) {
if (target->isAntialiasState()) {
- target->enableState(GrDrawTarget::kEdgeAA_StateBit);
EdgeArray edges;
GrMatrix inverse, matrix = target->getViewMatrix();
target->getViewInverse(&inverse);
count = computeEdgesAndOffsetVertices(matrix, inverse, base, count, &edges);
- GrPoint triangle[3];
- triangle[0] = base[0];
- Edge triangleEdges[6];
- triangleEdges[0] = *edges.back();
- triangleEdges[1] = edges[0];
- for (size_t i = 1; i < count - 1; i++) {
- triangle[1] = base[i];
- triangle[2] = base[i + 1];
- triangleEdges[2] = edges[i - 1];
- triangleEdges[3] = edges[i];
- triangleEdges[4] = edges[i];
- triangleEdges[5] = edges[i + 1];
- target->setVertexSourceToArray(layout, triangle, 3);
- target->setEdgeAAData(&triangleEdges[0].fX);
- target->drawNonIndexed(kTriangles_PrimitiveType, 0, 3);
+ int maxEdges = target->getMaxEdges();
+ if (count <= maxEdges) {
+ // All edges fit; upload all edges and draw all verts as a fan
+ target->setVertexSourceToArray(layout, base, count);
+ target->setEdgeAAData(&edges[0], count);
+ target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
+ } else {
+ // Upload "maxEdges" edges and verts at a time, and draw as
+ // separate fans
+ for (size_t i = 0; i < count - 2; i += maxEdges - 2) {
+ edges[i] = edges[0];
+ base[i] = base[0];
+ int size = GR_CT_MIN(count - i, maxEdges);
+ target->setVertexSourceToArray(layout, &base[i], size);
+ target->setEdgeAAData(&edges[i], size);
+ target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, size);
+ }
}
- target->disableState(GrDrawTarget::kEdgeAA_StateBit);
+ target->setEdgeAAData(NULL, 0);
} else {
target->setVertexSourceToArray(layout, base, count);
target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);