aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkClipStack.h10
-rw-r--r--include/gpu/GrClip.h2
-rw-r--r--src/core/SkClipStack.cpp22
-rw-r--r--src/gpu/GrAAHairLinePathRenderer.cpp17
-rw-r--r--src/gpu/GrClip.cpp6
-rw-r--r--src/gpu/GrClipMaskManager.cpp169
-rw-r--r--src/gpu/GrClipMaskManager.h8
-rw-r--r--src/gpu/GrSoftwarePathRenderer.cpp59
-rw-r--r--src/gpu/GrTextContext.cpp17
-rw-r--r--src/gpu/SkGpuDevice.cpp29
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp11
-rw-r--r--tests/ClipCacheTest.cpp18
-rw-r--r--tests/ClipStackTest.cpp6
13 files changed, 202 insertions, 172 deletions
diff --git a/include/core/SkClipStack.h b/include/core/SkClipStack.h
index 60ed9edf3b..c0fadb1ab1 100644
--- a/include/core/SkClipStack.h
+++ b/include/core/SkClipStack.h
@@ -51,13 +51,13 @@ public:
/**
* getBounds places the current finite bound in its first parameter. In its
* second, it indicates which kind of bound is being returned. If
- * 'finiteBound' is a normal bounding box then it encloses all writeable
- * pixels. If 'finiteBound' is an inside out bounding box then it
+ * 'canvFiniteBound' is a normal bounding box then it encloses all writeable
+ * pixels. If 'canvFiniteBound' is an inside out bounding box then it
* encloses all the un-writeable pixels and the true/normal bound is the
* infinite plane. isIntersectionOfRects is an optional parameter
- * that is true if 'finiteBound' resulted from an intersection of rects.
+ * that is true if 'canvFiniteBound' resulted from an intersection of rects.
*/
- void getBounds(SkRect* finiteBound,
+ void getBounds(SkRect* canvFiniteBound,
BoundsType* boundType,
bool* isIntersectionOfRects = NULL) const;
@@ -188,7 +188,7 @@ public:
int offsetY,
int maxWidth,
int maxHeight,
- SkRect* bounds,
+ SkRect* devBounds,
bool* isIntersectionOfRects = NULL) const;
private:
diff --git a/include/gpu/GrClip.h b/include/gpu/GrClip.h
index bb07c28de1..cf646a1282 100644
--- a/include/gpu/GrClip.h
+++ b/include/gpu/GrClip.h
@@ -237,7 +237,7 @@ public:
}
void getConservativeBounds(const GrSurface* surface,
- GrIRect* result,
+ GrIRect* devResult,
bool* isIntersectionOfRects = NULL) const;
};
diff --git a/src/core/SkClipStack.cpp b/src/core/SkClipStack.cpp
index 673981b3c6..d2c2035bef 100644
--- a/src/core/SkClipStack.cpp
+++ b/src/core/SkClipStack.cpp
@@ -449,16 +449,16 @@ void SkClipStack::restore() {
}
}
-void SkClipStack::getBounds(SkRect* finiteBound,
+void SkClipStack::getBounds(SkRect* canvFiniteBound,
BoundsType* boundType,
bool* isIntersectionOfRects) const {
- SkASSERT(NULL != finiteBound && NULL != boundType);
+ SkASSERT(NULL != canvFiniteBound && NULL != boundType);
Rec* rec = (Rec*)fDeque.back();
if (NULL == rec) {
// the clip is wide open - the infinite plane w/ no pixels un-writeable
- finiteBound->setEmpty();
+ canvFiniteBound->setEmpty();
*boundType = kInsideOut_BoundsType;
if (NULL != isIntersectionOfRects) {
*isIntersectionOfRects = false;
@@ -466,7 +466,7 @@ void SkClipStack::getBounds(SkRect* finiteBound,
return;
}
- *finiteBound = rec->fFiniteBound;
+ *canvFiniteBound = rec->fFiniteBound;
*boundType = rec->fFiniteBoundType;
if (NULL != isIntersectionOfRects) {
*isIntersectionOfRects = rec->fIsIntersectionOfRects;
@@ -673,24 +673,26 @@ void SkClipStack::getConservativeBounds(int offsetX,
int offsetY,
int maxWidth,
int maxHeight,
- SkRect* bounds,
+ SkRect* devBounds,
bool* isIntersectionOfRects) const {
- SkASSERT(NULL != bounds);
+ SkASSERT(NULL != devBounds);
- bounds->setLTRB(0, 0,
- SkIntToScalar(maxWidth), SkIntToScalar(maxHeight));
+ devBounds->setLTRB(0, 0,
+ SkIntToScalar(maxWidth), SkIntToScalar(maxHeight));
SkRect temp;
SkClipStack::BoundsType boundType;
+ // temp starts off in canvas space here
this->getBounds(&temp, &boundType, isIntersectionOfRects);
if (SkClipStack::kInsideOut_BoundsType == boundType) {
return;
}
+ // but is converted to device space here
temp.offset(SkIntToScalar(offsetX), SkIntToScalar(offsetY));
- if (!bounds->intersect(temp)) {
- bounds->setEmpty();
+ if (!devBounds->intersect(temp)) {
+ devBounds->setEmpty();
}
}
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index 13d61554bd..43e87d61e6 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -198,7 +198,7 @@ int num_quad_subdivs(const SkPoint p[3]) {
int generate_lines_and_quads(const SkPath& path,
const SkMatrix& m,
const SkVector& translate,
- GrIRect clip,
+ const GrIRect& devClipBounds,
PtArray* lines,
PtArray* quads,
IntArray* quadSubdivCnts) {
@@ -223,7 +223,7 @@ int generate_lines_and_quads(const SkPath& path,
bounds.setBounds(devPts, 2);
bounds.outset(SK_Scalar1, SK_Scalar1);
bounds.roundOut(&ibounds);
- if (SkIRect::Intersects(clip, ibounds)) {
+ if (SkIRect::Intersects(devClipBounds, ibounds)) {
SkPoint* pts = lines->push_back_n(2);
pts[0] = devPts[0];
pts[1] = devPts[1];
@@ -235,7 +235,7 @@ int generate_lines_and_quads(const SkPath& path,
bounds.setBounds(devPts, 3);
bounds.outset(SK_Scalar1, SK_Scalar1);
bounds.roundOut(&ibounds);
- if (SkIRect::Intersects(clip, ibounds)) {
+ if (SkIRect::Intersects(devClipBounds, ibounds)) {
int subdiv = num_quad_subdivs(devPts);
GrAssert(subdiv >= -1);
if (-1 == subdiv) {
@@ -262,7 +262,7 @@ int generate_lines_and_quads(const SkPath& path,
bounds.setBounds(devPts, 4);
bounds.outset(SK_Scalar1, SK_Scalar1);
bounds.roundOut(&ibounds);
- if (SkIRect::Intersects(clip, ibounds)) {
+ if (SkIRect::Intersects(devClipBounds, ibounds)) {
PREALLOC_PTARRAY(32) q;
// we don't need a direction if we aren't constraining the subdivision
static const SkPath::Direction kDummyDir = SkPath::kCCW_Direction;
@@ -290,7 +290,7 @@ int generate_lines_and_quads(const SkPath& path,
}
bounds.outset(SK_Scalar1, SK_Scalar1);
bounds.roundOut(&ibounds);
- if (SkIRect::Intersects(clip, ibounds)) {
+ if (SkIRect::Intersects(devClipBounds, ibounds)) {
int subdiv = num_quad_subdivs(qInDevSpace);
GrAssert(subdiv >= -1);
if (-1 == subdiv) {
@@ -511,8 +511,9 @@ bool GrAAHairLinePathRenderer::createGeom(
const GrDrawState& drawState = target->getDrawState();
int rtHeight = drawState.getRenderTarget()->height();
- GrIRect clip;
- target->getClip()->getConservativeBounds(drawState.getRenderTarget(), &clip);
+ GrIRect devClipBounds;
+ target->getClip()->getConservativeBounds(drawState.getRenderTarget(),
+ &devClipBounds);
GrVertexLayout layout = GrDrawTarget::kEdge_VertexLayoutBit;
GrMatrix viewM = drawState.getViewMatrix();
@@ -524,7 +525,7 @@ bool GrAAHairLinePathRenderer::createGeom(
if (NULL == translate) {
translate = &gZeroVec;
}
- *quadCnt = generate_lines_and_quads(path, viewM, *translate, clip,
+ *quadCnt = generate_lines_and_quads(path, viewM, *translate, devClipBounds,
&lines, &quads, &qSubdivs);
*lineCnt = lines.count() / 2;
diff --git a/src/gpu/GrClip.cpp b/src/gpu/GrClip.cpp
index a3905baefb..e8ea9a6399 100644
--- a/src/gpu/GrClip.cpp
+++ b/src/gpu/GrClip.cpp
@@ -252,7 +252,7 @@ void GrClip::Iter::reset(const GrClip& stack, IterStart startLoc) {
* isIntersectionOfRects will be set to true.
*/
void GrClipData::getConservativeBounds(const GrSurface* surface,
- GrIRect* result,
+ GrIRect* devResult,
bool* isIntersectionOfRects) const {
// Until we switch to using the SkClipStack directly we need to take
@@ -264,8 +264,10 @@ void GrClipData::getConservativeBounds(const GrSurface* surface,
SkIntToScalar(surface->width()),
SkIntToScalar(surface->height()));
+ // convervativeBounds starts off in canvas coordinates here
GrRect conservativeBounds = fClipStack->getConservativeBounds();
+ // but is translated into device coordinates here
conservativeBounds.offset(SkIntToScalar(-fOrigin.fX),
SkIntToScalar(-fOrigin.fY));
@@ -273,7 +275,7 @@ void GrClipData::getConservativeBounds(const GrSurface* surface,
conservativeBounds.setEmpty();
}
- conservativeBounds.roundOut(result);
+ conservativeBounds.roundOut(devResult);
if (NULL != isIntersectionOfRects) {
*isIntersectionOfRects = fClipStack->isRect();
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 97c102f66b..71743a03e9 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -38,7 +38,7 @@ namespace {
// sampler matrix this also alters the vertex layout
void setup_drawstate_aaclip(GrGpu* gpu,
GrTexture* result,
- const GrIRect &bound) {
+ const GrIRect &devBound) {
GrDrawState* drawState = gpu->drawState();
GrAssert(drawState);
@@ -46,7 +46,8 @@ void setup_drawstate_aaclip(GrGpu* gpu,
GrMatrix mat;
mat.setIDiv(result->width(), result->height());
- mat.preTranslate(SkIntToScalar(-bound.fLeft), SkIntToScalar(-bound.fTop));
+ mat.preTranslate(SkIntToScalar(-devBound.fLeft),
+ SkIntToScalar(-devBound.fTop));
mat.preConcat(drawState->getViewMatrix());
drawState->sampler(maskStage)->reset(mat);
@@ -158,11 +159,12 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn) {
// GrDrawTarget should have filtered this for us
GrAssert(NULL != rt);
- GrIRect bounds;
+ GrIRect devClipBounds;
bool isIntersectionOfRects = false;
- clipDataIn->getConservativeBounds(rt, &bounds, &isIntersectionOfRects);
- if (bounds.isEmpty()) {
+ clipDataIn->getConservativeBounds(rt, &devClipBounds,
+ &isIntersectionOfRects);
+ if (devClipBounds.isEmpty()) {
return false;
}
@@ -180,9 +182,9 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn) {
// The clip geometry is complex enough that it will be more
// efficient to create it entirely in software
GrTexture* result = NULL;
- GrIRect bound;
- if (this->createSoftwareClipMask(*clipDataIn, &result, &bound)) {
- setup_drawstate_aaclip(fGpu, result, bound);
+ GrIRect devBound;
+ if (this->createSoftwareClipMask(*clipDataIn, &result, &devBound)) {
+ setup_drawstate_aaclip(fGpu, result, devBound);
fGpu->disableScissor();
this->setGpuStencil();
return true;
@@ -202,9 +204,9 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn) {
// render target) we aren't going to use scissoring like the stencil
// path does (see scissorSettings below)
GrTexture* result = NULL;
- GrIRect bound;
- if (this->createAlphaClipMask(*clipDataIn, &result, &bound)) {
- setup_drawstate_aaclip(fGpu, result, bound);
+ GrIRect devBound;
+ if (this->createAlphaClipMask(*clipDataIn, &result, &devBound)) {
+ setup_drawstate_aaclip(fGpu, result, devBound);
fGpu->disableScissor();
this->setGpuStencil();
return true;
@@ -227,22 +229,23 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn) {
// If the clip is a rectangle then just set the scissor. Otherwise, create
// a stencil mask.
if (isIntersectionOfRects) {
- fGpu->enableScissor(bounds);
+ fGpu->enableScissor(devClipBounds);
this->setGpuStencil();
return true;
}
// use the stencil clip if we can't represent the clip as a rectangle.
- bool useStencil = !clipDataIn->fClipStack->isWideOpen() && !bounds.isEmpty();
+ bool useStencil = !clipDataIn->fClipStack->isWideOpen() &&
+ !devClipBounds.isEmpty();
if (useStencil) {
- this->createStencilClipMask(*clipDataIn, bounds);
+ this->createStencilClipMask(*clipDataIn, devClipBounds);
}
// This must occur after createStencilClipMask. That function may change
// the scissor. Also, it only guarantees that the stencil mask is correct
// within the bounds it was passed, so we must use both stencil and scissor
// test to the bounds for the final draw.
- fGpu->enableScissor(bounds);
+ fGpu->enableScissor(devClipBounds);
this->setGpuStencil();
return true;
}
@@ -259,19 +262,19 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn) {
namespace {
/**
- * Does "container" contain "containee"? If either is empty then
- * no containment is possible. "container" is in canvas coordinates while
- * "containee" is in device coordiates. "origin" provides the mapping between
+ * Does "canvContainer" contain "devContainee"? If either is empty then
+ * no containment is possible. "canvContainer" is in canvas coordinates while
+ * "devContainee" is in device coordiates. "origin" provides the mapping between
* the two.
*/
-bool contains(const SkRect& container,
- const SkIRect& containee,
+bool contains(const SkRect& canvContainer,
+ const SkIRect& devContainee,
const SkIPoint& origin) {
- return !containee.isEmpty() && !container.isEmpty() &&
- container.fLeft <= SkIntToScalar(containee.fLeft+origin.fX) &&
- container.fTop <= SkIntToScalar(containee.fTop+origin.fY) &&
- container.fRight >= SkIntToScalar(containee.fRight+origin.fX) &&
- container.fBottom >= SkIntToScalar(containee.fBottom+origin.fY);
+ return !devContainee.isEmpty() && !canvContainer.isEmpty() &&
+ canvContainer.fLeft <= SkIntToScalar(devContainee.fLeft+origin.fX) &&
+ canvContainer.fTop <= SkIntToScalar(devContainee.fTop+origin.fY) &&
+ canvContainer.fRight >= SkIntToScalar(devContainee.fRight+origin.fX) &&
+ canvContainer.fBottom >= SkIntToScalar(devContainee.fBottom+origin.fY);
}
////////////////////////////////////////////////////////////////////////////////
@@ -280,7 +283,7 @@ bool contains(const SkRect& container,
// and what op should be used to draw the first element that isn't skipped.
const GrClip::Iter::Clip* process_initial_clip_elements(
GrClip::Iter* iter,
- const GrIRect& bounds,
+ const GrIRect& devBounds,
bool* clearToInside,
SkRegion::Op* firstOp,
const GrClipData& clipData) {
@@ -311,7 +314,7 @@ const GrClip::Iter::Clip* process_initial_clip_elements(
// if this element contains the entire bounds then we
// can skip it.
if (NULL != clip->fRect &&
- contains(*clip->fRect, bounds, clipData.fOrigin)) {
+ contains(*clip->fRect, devBounds, clipData.fOrigin)) {
break;
}
// if everything is initially clearToInside then intersect is
@@ -452,6 +455,16 @@ bool draw_path(GrContext* context,
return true;
}
+// 'rect' enters in device coordinates and leaves in canvas coordinates
+void device_to_canvas(SkRect* rect, const SkIPoint& origin) {
+ GrAssert(NULL != rect);
+
+ rect->fLeft += SkIntToScalar(origin.fX);
+ rect->fTop += SkIntToScalar(origin.fY);
+ rect->fRight += SkIntToScalar(origin.fX);
+ rect->fBottom += SkIntToScalar(origin.fY);
+}
+
}
////////////////////////////////////////////////////////////////////////////////
@@ -544,7 +557,7 @@ void GrClipMaskManager::setupCache(const GrClip& clipIn,
// Returns true if there is no more work to be done (i.e., we got a cache hit)
bool GrClipMaskManager::clipMaskPreamble(const GrClipData& clipDataIn,
GrTexture** result,
- GrIRect* resultBounds) {
+ GrIRect* devResultBounds) {
GrDrawState* origDrawState = fGpu->drawState();
GrAssert(origDrawState->isClipState());
@@ -554,26 +567,26 @@ bool GrClipMaskManager::clipMaskPreamble(const GrClipData& clipDataIn,
// unlike the stencil path the alpha path is not bound to the size of the
// render target - determine the minimum size required for the mask
// Note: intBounds is in device (as opposed to canvas) coordinates
- GrIRect intBounds;
- clipDataIn.getConservativeBounds(rt, &intBounds);
+ GrIRect devClipBounds;
+ clipDataIn.getConservativeBounds(rt, &devClipBounds);
// need to outset a pixel since the standard bounding box computation
// path doesn't leave any room for antialiasing (esp. w.r.t. rects)
- intBounds.outset(1, 1);
+ devClipBounds.outset(1, 1);
// TODO: make sure we don't outset if bounds are still 0,0 @ min
if (fAACache.canReuse(*clipDataIn.fClipStack,
- intBounds.width(),
- intBounds.height())) {
+ devClipBounds.width(),
+ devClipBounds.height())) {
*result = fAACache.getLastMask();
- fAACache.getLastBound(resultBounds);
+ fAACache.getLastBound(devResultBounds);
return true;
}
- this->setupCache(*clipDataIn.fClipStack, intBounds);
+ this->setupCache(*clipDataIn.fClipStack, devClipBounds);
- *resultBounds = intBounds;
+ *devResultBounds = devClipBounds;
return false;
}
@@ -581,11 +594,11 @@ bool GrClipMaskManager::clipMaskPreamble(const GrClipData& clipDataIn,
// Create a 8-bit clip mask in alpha
bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
GrTexture** result,
- GrIRect *resultBounds) {
- GrAssert(NULL != resultBounds);
+ GrIRect *devResultBounds) {
+ GrAssert(NULL != devResultBounds);
GrAssert(kNone_ClipMaskType == fCurrClipMaskType);
- if (this->clipMaskPreamble(clipDataIn, result, resultBounds)) {
+ if (this->clipMaskPreamble(clipDataIn, result, devResultBounds)) {
fCurrClipMaskType = kAlpha_ClipMaskType;
return true;
}
@@ -603,13 +616,13 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
GrDrawTarget::AutoGeometryPush agp(fGpu);
- if (0 != resultBounds->fTop || 0 != resultBounds->fLeft ||
+ if (0 != devResultBounds->fTop || 0 != devResultBounds->fLeft ||
0 != clipDataIn.fOrigin.fX || 0 != clipDataIn.fOrigin.fY) {
// if we were able to trim down the size of the mask we need to
// offset the paths & rects that will be used to compute it
drawState->viewMatrix()->setTranslate(
- SkIntToScalar(-resultBounds->fLeft-clipDataIn.fOrigin.fX),
- SkIntToScalar(-resultBounds->fTop-clipDataIn.fOrigin.fY));
+ SkIntToScalar(-devResultBounds->fLeft-clipDataIn.fOrigin.fX),
+ SkIntToScalar(-devResultBounds->fTop-clipDataIn.fOrigin.fY));
}
bool clearToInside;
@@ -618,7 +631,7 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
GrClip::Iter iter(*clipDataIn.fClipStack,
GrClip::Iter::kBottom_IterStart);
const GrClip::Iter::Clip* clip = process_initial_clip_elements(&iter,
- *resultBounds,
+ *devResultBounds,
&clearToInside,
&firstOp,
clipDataIn);
@@ -647,17 +660,17 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
fGpu->clear(NULL, 0x00000000, accum->asRenderTarget());
setup_boolean_blendcoeffs(drawState, op);
- this->drawClipShape(accum, clip, *resultBounds);
+ this->drawClipShape(accum, clip, *devResultBounds);
} else if (SkRegion::kReverseDifference_Op == op ||
SkRegion::kIntersect_Op == op) {
// there is no point in intersecting a screen filling rectangle.
if (SkRegion::kIntersect_Op == op && NULL != clip->fRect &&
- contains(*clip->fRect, *resultBounds, clipDataIn.fOrigin)) {
+ contains(*clip->fRect, *devResultBounds, clipDataIn.fOrigin)) {
continue;
}
- getTemp(*resultBounds, &temp);
+ getTemp(*devResultBounds, &temp);
if (NULL == temp.texture()) {
fAACache.reset();
return false;
@@ -667,12 +680,12 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
fGpu->clear(NULL, 0x00000000, temp.texture()->asRenderTarget());
setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op);
- this->drawClipShape(temp.texture(), clip, *resultBounds);
+ this->drawClipShape(temp.texture(), clip, *devResultBounds);
// TODO: rather than adding these two translations here
// compute the bounding box needed to render the texture
// into temp
- if (0 != resultBounds->fTop || 0 != resultBounds->fLeft ||
+ if (0 != devResultBounds->fTop || 0 != devResultBounds->fLeft ||
0 != clipDataIn.fOrigin.fX || 0 != clipDataIn.fOrigin.fY) {
// In order for the merge of the temp clip into the accumulator
// to work we need to disable the translation
@@ -684,18 +697,18 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
setup_boolean_blendcoeffs(drawState, op);
this->drawTexture(accum, temp.texture());
- if (0 != resultBounds->fTop || 0 != resultBounds->fLeft ||
+ if (0 != devResultBounds->fTop || 0 != devResultBounds->fLeft ||
0 != clipDataIn.fOrigin.fX || 0 != clipDataIn.fOrigin.fY) {
drawState->viewMatrix()->setTranslate(
- SkIntToScalar(-resultBounds->fLeft-clipDataIn.fOrigin.fX),
- SkIntToScalar(-resultBounds->fTop-clipDataIn.fOrigin.fY));
+ SkIntToScalar(-devResultBounds->fLeft-clipDataIn.fOrigin.fX),
+ SkIntToScalar(-devResultBounds->fTop-clipDataIn.fOrigin.fY));
}
} else {
// all the remaining ops can just be directly draw into
// the accumulation buffer
setup_boolean_blendcoeffs(drawState, op);
- this->drawClipShape(accum, clip, *resultBounds);
+ this->drawClipShape(accum, clip, *devResultBounds);
}
}
@@ -705,10 +718,10 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
}
////////////////////////////////////////////////////////////////////////////////
-// Create a 1-bit clip mask in the stencil buffer. 'bounds' are in device
+// Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device
// (as opposed to canvas) coordinates
bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
- const GrIRect& bounds) {
+ const GrIRect& devClipBounds) {
GrAssert(kNone_ClipMaskType == fCurrClipMaskType);
@@ -734,7 +747,9 @@ bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
// we finish drawing it into the stencil.
const GrClipData* oldClipData = fGpu->getClip();
- GrClip newClipStack(bounds);
+ // The origin of 'newClipData' is (0, 0) so it is okay to place
+ // a device-coordinate bound in 'newClipStack'
+ GrClip newClipStack(devClipBounds);
GrClipData newClipData;
newClipData.fClipStack = &newClipStack;
@@ -748,12 +763,9 @@ bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
if (0 != clipDataIn.fOrigin.fX || 0 != clipDataIn.fOrigin.fY) {
// Add the saveLayer's offset to the view matrix rather than
// offset each individual draw
- GrMatrix m;
-
- m.setTranslate(SkIntToScalar(-clipDataIn.fOrigin.fX),
+ drawState->viewMatrix()->setTranslate(
+ SkIntToScalar(-clipDataIn.fOrigin.fX),
SkIntToScalar(-clipDataIn.fOrigin.fY));
-
- drawState->setViewMatrix(m);
}
#if !VISUALIZE_COMPLEX_CLIP
@@ -765,7 +777,7 @@ bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
"Ganesh only handles 16b or smaller stencil buffers");
clipBit = (1 << (clipBit-1));
- GrIRect rtRect = GrIRect::MakeWH(rt->width(), rt->height());
+ GrIRect devRTRect = GrIRect::MakeWH(rt->width(), rt->height());
bool clearToInside;
SkRegion::Op firstOp = SkRegion::kReplace_Op; // suppress warning
@@ -773,12 +785,12 @@ bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
GrClip::Iter iter(*oldClipData->fClipStack,
GrClip::Iter::kBottom_IterStart);
const GrClip::Iter::Clip* clip = process_initial_clip_elements(&iter,
- rtRect,
+ devRTRect,
&clearToInside,
&firstOp,
clipDataIn);
- fGpu->clearStencilClip(bounds, clearToInside);
+ fGpu->clearStencilClip(devClipBounds, clearToInside);
bool first = true;
// walk through each clip element and perform its set op
@@ -818,7 +830,7 @@ bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
// there is no point in intersecting a screen filling
// rectangle.
if (SkRegion::kIntersect_Op == op &&
- contains(*clip->fRect, rtRect, oldClipData->fOrigin)) {
+ contains(*clip->fRect, devRTRect, oldClipData->fOrigin)) {
continue;
}
} else if (NULL != clip->fPath) {
@@ -889,16 +901,14 @@ bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
}
} else {
SET_RANDOM_COLOR
- // 'bounds' is already in device coordinates so the
+ // 'devClipBounds' is already in device coordinates so the
// translation in the view matrix is inappropriate.
- // Apply the inverse translation so the drawn rect will
+ // Convert it to canvas space so the drawn rect will
// be in the correct location
- GrRect rect = GrRect::MakeLTRB(
- SkIntToScalar(bounds.fLeft+clipDataIn.fOrigin.fX),
- SkIntToScalar(bounds.fTop+clipDataIn.fOrigin.fY),
- SkIntToScalar(bounds.fRight+clipDataIn.fOrigin.fX),
- SkIntToScalar(bounds.fBottom+clipDataIn.fOrigin.fY));
- fGpu->drawSimpleRect(rect, NULL);
+ GrRect canvClipBounds;
+ canvClipBounds.set(devClipBounds);
+ device_to_canvas(&canvClipBounds, clipDataIn.fOrigin);
+ fGpu->drawSimpleRect(canvClipBounds, NULL);
}
}
}
@@ -1122,10 +1132,10 @@ GrPathFill invert_fill(GrPathFill fill) {
bool GrClipMaskManager::createSoftwareClipMask(const GrClipData& clipDataIn,
GrTexture** result,
- GrIRect* resultBounds) {
+ GrIRect* devResultBounds) {
GrAssert(kNone_ClipMaskType == fCurrClipMaskType);
- if (this->clipMaskPreamble(clipDataIn, result, resultBounds)) {
+ if (this->clipMaskPreamble(clipDataIn, result, devResultBounds)) {
return true;
}
@@ -1140,7 +1150,7 @@ bool GrClipMaskManager::createSoftwareClipMask(const GrClipData& clipDataIn,
GrMatrix matrix;
matrix.setTranslate(SkIntToScalar(-clipDataIn.fOrigin.fX),
SkIntToScalar(-clipDataIn.fOrigin.fY));
- helper.init(*resultBounds, &matrix);
+ helper.init(*devResultBounds, &matrix);
bool clearToInside;
SkRegion::Op firstOp = SkRegion::kReplace_Op; // suppress warning
@@ -1148,7 +1158,7 @@ bool GrClipMaskManager::createSoftwareClipMask(const GrClipData& clipDataIn,
GrClip::Iter iter(*clipDataIn.fClipStack,
GrClip::Iter::kBottom_IterStart);
const GrClip::Iter::Clip* clip = process_initial_clip_elements(&iter,
- *resultBounds,
+ *devResultBounds,
&clearToInside,
&firstOp,
clipDataIn);
@@ -1173,11 +1183,8 @@ bool GrClipMaskManager::createSoftwareClipMask(const GrClipData& clipDataIn,
// difference we invert all the pixels before clearing the ones
// outside the geometry.
if (SkRegion::kReverseDifference_Op == op) {
- SkRect temp = SkRect::MakeLTRB(
- SkIntToScalar(resultBounds->left()),
- SkIntToScalar(resultBounds->top()),
- SkIntToScalar(resultBounds->right()),
- SkIntToScalar(resultBounds->bottom()));
+ SkRect temp;
+ temp.set(*devResultBounds);
// invert the entire scene
helper.draw(temp, SkRegion::kXOR_Op, false, 0xFF);
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index 81be5ed919..3ba26d3818 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -328,16 +328,16 @@ private:
GrClipMaskCache fAACache; // cache for the AA path
bool createStencilClipMask(const GrClipData& clipDataIn,
- const GrIRect& bounds);
+ const GrIRect& devClipBounds);
bool createAlphaClipMask(const GrClipData& clipDataIn,
GrTexture** result,
- GrIRect *resultBounds);
+ GrIRect *devResultBounds);
bool createSoftwareClipMask(const GrClipData& clipDataIn,
GrTexture** result,
- GrIRect *resultBounds);
+ GrIRect *devResultBounds);
bool clipMaskPreamble(const GrClipData& clipDataIn,
GrTexture** result,
- GrIRect *resultBounds);
+ GrIRect *devResultBounds);
bool useSWOnlyPath(const GrClip& clipIn);
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 5b570b4b74..16b859fef1 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -37,17 +37,20 @@ namespace {
bool get_path_and_clip_bounds(const GrDrawTarget* target,
const SkPath& path,
const GrMatrix& matrix,
- GrIRect* pathBounds,
- GrIRect* clipBounds) {
+ GrIRect* devPathBounds,
+ GrIRect* devClipBounds) {
// compute bounds as intersection of rt size, clip, and path
const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
if (NULL == rt) {
return false;
}
- *pathBounds = GrIRect::MakeWH(rt->width(), rt->height());
+ *devPathBounds = GrIRect::MakeWH(rt->width(), rt->height());
- target->getClip()->getConservativeBounds(rt, clipBounds);
- if (!pathBounds->intersect(*clipBounds)) {
+ target->getClip()->getConservativeBounds(rt, devClipBounds);
+
+ // TODO: getConservativeBounds already intersects with the
+ // render target's bounding box. Remove this next line
+ if (!devPathBounds->intersect(*devClipBounds)) {
return false;
}
@@ -56,13 +59,13 @@ bool get_path_and_clip_bounds(const GrDrawTarget* target,
matrix.mapRect(&pathSBounds, path.getBounds());
GrIRect pathIBounds;
pathSBounds.roundOut(&pathIBounds);
- if (!pathBounds->intersect(pathIBounds)) {
+ if (!devPathBounds->intersect(pathIBounds)) {
// set the correct path bounds, as this would be used later.
- *pathBounds = pathIBounds;
+ *devPathBounds = pathIBounds;
return false;
}
} else {
- *pathBounds = GrIRect::EmptyIRect();
+ *devPathBounds = GrIRect::EmptyIRect();
return false;
}
return true;
@@ -70,31 +73,31 @@ bool get_path_and_clip_bounds(const GrDrawTarget* target,
////////////////////////////////////////////////////////////////////////////////
void draw_around_inv_path(GrDrawTarget* target,
- const GrIRect& clipBounds,
- const GrIRect& pathBounds) {
+ const GrIRect& devClipBounds,
+ const GrIRect& devPathBounds) {
GrDrawTarget::AutoDeviceCoordDraw adcd(target);
if (!adcd.succeeded()) {
return;
}
GrRect rect;
- if (clipBounds.fTop < pathBounds.fTop) {
- rect.iset(clipBounds.fLeft, clipBounds.fTop,
- clipBounds.fRight, pathBounds.fTop);
+ if (devClipBounds.fTop < devPathBounds.fTop) {
+ rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
+ devClipBounds.fRight, devPathBounds.fTop);
target->drawSimpleRect(rect, NULL);
}
- if (clipBounds.fLeft < pathBounds.fLeft) {
- rect.iset(clipBounds.fLeft, pathBounds.fTop,
- pathBounds.fLeft, pathBounds.fBottom);
+ if (devClipBounds.fLeft < devPathBounds.fLeft) {
+ rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
+ devPathBounds.fLeft, devPathBounds.fBottom);
target->drawSimpleRect(rect, NULL);
}
- if (clipBounds.fRight > pathBounds.fRight) {
- rect.iset(pathBounds.fRight, pathBounds.fTop,
- clipBounds.fRight, pathBounds.fBottom);
+ if (devClipBounds.fRight > devPathBounds.fRight) {
+ rect.iset(devPathBounds.fRight, devPathBounds.fTop,
+ devClipBounds.fRight, devPathBounds.fBottom);
target->drawSimpleRect(rect, NULL);
}
- if (clipBounds.fBottom > pathBounds.fBottom) {
- rect.iset(clipBounds.fLeft, pathBounds.fBottom,
- clipBounds.fRight, clipBounds.fBottom);
+ if (devClipBounds.fBottom > devPathBounds.fBottom) {
+ rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
+ devClipBounds.fRight, devClipBounds.fBottom);
target->drawSimpleRect(rect, NULL);
}
}
@@ -120,27 +123,27 @@ bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
vm.postTranslate(translate->fX, translate->fY);
}
- GrIRect pathBounds, clipBounds;
+ GrIRect devPathBounds, devClipBounds;
if (!get_path_and_clip_bounds(target, path, vm,
- &pathBounds, &clipBounds)) {
+ &devPathBounds, &devClipBounds)) {
if (GrIsFillInverted(fill)) {
- draw_around_inv_path(target, clipBounds, pathBounds);
+ draw_around_inv_path(target, devClipBounds, devPathBounds);
}
return true;
}
SkAutoTUnref<GrTexture> texture(
GrSWMaskHelper::DrawPathMaskToTexture(fContext, path,
- pathBounds, fill,
+ devPathBounds, fill,
antiAlias, &vm));
if (NULL == texture) {
return false;
}
- GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, pathBounds);
+ GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, devPathBounds);
if (GrIsFillInverted(fill)) {
- draw_around_inv_path(target, clipBounds, pathBounds);
+ draw_around_inv_path(target, devClipBounds, devPathBounds);
}
return true;
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index ab04bb48f5..576a5bdeae 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -70,6 +70,20 @@ void GrTextContext::flushGlyphs() {
fDrawTarget = NULL;
}
+namespace {
+
+// 'rect' enters in canvas coordinates and leaves in device coordinates
+void canvas_to_device(SkRect* rect, const SkIPoint& origin) {
+ GrAssert(NULL != rect);
+
+ rect->fLeft -= SkIntToScalar(origin.fX);
+ rect->fTop -= SkIntToScalar(origin.fY);
+ rect->fRight -= SkIntToScalar(origin.fX);
+ rect->fBottom -= SkIntToScalar(origin.fY);
+}
+
+};
+
GrTextContext::GrTextContext(GrContext* context,
const GrPaint& paint,
const GrMatrix* extMatrix) : fPaint(paint) {
@@ -88,8 +102,7 @@ GrTextContext::GrTextContext(GrContext* context,
const GrClipData* clipData = context->getClip();
GrRect conservativeBound = clipData->fClipStack->getConservativeBounds();
- conservativeBound.offset(SkIntToScalar(-clipData->fOrigin.fX),
- SkIntToScalar(-clipData->fOrigin.fY));
+ canvas_to_device(&conservativeBound, clipData->fOrigin);
if (!fExtMatrix.isIdentity()) {
GrMatrix inverse;
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index dcfb57b030..ec8f26c5fb 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -371,26 +371,27 @@ static void check_bounds(const SkClipStack& clipStack,
int renderTargetWidth,
int renderTargetHeight) {
- SkIRect bound;
- SkClipStack::BoundsType boundType;
- SkRect temp;
+ SkIRect devBound;
+
+ devBound.setLTRB(0, 0, renderTargetWidth, renderTargetHeight);
- bound.setLTRB(0, 0, renderTargetWidth, renderTargetHeight);
+ SkClipStack::BoundsType boundType;
+ SkRect canvTemp;
- clipStack.getBounds(&temp, &boundType);
+ clipStack.getBounds(&canvTemp, &boundType);
if (SkClipStack::kNormal_BoundsType == boundType) {
- SkIRect temp2;
+ SkIRect devTemp;
- temp.roundOut(&temp2);
+ canvTemp.roundOut(&devTemp);
- temp2.offset(-origin.fX, -origin.fY);
+ devTemp.offset(-origin.fX, -origin.fY);
- if (!bound.intersect(temp2)) {
- bound.setEmpty();
+ if (!devBound.intersect(devTemp)) {
+ devBound.setEmpty();
}
}
-// GrAssert(bound.contains(clipRegion.getBounds()));
+// GrAssert(devBound.contains(clipRegion.getBounds()));
}
#endif
@@ -413,15 +414,15 @@ static void convert_matrixclip(GrContext* context, const SkMatrix& matrix,
renderTargetWidth, renderTargetHeight);
#endif
- SkRect bounds;
+ SkRect devClipBounds;
bool isIntersectionOfRects = false;
clipStack.getConservativeBounds(0, 0,
renderTargetWidth,
renderTargetHeight,
- &bounds,
+ &devClipBounds,
&isIntersectionOfRects);
- result->setFromIterator(&iter, bounds);
+ result->setFromIterator(&iter, devClipBounds);
GrAssert(result->isRect() == isIntersectionOfRects);
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index b492fd4679..6d6d9167af 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -427,15 +427,16 @@ bool GrGpuGL::flushGraphicsState(DrawType type) {
this->flushScissor();
this->flushAAState(type);
- GrIRect* rect = NULL;
- GrIRect clipBounds;
+ GrIRect* devRect = NULL;
+ GrIRect devClipBounds;
if (drawState.isClipState()) {
- fClip->getConservativeBounds(drawState.getRenderTarget(), &clipBounds);
- rect = &clipBounds;
+ fClip->getConservativeBounds(drawState.getRenderTarget(),
+ &devClipBounds);
+ devRect = &devClipBounds;
}
// This must come after textures are flushed because a texture may need
// to be msaa-resolved (which will modify bound FBO state).
- this->flushRenderTarget(rect);
+ this->flushRenderTarget(devRect);
return true;
}
diff --git a/tests/ClipCacheTest.cpp b/tests/ClipCacheTest.cpp
index 516a6141c8..0a72be4a8b 100644
--- a/tests/ClipCacheTest.cpp
+++ b/tests/ClipCacheTest.cpp
@@ -68,14 +68,14 @@ static void test_clip_bounds(skiatest::Reporter* reporter, GrContext* context) {
stack.clipDevRect(clipRect, SkRegion::kReplace_Op, false);
bool isIntersectionOfRects = true;
- SkRect stackBounds;
+ SkRect devStackBounds;
stack.getConservativeBounds(0, 0, kXSize, kYSize,
- &stackBounds,
+ &devStackBounds,
&isIntersectionOfRects);
// make sure that the SkClipStack is behaving itself
- REPORTER_ASSERT(reporter, screen == stackBounds);
+ REPORTER_ASSERT(reporter, screen == devStackBounds);
REPORTER_ASSERT(reporter, isIntersectionOfRects);
// convert the SkClipStack to a GrClip
@@ -83,25 +83,25 @@ static void test_clip_bounds(skiatest::Reporter* reporter, GrContext* context) {
iter.reset(stack);
GrClip clip;
- clip.setFromIterator(&iter, stackBounds);
+ clip.setFromIterator(&iter, devStackBounds);
- const GrRect& grBound = clip.getConservativeBounds();
+ const GrRect& canvGrClipBound = clip.getConservativeBounds();
// make sure that GrClip is behaving itself
- REPORTER_ASSERT(reporter, clipRect == grBound);
+ REPORTER_ASSERT(reporter, clipRect == canvGrClipBound);
REPORTER_ASSERT(reporter, clip.isRect());
// wrap the GrClip in a GrClipData
GrClipData clipData;
clipData.fClipStack = &clip;
- SkIRect intGrBound;
+ SkIRect devGrClipDataBound;
clipData.getConservativeBounds(texture,
- &intGrBound,
+ &devGrClipDataBound,
&isIntersectionOfRects);
// make sure that GrClipData is behaving itself
- REPORTER_ASSERT(reporter, intScreen == intGrBound);
+ REPORTER_ASSERT(reporter, intScreen == devGrClipDataBound);
REPORTER_ASSERT(reporter, isIntersectionOfRects);
}
diff --git a/tests/ClipStackTest.cpp b/tests/ClipStackTest.cpp
index 160c5440b1..afbbd7e235 100644
--- a/tests/ClipStackTest.cpp
+++ b/tests/ClipStackTest.cpp
@@ -235,7 +235,7 @@ static void test_bounds(skiatest::Reporter* reporter, bool useRects) {
clipB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5));
SkClipStack stack;
- SkRect bound;
+ SkRect devClipBound;
bool isIntersectionOfRects = false;
int testCase = 0;
@@ -262,7 +262,7 @@ static void test_bounds(skiatest::Reporter* reporter, bool useRects) {
REPORTER_ASSERT(reporter, !stack.isWideOpen());
- stack.getConservativeBounds(0, 0, 100, 100, &bound,
+ stack.getConservativeBounds(0, 0, 100, 100, &devClipBound,
&isIntersectionOfRects);
if (useRects) {
@@ -273,7 +273,7 @@ static void test_bounds(skiatest::Reporter* reporter, bool useRects) {
}
SkASSERT(testCase < gNumCases);
- REPORTER_ASSERT(reporter, bound == gAnswerRectsBW[testCase]);
+ REPORTER_ASSERT(reporter, devClipBound == gAnswerRectsBW[testCase]);
++testCase;
stack.restore();