diff options
-rw-r--r-- | components/gfx/display_list/mod.rs | 146 | ||||
-rw-r--r-- | components/gfx/paint_task.rs | 34 | ||||
-rw-r--r-- | components/layout/display_list_builder.rs | 40 | ||||
-rw-r--r-- | components/layout/layout_task.rs | 16 | ||||
-rw-r--r-- | components/msg/compositor_msg.rs | 21 |
5 files changed, 152 insertions, 105 deletions
diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 792bb4df7ac..f1bd0efcbec 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -76,6 +76,51 @@ impl OpaqueNode { } } +/// LayerInfo is used to store PaintLayer metadata during DisplayList construction. +/// It is also used for tracking LayerIds when creating layers to preserve ordering when +/// layered DisplayItems should render underneath unlayered DisplayItems. +#[derive(Clone, Copy, Debug, HeapSizeOf, Deserialize, Serialize)] +pub struct LayerInfo { + /// The base LayerId of this layer. + pub layer_id: LayerId, + + /// The scroll policy of this layer. + pub scroll_policy: ScrollPolicy, + + /// The subpage that this layer represents, if there is one. + pub subpage_layer_info: Option<SubpageLayerInfo>, + + /// The id for the next layer in the sequence. This is used for synthesizing + /// layers for content that needs to be displayed on top of this layer. + pub next_layer_id: LayerId, +} + +impl LayerInfo { + pub fn new(id: LayerId, + scroll_policy: ScrollPolicy, + subpage_layer_info: Option<SubpageLayerInfo>) + -> LayerInfo { + LayerInfo { + layer_id: id, + scroll_policy: scroll_policy, + subpage_layer_info: subpage_layer_info, + next_layer_id: id.companion_layer_id(), + } + } + + fn next(&mut self) -> LayerInfo { + let new_layer_info = LayerInfo::new(self.next_layer_id, self.scroll_policy, None); + self.next_layer_id = self.next_layer_id.companion_layer_id(); + new_layer_info + } + + fn next_with_scroll_policy(&mut self, scroll_policy: ScrollPolicy) -> LayerInfo { + let mut new_layer_info = self.next(); + new_layer_info.scroll_policy = scroll_policy; + new_layer_info + } +} + /// Display items that make up a stacking context. "Steps" here refer to the steps in CSS 2.1 /// Appendix E. /// @@ -474,15 +519,8 @@ pub struct StackingContext { /// Whether this stacking context scrolls its overflow area. pub scrolls_overflow_area: bool, - /// The scrolling policy of this stacking context, if it is promoted - /// to a layer. - pub scroll_policy: ScrollPolicy, - - /// The layer id for this stacking context, if there is one. - pub layer_id: Option<LayerId>, - - /// The subpage that this stacking context represents, if there is one. - pub subpage_layer_info: Option<SubpageLayerInfo>, + /// The layer info for this stacking context, if there is any. + pub layer_info: Option<LayerInfo>, } impl StackingContext { @@ -498,9 +536,7 @@ impl StackingContext { perspective: Matrix4, establishes_3d_context: bool, scrolls_overflow_area: bool, - scroll_policy: ScrollPolicy, - layer_id: Option<LayerId>, - subpage_layer_info: Option<SubpageLayerInfo>) + layer_info: Option<LayerInfo>) -> StackingContext { let mut stacking_context = StackingContext { display_list: display_list, @@ -513,16 +549,14 @@ impl StackingContext { perspective: perspective, establishes_3d_context: establishes_3d_context, scrolls_overflow_area: scrolls_overflow_area, - scroll_policy: scroll_policy, - layer_id: layer_id, - subpage_layer_info: subpage_layer_info, + layer_info: layer_info, }; StackingContextLayerCreator::add_layers_to_preserve_drawing_order(&mut stacking_context); stacking_context } pub fn create_layered_child(&self, - layer_id: LayerId, + layer_info: LayerInfo, display_list: Box<DisplayList>) -> StackingContext { StackingContext { display_list: display_list, @@ -535,9 +569,7 @@ impl StackingContext { perspective: Matrix4::identity(), establishes_3d_context: false, scrolls_overflow_area: self.scrolls_overflow_area, - scroll_policy: self.scroll_policy, - layer_id: Some(layer_id), - subpage_layer_info: self.subpage_layer_info, + layer_info: Some(layer_info), } } @@ -569,7 +601,7 @@ impl StackingContext { // If a layer is being used, the transform for this layer // will be handled by the compositor. - let transform = match self.layer_id { + let transform = match self.layer_info { Some(..) => *transform, None => transform.mul(&self.transform), }; @@ -631,30 +663,37 @@ impl StackingContext { } fn print_with_tree(&self, print_tree: &mut PrintTree) { - if self.layer_id.is_some() { + if self.layer_info.is_some() { print_tree.new_level(format!("Layered StackingContext at {:?} with overflow {:?}:", - self.bounds, - self.overflow)); + self.bounds, + self.overflow)); } else { print_tree.new_level(format!("StackingContext at {:?} with overflow {:?}:", - self.bounds, - self.overflow)); + self.bounds, + self.overflow)); } self.display_list.print_with_tree(print_tree); print_tree.end_level(); } + + fn scroll_policy(&self) -> ScrollPolicy { + match self.layer_info { + Some(ref layer_info) => layer_info.scroll_policy, + None => ScrollPolicy::Scrollable, + } + } } struct StackingContextLayerCreator { display_list_for_next_layer: Option<Box<DisplayList>>, - all_following_children_need_layers: bool, + next_layer_info: Option<LayerInfo>, } impl StackingContextLayerCreator { fn new() -> StackingContextLayerCreator { StackingContextLayerCreator { display_list_for_next_layer: None, - all_following_children_need_layers: false, + next_layer_info: None, } } @@ -673,55 +712,56 @@ impl StackingContextLayerCreator { // FIXME(#7566, mrobinson): This should properly handle unlayered children that are on // top of unlayered children which have child stacking contexts with layers. for child_stacking_context in sorted_children.into_iter() { - if state.stacking_context_needs_layer(&child_stacking_context) { - state.add_stacking_context(child_stacking_context, stacking_context); - } else { - stacking_context.display_list.children.push_back(child_stacking_context); - } + state.add_stacking_context(child_stacking_context, stacking_context); } state.finish_building_current_layer(stacking_context); } #[inline] - fn stacking_context_needs_layer(&mut self, stacking_context: &Arc<StackingContext>) -> bool { - self.all_following_children_need_layers || stacking_context.layer_id.is_some() + fn all_following_children_need_layers(&self) -> bool { + self.next_layer_info.is_some() } #[inline] fn finish_building_current_layer(&mut self, stacking_context: &mut StackingContext) { if let Some(display_list) = self.display_list_for_next_layer.take() { - let next_layer_id = - stacking_context.display_list - .layered_children - .back() - .unwrap() - .id - .companion_layer_id(); + let layer_info = self.next_layer_info.take().unwrap(); let child_stacking_context = - Arc::new(stacking_context.create_layered_child(next_layer_id, display_list)); + Arc::new(stacking_context.create_layered_child(layer_info.clone(), display_list)); stacking_context.display_list.layered_children.push_back( - Arc::new(PaintLayer::new(next_layer_id, + Arc::new(PaintLayer::new(layer_info, color::transparent(), - child_stacking_context, - ScrollPolicy::Scrollable))); - self.all_following_children_need_layers = true; + child_stacking_context))); } } + #[inline] fn add_stacking_context(&mut self, stacking_context: Arc<StackingContext>, parent_stacking_context: &mut StackingContext) { - if let Some(layer_id) = stacking_context.layer_id { + if self.all_following_children_need_layers() || stacking_context.layer_info.is_some() { + self.add_layered_stacking_context(stacking_context, parent_stacking_context); + return; + } + + parent_stacking_context.display_list.children.push_back(stacking_context); + } + + fn add_layered_stacking_context(&mut self, + stacking_context: Arc<StackingContext>, + parent_stacking_context: &mut StackingContext) { + let layer_info = stacking_context.layer_info.clone(); + if let Some(mut layer_info) = layer_info { self.finish_building_current_layer(parent_stacking_context); - parent_stacking_context.display_list.layered_children.push_back( - Arc::new(PaintLayer::new(layer_id, - color::transparent(), - stacking_context, - ScrollPolicy::Scrollable))); // We have started processing layered stacking contexts, so any stacking context that // we process from now on needs its own layer to ensure proper rendering order. - self.all_following_children_need_layers = true; + self.next_layer_info = + Some(layer_info.next_with_scroll_policy(parent_stacking_context.scroll_policy())); + parent_stacking_context.display_list.layered_children.push_back( + Arc::new(PaintLayer::new_with_stacking_context(layer_info, + stacking_context, + color::transparent()))); return; } diff --git a/components/gfx/paint_task.rs b/components/gfx/paint_task.rs index c63c84d9970..08da0e6aaeb 100644 --- a/components/gfx/paint_task.rs +++ b/components/gfx/paint_task.rs @@ -8,7 +8,7 @@ use app_units::Au; use azure::AzFloat; use azure::azure_hl::{BackendType, Color, DrawTarget, SurfaceFormat}; use canvas_traits::CanvasMsg; -use display_list::{self, StackingContext}; +use display_list::{self, LayerInfo, StackingContext}; use euclid::Matrix4; use euclid::point::Point2D; use euclid::rect::Rect; @@ -19,7 +19,7 @@ use ipc_channel::ipc::IpcSender; use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet}; use layers::platform::surface::{NativeDisplay, NativeSurface}; use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties, PaintListener}; -use msg::compositor_msg::{ScrollPolicy}; +use msg::compositor_msg::{ScrollPolicy, SubpageLayerInfo}; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::PipelineExitType; use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; @@ -51,20 +51,36 @@ pub struct PaintLayer { pub stacking_context: Arc<StackingContext>, /// The scrolling policy of this layer. pub scroll_policy: ScrollPolicy, + /// The subpage that this layer represents, if there is one. + pub subpage_layer_info: Option<SubpageLayerInfo>, } impl PaintLayer { /// Creates a new `PaintLayer`. - pub fn new(id: LayerId, + pub fn new(layer_info: LayerInfo, background_color: Color, - stacking_context: Arc<StackingContext>, - scroll_policy: ScrollPolicy) + stacking_context: Arc<StackingContext>) -> PaintLayer { PaintLayer { - id: id, + id: layer_info.layer_id, background_color: background_color, stacking_context: stacking_context, - scroll_policy: scroll_policy, + scroll_policy: layer_info.scroll_policy, + subpage_layer_info: layer_info.subpage_layer_info, + } + } + + /// Creates a new `PaintLayer` with a stacking context. + pub fn new_with_stacking_context(layer_info: LayerInfo, + stacking_context: Arc<StackingContext>, + background_color: Color) + -> PaintLayer { + PaintLayer { + id: layer_info.layer_id, + background_color: background_color, + stacking_context: stacking_context, + scroll_policy: layer_info.scroll_policy, + subpage_layer_info: layer_info.subpage_layer_info, } } @@ -382,12 +398,12 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { parent_id: parent_id, rect: layer_position, background_color: paint_layer.background_color, - scroll_policy: paint_layer.stacking_context.scroll_policy, + scroll_policy: paint_layer.scroll_policy, transform: transform, perspective: perspective, establishes_3d_context: paint_layer.stacking_context.establishes_3d_context, scrolls_overflow_area: paint_layer.stacking_context.scrolls_overflow_area, - subpage_layer_info: paint_layer.stacking_context.subpage_layer_info, + subpage_layer_info: paint_layer.subpage_layer_info, }); // When there is a new layer, the transforms and origin are handled by the compositor, diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index d9da32cf69b..ebca14ba59f 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -25,7 +25,7 @@ use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayIte use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion}; use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayList}; use gfx::display_list::{GradientDisplayItem}; -use gfx::display_list::{GradientStop, ImageDisplayItem, LineDisplayItem}; +use gfx::display_list::{GradientStop, ImageDisplayItem, LayerInfo, LineDisplayItem}; use gfx::display_list::{OpaqueNode, SolidColorDisplayItem}; use gfx::display_list::{StackingContext, TextDisplayItem, TextOrientation}; use gfx::paint_task::THREAD_TINT_COLORS; @@ -1279,6 +1279,18 @@ impl FragmentDisplayListBuilding for Fragment { filters.push(Filter::Opacity(effects.opacity)) } + let subpage_layer_info = match self.specific { + SpecificFragmentInfo::Iframe(ref iframe_fragment_info) => { + let border_padding = self.border_padding.to_physical(self.style().writing_mode); + Some(SubpageLayerInfo { + pipeline_id: iframe_fragment_info.pipeline_id, + subpage_id: iframe_fragment_info.subpage_id, + origin: Point2D::new(border_padding.left, border_padding.top), + }) + } + _ => None, + }; + let canvas_or_iframe = match self.specific { SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Iframe(_) => true, _ => false @@ -1287,17 +1299,19 @@ impl FragmentDisplayListBuilding for Fragment { // There are three situations that need layers: when the fragment has the HAS_LAYER // flag, when this is a canvas or iframe fragment, and when we are building a layer // tree for overflow scrolling. - let layer_id = if mode == StackingContextCreationMode::InnerScrollWrapper { - Some(self.layer_id_for_overflow_scroll()) + let layer_info = if mode == StackingContextCreationMode::InnerScrollWrapper { + Some(LayerInfo::new(self.layer_id_for_overflow_scroll(), + scroll_policy, + subpage_layer_info)) } else if self.flags.contains(HAS_LAYER) || canvas_or_iframe { - Some(self.layer_id()) + Some(LayerInfo::new(self.layer_id(), scroll_policy, subpage_layer_info)) } else { None }; // If it's a canvas we must propagate the layer and the renderer to the paint task. if let SpecificFragmentInfo::Canvas(ref fragment_info) = self.specific { - let layer_id = layer_id.unwrap(); + let layer_id = layer_info.unwrap().layer_id; if let Some(ref ipc_renderer) = fragment_info.ipc_renderer { layout_context.shared .canvas_layers_sender @@ -1305,18 +1319,6 @@ impl FragmentDisplayListBuilding for Fragment { } } - let subpage_layer_info = match self.specific { - SpecificFragmentInfo::Iframe(ref iframe_fragment_info) => { - let border_padding = self.border_padding.to_physical(self.style().writing_mode); - Some(SubpageLayerInfo { - pipeline_id: iframe_fragment_info.pipeline_id, - subpage_id: iframe_fragment_info.subpage_id, - origin: Point2D::new(border_padding.left, border_padding.top), - }) - } - _ => None, - }; - let scrolls_overflow_area = mode == StackingContextCreationMode::OuterScrollWrapper; let transform_style = self.style().get_used_transform_style(); let establishes_3d_context = scrolls_overflow_area || @@ -1332,9 +1334,7 @@ impl FragmentDisplayListBuilding for Fragment { perspective, establishes_3d_context, scrolls_overflow_area, - scroll_policy, - layer_id, - subpage_layer_info)) + layer_info)) } fn clipping_region_for_children(&self, diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index ee77270e62b..a91a84ca2ee 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -27,8 +27,7 @@ use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUti use flow_ref::{self, FlowRef}; use fnv::FnvHasher; use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo}; -use gfx::display_list::StackingContext; -use gfx::display_list::{ClippingRegion, DisplayList, OpaqueNode}; +use gfx::display_list::{ClippingRegion, DisplayList, LayerInfo, OpaqueNode, StackingContext}; use gfx::font_cache_task::FontCacheTask; use gfx::font_context; use gfx::paint_task::{LayoutToPaintMsg, PaintLayer}; @@ -1119,7 +1118,6 @@ impl LayoutTask { .add_to(&mut *display_list); let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size); - let layer_id = layout_root.layer_id(); let stacking_context = Arc::new(StackingContext::new(display_list, &origin, &origin, @@ -1130,8 +1128,6 @@ impl LayoutTask { Matrix4::identity(), true, false, - ScrollPolicy::Scrollable, - Some(layer_id), None)); if opts::get().dump_display_list { stacking_context.print("DisplayList".to_owned()); @@ -1142,10 +1138,12 @@ impl LayoutTask { rw_data.stacking_context = Some(stacking_context.clone()); - let paint_layer = PaintLayer::new(layout_root.layer_id(), - root_background_color, - stacking_context, - ScrollPolicy::Scrollable); + let layer_info = LayerInfo::new(layout_root.layer_id(), + ScrollPolicy::Scrollable, + None); + let paint_layer = PaintLayer::new_with_stacking_context(layer_info, + stacking_context, + root_background_color); debug!("Layout done!"); diff --git a/components/msg/compositor_msg.rs b/components/msg/compositor_msg.rs index 1231a112112..681f5161f2c 100644 --- a/components/msg/compositor_msg.rs +++ b/components/msg/compositor_msg.rs @@ -50,9 +50,9 @@ pub struct LayerId( LayerType, /// The identifier for this layer's fragment, derived from the fragment memory address. usize, - /// Whether or not this layer is a companion layer, synthesized to ensure that + /// An index for identifying companion layers, synthesized to ensure that /// content on top of this layer's fragment has the proper rendering order. - bool + usize ); impl Debug for LayerId { @@ -65,30 +65,23 @@ impl Debug for LayerId { LayerType::AfterPseudoContent => "-AfterPseudoContent", }; - let companion_string = if companion { - "-companion" - } else { - "" - }; - - write!(f, "{}{}{}", id, type_string, companion_string) + write!(f, "{}{}-{}", id, type_string, companion) } } impl LayerId { /// FIXME(#2011, pcwalton): This is unfortunate. Maybe remove this in the future. pub fn null() -> LayerId { - LayerId(LayerType::FragmentBody, 0, false) + LayerId(LayerType::FragmentBody, 0, 0) } pub fn new_of_type(layer_type: LayerType, fragment_id: usize) -> LayerId { - LayerId(layer_type, fragment_id, false) + LayerId(layer_type, fragment_id, 0) } pub fn companion_layer_id(&self) -> LayerId { let LayerId(layer_type, id, companion) = *self; - assert!(!companion); - LayerId(layer_type, id, true) + LayerId(layer_type, id, companion + 1) } } @@ -172,7 +165,7 @@ pub enum ScriptToCompositorMsg { } /// Subpage (i.e. iframe)-specific information about each layer. -#[derive(Clone, Copy, Deserialize, Serialize, HeapSizeOf)] +#[derive(Clone, Copy, Debug, Deserialize, Serialize, HeapSizeOf)] pub struct SubpageLayerInfo { /// The ID of the pipeline. pub pipeline_id: PipelineId, |