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

Conversation

@flar
Copy link
Contributor

@flar flar commented Aug 16, 2024

The SkRect::intersect and SkIRect::intersect methods return values that must be handled or the calling code might end up with a non-empty answer for non-intersecting rectangles. There were 3 or 4 places in our code that we weren't doing this so now we check them all, in some cases even if we believe that the answer will not be empty.

This is prep work so that Skia can add [[nodiscard]] directives to these 2 methods so that nobody else makes that mistake.

@flar flar requested a review from knopp August 16, 2024 10:18
[[maybe_unused]]
bool ret2 = res.frame_damage.intersect(frame_clip);
if (!ret1 || !ret2) {
FML_LOG(ERROR) << "intersect was not handled: " << ret1 << ", " << ret2;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@knopp this is the interesting case here where I wanted to either turn these into FML_DCHECK(ret) calls or write a test case that verifies that we do the right thing here.

I was unable to figure out how to write a test case that specifically tested this case (see my ifdef'd out test case in diff_context_unittests.cc), but when I put in the FML_DCHECK calls they got triggered in several flow layer tests.

Please advise how I can write a better test case in the unittests and which gets the wrong answer if we don't handle the return values here and I'll change these to deal with the return value. Typically I use if (!r1.intersect(r2)) { r1.setEmpty(); } if that will work in this case...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obviously the other tests in the *_layer_unittests.cc files do run into this case, but they aren't specifically trying to test it, so they may either be hitting this as a side effect of the way they're written to test something else, or they are bad tests for what they are really trying to do. In either case, I don't want to rely on them to test this particular change...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking further into the cases where the other unit tests were triggering this code, in all cases it was because the damage rects were already empty so ignoring the return value in that case didn't matter as the result rects were already empty and did not "need" to be set to empty again.

So, I'd like to be able to rule this out or find a test case that can trigger it without the damage rects being "already empty".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, I fixed the test code and found a way to trigger this problem so I just need a review now.

EXPECT_EQ(damage.buffer_damage, SkIRect::MakeLTRB(16, 16, 64, 64));
}

#ifdef NOT_WORKING_YET
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@knopp here was my attempt to write a test case that triggered the above code, but it didn't seem to work (in fact it crashed a few times as I was working on it).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take a look at this first thing tomorrow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually fixed it. The reason I was having trouble reproducing it is that the test helper function was inserting a clip layer which effectively deleted the out-of-range layer. By "rolling my own" in the test case I was able to get the code that checks the return value to actually encounter a case where the frame/buffer damage was not empty, but needed to be set to empty and the test case triggers that condition now.

I wonder if there were any bugs in partial repaint caused by this? (i.e. something animating off screen and we kept repainting even though we didn't need to?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I was thinking. I don't know how likely it is though for a layer tree like that to come from a framework in practice since there are are usually clips present.

@flar flar changed the title Check return values for SkRect::intersect Check return values for S[I]kRect::intersect Aug 16, 2024
@flar flar changed the title Check return values for S[I]kRect::intersect Check return values for Sk[I]Rect::intersect Aug 16, 2024
Copy link
Member

@knopp knopp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for catching this.

@flar flar added the autosubmit Merge PR when tree becomes green via auto submit App label Aug 20, 2024
@auto-submit auto-submit bot merged commit 0ac9e97 into flutter:main Aug 20, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Aug 20, 2024
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Aug 20, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

autosubmit Merge PR when tree becomes green via auto submit App

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants