Skip to content
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

Don't create empty stacking contexts in display lists #26758

Merged
merged 3 commits into from Jun 9, 2020
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

layout: Don't built stacking contexts or display lists for empty blocks.

  • Loading branch information
jdm committed Jun 9, 2020
commit 08427ccee5e9e9d94155c1030d016ffd8ab87dd6
@@ -1571,6 +1571,11 @@ impl Fragment {
return;
}

// If this fragment takes up no space, we don't need to build any display items for it.
if self.has_non_invertible_transform() {
return;
}

debug!(
"Fragment::build_display_list at rel={:?}, abs={:?}: {:?}",
self.border_box, stacking_relative_border_box, self
@@ -2376,6 +2381,11 @@ impl BlockFlow {
state: &mut StackingContextCollectionState,
flags: StackingContextCollectionFlags,
) {
// This block flow produces no stacking contexts if it takes up no space.
if self.has_non_invertible_transform() {
return;
}

let mut preserved_state = SavedStackingContextCollectionState::new(state);

let stacking_context_type = self.stacking_context_type(flags);
@@ -217,6 +217,12 @@ impl StackingContext {
parent_clipping_and_scrolling: ClippingAndScrolling,
established_reference_frame: Option<ClipScrollNodeIndex>,
) -> StackingContext {
if let Some(ref t) = transform {
// These are used as scale values by webrender, and it can't handle
// divisors of 0 when scaling.
assert_ne!(t.m11, 0.);
assert_ne!(t.m22, 0.);
}
StackingContext {
id,
context_type,
@@ -273,6 +273,22 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
might_have_floats_in_or_out
}

fn has_non_invertible_transform(&self) -> bool {
if !self.class().is_block_like() ||
self.as_block()
.fragment
.style
.get_box()
.transform
.0
.is_empty()
{
return false;
}

self.as_block().fragment.has_non_invertible_transform()
}

fn get_overflow_in_parent_coordinates(&self) -> Overflow {
// FIXME(#2795): Get the real container size.
let container_size = Size2D::zero();
@@ -1160,7 +1176,9 @@ impl BaseFlow {
state: &mut StackingContextCollectionState,
) {
for kid in self.children.iter_mut() {
kid.collect_stacking_contexts(state);
if !kid.has_non_invertible_transform() {
kid.collect_stacking_contexts(state);
}
}
}

@@ -2730,6 +2730,12 @@ impl Fragment {
self.style().get_box().perspective != Perspective::None
}

/// Returns true if this fragment has a transform applied that causes it to take up no space.
pub fn has_non_invertible_transform(&self) -> bool {
self.transform_matrix(&Rect::default())
.map_or(false, |matrix| !matrix.is_invertible())
}

/// Returns true if this fragment establishes a new stacking context and false otherwise.
pub fn establishes_stacking_context(&self) -> bool {
// Text fragments shouldn't create stacking contexts.
@@ -1871,6 +1871,11 @@ impl Flow for InlineFlow {
let previous_cb_clipping_and_scrolling = state.containing_block_clipping_and_scrolling;

for fragment in self.fragments.fragments.iter_mut() {
// If a particular fragment would establish a stacking context but has a transform
// applied that causes it to take up no space, we can skip it entirely.
if fragment.has_non_invertible_transform() {
continue;
}
state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling;

let abspos_containing_block = fragment.style.get_box().position != Position::Static;
@@ -346,6 +346,10 @@ pub struct BuildDisplayList<'a> {
impl<'a> BuildDisplayList<'a> {
#[inline]
pub fn traverse(&mut self, flow: &mut dyn Flow) {
if flow.has_non_invertible_transform() {
return;
}

let parent_stacking_context_id = self.state.current_stacking_context_id;
self.state.current_stacking_context_id = flow.base().stacking_context_id;

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.