diff options
-rw-r--r-- | include/core/SkRect.h | 11 | ||||
-rw-r--r-- | src/gpu/GrClipMaskManager.cpp | 76 | ||||
-rw-r--r-- | src/gpu/GrClipMaskManager.h | 18 | ||||
-rw-r--r-- | tests/ClipCacheTest.cpp | 14 |
4 files changed, 69 insertions, 50 deletions
diff --git a/include/core/SkRect.h b/include/core/SkRect.h index 702627775b..2fa3256e1c 100644 --- a/include/core/SkRect.h +++ b/include/core/SkRect.h @@ -144,7 +144,7 @@ struct SK_API SkIRect { /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards, making the rectangle narrower. If dx is negative, then the sides are moved outwards, - making the rectangle wider. The same hods true for dy and the top and bottom. + making the rectangle wider. The same holds true for dy and the top and bottom. */ void inset(int32_t dx, int32_t dy) { fLeft += dx; @@ -153,6 +153,13 @@ struct SK_API SkIRect { fBottom -= dy; } + /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are + moved outwards, making the rectangle wider. If dx is negative, then the + sides are moved inwards, making the rectangle narrower. The same holds + true for dy and the top and bottom. + */ + void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); } + bool quickReject(int l, int t, int r, int b) const { return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b; } @@ -481,7 +488,7 @@ struct SK_API SkRect { /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are moved outwards, making the rectangle wider. If dx is negative, then the - sides are moved inwards, making the rectangle narrower. The same hods + sides are moved inwards, making the rectangle narrower. The same holds true for dy and the top and bottom. */ void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); } diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp index 43b27431ba..15aae1e2dc 100644 --- a/src/gpu/GrClipMaskManager.cpp +++ b/src/gpu/GrClipMaskManager.cpp @@ -32,7 +32,7 @@ namespace { // sampler matrix this also alters the vertex layout void setup_drawstate_aaclip(GrGpu* gpu, GrTexture* result, - const GrRect &bound) { + const GrIRect &bound) { GrDrawState* drawState = gpu->drawState(); GrAssert(drawState); @@ -40,7 +40,7 @@ void setup_drawstate_aaclip(GrGpu* gpu, GrMatrix mat; mat.setIDiv(result->width(), result->height()); - mat.preTranslate(-bound.fLeft, -bound.fTop); + mat.preTranslate(SkIntToScalar(-bound.fLeft), SkIntToScalar(-bound.fTop)); mat.preConcat(drawState->getViewMatrix()); drawState->sampler(maskStage)->reset(GrSamplerState::kClamp_WrapMode, @@ -89,7 +89,7 @@ bool GrClipMaskManager::createClipMask(GrGpu* gpu, // The clip geometry is complex enough that it will be more // efficient to create it entirely in software GrTexture* result = NULL; - GrRect bound; + GrIRect bound; if (this->createSoftwareClipMask(gpu, clipIn, &result, &bound)) { fClipMaskInAlpha = true; @@ -108,7 +108,7 @@ bool GrClipMaskManager::createClipMask(GrGpu* gpu, // render target) we aren't going to use scissoring like the stencil // path does (see scissorSettings below) GrTexture* result = NULL; - GrRect bound; + GrIRect bound; if (this->createAlphaClipMask(gpu, clipIn, &result, &bound)) { fClipMaskInAlpha = true; @@ -165,12 +165,25 @@ bool GrClipMaskManager::createClipMask(GrGpu* gpu, #endif namespace { +/** + * Does "container" contain "containee"? If either is empty then + * no containment is possible. + */ +bool contains(const SkRect& container, const SkIRect& containee) { + return !containee.isEmpty() && !container.isEmpty() && + container.fLeft <= SkIntToScalar(containee.fLeft) && + container.fTop <= SkIntToScalar(containee.fTop) && + container.fRight >= SkIntToScalar(containee.fRight) && + container.fBottom >= SkIntToScalar(containee.fBottom); +} + + //////////////////////////////////////////////////////////////////////////////// // determines how many elements at the head of the clip can be skipped and // whether the initial clear should be to the inside- or outside-the-clip value, // and what op should be used to draw the first element that isn't skipped. int process_initial_clip_elements(const GrClip& clip, - const GrRect& bounds, + const GrIRect& bounds, bool* clearToInside, SkRegion::Op* startOp) { @@ -196,7 +209,7 @@ int process_initial_clip_elements(const GrClip& clip, // if this element contains the entire bounds then we // can skip it. if (kRect_ClipType == clip.getElementType(curr) - && clip.getRect(curr).contains(bounds)) { + && contains(clip.getRect(curr), bounds)) { break; } // if everything is initially clearToInside then intersect is @@ -378,7 +391,7 @@ void clear(GrGpu* gpu, // get a texture to act as a temporary buffer for AA clip boolean operations // TODO: given the expense of createTexture we may want to just cache this too -void GrClipMaskManager::getTemp(const GrRect& bounds, +void GrClipMaskManager::getTemp(const GrIRect& bounds, GrAutoScratchTexture* temp) { if (NULL != temp->texture()) { // we've already allocated the temp texture @@ -387,8 +400,8 @@ void GrClipMaskManager::getTemp(const GrRect& bounds, const GrTextureDesc desc = { kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit, - SkScalarCeilToInt(bounds.width()), - SkScalarCeilToInt(bounds.height()), + bounds.width(), + bounds.height(), kAlpha_8_GrPixelConfig, 0 // samples }; @@ -398,15 +411,15 @@ void GrClipMaskManager::getTemp(const GrRect& bounds, void GrClipMaskManager::setupCache(const GrClip& clipIn, - const GrRect& bounds) { + const GrIRect& bounds) { // Since we are setting up the cache we know the last lookup was a miss // Free up the currently cached mask so it can be reused fAACache.reset(); const GrTextureDesc desc = { kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit, - SkScalarCeilToInt(bounds.width()), - SkScalarCeilToInt(bounds.height()), + bounds.width(), + bounds.height(), kAlpha_8_GrPixelConfig, 0 // samples }; @@ -422,7 +435,7 @@ void GrClipMaskManager::setupCache(const GrClip& clipIn, bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu, const GrClip& clipIn, GrTexture** result, - GrRect *resultBounds) { + GrIRect *resultBounds) { GrDrawState* origDrawState = gpu->drawState(); GrAssert(origDrawState->isClipState()); @@ -449,28 +462,26 @@ bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu, bounds = rtRect; } - bounds.roundOut(); + GrIRect intBounds; + bounds.roundOut(&intBounds); // need to outset a pixel since the standard bounding box computation // path doesn't leave any room for antialiasing (esp. w.r.t. rects) - bounds.outset(SkIntToScalar(1), SkIntToScalar(1)); + intBounds.outset(1, 1); // TODO: make sure we don't outset if bounds are still 0,0 @ min - GrAssert(SkScalarIsInt(bounds.width())); - GrAssert(SkScalarIsInt(bounds.height())); - if (fAACache.canReuse(clipIn, - SkScalarCeilToInt(bounds.width()), - SkScalarCeilToInt(bounds.height()))) { + intBounds.width(), + intBounds.height())) { *result = fAACache.getLastMask(); fAACache.getLastBound(resultBounds); return true; } - this->setupCache(clipIn, bounds); + this->setupCache(clipIn, intBounds); - *resultBounds = bounds; + *resultBounds = intBounds; return false; } @@ -479,7 +490,7 @@ bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu, bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu, const GrClip& clipIn, GrTexture** result, - GrRect *resultBounds) { + GrIRect *resultBounds) { if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) { return true; @@ -504,7 +515,8 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu, // offset the paths & rects that will be used to compute it GrMatrix m; - m.setTranslate(-resultBounds->fLeft, -resultBounds->fTop); + m.setTranslate(SkIntToScalar(-resultBounds->fLeft), + SkIntToScalar(-resultBounds->fTop)); drawState->setViewMatrix(m); } @@ -541,7 +553,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu, // there is no point in intersecting a screen filling rectangle. if (SkRegion::kIntersect_Op == op && kRect_ClipType == clipIn.getElementType(c) && - clipIn.getRect(c).contains(*resultBounds)) { + contains(clipIn.getRect(c), *resultBounds)) { continue; } @@ -564,7 +576,8 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu, if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) { GrMatrix m; - m.setTranslate(resultBounds->fLeft, resultBounds->fTop); + m.setTranslate(SkIntToScalar(resultBounds->fLeft), + SkIntToScalar(resultBounds->fTop)); drawState->preConcatViewMatrix(m); } @@ -577,7 +590,8 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu, if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) { GrMatrix m; - m.setTranslate(-resultBounds->fLeft, -resultBounds->fTop); + m.setTranslate(SkIntToScalar(-resultBounds->fLeft), + SkIntToScalar(-resultBounds->fTop)); drawState->preConcatViewMatrix(m); } @@ -643,9 +657,7 @@ bool GrClipMaskManager::createStencilClipMask(GrGpu* gpu, "Ganesh only handles 16b or smaller stencil buffers"); clipBit = (1 << (clipBit-1)); - GrRect rtRect; - rtRect.setLTRB(0, 0, - GrIntToScalar(rt->width()), GrIntToScalar(rt->height())); + GrIRect rtRect = GrIRect::MakeWH(rt->width(), rt->height()); bool clearToInside; SkRegion::Op startOp = SkRegion::kReplace_Op; // suppress warning @@ -681,7 +693,7 @@ bool GrClipMaskManager::createStencilClipMask(GrGpu* gpu, // there is no point in intersecting a screen filling // rectangle. if (SkRegion::kIntersect_Op == op && - clipCopy.getRect(c).contains(rtRect)) { + contains(clipCopy.getRect(c), rtRect)) { continue; } } else { @@ -769,7 +781,7 @@ bool GrClipMaskManager::createStencilClipMask(GrGpu* gpu, bool GrClipMaskManager::createSoftwareClipMask(GrGpu* gpu, const GrClip& clipIn, GrTexture** result, - GrRect *resultBounds) { + GrIRect *resultBounds) { if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) { return true; diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h index c87bb7c32a..02fc875f83 100644 --- a/src/gpu/GrClipMaskManager.h +++ b/src/gpu/GrClipMaskManager.h @@ -151,7 +151,7 @@ public: void acquireMask(const GrClip& clip, const GrTextureDesc& desc, - const GrRect& bound) { + const GrIRect& bound) { if (fStack.empty()) { GrAssert(false); @@ -195,7 +195,7 @@ public: return back->fLastMask.texture()->height(); } - void getLastBound(GrRect* bound) const { + void getLastBound(GrIRect* bound) const { if (fStack.empty()) { GrAssert(false); @@ -237,7 +237,7 @@ private: void acquireMask(GrContext* context, const GrClip& clip, const GrTextureDesc& desc, - const GrRect& bound) { + const GrIRect& bound) { fLastClip = clip; @@ -263,7 +263,7 @@ private: // fLastBound stores the bounding box of the clip mask in canvas // space. The left and top fields are used to offset the uvs for // geometry drawn with this mask (in setupDrawStateAAClip) - GrRect fLastBound; + GrIRect fLastBound; }; GrContext* fContext; @@ -322,15 +322,15 @@ private: bool createAlphaClipMask(GrGpu* gpu, const GrClip& clipIn, GrTexture** result, - GrRect *resultBounds); + GrIRect *resultBounds); bool createSoftwareClipMask(GrGpu* gpu, const GrClip& clipIn, GrTexture** result, - GrRect *resultBounds); + GrIRect *resultBounds); bool clipMaskPreamble(GrGpu* gpu, const GrClip& clipIn, GrTexture** result, - GrRect *resultBounds); + GrIRect *resultBounds); bool drawPath(GrGpu* gpu, const SkPath& path, @@ -346,10 +346,10 @@ private: GrTexture* target, GrTexture* texture); - void getTemp(const GrRect& bounds, GrAutoScratchTexture* temp); + void getTemp(const GrIRect& bounds, GrAutoScratchTexture* temp); void setupCache(const GrClip& clip, - const GrRect& bounds); + const GrIRect& bounds); // determines the path renderer used to draw a clip path element. GrPathRenderer* getClipPathRenderer(GrGpu* gpu, diff --git a/tests/ClipCacheTest.cpp b/tests/ClipCacheTest.cpp index 1fc5d45b8f..a0888d85e4 100644 --- a/tests/ClipCacheTest.cpp +++ b/tests/ClipCacheTest.cpp @@ -42,14 +42,14 @@ static void check_state(skiatest::Reporter* reporter, const GrClipMaskCache& cache, const GrClip& clip, GrTexture* mask, - const GrRect& bound) { + const GrIRect& bound) { GrClip cacheClip; cache.getLastClip(&cacheClip); REPORTER_ASSERT(reporter, clip == cacheClip); REPORTER_ASSERT(reporter, mask == cache.getLastMask()); - GrRect cacheBound; + GrIRect cacheBound; cache.getLastBound(&cacheBound); REPORTER_ASSERT(reporter, bound == cacheBound); } @@ -66,18 +66,18 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) { GrClip emptyClip; emptyClip.setEmpty(); - GrRect emptyBound; + GrIRect emptyBound; emptyBound.setEmpty(); // check initial state check_state(reporter, cache, emptyClip, NULL, emptyBound); // set the current state - GrRect bound1; + GrIRect bound1; bound1.set(0, 0, 100, 100); GrClip clip1; - clip1.setFromRect(bound1); + clip1.setFromIRect(bound1); const GrTextureDesc desc = { kRenderTarget_GrTextureFlagBit, @@ -107,12 +107,12 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) { REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt()); // modify the new state - GrRect bound2; + GrIRect bound2; bound2.set(-10, -10, 10, 10); GrClip clip2; clip2.setEmpty(); - clip2.setFromRect(bound2); + clip2.setFromIRect(bound2); cache.acquireMask(clip2, desc, bound2); |