aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-05-20 16:49:06 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-05-20 16:49:06 +0000
commit1dd9baa6c8faeb4ce837c39d179ce9c9a09719ef (patch)
tree88e17eed25b5991988421c66f1c69d430ead991f
parent4b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cb (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.cpp21
-rw-r--r--src/gpu/GrAAHairLinePathRenderer.cpp65
-rw-r--r--src/gpu/GrAAHairLinePathRenderer.h4
-rw-r--r--src/gpu/GrDefaultPathRenderer.cpp15
-rw-r--r--src/gpu/GrPathRenderer.cpp12
-rw-r--r--src/gpu/GrPathRenderer.h18
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;