From 7b11289b4e4d117bbcee6d2460b057d0fcf6e437 Mon Sep 17 00:00:00 2001 From: "robertphillips@google.com" Date: Tue, 31 Jul 2012 15:18:21 +0000 Subject: [PATCH] Added dev- & canv- prefixes to Ganesh bounding boxes to indicate coordinate space http://codereview.appspot.com/6457061/ git-svn-id: http://skia.googlecode.com/svn/trunk@4856 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/core/SkClipStack.h | 10 +-- include/gpu/GrClip.h | 2 +- src/core/SkClipStack.cpp | 22 ++--- src/gpu/GrAAHairLinePathRenderer.cpp | 17 ++-- src/gpu/GrClip.cpp | 6 +- src/gpu/GrClipMaskManager.cpp | 169 ++++++++++++++++++----------------- src/gpu/GrClipMaskManager.h | 8 +- src/gpu/GrSoftwarePathRenderer.cpp | 59 ++++++------ src/gpu/GrTextContext.cpp | 17 +++- src/gpu/SkGpuDevice.cpp | 29 +++--- src/gpu/gl/GrGpuGL_program.cpp | 11 +-- tests/ClipCacheTest.cpp | 18 ++-- tests/ClipStackTest.cpp | 6 +- 13 files changed, 202 insertions(+), 172 deletions(-) diff --git a/include/core/SkClipStack.h b/include/core/SkClipStack.h index 60ed9ed..c0fadb1 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 bb07c28..cf646a1 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 673981b..d2c2035 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 13d6155..43e87d6 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 a3905ba..e8ea9a6 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 97c102f..71743a0 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 81be5ed..3ba26d3 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 5b570b4..16b859f 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 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 ab04bb4..576a5bd 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 dcfb57b..ec8f26c 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 b492fd4..6d6d916 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 516a614..0a72be4 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 160c544..afbbd7e 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(); -- 2.7.4