diff options
author | Chris Dalton <csmartdalton@google.com> | 2017-06-05 13:15:37 -0600 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-06-05 19:53:06 +0000 |
commit | 348060fa820e1ee7a4fd246afe517a80a9ef311d (patch) | |
tree | 04e6e87d8b141f562116f107d42dcb77edda6341 | |
parent | 70898afe073c49d8151b25cc5bf234f61c76ffae (diff) |
Fix GrReducedClip.cpp: assertion failure surrounding tiny query bounds
Some assertions cannot be relied upon due to FP error.
Bug: skia:5990
Change-Id: I32445b320b9100ae2f80d2f762707d823da77805
Reviewed-on: https://skia-review.googlesource.com/18602
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
-rw-r--r-- | src/gpu/GrClip.h | 16 | ||||
-rw-r--r-- | src/gpu/GrReducedClip.cpp | 12 | ||||
-rw-r--r-- | tests/ClipStackTest.cpp | 31 |
3 files changed, 50 insertions, 9 deletions
diff --git a/src/gpu/GrClip.h b/src/gpu/GrClip.h index c44653baad..2e247c82f2 100644 --- a/src/gpu/GrClip.h +++ b/src/gpu/GrClip.h @@ -90,12 +90,16 @@ public: */ template <typename TRect> constexpr static bool IsOutsideClip(const TRect& outerClipBounds, const SkRect& queryBounds) { - return outerClipBounds.fRight - outerClipBounds.fLeft <= kBoundsTolerance || - outerClipBounds.fBottom - outerClipBounds.fTop <= kBoundsTolerance || - outerClipBounds.fLeft >= queryBounds.fRight - kBoundsTolerance || - outerClipBounds.fTop >= queryBounds.fBottom - kBoundsTolerance || - outerClipBounds.fRight <= queryBounds.fLeft + kBoundsTolerance || - outerClipBounds.fBottom <= queryBounds.fTop + kBoundsTolerance; + return + // Is the clip so small that it is effectively empty? + outerClipBounds.fRight - outerClipBounds.fLeft <= kBoundsTolerance || + outerClipBounds.fBottom - outerClipBounds.fTop <= kBoundsTolerance || + + // Are the query bounds effectively outside the clip? + outerClipBounds.fLeft >= queryBounds.fRight - kBoundsTolerance || + outerClipBounds.fTop >= queryBounds.fBottom - kBoundsTolerance || + outerClipBounds.fRight <= queryBounds.fLeft + kBoundsTolerance || + outerClipBounds.fBottom <= queryBounds.fTop + kBoundsTolerance; } /** diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp index b7ffa7b26f..8c98ac1c71 100644 --- a/src/gpu/GrReducedClip.cpp +++ b/src/gpu/GrReducedClip.cpp @@ -45,7 +45,7 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds bool iior; stack.getBounds(&stackBounds, &stackBoundsType, &iior); - if (stackBounds.isEmpty() || GrClip::IsOutsideClip(stackBounds, queryBounds)) { + if (GrClip::IsOutsideClip(stackBounds, queryBounds)) { bool insideOut = SkClipStack::kInsideOut_BoundsType == stackBoundsType; fInitialState = insideOut ? InitialState::kAllIn : InitialState::kAllOut; return; @@ -72,7 +72,10 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds SkRect tightBounds; SkAssertResult(tightBounds.intersect(stackBounds, queryBounds)); fIBounds = GrClip::GetPixelIBounds(tightBounds); - SkASSERT(!fIBounds.isEmpty()); // Empty should have been blocked by IsOutsideClip above. + if (fIBounds.isEmpty()) { + fInitialState = InitialState::kAllOut; + return; + } fHasIBounds = true; // Implement the clip with an AA rect element. @@ -92,7 +95,10 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds } fIBounds = GrClip::GetPixelIBounds(tighterQuery); - SkASSERT(!fIBounds.isEmpty()); // Empty should have been blocked by IsOutsideClip above. + if (fIBounds.isEmpty()) { + fInitialState = InitialState::kAllOut; + return; + } fHasIBounds = true; // Now that we have determined the bounds to use and filtered out the trivial cases, call the diff --git a/tests/ClipStackTest.cpp b/tests/ClipStackTest.cpp index e0df2ca902..1cb644a80f 100644 --- a/tests/ClipStackTest.cpp +++ b/tests/ClipStackTest.cpp @@ -1357,6 +1357,36 @@ static void test_reduced_clip_stack_aa(skiatest::Reporter* reporter) { } } +static void test_tiny_query_bounds_assertion_bug(skiatest::Reporter* reporter) { + // https://bugs.chromium.org/p/skia/issues/detail?id=5990 + const SkRect clipBounds = SkRect::MakeXYWH(1.5f, 100, 1000, 1000); + + SkClipStack rectStack; + rectStack.clipRect(clipBounds, SkMatrix::I(), kIntersect_SkClipOp, true); + + SkPath clipPath; + clipPath.moveTo(clipBounds.left(), clipBounds.top()); + clipPath.quadTo(clipBounds.right(), clipBounds.top(), + clipBounds.right(), clipBounds.bottom()); + clipPath.quadTo(clipBounds.left(), clipBounds.bottom(), + clipBounds.left(), clipBounds.top()); + SkClipStack pathStack; + pathStack.clipPath(clipPath, SkMatrix::I(), kIntersect_SkClipOp, true); + + for (const SkClipStack& stack : {rectStack, pathStack}) { + for (SkRect queryBounds : {SkRect::MakeXYWH(53, 60, GrClip::kBoundsTolerance, 1000), + SkRect::MakeXYWH(53, 60, GrClip::kBoundsTolerance/2, 1000), + SkRect::MakeXYWH(53, 160, 1000, GrClip::kBoundsTolerance), + SkRect::MakeXYWH(53, 160, 1000, GrClip::kBoundsTolerance/2)}) { + const GrReducedClip reduced(stack, queryBounds); + REPORTER_ASSERT(reporter, !reduced.hasIBounds()); + REPORTER_ASSERT(reporter, reduced.elements().isEmpty()); + REPORTER_ASSERT(reporter, + GrReducedClip::InitialState::kAllOut == reduced.initialState()); + } + } +} + #endif DEF_TEST(ClipStack, reporter) { @@ -1409,6 +1439,7 @@ DEF_TEST(ClipStack, reporter) { test_reduced_clip_stack_genid(reporter); test_reduced_clip_stack_no_aa_crash(reporter); test_reduced_clip_stack_aa(reporter); + test_tiny_query_bounds_assertion_bug(reporter); #endif } |