optimization/fix: dirty the clip-bounds when we mod the clip in savelayer

Before the fix, we could use a stale cache of the clipbounds in quickReject. Often this could return false negatives, meaning we would try to draw more than we should (it would eventually be really clipped). Occasionally this could also report false positives (if the layer were outside of the normal canvas bounds, e.g. a layer with an offset imagefilter).

BUG=skia:
NOTREECHECKS=True

Review URL: https://codereview.chromium.org/983243003
This commit is contained in:
reed 2015-03-11 08:47:12 -07:00 committed by Commit bot
parent cc99dbc57b
commit 9b3aa54bc9
2 changed files with 20 additions and 1 deletions

View File

@ -831,7 +831,7 @@ static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
}
bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
SkIRect* intersection, const SkImageFilter* imageFilter) {
SkIRect* intersection, const SkImageFilter* imageFilter) {
SkIRect clipBounds;
SkRegion::Op op = SkRegion::kIntersect_Op;
if (!this->getClipDeviceBounds(&clipBounds)) {
@ -854,6 +854,7 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
// early exit if the layer's bounds are clipped out
if (!ir.intersect(clipBounds)) {
if (bounds_affects_clip(flags)) {
fCachedLocalClipBoundsDirty = true;
fMCRec->fRasterClip.setEmpty();
}
return false;
@ -863,6 +864,7 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
}
if (bounds_affects_clip(flags)) {
fCachedLocalClipBoundsDirty = true;
fClipStack->clipDevRect(ir, op);
// early exit if the clip is now empty
if (!fMCRec->fRasterClip.op(ir, op)) {

View File

@ -87,6 +87,23 @@ static void test_drawBitmap(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, 0xFFFFFFFF == *dst.getAddr32(5, 5));
}
static void test_layers(skiatest::Reporter* reporter) {
SkCanvas canvas(100, 100);
SkRect r = SkRect::MakeWH(10, 10);
REPORTER_ASSERT(reporter, false == canvas.quickReject(r));
r.offset(300, 300);
REPORTER_ASSERT(reporter, true == canvas.quickReject(r));
// Test that saveLayer updates quickReject
SkRect bounds = SkRect::MakeLTRB(50, 50, 70, 70);
canvas.saveLayer(&bounds, NULL);
REPORTER_ASSERT(reporter, true == canvas.quickReject(SkRect::MakeWH(10, 10)));
REPORTER_ASSERT(reporter, false == canvas.quickReject(SkRect::MakeWH(60, 60)));
}
DEF_TEST(QuickReject, reporter) {
test_drawBitmap(reporter);
test_layers(reporter);
}