Skip to content

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

Merged
merged 1 commit into from
Oct 5, 2018

Conversation

gw3583
Copy link
Contributor

@gw3583 gw3583 commented Oct 4, 2018

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 Reviewable

@gw3583
Copy link
Contributor Author

gw3583 commented Oct 4, 2018

r? @gankro

Pending try:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=c94d12d7017379f652427b658247b959a57fa59c

I think this makes the shadow handling code a bit conceptually simpler too, in addition to being useful for the reasons above.

Copy link
Contributor

@Gankra Gankra left a 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!"
Copy link
Contributor

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

Copy link
Contributor Author

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()
}

Copy link
Contributor

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)

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 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).

Copy link
Contributor

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)
//
Copy link
Contributor

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"); ... }

Copy link
Contributor

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)

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'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?

Copy link
Contributor

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());
Copy link
Contributor

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);
}
}
Copy link
Contributor

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

Copy link
Contributor Author

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.
@gw3583
Copy link
Contributor Author

gw3583 commented Oct 5, 2018

OK, try run looks good. There is one failure, but that's due to the revert of the pre/post-translate patch by @staktrace .

@Gankra
Copy link
Contributor

Gankra commented Oct 5, 2018

@bors-servo r+

@bors-servo
Copy link
Contributor

📌 Commit 90f3d14 has been approved by Gankro

@bors-servo
Copy link
Contributor

⌛ Testing commit 90f3d14 with merge fb1705b...

bors-servo pushed a commit that referenced this pull request Oct 5, 2018
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 -->
@gw3583
Copy link
Contributor Author

gw3583 commented Oct 5, 2018

@gankro Sounds good, thanks!

@bors-servo
Copy link
Contributor

☀️ Test successful - status-appveyor, status-taskcluster
Approved by: Gankro
Pushing fb1705b to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants