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 <bsalomon@google.com> Reviewed-by: Chris Dalton <csmartdalton@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
0dec9927af
commit
d30e9efdab
@ -125,7 +125,7 @@ static bool shape_contains_rect(
|
||||
if (!mixedAAMode && aToDevice == bToDevice) {
|
||||
// A and B are in the same coordinate space, so don't bother mapping
|
||||
return a.conservativeContains(b);
|
||||
} else if (bToDevice.isIdentity() && aToDevice.isScaleTranslate()) {
|
||||
} else if (bToDevice.isIdentity() && aToDevice.preservesAxisAlignment()) {
|
||||
// Optimize the common case of draws (B, with identity matrix) and axis-aligned shapes,
|
||||
// instead of checking the four corners separately.
|
||||
SkRect bInA = b;
|
||||
@ -543,7 +543,7 @@ void GrClipStack::RawElement::simplify(const SkIRect& deviceBounds, bool forceAA
|
||||
// Except for axis-aligned clip rects, upgrade to AA when forced. We skip axis-aligned clip
|
||||
// rects because a non-AA axis aligned rect can always be set as just a scissor test or window
|
||||
// rect, avoiding an expensive stencil mask generation.
|
||||
if (forceAA && !(fShape.isRect() && fLocalToDevice.isScaleTranslate())) {
|
||||
if (forceAA && !(fShape.isRect() && fLocalToDevice.preservesAxisAlignment())) {
|
||||
fAA = GrAA::kYes;
|
||||
}
|
||||
|
||||
@ -551,7 +551,7 @@ void GrClipStack::RawElement::simplify(const SkIRect& deviceBounds, bool forceAA
|
||||
// mapped bounds of the shape.
|
||||
fOuterBounds = GrClip::GetPixelIBounds(outer, fAA, BoundsType::kExterior);
|
||||
|
||||
if (fLocalToDevice.isScaleTranslate()) {
|
||||
if (fLocalToDevice.preservesAxisAlignment()) {
|
||||
if (fShape.isRect()) {
|
||||
// The actual geometry can be updated to the device-intersected bounds and we can
|
||||
// know the inner bounds
|
||||
|
@ -1108,6 +1108,7 @@ DEF_TEST(GrClipStack_DeviceRRect, r) {
|
||||
DEF_TEST(GrClipStack_ScaleTranslate, r) {
|
||||
SkMatrix lm = SkMatrix::Scale(2.f, 4.f);
|
||||
lm.postTranslate(15.5f, 14.3f);
|
||||
SkASSERT(lm.preservesAxisAlignment() && lm.isScaleTranslate());
|
||||
|
||||
// Rect -> matrix is applied up front
|
||||
SkRect rect = {0.f, 0.f, 10.f, 10.f};
|
||||
@ -1140,6 +1141,43 @@ DEF_TEST(GrClipStack_ScaleTranslate, r) {
|
||||
.finishTest());
|
||||
}
|
||||
|
||||
// Tests that rect-stays-rect matrices that are not scale+translate matrices are pre-applied.
|
||||
DEF_TEST(GrClipStack_PreserveAxisAlignment, r) {
|
||||
SkMatrix lm = SkMatrix::RotateDeg(90.f);
|
||||
lm.postTranslate(15.5f, 14.3f);
|
||||
SkASSERT(lm.preservesAxisAlignment() && !lm.isScaleTranslate());
|
||||
|
||||
// Rect -> matrix is applied up front
|
||||
SkRect rect = {0.f, 0.f, 10.f, 10.f};
|
||||
run_test_case(r, TestCase::Build("r90+rect", kDeviceBounds)
|
||||
.actual().rect(rect, lm, GrAA::kYes, SkClipOp::kIntersect)
|
||||
.finishElements()
|
||||
.expect().rect(lm.mapRect(rect), GrAA::kYes, SkClipOp::kIntersect)
|
||||
.finishElements()
|
||||
.state(GrClipStack::ClipState::kDeviceRect)
|
||||
.finishTest());
|
||||
|
||||
// RRect -> matrix is applied up front
|
||||
SkRRect localRRect = SkRRect::MakeRectXY(rect, 2.f, 2.f);
|
||||
SkRRect deviceRRect;
|
||||
SkAssertResult(localRRect.transform(lm, &deviceRRect));
|
||||
run_test_case(r, TestCase::Build("r90+rrect", kDeviceBounds)
|
||||
.actual().rrect(localRRect, lm, GrAA::kYes, SkClipOp::kIntersect)
|
||||
.finishElements()
|
||||
.expect().rrect(deviceRRect, GrAA::kYes, SkClipOp::kIntersect)
|
||||
.finishElements()
|
||||
.state(GrClipStack::ClipState::kDeviceRRect)
|
||||
.finishTest());
|
||||
|
||||
// Path -> matrix is NOT applied
|
||||
run_test_case(r, TestCase::Build("r90+path", kDeviceBounds)
|
||||
.actual().intersect().localToDevice(lm).path(make_octagon(rect))
|
||||
.finishElements()
|
||||
.expectActual()
|
||||
.state(GrClipStack::ClipState::kComplex)
|
||||
.finishTest());
|
||||
}
|
||||
|
||||
// Tests that a convex path element can contain a rect or round rect, allowing the stack to be
|
||||
// simplified
|
||||
DEF_TEST(GrClipStack_ConvexPathContains, r) {
|
||||
|
Loading…
Reference in New Issue
Block a user