-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] separate algorithm for computing render target size. #54604
Changes from 1 commit
9d59af1
a935594
7aa3a48
54cea5a
e6e56d8
98a5d68
81ccaa0
55a6a50
3591395
a8f0e2c
1c55cf5
a6f5f21
a646c1b
8daf291
199a846
b2eb6b9
d347783
24442e0
78b7f60
2a4ac2d
3eff88b
04b5be5
086abb8
4a5f30b
fa3afcc
4e7a707
e0105d7
e8f34ac
8a3d1ef
24ef59a
0cae7a8
ae57e62
bc2276e
b3ab833
334e5e9
82a6621
5011b3c
008b6f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,7 +22,6 @@ std::optional<Rect> ComputeSaveLayerCoverage( | |
| // developer, in this case we still use the content coverage even if the | ||
| // saveLayer itself is unbounded. | ||
| bool save_layer_is_unbounded = has_backdrop_filter || destructive_blend; | ||
|
|
||
| // Otherwise, the save layer is bounded by either its contents or by | ||
| // a specified coverage limit. In these cases the coverage value is used | ||
| // and intersected with the coverage limit. | ||
|
|
@@ -40,22 +39,17 @@ std::optional<Rect> ComputeSaveLayerCoverage( | |
| // into any computed bounds. That is, a canvas scaling transform of 0.5 | ||
| // changes the coverage of the contained entities directly and doesnt need to | ||
| // be additionally incorporated into the coverage computation here. | ||
| std::optional<Rect> result_bounds; | ||
| if (image_filter) { | ||
| std::optional<Rect> source_coverage_limit = | ||
| image_filter->GetSourceCoverage(effect_transform, coverage_limit); | ||
| if (!source_coverage_limit.has_value()) { | ||
| // No intersection with parent coverage limit. | ||
| return std::nullopt; | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm trying to wrap my head around this. Why aren't we handing in content_coverage? That might be the same as coverage_limit if there was flooding, but it could be less.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure what you mean exactly. A case where this would fire is, you an IF that translates a SL entirely offscreen, or somethng like that.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was a case of clicking on the wrong line. I was referring to the fact that you pass the coverage_limit in to the GetSourceCoverage call and I was pointing out that the content size might be much smaller. But, in typing that out I suddenly realized that the point there is not to compute the actual result, but to compute the "worst case scenario for input pixels" against which you clip the indicated coverage. So, I think this is fine, but I didn't get the explanation on my first reading. The intersection with the source coverage happens right after this comment, so this code is only making the current input coverage smaller - but based on the reverse filter size of the output limit - which means passing in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I moved the comment around a bit so it should be clearer. |
||
| result_bounds = input_coverage.Intersection(source_coverage_limit.value()); | ||
|
|
||
| // Finally, transform the resulting bounds back into the global coordinate | ||
| // space. | ||
| if (result_bounds.has_value()) { | ||
| return result_bounds->TransformBounds(effect_transform); | ||
| } | ||
| return std::nullopt; | ||
| // Transform the input coverage into the global coordinate space before | ||
| // computing the bounds limit intersection. | ||
| return input_coverage.TransformBounds(effect_transform) | ||
| .Intersection(source_coverage_limit.value()); | ||
| } | ||
|
|
||
| // If the input coverage is maximum, just return the coverage limit that | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@flar I think this is a bug in that we can have a saveLayer with bounds but end up blowing away the coverage value. In the case I saw, we did a with bounds and a backdrop filter, the layer itself had no contents. The bounds from caller were overwritten to empty, however the save layer state of bounds from caller was still reported as true, which makes it look like the caller specified empty bounds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case I can work around it by ignoring bounds from caller when there is a bdf, as I don't believe its possible to specify saveLayer bounds on backdrop filters from flutter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, or maybe its the line above actually
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Um, the bounds of the content of the saveLayer bounds are empty and that is correct. It doesn't matter if the bounds came from the caller or not. Empty saveLayer bounds do not mean that the saveLayer is a NOP, they just mean that there is nothing to draw into the bounds.
But, the backdrop filter is a separate aspect of the operation.
Everything is working as intended, but you are interpreting the bounds as if it contains the BDF, but it does not. It is providing you with information about the contents of the layer and you must combine that with other information to figure out the RT size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case I am specifying non empty bounds of a particular size on a savayer with no content. The bounds are overwritten to empty here
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are specifying non-empty bounds? Are you saying that you have:
if that is the case then you claimed that there was content that was 100x100 in size, but you gave no content, so I corrected it to 0x0. You also specified a backdrop filter which also (completely 100% independently of the saveLayer argument) contribute to the resulting output.
Everything there is working as intended.
If you want to clip the BDF, you have to put a clip around the saveLayer, as in:
(The outer save/restore are only if you are installing that clip just for the SaveLayer.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So bounds from caller really isn't what I wanted then. Bdf aside, the original reason I incorporated it was to try and deal with unbounded contents. But instead of bounds from caller I should be using the content clipped setting then
Thanks for the pointers!
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you'd use the content clipped setting for, though. It means that the natural bounds of the content extends outside of the bounds provided in the saveLayer, such as:
In that case the layer was suggested to capture a 10x10 set of pixels, though the rendering commands draw to a larger area. The legacy behavior of this is that only the 10x10 set of pixels is captured (in scale-translate cases).
It's primary intent is for the case where group opacity "might" be used and in that case it is a contra-indication. If that SaveLayer had alpha in the paint then you can't just completely elide the SaveLayer like you might do if you are applying opacity inheritance optimizations, because that would draw too much. It has to look like you actually allocated the layer, drew the content, and then faded it - which means some form of clipping would be involved. One solution might be to replace the SaveLayer with a Save and a clip, but so far the Skia implementation has simply avoided the opacity optimization instead. It is possible to notice the difference, but it depends on other factors like transform, etc. We talked about this before and the response was that we didn't want to do the clip in that case because it was expensive - except that the alternative to doing a clip is to use an alternate layer. Which would be faster? A clip or the layer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A clip will definitely be faster.
basically for destructive blends that flood the clip. But actually it sounds like display list bounds will already take that into account and I can take them as is?