-
Notifications
You must be signed in to change notification settings - Fork 294
Refactor shadow flattening to do work in pop_all_shadows. #3167
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
r? @gankro Pending try: I think this makes the shadow handling code a bit conceptually simpler too, in addition to being useful for the reasons above. |
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.
Actual details seem fine, but I'd prefer we remove the contortions to support the unused pattern I discuss in the review.
@@ -1207,7 +1183,7 @@ impl<'a> DisplayListFlattener<'a> { | |||
} | |||
|
|||
assert!( | |||
self.shadow_stack.is_empty(), | |||
self.pending_shadow_items.is_empty(), | |||
"Found unpopped text shadows when popping stacking context!" |
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.
The text of this assertion is out of date
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.
Fixed
pub fn is_empty(&self) -> bool { | ||
self.prim_instances.is_empty() | ||
} | ||
|
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.
An idle reminder that this sort of thing can go awry if item culling is too aggressive -- e.g. transparent text can be dropped from rendering, but still casts a visible shadow.
(We have to explicitly prevent this optimization in gecko when building the wr DL)
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 think that's not relevant in this case - because it's just checking if any primitives are present, and if not, they can't cast a shadow (e.g. if the alpha of the primitives was all zero so they weren't added).
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.
yeah we have several tests that incidentally check that invisible things cast shadows anyway
// - Add *any* primitives that remain in the item list to this shadow. | ||
// If the item is a primitive: | ||
// - Add that primitive as a normal item (if alpha > 0) | ||
// |
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.
This all seems a bit heavy-handed to explicitly support the (never emitted, and quite frankly low-value) pattern the display-list format incidentally implies of [shadow, item, shadow, item, pop-all]
. I would prefer that we just write if off and do:
shadows: Vec<Shadow>,
shadow_prims: Vec<PendingItem>,
fn add_shadow(..) { assert!(shadow_prims.is_empty(), "shadows and items being interleaved isn't supported"); ... }
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.
(it's possible I checked in a test that checks this pattern works but i'm fully convinced that it's not worth our time anymore)
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 fine with doing that, although hesitant to change that now without testing servo as well. Would you be fine with landing it like this and I'll file an issue to simplify this API in the future?
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 fairly certain servo wouldn't emit it, but yeah I guess sure, I can do the followup to unblock you.
let pipeline_id = self.sc_stack.last().unwrap().pipeline_id; | ||
let max_clip = LayoutRect::max_rect(); | ||
let mut items = mem::replace(&mut self.pending_shadow_items, VecDeque::new()); |
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.
Just ~18 more weeks until NLL!!!
// Add the new primitive to the shadow picture. | ||
shadow_pic.add_primitive(shadow_prim_index); | ||
} | ||
} |
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.
blindly assuming this block is a cut-paste from add_primitive
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.
Yep, it is.
This simplifies how shadow contexts are handled, by deferring the work of adding shadows and primitives until pop_all_shadows. Longer explanation below: Instead of adding a picture primitive, and then adding primitives to it, the picture API will be modified to take an immutable list of primitives during construction. This will be part of the changes to support interning of primitives for picture caching. This patch allows all the primitives for a shadow to be created before the shadow picture itself is added / created, which is required to work with these planned changes. Additionally, we can now detect if the shadow ended up having no primitives in it, and skip adding the picture in this case. This is probably a small win in some cases.
OK, try run looks good. There is one failure, but that's due to the revert of the pre/post-translate patch by @staktrace . |
@bors-servo r+ |
📌 Commit 90f3d14 has been approved by |
Refactor shadow flattening to do work in pop_all_shadows. This simplifies how shadow contexts are handled, by deferring the work of adding shadows and primitives until pop_all_shadows. Longer explanation below: Instead of adding a picture primitive, and then adding primitives to it, the picture API will be modified to take an immutable list of primitives during construction. This will be part of the changes to support interning of primitives for picture caching. This patch allows all the primitives for a shadow to be created before the shadow picture itself is added / created, which is required to work with these planned changes. Additionally, we can now detect if the shadow ended up having no primitives in it, and skip adding the picture in this case. This is probably a small win in some cases. <!-- 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/3167) <!-- Reviewable:end -->
@gankro Sounds good, thanks! |
☀️ Test successful - status-appveyor, status-taskcluster |
This simplifies how shadow contexts are handled, by deferring the
work of adding shadows and primitives until pop_all_shadows.
Longer explanation below:
Instead of adding a picture primitive, and then adding primitives
to it, the picture API will be modified to take an immutable list
of primitives during construction. This will be part of the changes
to support interning of primitives for picture caching. This patch
allows all the primitives for a shadow to be created before the
shadow picture itself is added / created, which is required to work
with these planned changes.
Additionally, we can now detect if the shadow ended up having no
primitives in it, and skip adding the picture in this case. This
is probably a small win in some cases.
This change is