aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/gfx/display_list/mod.rs146
-rw-r--r--components/gfx/paint_task.rs34
-rw-r--r--components/layout/display_list_builder.rs40
-rw-r--r--components/layout/layout_task.rs16
-rw-r--r--components/msg/compositor_msg.rs21
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,