diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-02-22 20:34:01 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-02-22 20:34:01 +0000 |
commit | ffca400ef6f96a280c3e2c09210f950af64a1f24 (patch) | |
tree | 2292badadfe451a456616652c8df3291d8a80158 /gpu/src | |
parent | bdee9fc778d4387d805d717f2cd7fc7074991fdb (diff) |
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
Diffstat (limited to 'gpu/src')
-rw-r--r-- | gpu/src/GrContext.cpp | 354 | ||||
-rw-r--r-- | gpu/src/GrDrawTarget.cpp | 14 | ||||
-rw-r--r-- | gpu/src/GrGpu.cpp | 6 | ||||
-rw-r--r-- | gpu/src/GrGpuGL.cpp | 10 | ||||
-rw-r--r-- | gpu/src/GrGpuGL.h | 6 | ||||
-rw-r--r-- | gpu/src/GrGpuGLFixed.cpp | 2 | ||||
-rw-r--r-- | gpu/src/GrGpuGLFixed.h | 2 | ||||
-rw-r--r-- | gpu/src/GrGpuGLShaders2.cpp | 6 | ||||
-rw-r--r-- | gpu/src/GrGpuGLShaders2.h | 6 | ||||
-rw-r--r-- | gpu/src/GrInOrderDrawBuffer.cpp | 11 | ||||
-rw-r--r-- | gpu/src/GrPathRenderer.cpp | 352 | ||||
-rw-r--r-- | gpu/src/GrPathRenderer.h | 64 | ||||
-rw-r--r-- | gpu/src/GrTextContext.cpp | 5 | ||||
-rw-r--r-- | gpu/src/gr_files.mk | 3 |
14 files changed, 469 insertions, 372 deletions
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp index 7ce8f35a65..dbc7f6ce18 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 @@ GrContext::~GrContext() { delete fDrawBuffer;
delete fDrawBufferVBAllocPool;
delete fDrawBufferVBAllocPool;
+ delete fPathRenderer;
}
void GrContext::abandonAllTextures() {
@@ -146,7 +148,7 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key, 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 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key, 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 @@ void GrContext::drawRect(const GrPaint& paint, 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 @@ void GrContext::drawRect(const GrPaint& paint, 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 @@ void GrContext::drawRectToRect(const GrPaint& paint, 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::drawRectToRect(const GrPaint& paint, }
void GrContext::drawVertices(const GrPaint& paint,
- GrDrawTarget::PrimitiveType primitiveType,
+ GrPrimitiveType primitiveType,
int vertexCount,
const GrPoint positions[],
const GrPoint texCoords[],
@@ -529,339 +531,19 @@ void GrContext::drawVertices(const GrPaint& paint, ////////////////////////////////////////////////////////////////////////////////
-#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);
- }
- // 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];
- }
- }
+ enabledStages |= 1;
}
+ fPathRenderer->drawPath(target, enabledStages, path, fill, translate);
}
////////////////////////////////////////////////////////////////////////////////
@@ -918,8 +600,8 @@ void GrContext::writePixels(int left, int top, int width, int height, 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 @@ void GrContext::writePixels(int left, int top, int width, int height, 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 @@ GrContext::GrContext(GrGpu* gpu) { #if BATCH_RECT_TO_RECT
fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
#endif
-
+ fPathRenderer = new GrDefaultPathRenderer(fGpu->supportsSingleStencilPassWinding());
}
bool GrContext::finalizeTextureKey(GrTextureKey* key,
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp index 63e59c4831..ca525b3b02 100644 --- a/gpu/src/GrDrawTarget.cpp +++ b/gpu/src/GrDrawTarget.cpp @@ -374,8 +374,8 @@ void GrDrawTarget::disableState(uint32_t bits) { fCurrDrawState.fFlagBits &= ~(bits); } -void GrDrawTarget::setBlendFunc(BlendCoeff srcCoef, - BlendCoeff dstCoef) { +void GrDrawTarget::setBlendFunc(GrBlendCoeff srcCoef, + GrBlendCoeff dstCoef) { fCurrDrawState.fSrcBlend = srcCoef; fCurrDrawState.fDstBlend = dstCoef; } @@ -515,12 +515,10 @@ bool GrDrawTarget::canDisableBlend() const { /////////////////////////////////////////////////////////////////////////////// void GrDrawTarget::drawRect(const GrRect& rect, const GrMatrix* matrix, - int stageEnableMask, + StageBitfield stageEnableBitfield, const GrRect* srcRects[], const GrMatrix* srcMatrices[]) { - GR_STATIC_ASSERT(8*sizeof(int) >= kNumStages); - - GrVertexLayout layout = GetRectVertexLayout(stageEnableMask, srcRects); + GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects); AutoReleaseGeometry geo(this, layout, 4, 0); @@ -530,13 +528,13 @@ void GrDrawTarget::drawRect(const GrRect& rect, drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4); } -GrVertexLayout GrDrawTarget::GetRectVertexLayout(int stageEnableMask, +GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageBitfield stageEnableBitfield, const GrRect* srcRects[]) { GrVertexLayout layout = 0; for (int i = 0; i < kNumStages; ++i) { int numTC = 0; - if (stageEnableMask & (1 << i)) { + if (stageEnableBitfield & (1 << i)) { if (NULL != srcRects && NULL != srcRects[i]) { layout |= StageTexCoordVertexLayoutBit(i, numTC); ++numTC; diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp index 9e9c1859c7..019c99ff6d 100644 --- a/gpu/src/GrGpu.cpp +++ b/gpu/src/GrGpu.cpp @@ -167,7 +167,7 @@ void GrGpu::clipWillBeSet(const GrClip& newClip) { } } -bool GrGpu::setupClipAndFlushState(PrimitiveType type) { +bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { const GrIRect* r = NULL; // we check this early because we need a valid @@ -254,7 +254,7 @@ bool GrGpu::setupClipAndFlushState(PrimitiveType type) { /////////////////////////////////////////////////////////////////////////////// -void GrGpu::drawIndexed(PrimitiveType type, +void GrGpu::drawIndexed(GrPrimitiveType type, int startVertex, int startIndex, int vertexCount, @@ -282,7 +282,7 @@ void GrGpu::drawIndexed(PrimitiveType type, vertexCount, indexCount); } -void GrGpu::drawNonIndexed(PrimitiveType type, +void GrGpu::drawNonIndexed(GrPrimitiveType type, int startVertex, int vertexCount) { GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc || diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp index 8cfc4a07ba..edcadb4be6 100644 --- a/gpu/src/GrGpuGL.cpp +++ b/gpu/src/GrGpuGL.cpp @@ -443,8 +443,8 @@ void GrGpuGL::resetContextHelper() { fHWDrawState.fFlagBits = 0; // illegal values - fHWDrawState.fSrcBlend = (BlendCoeff)-1; - fHWDrawState.fDstBlend = (BlendCoeff)-1; + fHWDrawState.fSrcBlend = (GrBlendCoeff)-1; + fHWDrawState.fDstBlend = (GrBlendCoeff)-1; fHWDrawState.fColor = GrColor_ILLEGAL; fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix(); @@ -1183,7 +1183,7 @@ GLenum gPrimitiveType2GLMode[] = { GL_LINE_STRIP }; -void GrGpuGL::drawIndexedHelper(PrimitiveType type, +void GrGpuGL::drawIndexedHelper(GrPrimitiveType type, uint32_t startVertex, uint32_t startIndex, uint32_t vertexCount, @@ -1203,7 +1203,7 @@ void GrGpuGL::drawIndexedHelper(PrimitiveType type, GL_UNSIGNED_SHORT, indices)); } -void GrGpuGL::drawNonIndexedHelper(PrimitiveType type, +void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type, uint32_t startVertex, uint32_t vertexCount) { GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode)); @@ -1458,7 +1458,7 @@ void GrGpuGL::flushStencil() { } } -bool GrGpuGL::flushGLStateCommon(PrimitiveType type) { +bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { // GrGpu::setupClipAndFlushState should have already checked this // and bailed if not true. diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h index 017d9ea403..f6216c5c6e 100644 --- a/gpu/src/GrGpuGL.h +++ b/gpu/src/GrGpuGL.h @@ -98,12 +98,12 @@ protected: GrGLExts fExts; // GrGpu overrides - virtual void drawIndexedHelper(PrimitiveType type, + virtual void drawIndexedHelper(GrPrimitiveType type, uint32_t startVertex, uint32_t startIndex, uint32_t vertexCount, uint32_t indexCount); - virtual void drawNonIndexedHelper(PrimitiveType type, + virtual void drawNonIndexedHelper(GrPrimitiveType type, uint32_t vertexCount, uint32_t numVertices); virtual void flushScissor(const GrIRect* rect); @@ -127,7 +127,7 @@ protected: // sampler state (filtering, tiling) // FBO binding // line width - bool flushGLStateCommon(PrimitiveType type); + bool flushGLStateCommon(GrPrimitiveType type); // adjusts texture matrix to account for orientation, size, and npotness static void AdjustTextureMatrix(const GrGLTexture* texture, diff --git a/gpu/src/GrGpuGLFixed.cpp b/gpu/src/GrGpuGLFixed.cpp index efb09908a0..516381e308 100644 --- a/gpu/src/GrGpuGLFixed.cpp +++ b/gpu/src/GrGpuGLFixed.cpp @@ -128,7 +128,7 @@ void GrGpuGLFixed::flushProjectionMatrix() { GR_GL(LoadMatrixf(mat)); } -bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) { +bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) { bool usingTextures[kNumStages]; diff --git a/gpu/src/GrGpuGLFixed.h b/gpu/src/GrGpuGLFixed.h index e5d472dd2e..5b81ea616d 100644 --- a/gpu/src/GrGpuGLFixed.h +++ b/gpu/src/GrGpuGLFixed.h @@ -30,7 +30,7 @@ public: protected: // overrides from GrGpu - virtual bool flushGraphicsState(PrimitiveType type); + virtual bool flushGraphicsState(GrPrimitiveType type); virtual void setupGeometry(int* startVertex, int* startIndex, int vertexCount, diff --git a/gpu/src/GrGpuGLShaders2.cpp b/gpu/src/GrGpuGLShaders2.cpp index 34e7c87e50..14134e7b6c 100644 --- a/gpu/src/GrGpuGLShaders2.cpp +++ b/gpu/src/GrGpuGLShaders2.cpp @@ -979,7 +979,7 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc, program->fViewMatrix = GrMatrix::InvalidMatrix(); } -void GrGpuGLShaders2::getProgramDesc(PrimitiveType primType, ProgramDesc* desc) { +void GrGpuGLShaders2::getProgramDesc(GrPrimitiveType primType, ProgramDesc* desc) { // Must initialize all fields or cache will have false negatives! desc->fVertexLayout = fGeometrySrc.fVertexLayout; @@ -1220,7 +1220,7 @@ void GrGpuGLShaders2::flushRadial2(int stage) { unis)); } -void GrGpuGLShaders2::flushProgram(PrimitiveType type) { +void GrGpuGLShaders2::flushProgram(GrPrimitiveType type) { ProgramDesc desc; getProgramDesc(type, &desc); fProgram = fProgramCache->getProgram(desc); @@ -1234,7 +1234,7 @@ void GrGpuGLShaders2::flushProgram(PrimitiveType type) { } } -bool GrGpuGLShaders2::flushGraphicsState(PrimitiveType type) { +bool GrGpuGLShaders2::flushGraphicsState(GrPrimitiveType type) { if (!flushGLStateCommon(type)) { return false; diff --git a/gpu/src/GrGpuGLShaders2.h b/gpu/src/GrGpuGLShaders2.h index 2647e23a15..e8785c9677 100644 --- a/gpu/src/GrGpuGLShaders2.h +++ b/gpu/src/GrGpuGLShaders2.h @@ -30,7 +30,7 @@ public: protected: // overrides from GrGpu - virtual bool flushGraphicsState(PrimitiveType type); + virtual bool flushGraphicsState(GrPrimitiveType type); virtual void setupGeometry(int* startVertex, int* startIndex, int vertexCount, @@ -54,7 +54,7 @@ private: void flushRadial2(int stage); // called at flush time to setup the appropriate program - void flushProgram(PrimitiveType type); + void flushProgram(GrPrimitiveType type); struct Program; @@ -69,7 +69,7 @@ private: class ProgramCache; // gets a description of needed shader - void getProgramDesc(PrimitiveType primType, ProgramDesc* desc); + void getProgramDesc(GrPrimitiveType primType, ProgramDesc* desc); // generates and compiles a program from a description and vertex layout // will change GL's bound program diff --git a/gpu/src/GrInOrderDrawBuffer.cpp b/gpu/src/GrInOrderDrawBuffer.cpp index 25e74e37e4..68590fc8ab 100644 --- a/gpu/src/GrInOrderDrawBuffer.cpp +++ b/gpu/src/GrInOrderDrawBuffer.cpp @@ -74,7 +74,7 @@ void GrInOrderDrawBuffer::setQuadIndexBuffer(const GrIndexBuffer* indexBuffer) { void GrInOrderDrawBuffer::drawRect(const GrRect& rect, const GrMatrix* matrix, - int stageEnableMask, + StageBitfield stageEnableBitfield, const GrRect* srcRects[], const GrMatrix* srcMatrices[]) { @@ -87,7 +87,7 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, if (fMaxQuads) { bool appendToPreviousDraw = false; - GrVertexLayout layout = GetRectVertexLayout(stageEnableMask, srcRects); + GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects); AutoReleaseGeometry geo(this, layout, 4, 0); AutoViewMatrixRestore avmr(this); GrMatrix combinedMatrix = this->getViewMatrix(); @@ -167,13 +167,12 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, if (disabledClip) { this->enableState(kClip_StateBit); } -this->enableState(kClip_StateBit); } else { - INHERITED::drawRect(rect, matrix, stageEnableMask, srcRects, srcMatrices); + INHERITED::drawRect(rect, matrix, stageEnableBitfield, srcRects, srcMatrices); } } -void GrInOrderDrawBuffer::drawIndexed(PrimitiveType primitiveType, +void GrInOrderDrawBuffer::drawIndexed(GrPrimitiveType primitiveType, int startVertex, int startIndex, int vertexCount, @@ -239,7 +238,7 @@ void GrInOrderDrawBuffer::drawIndexed(PrimitiveType primitiveType, draw.fIndexBuffer->ref(); } -void GrInOrderDrawBuffer::drawNonIndexed(PrimitiveType primitiveType, +void GrInOrderDrawBuffer::drawNonIndexed(GrPrimitiveType primitiveType, int startVertex, int vertexCount) { if (!vertexCount) { diff --git a/gpu/src/GrPathRenderer.cpp b/gpu/src/GrPathRenderer.cpp new file mode 100644 index 0000000000..c47b6e522c --- /dev/null +++ b/gpu/src/GrPathRenderer.cpp @@ -0,0 +1,352 @@ +#include "GrPathRenderer.h" + +#include "GrPoint.h" +#include "GrDrawTarget.h" +#include "GrPathIter.h" +#include "GrMemory.h" +#include "GrTexture.h" + + + +GrDefaultPathRenderer::GrDefaultPathRenderer(bool singlePassWindingStencil) + : fSinglePassWindingStencil(singlePassWindingStencil) { + +} + +//////////////////////////////////////////////////////////////////////////////// +// Helpers for draw Path + +#define STENCIL_OFF 0 // Always disable stencil (even when needed) +static const GrScalar gTolerance = 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]); + 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, + GrPathFill fill, + const GrDrawTarget& target) { +#if STENCIL_OFF + return true; +#else + if (kEvenOdd_PathFill == fill) { + GrPathIter::ConvexHint hint = path.hint(); + return hint == GrPathIter::kConvex_ConvexHint || + hint == GrPathIter::kNonOverlappingConvexPieces_ConvexHint; + } else if (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 GrDefaultPathRenderer::drawPath(GrDrawTarget* target, + GrDrawTarget::StageBitfield stages, + GrPathIter* path, + GrPathFill fill, + const GrPoint* translate) { + + 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 = gTolerance; + + if (!useStretch) { + // TODO: deal with perspective in some better way. + tol /= 10; + } else { + GrScalar sinv = GR_Scalar1 / stretch; + tol = GrMul(tol, sinv); + } + GrScalar tolSqd = GrMul(tol, tol); + + int subpathCnt; + int maxPts = worst_case_point_count(path, + &subpathCnt, + tol); + + GrVertexLayout layout = 0; + for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { + if ((1 << s) & stages) { + layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s); + } + } + + // 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 + GrPrimitiveType type; + int passCount = 0; + GrDrawTarget::StencilPass passes[3]; + bool reverse = false; + + if (kHairLine_PathFill == fill) { + type = kLineStrip_PrimitiveType; + passCount = 1; + passes[0] = GrDrawTarget::kNone_StencilPass; + } else { + type = 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 (fSinglePassWindingStencil) { + 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(kTriangleFan_PrimitiveType, + maxPts, 4); + + } else { + int baseVertex = 0; + for (int sp = 0; sp < subpathCnt; ++sp) { + target->drawNonIndexed(type, + baseVertex, + subpathVertCount[sp]); + baseVertex += subpathVertCount[sp]; + } + } + } +} diff --git a/gpu/src/GrPathRenderer.h b/gpu/src/GrPathRenderer.h new file mode 100644 index 0000000000..e3fd71507a --- /dev/null +++ b/gpu/src/GrPathRenderer.h @@ -0,0 +1,64 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#ifndef GrPathRenderer_DEFINED +#define GrPathRenderer_DEFINED + +#include "GrDrawTarget.h" + +class GrPathIter; +struct GrPoint; + +/** + * A path renderer. + */ +class GrPathRenderer { +public: + /** + * Draws a path into the draw target. The target will already have its draw + * state configured for the draw. + * @param target the target to draw into. + * @param stages indicates which stages the are already + * in use. All enabled stages expect positions + * as texture coordinates. The path renderer + * use the remaining stages for its path + * filling algorithm. + * @param path the path to draw. + * @param fill the fill rule to apply. + * @param translate optional additional translation to apply to + * the path NULL means (0,0). + */ + virtual void drawPath(GrDrawTarget* target, + GrDrawTarget::StageBitfield stages, + GrPathIter* path, + GrPathFill fill, + const GrPoint* translate) = 0; +}; + +class GrDefaultPathRenderer : public GrPathRenderer { +public: + GrDefaultPathRenderer(bool singlePassWindingStencil); + + virtual void drawPath(GrDrawTarget* target, + GrDrawTarget::StageBitfield stages, + GrPathIter* path, + GrPathFill fill, + const GrPoint* translate); +private: + bool fSinglePassWindingStencil; +}; + +#endif
\ No newline at end of file diff --git a/gpu/src/GrTextContext.cpp b/gpu/src/GrTextContext.cpp index 0f244a2e81..8ce45e40eb 100644 --- a/gpu/src/GrTextContext.cpp +++ b/gpu/src/GrTextContext.cpp @@ -23,6 +23,7 @@ #include "GrFontScaler.h" #include "GrIndexBuffer.h" #include "GrGpuVertex.h" +#include "GrDrawTarget.h" static const int TEXT_STAGE = 1; @@ -47,7 +48,7 @@ void GrTextContext::flushGlyphs() { fDrawTarget->setTexture(TEXT_STAGE, fCurrTexture); fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); - fDrawTarget->drawIndexed(GrDrawTarget::kTriangles_PrimitiveType, + fDrawTarget->drawIndexed(kTriangles_PrimitiveType, 0, 0, fCurrVertex, nIndices); fDrawTarget->releaseReservedGeometry(); fVertices = NULL; @@ -178,7 +179,7 @@ void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed, GrPoint translate; translate.set(GrFixedToScalar(vx - GrIntToFixed(glyph->fBounds.fLeft)), GrFixedToScalar(vy - GrIntToFixed(glyph->fBounds.fTop))); - fContext->drawPath(fPaint, &iter, GrContext::kWinding_PathFill, + fContext->drawPath(fPaint, &iter, kWinding_PathFill, &translate); return; } diff --git a/gpu/src/gr_files.mk b/gpu/src/gr_files.mk index e6d69972cb..88aa84b222 100644 --- a/gpu/src/gr_files.mk +++ b/gpu/src/gr_files.mk @@ -21,4 +21,5 @@ SOURCE := \ GrTextureCache.cpp \ GrTextContext.cpp \ GrTextStrike.cpp \ - GrBufferAllocPool.cpp + GrBufferAllocPool.cpp\ + GrPathRenderer.cpp |