-
Notifications
You must be signed in to change notification settings - Fork 290
Major refactoring of how clips are processed down the pipeline #512
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Now that I think of it, this might be incorrect. I'm borrowing the |
I rewrote the code to solve the concern by cloning the aux lists into the |
At the moment, I try do avoid passing the auxiliary lists around to many APIs, and instead resolve them all at one part of the frame. This has the added advantage that we only resolve items from the auxiliary lists when they first come on screen, avoiding a large upfront cost for a new scene. Is it possible do just make clips work the same way as all the other primitives, or does something prevent that? |
☔ The latest upstream changes (presumably #514) made this pull request unmergeable. Please resolve the merge conflicts. |
Redesigned the whole thing after talking to @glennw . The auxiliary lists are no longer accessed at all during the primitive population, and are only passed down (by reference, no cloning) during the frame building. This is also an optimization, since we only resolve the aux lists for visible primitives now. |
@@ -58,15 +58,38 @@ pub struct PrimitiveCacheInfo { | |||
pub key: PrimitiveCacheKey, | |||
} | |||
|
|||
#[derive(Debug)] | |||
pub enum PrimitiveClipInfo { |
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.
Is the idea here that it gets resolved from Complex / Region to GpuAddress? Would it make more sense to split into a "source" and "resolved" field perhaps?
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.
Yes, that's the idea. The reason I decided not to have separate fields for source/resolved is because they are mutually exclusive (or at least, the source make no sense once the resolved is set), which is reflected here by the use of enum
. I agree this is probably the most controversial aspect of this PR, just not seeing a better solution at the moment.
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.
OK, I think that's fine - we might like to make some of the conditions marked as unreachable!() or something like that (e.g. if the non-resolved type gets encountered after it should always have been resolved). But no need to do that now.
} | ||
|
||
impl PrimitiveClipInfo { | ||
pub fn is_clipped(&self) -> bool { |
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.
Will this return true even for a rectangular clip only? (If so, that will prevent occlusion culling where it is being used).
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 right, this part doesn't seem right. If it's called after after the prepare_*
body (and I think it does), the only variant here would be GpuAddress
. Will be fixed in a minute.
auxiliary_lists: &AuxiliaryLists) -> bool { | ||
let metadata = &mut self.cpu_metadata[prim_index.0]; | ||
debug_assert!(metadata.need_to_build_cache); | ||
metadata.need_to_build_cache = false; | ||
|
||
if let Some(mask_key) = metadata.mask_image { | ||
let tex_cache = resource_cache.get_image(mask_key, ImageRendering::Auto, frame_id); | ||
let clip_data_mask = match metadata.clip_info.as_ref() { |
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.
Does this mean that we'll end up with a complex clip region enabled when the clip region is a simple rect with zero radius? If so, that will introduce a lot more expensive clip shaders than needed.
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 don't think we handled the zero radius anywhere except this piece:
if scrollbar_prim.border_radius == 0.0 {
- self.prim_store.set_complex_clip(scrollbar_prim.prim_index, None);
+ self.prim_store.unset_complex_clip(scrollbar_prim.prim_index)
} else {
The general case of no ComplexClipRegion
given is handled below, here:
let clip_data = match clips.len() {
0 if clip_region.image_mask.is_none() => None,
So I don't think this PR changes the logic in a way that makes the shaders more expensive.
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.
Yup, that should handle it.
@kvark I ran the mozilla css tests subset with this patch - border_radius_clip_a.html fails but everything else passes. Could you take a look at that failure when you have time? |
@glennw I was also checking the tests, saw that one, and confirmed it happens without this PR equally. |
Generally looks good to me - this fits in quite well with the rest of the items that use ItemRange. Just need to get the test failures sorted and then this should be good to go. |
☔ The latest upstream changes (presumably #523) made this pull request unmergeable. Please resolve the merge conflicts. |
9a44521
to
c553d77
Compare
…eparation to multiple transformed clip support. Removed MaskImageSource, introduced PrimitiveClipSource to the metadata. Avoided cloning the auxiliary lists map.
@bors-servo r+ |
📌 Commit 4ba3493 has been approved by |
⚡ Test exempted - status |
Major refactoring of how clips are processed down the pipeline This moves the clipping hack down the road (from `Frame` to `FrameBuilder`), allowing to eventually implement multiple transformed clips properly (#498), as discussed on IRC with @glennw . <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/512) <!-- Reviewable:end -->
Looks good, thanks! |
This moves the clipping hack down the road (from
Frame
toFrameBuilder
), allowing to eventually implement multiple transformed clips properly (#498), as discussed on IRC with @glennw .This change is