diff options
author | 2013-05-20 16:49:06 +0000 | |
---|---|---|
committer | 2013-05-20 16:49:06 +0000 | |
commit | 1dd9baa6c8faeb4ce837c39d179ce9c9a09719ef (patch) | |
tree | 88e17eed25b5991988421c66f1c69d430ead991f | |
parent | 4b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cb (diff) |
Reland path bounds change with correct bounds for convex and hairline path renderers.
R=robertphillips@google.com
Review URL: https://codereview.chromium.org/15465005
git-svn-id: http://skia.googlecode.com/svn/trunk@9194 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | src/gpu/GrAAConvexPathRenderer.cpp | 21 | ||||
-rw-r--r-- | src/gpu/GrAAHairLinePathRenderer.cpp | 65 | ||||
-rw-r--r-- | src/gpu/GrAAHairLinePathRenderer.h | 4 | ||||
-rw-r--r-- | src/gpu/GrDefaultPathRenderer.cpp | 15 | ||||
-rw-r--r-- | src/gpu/GrPathRenderer.cpp | 12 | ||||
-rw-r--r-- | src/gpu/GrPathRenderer.h | 18 |
6 files changed, 113 insertions, 22 deletions
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index fc6cae68c6..e76f0c805a 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -660,6 +660,24 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, SkSTArray<kPreallocDrawCnt, Draw, true> draws; create_vertices(segments, fanPt, &draws, verts, idxs); + // This is valid because all the computed verts are within 1 pixel of the path control points. + SkRect devBounds; + devBounds = origPath.getBounds(); + adcd.getOriginalMatrix().mapRect(&devBounds); + devBounds.outset(SK_Scalar1, SK_Scalar1); + + // Check devBounds +#if GR_DEBUG + SkRect tolDevBounds = devBounds; + tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000); + SkRect actualBounds; + actualBounds.set(verts[0].fPos, verts[1].fPos); + for (int i = 2; i < vCount; ++i) { + actualBounds.growToInclude(verts[i].fPos.fX, verts[i].fPos.fY); + } + GrAssert(tolDevBounds.contains(actualBounds)); +#endif + int vOffset = 0; for (int i = 0; i < draws.count(); ++i) { const Draw& draw = draws[i]; @@ -667,7 +685,8 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, vOffset, // start vertex 0, // start index draw.fVertexCnt, - draw.fIndexCnt); + draw.fIndexCnt, + &devBounds); vOffset += draw.fVertexCnt; } diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index da54ed643c..8e3ec5b02e 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -360,7 +360,8 @@ void intersect_lines(const SkPoint& ptA, const SkVector& normA, } void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, - const SkMatrix* toSrc, Vertex verts[kVertsPerQuad]) { + const SkMatrix* toSrc, Vertex verts[kVertsPerQuad], + SkRect* devBounds) { GrAssert(!toDevice == !toSrc); // original quad is specified by tri a,b,c SkPoint a = qpts[0]; @@ -427,7 +428,10 @@ void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, c1.fPos = c; c1.fPos -= cbN; + // This point may not be within 1 pixel of a control point. We update the bounding box to + // include it. intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); + devBounds->growToInclude(b0.fPos.fX, b0.fPos.fY); if (toSrc) { toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad); @@ -439,15 +443,16 @@ void add_quads(const SkPoint p[3], int subdiv, const SkMatrix* toDevice, const SkMatrix* toSrc, - Vertex** vert) { + Vertex** vert, + SkRect* devBounds) { GrAssert(subdiv >= 0); if (subdiv) { SkPoint newP[5]; SkChopQuadAtHalf(p, newP); - add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert); - add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert); + add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert, devBounds); + add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert, devBounds); } else { - bloat_quad(p, toDevice, toSrc, *vert); + bloat_quad(p, toDevice, toSrc, *vert, devBounds); *vert += kVertsPerQuad; } } @@ -704,7 +709,8 @@ bool GrAAHairLinePathRenderer::createGeom( GrDrawTarget* target, int* lineCnt, int* quadCnt, - GrDrawTarget::AutoReleaseGeometry* arg) { + GrDrawTarget::AutoReleaseGeometry* arg, + SkRect* devBounds) { GrDrawState* drawState = target->drawState(); int rtHeight = drawState->getRenderTarget()->height(); @@ -714,6 +720,13 @@ bool GrAAHairLinePathRenderer::createGeom( SkMatrix viewM = drawState->getViewMatrix(); + // All the vertices that we compute are within 1 of path control points with the exception of + // one of the bounding vertices for each quad. The add_quads() function will update the bounds + // for each quad added. + *devBounds = path.getBounds(); + viewM.mapRect(devBounds); + devBounds->outset(SK_Scalar1, SK_Scalar1); + PREALLOC_PTARRAY(128) lines; PREALLOC_PTARRAY(128) quads; IntArray qSubdivs; @@ -750,7 +763,7 @@ bool GrAAHairLinePathRenderer::createGeom( int unsubdivQuadCnt = quads.count() / 3; for (int i = 0; i < unsubdivQuadCnt; ++i) { GrAssert(qSubdivs[i] >= 0); - add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts); + add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds); } return true; @@ -781,11 +794,14 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, int lineCnt; int quadCnt; GrDrawTarget::AutoReleaseGeometry arg; + SkRect devBounds; + if (!this->createGeom(path, target, &lineCnt, &quadCnt, - &arg)) { + &arg, + &devBounds)) { return false; } @@ -816,6 +832,33 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create(); GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create(); + // Check devBounds +#if GR_DEBUG + SkRect tolDevBounds = devBounds; + tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000); + SkRect actualBounds; + Vertex* verts = reinterpret_cast<Vertex*>(arg.vertices()); + int vCount = kVertsPerLineSeg * lineCnt + kVertsPerQuad * quadCnt; + bool first = true; + for (int i = 0; i < vCount; ++i) { + SkPoint pos = verts[i].fPos; + // This is a hack to workaround the fact that we move some degenerate segments offscreen. + if (SK_ScalarMax == pos.fX) { + continue; + } + drawState->getViewMatrix().mapPoints(&pos, 1); + if (first) { + actualBounds.set(pos.fX, pos.fY, pos.fX, pos.fY); + first = false; + } else { + actualBounds.growToInclude(pos.fX, pos.fY); + } + } + if (!first) { + GrAssert(tolDevBounds.contains(actualBounds)); + } +#endif + target->setIndexSourceToBuffer(fLinesIndexBuffer); int lines = 0; int nBufLines = fLinesIndexBuffer->maxQuads(); @@ -826,7 +869,8 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, kVertsPerLineSeg*lines, // startV 0, // startI kVertsPerLineSeg*n, // vCount - kIdxsPerLineSeg*n); // iCount + kIdxsPerLineSeg*n, + &devBounds); // iCount lines += n; } @@ -839,7 +883,8 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, 4 * lineCnt + kVertsPerQuad*quads, // startV 0, // startI kVertsPerQuad*n, // vCount - kIdxsPerQuad*n); // iCount + kIdxsPerQuad*n, // iCount + &devBounds); quads += n; } target->resetIndexSource(); diff --git a/src/gpu/GrAAHairLinePathRenderer.h b/src/gpu/GrAAHairLinePathRenderer.h index 7d1a6db5d2..5a64905fc2 100644 --- a/src/gpu/GrAAHairLinePathRenderer.h +++ b/src/gpu/GrAAHairLinePathRenderer.h @@ -29,7 +29,6 @@ protected: bool antiAlias) SK_OVERRIDE; private: - GrAAHairLinePathRenderer(const GrContext* context, const GrIndexBuffer* fLinesIndexBuffer, const GrIndexBuffer* fQuadsIndexBuffer); @@ -38,7 +37,8 @@ private: GrDrawTarget* target, int* lineCnt, int* quadCnt, - GrDrawTarget::AutoReleaseGeometry* arg); + GrDrawTarget::AutoReleaseGeometry* arg, + SkRect* devBounds ); const GrIndexBuffer* fLinesIndexBuffer; const GrIndexBuffer* fQuadsIndexBuffer; diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp index 43809ed6a3..87deb9c406 100644 --- a/src/gpu/GrDefaultPathRenderer.cpp +++ b/src/gpu/GrDefaultPathRenderer.cpp @@ -445,7 +445,9 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, } } - { + SkRect devBounds; + GetPathDevBounds(path, drawState->getRenderTarget(), viewM, &devBounds); + for (int p = 0; p < passCount; ++p) { drawState->setDrawFace(drawFace[p]); if (NULL != passes[p]) { @@ -460,10 +462,8 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, GrDrawState::AutoDeviceCoordDraw adcd; if (reverse) { GrAssert(NULL != drawState->getRenderTarget()); - // draw over the whole world. - bounds.setLTRB(0, 0, - SkIntToScalar(drawState->getRenderTarget()->width()), - SkIntToScalar(drawState->getRenderTarget()->height())); + // draw over the dev bounds (which will be the whole dst surface for inv fill). + bounds = devBounds; SkMatrix vmi; // mapRect through persp matrix may not be correct if (!drawState->getViewMatrix().hasPerspective() && @@ -483,13 +483,12 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, } if (indexCnt) { target->drawIndexed(primType, 0, 0, - vertexCnt, indexCnt); + vertexCnt, indexCnt, &devBounds); } else { - target->drawNonIndexed(primType, 0, vertexCnt); + target->drawNonIndexed(primType, 0, vertexCnt, &devBounds); } } } - } return true; } diff --git a/src/gpu/GrPathRenderer.cpp b/src/gpu/GrPathRenderer.cpp index e0d2682bcd..e88db22b30 100644 --- a/src/gpu/GrPathRenderer.cpp +++ b/src/gpu/GrPathRenderer.cpp @@ -12,3 +12,15 @@ SK_DEFINE_INST_COUNT(GrPathRenderer) GrPathRenderer::GrPathRenderer() { } + +void GrPathRenderer::GetPathDevBounds(const SkPath& path, + int devW, int devH, + const SkMatrix& matrix, + SkRect* bounds) { + if (path.isInverseFillType()) { + *bounds = SkRect::MakeWH(SkIntToScalar(devW), SkIntToScalar(devH)); + return; + } + *bounds = path.getBounds(); + matrix.mapRect(bounds); +} diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h index ebd464ffb3..3d4c993c52 100644 --- a/src/gpu/GrPathRenderer.h +++ b/src/gpu/GrPathRenderer.h @@ -1,4 +1,4 @@ - + /* * Copyright 2011 Google Inc. * @@ -173,6 +173,22 @@ protected: this->drawPath(path, stroke, target, false); } + // Helper for getting the device bounds of a path. Inverse filled paths will have bounds set + // by devSize. Non-inverse path bounds will not necessarily be clipped to devSize. + static void GetPathDevBounds(const SkPath& path, + int devW, + int devH, + const SkMatrix& matrix, + SkRect* bounds); + + // Helper version that gets the dev width and height from a GrSurface. + static void GetPathDevBounds(const SkPath& path, + const GrSurface* device, + const SkMatrix& matrix, + SkRect* bounds) { + GetPathDevBounds(path, device->width(), device->height(), matrix, bounds); + } + private: typedef GrRefCnt INHERITED; |