Make a separate path renderer object. Move enum types to GrTypes.h
Review URL http://codereview.appspot.com/4167067/
git-svn-id: http://skia.googlecode.com/svn/trunk@829 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 7ce8f35..dbc7f6c 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -24,6 +24,7 @@
#include "GrIndexBuffer.h"
#include "GrInOrderDrawBuffer.h"
#include "GrBufferAllocPool.h"
+#include "GrPathRenderer.h"
#define DEFER_TEXT_RENDERING 1
@@ -62,6 +63,7 @@
delete fDrawBuffer;
delete fDrawBufferVBAllocPool;
delete fDrawBufferVBAllocPool;
+ delete fPathRenderer;
}
void GrContext::abandonAllTextures() {
@@ -146,7 +148,7 @@
fGpu->setStencilPass(GrDrawTarget::kNone_StencilPass);
fGpu->setViewMatrix(GrMatrix::I());
fGpu->setAlpha(0xff);
- fGpu->setBlendFunc(GrDrawTarget::kOne_BlendCoeff, GrDrawTarget::kZero_BlendCoeff);
+ fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);
fGpu->disableState(GrDrawTarget::kDither_StateBit |
GrDrawTarget::kClip_StateBit |
GrDrawTarget::kAntialias_StateBit);
@@ -166,7 +168,7 @@
texture->height(),
2*sizeof(GrPoint));
verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
- fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType,
+ fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,
0, 4);
entry = fTextureCache->createAndLock(*key, texture);
}
@@ -349,18 +351,18 @@
return;
}
- GrDrawTarget::PrimitiveType primType;
+ GrPrimitiveType primType;
int vertCount;
GrPoint* vertex = geo.positions();
if (width > 0) {
vertCount = 10;
- primType = GrDrawTarget::kTriangleStrip_PrimitiveType;
+ primType = kTriangleStrip_PrimitiveType;
setStrokeRectStrip(vertex, rect, width);
} else {
// hairline
vertCount = 5;
- primType = GrDrawTarget::kLineStrip_PrimitiveType;
+ primType = kLineStrip_PrimitiveType;
vertex[0].set(rect.fLeft, rect.fTop);
vertex[1].set(rect.fRight, rect.fTop);
vertex[2].set(rect.fRight, rect.fBottom);
@@ -398,7 +400,7 @@
if (textured) {
target->preConcatSamplerMatrix(0, m);
}
- target->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);
+ target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
#else
target->drawSimpleRect(rect, matrix, textured ? 1 : 0);
#endif
@@ -443,7 +445,7 @@
target->preConcatSamplerMatrix(0, m);
target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer());
- target->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);
+ target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
#else
GrDrawTarget* target;
@@ -463,7 +465,7 @@
}
void GrContext::drawVertices(const GrPaint& paint,
- GrDrawTarget::PrimitiveType primitiveType,
+ GrPrimitiveType primitiveType,
int vertexCount,
const GrPoint positions[],
const GrPoint texCoords[],
@@ -529,339 +531,19 @@
////////////////////////////////////////////////////////////////////////////////
-#define STENCIL_OFF 0 // Always disable stencil (even when needed)
-#define EVAL_TOL GR_Scalar1
-
-static const uint32_t MAX_POINTS_PER_CURVE = 1 << 10;
-
-static uint32_t quadratic_point_count(const GrPoint points[], GrScalar tol) {
- GrScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]);
- // TODO: fixed points sqrt
- if (d < tol) {
- return 1;
- } else {
- // Each time we subdivide, d should be cut in 4. So we need to
- // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x)
- // points.
- // 2^(log4(x)) = sqrt(x);
- d = ceilf(sqrtf(d/tol));
- return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE);
- }
-}
-
-static uint32_t generate_quadratic_points(const GrPoint& p0,
- const GrPoint& p1,
- const GrPoint& p2,
- GrScalar tolSqd,
- GrPoint** points,
- uint32_t pointsLeft) {
- if (pointsLeft < 2 ||
- (p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) {
- (*points)[0] = p2;
- *points += 1;
- return 1;
- }
-
- GrPoint q[] = {
- GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),
- GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),
- };
- GrPoint r(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY));
-
- pointsLeft >>= 1;
- uint32_t a = generate_quadratic_points(p0, q[0], r, tolSqd, points, pointsLeft);
- uint32_t b = generate_quadratic_points(r, q[1], p2, tolSqd, points, pointsLeft);
- return a + b;
-}
-
-static uint32_t cubic_point_count(const GrPoint points[], GrScalar tol) {
- GrScalar d = GrMax(points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]),
- points[2].distanceToLineSegmentBetweenSqd(points[0], points[3]));
- d = sqrtf(d);
- if (d < tol) {
- return 1;
- } else {
- d = ceilf(sqrtf(d/tol));
- return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE);
- }
-}
-
-static uint32_t generate_cubic_points(const GrPoint& p0,
- const GrPoint& p1,
- const GrPoint& p2,
- const GrPoint& p3,
- GrScalar tolSqd,
- GrPoint** points,
- uint32_t pointsLeft) {
- if (pointsLeft < 2 ||
- (p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd &&
- p2.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd)) {
- (*points)[0] = p3;
- *points += 1;
- return 1;
- }
- GrPoint q[] = {
- GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),
- GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),
- GrPoint(GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY))
- };
- GrPoint r[] = {
- GrPoint(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY)),
- GrPoint(GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY))
- };
- GrPoint s(GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY));
- pointsLeft >>= 1;
- uint32_t a = generate_cubic_points(p0, q[0], r[0], s, tolSqd, points, pointsLeft);
- uint32_t b = generate_cubic_points(s, r[1], q[2], p3, tolSqd, points, pointsLeft);
- return a + b;
-}
-
-static int worst_case_point_count(GrPathIter* path,
- int* subpaths,
- GrScalar tol) {
- int pointCount = 0;
- *subpaths = 1;
-
- bool first = true;
-
- GrPathIter::Command cmd;
-
- GrPoint pts[4];
- while ((cmd = path->next(pts)) != GrPathIter::kEnd_Command) {
-
- switch (cmd) {
- case GrPathIter::kLine_Command:
- pointCount += 1;
- break;
- case GrPathIter::kQuadratic_Command:
- pointCount += quadratic_point_count(pts, tol);
- break;
- case GrPathIter::kCubic_Command:
- pointCount += cubic_point_count(pts, tol);
- break;
- case GrPathIter::kMove_Command:
- pointCount += 1;
- if (!first) {
- ++(*subpaths);
- }
- break;
- default:
- break;
- }
- first = false;
- }
- return pointCount;
-}
-
-static inline bool single_pass_path(const GrPathIter& path,
- GrContext::PathFills fill,
- const GrDrawTarget& target) {
-#if STENCIL_OFF
- return true;
-#else
- if (GrContext::kEvenOdd_PathFill == fill) {
- GrPathIter::ConvexHint hint = path.hint();
- return hint == GrPathIter::kConvex_ConvexHint ||
- hint == GrPathIter::kNonOverlappingConvexPieces_ConvexHint;
- } else if (GrContext::kWinding_PathFill == fill) {
- GrPathIter::ConvexHint hint = path.hint();
- return hint == GrPathIter::kConvex_ConvexHint ||
- hint == GrPathIter::kNonOverlappingConvexPieces_ConvexHint ||
- (hint == GrPathIter::kSameWindingConvexPieces_ConvexHint &&
- target.canDisableBlend() && !target.isDitherState());
-
- }
- return false;
-#endif
-}
-
void GrContext::drawPath(const GrPaint& paint,
GrPathIter* path,
- PathFills fill,
+ GrPathFill fill,
const GrPoint* translate) {
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
- GrDrawTarget::AutoStateRestore asr(target);
-
- GrMatrix viewM = target->getViewMatrix();
- // In order to tesselate the path we get a bound on how much the matrix can
- // stretch when mapping to screen coordinates.
- GrScalar stretch = viewM.getMaxStretch();
- bool useStretch = stretch > 0;
- GrScalar tol = EVAL_TOL;
- if (!useStretch) {
- // TODO: deal with perspective in some better way.
- tol /= 10;
- } else {
- // TODO: fixed point divide
- GrScalar sinv = 1 / stretch;
- tol = GrMul(tol, sinv);
- }
- GrScalar tolSqd = GrMul(tol, tol);
-
- int subpathCnt;
- int maxPts = worst_case_point_count(path,
- &subpathCnt,
- tol);
- GrVertexLayout layout = 0;
-
+ GrDrawTarget::StageBitfield enabledStages = 0;
if (NULL != paint.getTexture()) {
- layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
+ enabledStages |= 1;
}
- // add 4 to hold the bounding rect
- GrDrawTarget::AutoReleaseGeometry arg(target, layout, maxPts + 4, 0);
-
- GrPoint* base = (GrPoint*) arg.vertices();
- GrPoint* vert = base;
- GrPoint* subpathBase = base;
-
- GrAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);
-
- path->rewind();
-
- // TODO: use primitve restart if available rather than multiple draws
- GrDrawTarget::PrimitiveType type;
- int passCount = 0;
- GrDrawTarget::StencilPass passes[3];
- bool reverse = false;
-
- if (kHairLine_PathFill == fill) {
- type = GrDrawTarget::kLineStrip_PrimitiveType;
- passCount = 1;
- passes[0] = GrDrawTarget::kNone_StencilPass;
- } else {
- type = GrDrawTarget::kTriangleFan_PrimitiveType;
- if (single_pass_path(*path, fill, *target)) {
- passCount = 1;
- passes[0] = GrDrawTarget::kNone_StencilPass;
- } else {
- switch (fill) {
- case kInverseEvenOdd_PathFill:
- reverse = true;
- // fallthrough
- case kEvenOdd_PathFill:
- passCount = 2;
- passes[0] = GrDrawTarget::kEvenOddStencil_StencilPass;
- passes[1] = GrDrawTarget::kEvenOddColor_StencilPass;
- break;
-
- case kInverseWinding_PathFill:
- reverse = true;
- // fallthrough
- case kWinding_PathFill:
- passes[0] = GrDrawTarget::kWindingStencil1_StencilPass;
- if (fGpu->supportsSingleStencilPassWinding()) {
- passes[1] = GrDrawTarget::kWindingColor_StencilPass;
- passCount = 2;
- } else {
- passes[1] = GrDrawTarget::kWindingStencil2_StencilPass;
- passes[2] = GrDrawTarget::kWindingColor_StencilPass;
- passCount = 3;
- }
- break;
- default:
- GrAssert(!"Unknown path fill!");
- return;
- }
- }
- }
- target->setReverseFill(reverse);
-
- GrPoint pts[4];
-
- bool first = true;
- int subpath = 0;
-
- for (;;) {
- GrPathIter::Command cmd = path->next(pts);
- switch (cmd) {
- case GrPathIter::kMove_Command:
- if (!first) {
- subpathVertCount[subpath] = vert-subpathBase;
- subpathBase = vert;
- ++subpath;
- }
- *vert = pts[0];
- vert++;
- break;
- case GrPathIter::kLine_Command:
- *vert = pts[1];
- vert++;
- break;
- case GrPathIter::kQuadratic_Command: {
- generate_quadratic_points(pts[0], pts[1], pts[2],
- tolSqd, &vert,
- quadratic_point_count(pts, tol));
- break;
- }
- case GrPathIter::kCubic_Command: {
- generate_cubic_points(pts[0], pts[1], pts[2], pts[3],
- tolSqd, &vert,
- cubic_point_count(pts, tol));
- break;
- }
- case GrPathIter::kClose_Command:
- break;
- case GrPathIter::kEnd_Command:
- subpathVertCount[subpath] = vert-subpathBase;
- ++subpath; // this could be only in debug
- goto FINISHED;
- }
- first = false;
- }
-FINISHED:
- GrAssert(subpath == subpathCnt);
- GrAssert((vert - base) <= maxPts);
-
- if (translate) {
- int count = vert - base;
- for (int i = 0; i < count; i++) {
- base[i].offset(translate->fX, translate->fY);
- }
- }
-
- // arbitrary path complexity cutoff
- bool useBounds = fill != kHairLine_PathFill &&
- (reverse || (vert - base) > 8);
- GrPoint* boundsVerts = base + maxPts;
- if (useBounds) {
- GrRect bounds;
- if (reverse) {
- GrAssert(NULL != target->getRenderTarget());
- // draw over the whole world.
- bounds.setLTRB(0, 0,
- GrIntToScalar(target->getRenderTarget()->width()),
- GrIntToScalar(target->getRenderTarget()->height()));
- GrMatrix vmi;
- if (target->getViewInverse(&vmi)) {
- vmi.mapRect(&bounds);
- }
- } else {
- bounds.setBounds((GrPoint*)base, vert - base);
- }
- boundsVerts[0].setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight,
- bounds.fBottom);
- }
-
- for (int p = 0; p < passCount; ++p) {
- target->setStencilPass(passes[p]);
- if (useBounds && (GrDrawTarget::kEvenOddColor_StencilPass == passes[p] ||
- GrDrawTarget::kWindingColor_StencilPass == passes[p])) {
- target->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType,
- maxPts, 4);
-
- } else {
- int baseVertex = 0;
- for (int sp = 0; sp < subpathCnt; ++sp) {
- target->drawNonIndexed(type,
- baseVertex,
- subpathVertCount[sp]);
- baseVertex += subpathVertCount[sp];
- }
- }
- }
+ fPathRenderer->drawPath(target, enabledStages, path, fill, translate);
}
////////////////////////////////////////////////////////////////////////////////
@@ -918,8 +600,8 @@
fGpu->disableState(GrDrawTarget::kClip_StateBit);
fGpu->setAlpha(0xFF);
- fGpu->setBlendFunc(GrDrawTarget::kOne_BlendCoeff,
- GrDrawTarget::kZero_BlendCoeff);
+ fGpu->setBlendFunc(kOne_BlendCoeff,
+ kZero_BlendCoeff);
fGpu->setTexture(0, texture);
GrSamplerState sampler;
@@ -936,7 +618,7 @@
return;
}
((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
- fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, VCOUNT);
+ fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);
}
////////////////////////////////////////////////////////////////////////////////
@@ -1069,7 +751,7 @@
#if BATCH_RECT_TO_RECT
fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
#endif
-
+ fPathRenderer = new GrDefaultPathRenderer(fGpu->supportsSingleStencilPassWinding());
}
bool GrContext::finalizeTextureKey(GrTextureKey* key,