From 1c09b1d8aae5074669560d81d272414f4d0d2793 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Wed, 26 Aug 2015 08:17:40 -0700 Subject: [PATCH] Split out layered child stacking contexts in display lists This patch is in preparation for more dynamic layerization of the pieces of display lists. It also prevents having to sort the children by z-index multiple times. --- components/gfx/display_list/mod.rs | 52 ++++++++++++++++++++++-------- components/gfx/paint_task.rs | 10 ++---- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 5713a91d71e..9555a3fb98f 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -98,6 +98,8 @@ pub struct DisplayList { pub outlines: LinkedList, /// Child stacking contexts. pub children: LinkedList>, + /// Child stacking contexts with their own layers. + pub layered_children: LinkedList>, } impl DisplayList { @@ -112,6 +114,28 @@ impl DisplayList { positioned_content: LinkedList::new(), outlines: LinkedList::new(), children: LinkedList::new(), + layered_children: LinkedList::new(), + } + } + + /// Sort all children by their z-index and split layered children into their own + /// section of the display list. + /// TODO(mrobinson): This should properly handle unlayered children that are on + /// top of layered children. + #[inline] + pub fn sort_and_layerize_children(&mut self) { + let mut children: SmallVec<[Arc; 8]> = SmallVec::new(); + while let Some(stacking_context) = self.children.pop_front() { + children.push(stacking_context); + } + children.sort_by(|this, other| this.z_index.cmp(&other.z_index)); + + for stacking_context in children.into_iter() { + if stacking_context.layer.is_some() { + self.layered_children.push_back(stacking_context); + } else { + self.children.push_back(stacking_context); + } } } @@ -126,6 +150,7 @@ impl DisplayList { self.positioned_content.append(&mut other.positioned_content); self.outlines.append(&mut other.outlines); self.children.append(&mut other.children); + self.layered_children.append(&mut other.children); } /// Merges all display items from all non-float stacking levels to the `float` stacking level. @@ -222,6 +247,15 @@ impl DisplayList { &indentation[0..MIN_INDENTATION_LENGTH]); } } + if !self.layered_children.is_empty() { + println!("{} Layered children stacking contexts list length: {}", + indentation, + self.layered_children.len()); + for stacking_context in &self.layered_children { + stacking_context.print(indentation.clone() + + &indentation[0..MIN_INDENTATION_LENGTH]); + } + } } } @@ -266,7 +300,7 @@ pub struct StackingContext { impl StackingContext { /// Creates a new stacking context. #[inline] - pub fn new(display_list: Box, + pub fn new(mut display_list: Box, bounds: &Rect, overflow: &Rect, z_index: i32, @@ -278,6 +312,7 @@ impl StackingContext { establishes_3d_context: bool, scrolls_overflow_area: bool) -> StackingContext { + display_list.sort_and_layerize_children(); StackingContext { display_list: display_list, bounds: *bounds, @@ -317,15 +352,6 @@ impl StackingContext { display_list.print_items("####".to_owned()); } - // Sort positioned children according to z-index. - let mut positioned_children: SmallVec<[Arc; 8]> = SmallVec::new(); - for kid in &display_list.children { - if kid.layer.is_none() { - positioned_children.push((*kid).clone()); - } - } - positioned_children.sort_by(|this, other| this.z_index.cmp(&other.z_index)); - // Set up our clip rect and transform. let old_transform = paint_subcontext.draw_target.get_transform(); let xform_2d = Matrix2D::new(transform.m11, transform.m12, @@ -340,7 +366,7 @@ impl StackingContext { } // Step 3: Positioned descendants with negative z-indices. - for positioned_kid in &*positioned_children { + for positioned_kid in &display_list.children { if positioned_kid.z_index >= 0 { break } @@ -382,7 +408,7 @@ impl StackingContext { } // Step 9: Positioned descendants with nonnegative, numeric z-indices. - for positioned_kid in &*positioned_children { + for positioned_kid in &self.display_list.children { if positioned_kid.z_index < 0 { continue } @@ -614,7 +640,7 @@ pub fn find_stacking_context_with_layer_id(this: &Arc, layer_id Some(_) | None => {} } - for kid in &this.display_list.children { + for kid in &this.display_list.layered_children { match find_stacking_context_with_layer_id(kid, layer_id) { Some(stacking_context) => return Some(stacking_context), None => {} diff --git a/components/gfx/paint_task.rs b/components/gfx/paint_task.rs index 43ca598c38a..0d0a8bf1e49 100644 --- a/components/gfx/paint_task.rs +++ b/components/gfx/paint_task.rs @@ -28,7 +28,6 @@ use profile_traits::mem::{self, ReportsChan}; use profile_traits::time::{self, profile}; use rand::{self, Rng}; use skia::gl_context::GLContext; -use smallvec::SmallVec; use std::borrow::ToOwned; use std::collections::HashMap; use std::mem as std_mem; @@ -394,14 +393,11 @@ impl PaintTask where C: PaintListener + Send + 'static { } }; - // Sort positioned children according to z-index. - let mut positioned_children: SmallVec<[Arc; 8]> = SmallVec::new(); - for kid in &stacking_context.display_list.children { - positioned_children.push((*kid).clone()); + for kid in stacking_context.display_list.children.iter() { + build(properties, &**kid, &page_position, &transform, &perspective, next_parent_id) } - positioned_children.sort_by(|this, other| this.z_index.cmp(&other.z_index)); - for kid in positioned_children.iter() { + for kid in stacking_context.display_list.layered_children.iter() { build(properties, &**kid, &page_position, &transform, &perspective, next_parent_id) } }