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

Commit d30e9ef

Browse files
lhkbobSkia Commit-Bot
authored and
Skia Commit-Bot
committed
Use preservesAxisAlignment instead of scaleTranslate for clip simplification
This lets more matrix types pre-convert rects and rrects to device space. Since the clip geometry isn't itself shaded, we can apply the matrix without worrying about preserving local vs. device coordinates. Bug: skia:10730 Change-Id: I61ae3e13eec66f0e5eb83a6504dcb8004620b151 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/320222 Reviewed-by: Brian Salomon <[email protected]> Reviewed-by: Chris Dalton <[email protected]> Commit-Queue: Michael Ludwig <[email protected]>
1 parent 0dec992 commit d30e9ef

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

src/gpu/GrClipStack.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ static bool shape_contains_rect(
125125
if (!mixedAAMode && aToDevice == bToDevice) {
126126
// A and B are in the same coordinate space, so don't bother mapping
127127
return a.conservativeContains(b);
128-
} else if (bToDevice.isIdentity() && aToDevice.isScaleTranslate()) {
128+
} else if (bToDevice.isIdentity() && aToDevice.preservesAxisAlignment()) {
129129
// Optimize the common case of draws (B, with identity matrix) and axis-aligned shapes,
130130
// instead of checking the four corners separately.
131131
SkRect bInA = b;
@@ -543,15 +543,15 @@ void GrClipStack::RawElement::simplify(const SkIRect& deviceBounds, bool forceAA
543543
// Except for axis-aligned clip rects, upgrade to AA when forced. We skip axis-aligned clip
544544
// rects because a non-AA axis aligned rect can always be set as just a scissor test or window
545545
// rect, avoiding an expensive stencil mask generation.
546-
if (forceAA && !(fShape.isRect() && fLocalToDevice.isScaleTranslate())) {
546+
if (forceAA && !(fShape.isRect() && fLocalToDevice.preservesAxisAlignment())) {
547547
fAA = GrAA::kYes;
548548
}
549549

550550
// Except for non-AA axis-aligned rects, the outer bounds is the rounded-out device-space
551551
// mapped bounds of the shape.
552552
fOuterBounds = GrClip::GetPixelIBounds(outer, fAA, BoundsType::kExterior);
553553

554-
if (fLocalToDevice.isScaleTranslate()) {
554+
if (fLocalToDevice.preservesAxisAlignment()) {
555555
if (fShape.isRect()) {
556556
// The actual geometry can be updated to the device-intersected bounds and we can
557557
// know the inner bounds

tests/GrClipStackTest.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,7 @@ DEF_TEST(GrClipStack_DeviceRRect, r) {
11081108
DEF_TEST(GrClipStack_ScaleTranslate, r) {
11091109
SkMatrix lm = SkMatrix::Scale(2.f, 4.f);
11101110
lm.postTranslate(15.5f, 14.3f);
1111+
SkASSERT(lm.preservesAxisAlignment() && lm.isScaleTranslate());
11111112

11121113
// Rect -> matrix is applied up front
11131114
SkRect rect = {0.f, 0.f, 10.f, 10.f};
@@ -1140,6 +1141,43 @@ DEF_TEST(GrClipStack_ScaleTranslate, r) {
11401141
.finishTest());
11411142
}
11421143

1144+
// Tests that rect-stays-rect matrices that are not scale+translate matrices are pre-applied.
1145+
DEF_TEST(GrClipStack_PreserveAxisAlignment, r) {
1146+
SkMatrix lm = SkMatrix::RotateDeg(90.f);
1147+
lm.postTranslate(15.5f, 14.3f);
1148+
SkASSERT(lm.preservesAxisAlignment() && !lm.isScaleTranslate());
1149+
1150+
// Rect -> matrix is applied up front
1151+
SkRect rect = {0.f, 0.f, 10.f, 10.f};
1152+
run_test_case(r, TestCase::Build("r90+rect", kDeviceBounds)
1153+
.actual().rect(rect, lm, GrAA::kYes, SkClipOp::kIntersect)
1154+
.finishElements()
1155+
.expect().rect(lm.mapRect(rect), GrAA::kYes, SkClipOp::kIntersect)
1156+
.finishElements()
1157+
.state(GrClipStack::ClipState::kDeviceRect)
1158+
.finishTest());
1159+
1160+
// RRect -> matrix is applied up front
1161+
SkRRect localRRect = SkRRect::MakeRectXY(rect, 2.f, 2.f);
1162+
SkRRect deviceRRect;
1163+
SkAssertResult(localRRect.transform(lm, &deviceRRect));
1164+
run_test_case(r, TestCase::Build("r90+rrect", kDeviceBounds)
1165+
.actual().rrect(localRRect, lm, GrAA::kYes, SkClipOp::kIntersect)
1166+
.finishElements()
1167+
.expect().rrect(deviceRRect, GrAA::kYes, SkClipOp::kIntersect)
1168+
.finishElements()
1169+
.state(GrClipStack::ClipState::kDeviceRRect)
1170+
.finishTest());
1171+
1172+
// Path -> matrix is NOT applied
1173+
run_test_case(r, TestCase::Build("r90+path", kDeviceBounds)
1174+
.actual().intersect().localToDevice(lm).path(make_octagon(rect))
1175+
.finishElements()
1176+
.expectActual()
1177+
.state(GrClipStack::ClipState::kComplex)
1178+
.finishTest());
1179+
}
1180+
11431181
// Tests that a convex path element can contain a rect or round rect, allowing the stack to be
11441182
// simplified
11451183
DEF_TEST(GrClipStack_ConvexPathContains, r) {

0 commit comments

Comments
 (0)