Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 1c0b05a

Browse files
bsalomonSkia Commit-Bot
authored andcommitted
SkClipStack::isRRect succeeds if stack is an intersection of rects.
This helps enable optimizations that rely on the entire clip reducing to a single rectangle, such as converting a drawRect to a clear. Bug: b/122296071 Change-Id: I1fea4565644280d57610f8585b76babb557301d8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/209382 Commit-Queue: Brian Salomon <[email protected]> Reviewed-by: Robert Phillips <[email protected]>
1 parent 84d36cd commit 1c0b05a

2 files changed

Lines changed: 52 additions & 5 deletions

File tree

src/core/SkClipStack.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -960,13 +960,18 @@ void SkClipStack::getConservativeBounds(int offsetX,
960960
}
961961

962962
bool SkClipStack::isRRect(const SkRect& bounds, SkRRect* rrect, bool* aa) const {
963-
// We limit to 5 elements. This means the back element will be bounds checked at most 4 times if
964-
// it is an rrect.
965-
int cnt = fDeque.count();
966-
if (!cnt || cnt > 5) {
963+
const Element* back = static_cast<const Element*>(fDeque.back());
964+
if (!back) {
965+
// TODO: return bounds?
967966
return false;
968967
}
969-
const Element* back = static_cast<const Element*>(fDeque.back());
968+
// First check if the entire stack is known to be a rect by the top element.
969+
if (back->fIsIntersectionOfRects && back->fFiniteBoundType == BoundsType::kNormal_BoundsType) {
970+
rrect->setRect(back->fFiniteBound);
971+
*aa = back->isAA();
972+
return true;
973+
}
974+
970975
if (back->getDeviceSpaceType() != SkClipStack::Element::DeviceSpaceType::kRect &&
971976
back->getDeviceSpaceType() != SkClipStack::Element::DeviceSpaceType::kRRect) {
972977
return false;
@@ -982,6 +987,12 @@ bool SkClipStack::isRRect(const SkRect& bounds, SkRRect* rrect, bool* aa) const
982987
if (!backBounds.intersect(bounds, back->asDeviceSpaceRRect().rect())) {
983988
return false;
984989
}
990+
// We limit to 5 elements. This means the back element will be bounds checked at most 4
991+
// times if it is an rrect.
992+
int cnt = fDeque.count();
993+
if (cnt > 5) {
994+
return false;
995+
}
985996
if (cnt > 1) {
986997
SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart);
987998
SkAssertResult(static_cast<const Element*>(iter.prev()) == back);

tests/ClipStackTest.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,41 @@ static void test_tiny_query_bounds_assertion_bug(skiatest::Reporter* reporter) {
14251425
}
14261426
}
14271427

1428+
static void test_is_rrect_deep_rect_stack(skiatest::Reporter* reporter) {
1429+
static constexpr SkRect kTargetBounds = SkRect::MakeWH(1000, 500);
1430+
// All antialiased or all not antialiased.
1431+
for (bool aa : {false, true}) {
1432+
SkClipStack stack;
1433+
for (int i = 0; i <= 100; ++i) {
1434+
stack.save();
1435+
stack.clipRect(SkRect::MakeLTRB(i, 0.5, kTargetBounds.width(), kTargetBounds.height()),
1436+
SkMatrix::I(), SkClipOp::kIntersect, aa);
1437+
}
1438+
SkRRect rrect;
1439+
bool isAA;
1440+
SkRRect expected = SkRRect::MakeRect(
1441+
SkRect::MakeLTRB(100, 0.5, kTargetBounds.width(), kTargetBounds.height()));
1442+
if (stack.isRRect(kTargetBounds, &rrect, &isAA)) {
1443+
REPORTER_ASSERT(reporter, rrect == expected);
1444+
REPORTER_ASSERT(reporter, aa == isAA);
1445+
} else {
1446+
ERRORF(reporter, "Expected to be an rrect.");
1447+
}
1448+
}
1449+
// Mixed AA and non-AA without simple containment.
1450+
SkClipStack stack;
1451+
for (int i = 0; i <= 100; ++i) {
1452+
bool aa = i & 0b1;
1453+
int j = 100 - i;
1454+
stack.save();
1455+
stack.clipRect(SkRect::MakeLTRB(i, j + 0.5, kTargetBounds.width(), kTargetBounds.height()),
1456+
SkMatrix::I(), SkClipOp::kIntersect, aa);
1457+
}
1458+
SkRRect rrect;
1459+
bool isAA;
1460+
REPORTER_ASSERT(reporter, !stack.isRRect(kTargetBounds, &rrect, &isAA));
1461+
}
1462+
14281463
DEF_TEST(ClipStack, reporter) {
14291464
SkClipStack stack;
14301465

@@ -1477,6 +1512,7 @@ DEF_TEST(ClipStack, reporter) {
14771512
test_reduced_clip_stack_no_aa_crash(reporter);
14781513
test_reduced_clip_stack_aa(reporter);
14791514
test_tiny_query_bounds_assertion_bug(reporter);
1515+
test_is_rrect_deep_rect_stack(reporter);
14801516
}
14811517

14821518
//////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)