Have PaintLayers own StackingContexts instead of the opposite

Previously, StackingContexts might have a PaintLayer. We switch the
ownership, for several reasons:

   * We want PaintLayers to potentially contain something other
     than a StackingContext soon.
   * We want to delay the creation of PaintLayers until the last
     minute, so that we can synthesize new layers for sandwiched
     content.

This commit also implements the second goal. Instead of creating
PaintLayers during layout itself, wait until we are sorting and
layerizing a completed DisplayList.
This commit is contained in:
Martin Robinson 2015-08-31 18:05:17 -07:00
parent dbf8c9d2bc
commit 4ca93c39d6
6 changed files with 198 additions and 161 deletions

View file

@ -28,8 +28,9 @@ use azure::azure_hl::Color;
use euclid::approxeq::ApproxEq; use euclid::approxeq::ApproxEq;
use euclid::num::Zero; use euclid::num::Zero;
use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Matrix2D, Matrix4}; use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Matrix2D, Matrix4};
use gfx_traits::color;
use libc::uintptr_t; use libc::uintptr_t;
use msg::compositor_msg::{LayerId, LayerKind}; use msg::compositor_msg::{LayerId, LayerKind, ScrollPolicy};
use net_traits::image::base::Image; use net_traits::image::base::Image;
use paint_task::PaintLayer; use paint_task::PaintLayer;
use smallvec::SmallVec; use smallvec::SmallVec;
@ -98,8 +99,8 @@ pub struct DisplayList {
pub outlines: LinkedList<DisplayItem>, pub outlines: LinkedList<DisplayItem>,
/// Child stacking contexts. /// Child stacking contexts.
pub children: LinkedList<Arc<StackingContext>>, pub children: LinkedList<Arc<StackingContext>>,
/// Child stacking contexts with their own layers. /// Child PaintLayers that will be rendered on top of everything else.
pub layered_children: LinkedList<Arc<StackingContext>>, pub layered_children: LinkedList<PaintLayer>,
} }
impl DisplayList { impl DisplayList {
@ -131,10 +132,10 @@ impl DisplayList {
children.sort_by(|this, other| this.z_index.cmp(&other.z_index)); children.sort_by(|this, other| this.z_index.cmp(&other.z_index));
for stacking_context in children.into_iter() { for stacking_context in children.into_iter() {
if stacking_context.layer.is_some() { match stacking_context.layer_id {
self.layered_children.push_back(stacking_context); Some(layer_id) => self.layered_children.push_back(
} else { PaintLayer::new(layer_id, color::transparent(), stacking_context)),
self.children.push_back(stacking_context); None => self.children.push_back(stacking_context),
} }
} }
} }
@ -150,7 +151,7 @@ impl DisplayList {
self.positioned_content.append(&mut other.positioned_content); self.positioned_content.append(&mut other.positioned_content);
self.outlines.append(&mut other.outlines); self.outlines.append(&mut other.outlines);
self.children.append(&mut other.children); self.children.append(&mut other.children);
self.layered_children.append(&mut other.children); self.layered_children.append(&mut other.layered_children);
} }
/// Merges all display items from all non-float stacking levels to the `float` stacking level. /// Merges all display items from all non-float stacking levels to the `float` stacking level.
@ -248,11 +249,11 @@ impl DisplayList {
} }
} }
if !self.layered_children.is_empty() { if !self.layered_children.is_empty() {
println!("{} Layered children stacking contexts list length: {}", println!("{} Child layers list length: {}",
indentation, indentation,
self.layered_children.len()); self.layered_children.len());
for stacking_context in &self.layered_children { for paint_layer in &self.layered_children {
stacking_context.print(indentation.clone() + paint_layer.stacking_context.print(indentation.clone() +
&indentation[0..MIN_INDENTATION_LENGTH]); &indentation[0..MIN_INDENTATION_LENGTH]);
} }
} }
@ -265,10 +266,6 @@ pub struct StackingContext {
/// The display items that make up this stacking context. /// The display items that make up this stacking context.
pub display_list: Box<DisplayList>, pub display_list: Box<DisplayList>,
/// The layer for this stacking context, if there is one.
#[ignore_heap_size_of = "FIXME(njn): should measure this at some point"]
pub layer: Option<PaintLayer>,
/// The position and size of this stacking context. /// The position and size of this stacking context.
pub bounds: Rect<Au>, pub bounds: Rect<Au>,
@ -295,6 +292,13 @@ pub struct StackingContext {
/// Whether this stacking context scrolls its overflow area. /// Whether this stacking context scrolls its overflow area.
pub scrolls_overflow_area: bool, 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>,
} }
impl StackingContext { impl StackingContext {
@ -306,11 +310,12 @@ impl StackingContext {
z_index: i32, z_index: i32,
filters: filter::T, filters: filter::T,
blend_mode: mix_blend_mode::T, blend_mode: mix_blend_mode::T,
layer: Option<PaintLayer>,
transform: Matrix4, transform: Matrix4,
perspective: Matrix4, perspective: Matrix4,
establishes_3d_context: bool, establishes_3d_context: bool,
scrolls_overflow_area: bool) scrolls_overflow_area: bool,
scroll_policy: ScrollPolicy,
layer_id: Option<LayerId>)
-> StackingContext { -> StackingContext {
display_list.sort_and_layerize_children(); display_list.sort_and_layerize_children();
StackingContext { StackingContext {
@ -320,11 +325,12 @@ impl StackingContext {
z_index: z_index, z_index: z_index,
filters: filters, filters: filters,
blend_mode: blend_mode, blend_mode: blend_mode,
layer: layer,
transform: transform, transform: transform,
perspective: perspective, perspective: perspective,
establishes_3d_context: establishes_3d_context, establishes_3d_context: establishes_3d_context,
scrolls_overflow_area: scrolls_overflow_area, scrolls_overflow_area: scrolls_overflow_area,
scroll_policy: scroll_policy,
layer_id: layer_id,
} }
} }
@ -452,7 +458,7 @@ impl StackingContext {
// If a layer is being used, the transform for this layer // If a layer is being used, the transform for this layer
// will be handled by the compositor. // will be handled by the compositor.
let transform = match self.layer { let transform = match self.layer_id {
Some(..) => *transform, Some(..) => *transform,
None => transform.mul(&self.transform), None => transform.mul(&self.transform),
}; };
@ -556,6 +562,14 @@ impl StackingContext {
point.y.to_f32_px())); point.y.to_f32_px()));
point = Point2D::new(Au::from_f32_px(frac_point.x), Au::from_f32_px(frac_point.y)); point = Point2D::new(Au::from_f32_px(frac_point.x), Au::from_f32_px(frac_point.y));
// Layers are positioned on top of this layer should get a shot at the hit test first.
for layer in self.display_list.layered_children.iter().rev() {
layer.stacking_context.hit_test(point, result, topmost_only);
if topmost_only && !result.is_empty() {
return
}
}
// Iterate through display items in reverse stacking order. Steps here refer to the // Iterate through display items in reverse stacking order. Steps here refer to the
// painting steps in CSS 2.1 Appendix E. // painting steps in CSS 2.1 Appendix E.
// //
@ -635,15 +649,15 @@ impl StackingContext {
/// Returns the stacking context in the given tree of stacking contexts with a specific layer ID. /// Returns the stacking context in the given tree of stacking contexts with a specific layer ID.
pub fn find_stacking_context_with_layer_id(this: &Arc<StackingContext>, layer_id: LayerId) pub fn find_stacking_context_with_layer_id(this: &Arc<StackingContext>, layer_id: LayerId)
-> Option<Arc<StackingContext>> { -> Option<Arc<StackingContext>> {
match this.layer { for kid in &this.display_list.layered_children {
Some(ref layer) if layer.id == layer_id => return Some((*this).clone()), if let Some(stacking_context) = kid.find_stacking_context_with_layer_id(layer_id) {
Some(_) | None => {} return Some(stacking_context);
}
} }
for kid in &this.display_list.layered_children { for kid in &this.display_list.children {
match find_stacking_context_with_layer_id(kid, layer_id) { if let Some(stacking_context) = find_stacking_context_with_layer_id(kid, layer_id) {
Some(stacking_context) => return Some(stacking_context), return Some(stacking_context);
None => {}
} }
} }

View file

@ -63,7 +63,6 @@ impl DisplayListOptimizer {
stacking_contexts: I) stacking_contexts: I)
where I: Iterator<Item=&'a Arc<StackingContext>> { where I: Iterator<Item=&'a Arc<StackingContext>> {
for stacking_context in stacking_contexts { for stacking_context in stacking_contexts {
if stacking_context.layer.is_none() {
// Transform this stacking context to get it into the same space as // Transform this stacking context to get it into the same space as
// the parent stacking context. // the parent stacking context.
let origin_x = stacking_context.bounds.origin.x.to_f32_px(); let origin_x = stacking_context.bounds.origin.x.to_f32_px();
@ -86,5 +85,4 @@ impl DisplayListOptimizer {
} }
} }
} }
}
} }

View file

@ -20,7 +20,7 @@ use ipc_channel::ipc::IpcSender;
use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet}; use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet};
use layers::platform::surface::{NativeDisplay, NativeSurface}; use layers::platform::surface::{NativeDisplay, NativeSurface};
use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerKind}; use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerKind};
use msg::compositor_msg::{LayerProperties, PaintListener, ScrollPolicy}; use msg::compositor_msg::{LayerProperties, PaintListener};
use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::PipelineExitType; use msg::constellation_msg::PipelineExitType;
use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; use msg::constellation_msg::{ConstellationChan, Failure, PipelineId};
@ -41,25 +41,35 @@ use util::task::spawn_named_with_send_on_failure;
use util::task_state; use util::task_state;
/// Information about a hardware graphics layer that layout sends to the painting task. /// Information about a hardware graphics layer that layout sends to the painting task.
#[derive(Clone, Deserialize, Serialize)] #[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
pub struct PaintLayer { pub struct PaintLayer {
/// A per-pipeline ID describing this layer that should be stable across reflows. /// A per-pipeline ID describing this layer that should be stable across reflows.
pub id: LayerId, pub id: LayerId,
/// The color of the background in this layer. Used for unpainted content. /// The color of the background in this layer. Used for unpainted content.
pub background_color: Color, pub background_color: Color,
/// The scrolling policy of this layer. /// The stacking context that represents the content of this layer.
pub scroll_policy: ScrollPolicy, pub stacking_context: Arc<StackingContext>,
} }
impl PaintLayer { impl PaintLayer {
/// Creates a new `PaintLayer`. /// Creates a new `PaintLayer`.
pub fn new(id: LayerId, background_color: Color, scroll_policy: ScrollPolicy) -> PaintLayer { pub fn new(id: LayerId, background_color: Color, stacking_context: Arc<StackingContext>) -> PaintLayer {
PaintLayer { PaintLayer {
id: id, id: id,
background_color: background_color, background_color: background_color,
scroll_policy: scroll_policy, stacking_context: stacking_context,
} }
} }
pub fn find_stacking_context_with_layer_id(&self,
layer_id: LayerId)
-> Option<Arc<StackingContext>> {
if self.id == layer_id {
return Some(self.stacking_context.clone());
}
display_list::find_stacking_context_with_layer_id(&self.stacking_context, layer_id)
}
} }
pub struct PaintRequest { pub struct PaintRequest {
@ -77,7 +87,7 @@ pub enum Msg {
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub enum LayoutToPaintMsg { pub enum LayoutToPaintMsg {
PaintInit(Epoch, Arc<StackingContext>), PaintInit(Epoch, PaintLayer),
CanvasLayer(LayerId, IpcSender<CanvasMsg>), CanvasLayer(LayerId, IpcSender<CanvasMsg>),
Exit(Option<IpcSender<()>>, PipelineExitType), Exit(Option<IpcSender<()>>, PipelineExitType),
} }
@ -101,8 +111,8 @@ pub struct PaintTask<C> {
/// A channel to the time profiler. /// A channel to the time profiler.
time_profiler_chan: time::ProfilerChan, time_profiler_chan: time::ProfilerChan,
/// The root stacking context sent to us by the layout thread. /// The root paint layer sent to us by the layout thread.
root_stacking_context: Option<Arc<StackingContext>>, root_paint_layer: Option<PaintLayer>,
/// Permission to send paint messages to the compositor /// Permission to send paint messages to the compositor
paint_permission: bool, paint_permission: bool,
@ -159,7 +169,7 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
compositor: compositor, compositor: compositor,
constellation_chan: constellation_chan, constellation_chan: constellation_chan,
time_profiler_chan: time_profiler_chan, time_profiler_chan: time_profiler_chan,
root_stacking_context: None, root_paint_layer: None,
paint_permission: false, paint_permission: false,
current_epoch: None, current_epoch: None,
worker_threads: worker_threads, worker_threads: worker_threads,
@ -205,9 +215,9 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
}; };
match message { match message {
Msg::FromLayout(LayoutToPaintMsg::PaintInit(epoch, stacking_context)) => { Msg::FromLayout(LayoutToPaintMsg::PaintInit(epoch, paint_layer)) => {
self.current_epoch = Some(epoch); self.current_epoch = Some(epoch);
self.root_stacking_context = Some(stacking_context.clone()); self.root_paint_layer = Some(paint_layer);
if !self.paint_permission { if !self.paint_permission {
debug!("PaintTask: paint ready msg"); debug!("PaintTask: paint ready msg");
@ -253,7 +263,7 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
Msg::FromChrome(ChromeToPaintMsg::PaintPermissionGranted) => { Msg::FromChrome(ChromeToPaintMsg::PaintPermissionGranted) => {
self.paint_permission = true; self.paint_permission = true;
if self.root_stacking_context.is_some() { if self.root_paint_layer.is_some() {
self.initialize_layers(); self.initialize_layers();
} }
} }
@ -286,10 +296,9 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
layer_id: LayerId, layer_id: LayerId,
layer_kind: LayerKind) { layer_kind: LayerKind) {
time::profile(time::ProfilerCategory::Painting, None, self.time_profiler_chan.clone(), || { time::profile(time::ProfilerCategory::Painting, None, self.time_profiler_chan.clone(), || {
// Bail out if there is no appropriate stacking context. // Bail out if there is no appropriate layer.
let stacking_context = if let Some(ref stacking_context) = self.root_stacking_context { let stacking_context = if let Some(ref paint_layer) = self.root_paint_layer {
match display_list::find_stacking_context_with_layer_id(stacking_context, match paint_layer.find_stacking_context_with_layer_id(layer_id) {
layer_id) {
Some(stacking_context) => stacking_context, Some(stacking_context) => stacking_context,
None => return, None => return,
} }
@ -322,14 +331,14 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
} }
fn initialize_layers(&mut self) { fn initialize_layers(&mut self) {
let root_stacking_context = match self.root_stacking_context { let root_paint_layer = match self.root_paint_layer {
None => return, None => return,
Some(ref root_stacking_context) => root_stacking_context, Some(ref root_paint_layer) => root_paint_layer,
}; };
let mut properties = Vec::new(); let mut properties = Vec::new();
build(&mut properties, build_from_paint_layer(&mut properties,
&**root_stacking_context, root_paint_layer,
&ZERO_POINT, &ZERO_POINT,
&Matrix4::identity(), &Matrix4::identity(),
&Matrix4::identity(), &Matrix4::identity(),
@ -338,29 +347,24 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
properties, properties,
self.current_epoch.unwrap()); self.current_epoch.unwrap());
fn build(properties: &mut Vec<LayerProperties>, fn build_from_paint_layer(properties: &mut Vec<LayerProperties>,
stacking_context: &StackingContext, paint_layer: &PaintLayer,
page_position: &Point2D<Au>, page_position: &Point2D<Au>,
transform: &Matrix4, transform: &Matrix4,
perspective: &Matrix4, perspective: &Matrix4,
parent_id: Option<LayerId>) { parent_id: Option<LayerId>) {
let transform = transform.mul(&stacking_context.transform); let transform = transform.mul(&paint_layer.stacking_context.transform);
let perspective = perspective.mul(&stacking_context.perspective); let perspective = perspective.mul(&paint_layer.stacking_context.perspective);
let (next_parent_id, page_position, transform, perspective) =
match stacking_context.layer {
Some(ref paint_layer) => {
let overflow_size = let overflow_size =
Size2D::new(stacking_context.overflow.size.width.to_nearest_px() as f32, Size2D::new(paint_layer.stacking_context.overflow.size.width.to_nearest_px() as f32,
stacking_context.overflow.size.height.to_nearest_px() as f32); paint_layer.stacking_context.overflow.size.height.to_nearest_px() as f32);
let establishes_3d_context = stacking_context.establishes_3d_context;
let scrolls_overflow_area = stacking_context.scrolls_overflow_area;
// Layers start at the top left of their overflow rect, as far as the info // Layers start at the top left of their overflow rect, as far as the info
// we give to the compositor is concerned. // we give to the compositor is concerned.
let overflow_relative_page_position = *page_position + let overflow_relative_page_position = *page_position +
stacking_context.bounds.origin + paint_layer.stacking_context.bounds.origin +
stacking_context.overflow.origin; paint_layer.stacking_context.overflow.origin;
let layer_position = Rect::new( let layer_position = Rect::new(
Point2D::new(overflow_relative_page_position.x.to_nearest_px() as f32, Point2D::new(overflow_relative_page_position.x.to_nearest_px() as f32,
overflow_relative_page_position.y.to_nearest_px() as f32), overflow_relative_page_position.y.to_nearest_px() as f32),
@ -371,35 +375,61 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
parent_id: parent_id, parent_id: parent_id,
rect: layer_position, rect: layer_position,
background_color: paint_layer.background_color, background_color: paint_layer.background_color,
scroll_policy: paint_layer.scroll_policy, scroll_policy: paint_layer.stacking_context.scroll_policy,
transform: transform, transform: transform,
perspective: perspective, perspective: perspective,
establishes_3d_context: establishes_3d_context, establishes_3d_context: paint_layer.stacking_context.establishes_3d_context,
scrolls_overflow_area: scrolls_overflow_area, scrolls_overflow_area: paint_layer.stacking_context.scrolls_overflow_area,
}); });
// When there is a new layer, the transforms and origin // When there is a new layer, the transforms and origin are handled by the compositor,
// are handled by the compositor. // so the new transform and perspective matrices are just the identity.
(Some(paint_layer.id), continue_walking_stacking_context(properties,
-stacking_context.overflow.origin, &paint_layer.stacking_context,
Matrix4::identity(), &-paint_layer.stacking_context.overflow.origin,
Matrix4::identity()) &Matrix4::identity(),
&Matrix4::identity(),
Some(paint_layer.id));
} }
None => {
(parent_id,
stacking_context.bounds.origin + *page_position,
transform,
perspective)
}
};
fn build_from_stacking_context(properties: &mut Vec<LayerProperties>,
stacking_context: &Arc<StackingContext>,
page_position: &Point2D<Au>,
transform: &Matrix4,
perspective: &Matrix4,
parent_id: Option<LayerId>) {
continue_walking_stacking_context(properties,
stacking_context,
&(stacking_context.bounds.origin + *page_position),
&transform.mul(&stacking_context.transform),
&perspective.mul(&stacking_context.perspective),
parent_id);
}
fn continue_walking_stacking_context(properties: &mut Vec<LayerProperties>,
stacking_context: &Arc<StackingContext>,
page_position: &Point2D<Au>,
transform: &Matrix4,
perspective: &Matrix4,
parent_id: Option<LayerId>) {
for kid in stacking_context.display_list.children.iter() { for kid in stacking_context.display_list.children.iter() {
build(properties, &**kid, &page_position, &transform, &perspective, next_parent_id) build_from_stacking_context(properties,
&kid,
&page_position,
&transform,
&perspective,
parent_id)
} }
for kid in stacking_context.display_list.layered_children.iter() { for kid in stacking_context.display_list.layered_children.iter() {
build(properties, &**kid, &page_position, &transform, &perspective, next_parent_id) build_from_paint_layer(properties,
&kid,
&page_position,
&transform,
&perspective,
parent_id)
} }
} }
} }
} }

View file

@ -33,7 +33,7 @@ use gfx::display_list::{GradientDisplayItem};
use gfx::display_list::{GradientStop, ImageDisplayItem, LineDisplayItem}; use gfx::display_list::{GradientStop, ImageDisplayItem, LineDisplayItem};
use gfx::display_list::{OpaqueNode, SolidColorDisplayItem}; use gfx::display_list::{OpaqueNode, SolidColorDisplayItem};
use gfx::display_list::{StackingContext, TextDisplayItem, TextOrientation}; use gfx::display_list::{StackingContext, TextDisplayItem, TextOrientation};
use gfx::paint_task::{PaintLayer, THREAD_TINT_COLORS}; use gfx::paint_task::THREAD_TINT_COLORS;
use gfx_traits::color; use gfx_traits::color;
use ipc_channel::ipc::{self, IpcSharedMemory}; use ipc_channel::ipc::{self, IpcSharedMemory};
use msg::compositor_msg::{ScrollPolicy, LayerId}; use msg::compositor_msg::{ScrollPolicy, LayerId};
@ -69,9 +69,9 @@ use util::opts;
/// FIXME(pcwalton): This is pretty ugly. Consider modifying `LayerId` somehow. /// FIXME(pcwalton): This is pretty ugly. Consider modifying `LayerId` somehow.
const FAKE_FRAGMENT_ID_FOR_OVERFLOW_SCROLL: u32 = 1000000; const FAKE_FRAGMENT_ID_FOR_OVERFLOW_SCROLL: u32 = 1000000;
/// A possible `PaintLayer` for an stacking context /// Whether a stacking context needs a layer or not.
pub enum StackingContextLayer { pub enum StackingContextLayerNecessity {
Existing(PaintLayer), Always(LayerId, ScrollPolicy),
IfCanvas(LayerId), IfCanvas(LayerId),
} }
@ -261,7 +261,7 @@ pub trait FragmentDisplayListBuilding {
base_flow: &BaseFlow, base_flow: &BaseFlow,
display_list: Box<DisplayList>, display_list: Box<DisplayList>,
layout_context: &LayoutContext, layout_context: &LayoutContext,
layer: StackingContextLayer, needs_layer: StackingContextLayerNecessity,
mode: StackingContextCreationMode) mode: StackingContextCreationMode)
-> Arc<StackingContext>; -> Arc<StackingContext>;
@ -1145,7 +1145,7 @@ impl FragmentDisplayListBuilding for Fragment {
base_flow: &BaseFlow, base_flow: &BaseFlow,
display_list: Box<DisplayList>, display_list: Box<DisplayList>,
layout_context: &LayoutContext, layout_context: &LayoutContext,
layer: StackingContextLayer, needs_layer: StackingContextLayerNecessity,
mode: StackingContextCreationMode) mode: StackingContextCreationMode)
-> Arc<StackingContext> { -> Arc<StackingContext> {
let border_box = match mode { let border_box = match mode {
@ -1259,13 +1259,14 @@ impl FragmentDisplayListBuilding for Fragment {
} }
// Ensure every canvas has a layer // Ensure every canvas has a layer
let layer = match layer { let (scroll_policy, layer_id) = match needs_layer {
StackingContextLayer::Existing(existing_layer) => Some(existing_layer), StackingContextLayerNecessity::Always(layer_id, scroll_policy) =>
StackingContextLayer::IfCanvas(layer_id) => { (scroll_policy, Some(layer_id)),
StackingContextLayerNecessity::IfCanvas(layer_id) => {
if let SpecificFragmentInfo::Canvas(_) = self.specific { if let SpecificFragmentInfo::Canvas(_) = self.specific {
Some(PaintLayer::new(layer_id, color::transparent(), ScrollPolicy::Scrollable)) (ScrollPolicy::Scrollable, Some(layer_id))
} else { } else {
None (ScrollPolicy::Scrollable, None)
} }
} }
}; };
@ -1273,7 +1274,7 @@ impl FragmentDisplayListBuilding for Fragment {
// If it's a canvas we must propagate the layer and the renderer to the paint // If it's a canvas we must propagate the layer and the renderer to the paint
// task // task
if let SpecificFragmentInfo::Canvas(ref fragment_info) = self.specific { if let SpecificFragmentInfo::Canvas(ref fragment_info) = self.specific {
let layer_id = layer.as_ref().unwrap().id; let layer_id = layer_id.unwrap();
if let Some(ref ipc_renderer) = fragment_info.ipc_renderer { if let Some(ref ipc_renderer) = fragment_info.ipc_renderer {
layout_context.shared layout_context.shared
.canvas_layers_sender .canvas_layers_sender
@ -1292,11 +1293,12 @@ impl FragmentDisplayListBuilding for Fragment {
self.style().get_box().z_index.number_or_zero(), self.style().get_box().z_index.number_or_zero(),
filters, filters,
self.style().get_effects().mix_blend_mode, self.style().get_effects().mix_blend_mode,
layer,
transform, transform,
perspective, perspective,
establishes_3d_context, establishes_3d_context,
scrolls_overflow_area)) scrolls_overflow_area,
scroll_policy,
layer_id))
} }
#[inline(never)] #[inline(never)]
@ -1565,15 +1567,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
ScrollPolicy::Scrollable ScrollPolicy::Scrollable
}; };
let paint_layer = PaintLayer::new(self.layer_id(0),
color::transparent(),
scroll_policy);
let layer = StackingContextLayer::Existing(paint_layer);
let stacking_context = self.fragment.create_stacking_context( let stacking_context = self.fragment.create_stacking_context(
&self.base, &self.base,
display_list, display_list,
layout_context, layout_context,
layer, StackingContextLayerNecessity::Always(self.layer_id(0), scroll_policy),
StackingContextCreationMode::Normal); StackingContextCreationMode::Normal);
DisplayListBuildingResult::StackingContext(stacking_context) DisplayListBuildingResult::StackingContext(stacking_context)
} else if self.fragment.establishes_stacking_context() { } else if self.fragment.establishes_stacking_context() {
@ -1582,7 +1580,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&self.base, &self.base,
display_list, display_list,
layout_context, layout_context,
StackingContextLayer::IfCanvas(self.layer_id(0)), StackingContextLayerNecessity::IfCanvas(self.layer_id(0)),
StackingContextCreationMode::Normal)) StackingContextCreationMode::Normal))
} else { } else {
match self.fragment.style.get_box().position { match self.fragment.style.get_box().position {
@ -1659,7 +1657,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&self.base, &self.base,
display_list, display_list,
layout_context, layout_context,
StackingContextLayer::IfCanvas(self.layer_id(0)), StackingContextLayerNecessity::IfCanvas(self.layer_id(0)),
StackingContextCreationMode::Normal)); StackingContextCreationMode::Normal));
} }
return return
@ -1683,26 +1681,22 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
} else { } else {
self.layer_id(0) self.layer_id(0)
}; };
let paint_layer = PaintLayer::new(layer_id, color::transparent(), scroll_policy);
let stacking_context = self.fragment.create_stacking_context( let stacking_context = self.fragment.create_stacking_context(
&self.base, &self.base,
display_list, display_list,
layout_context, layout_context,
StackingContextLayer::Existing(paint_layer), StackingContextLayerNecessity::Always(layer_id, scroll_policy),
stacking_context_creation_mode); stacking_context_creation_mode);
let outermost_stacking_context = match outer_display_list_for_overflow_scroll { let outermost_stacking_context = match outer_display_list_for_overflow_scroll {
Some(mut outer_display_list_for_overflow_scroll) => { Some(mut outer_display_list_for_overflow_scroll) => {
outer_display_list_for_overflow_scroll.children.push_back(stacking_context); outer_display_list_for_overflow_scroll.children.push_back(stacking_context);
let paint_layer = PaintLayer::new(self.layer_id(0),
color::transparent(),
scroll_policy);
self.fragment.create_stacking_context( self.fragment.create_stacking_context(
&self.base, &self.base,
outer_display_list_for_overflow_scroll, outer_display_list_for_overflow_scroll,
layout_context, layout_context,
StackingContextLayer::Existing(paint_layer), StackingContextLayerNecessity::Always(self.layer_id(0), scroll_policy),
StackingContextCreationMode::OuterScrollWrapper) StackingContextCreationMode::OuterScrollWrapper)
} }
None => stacking_context, None => stacking_context,
@ -1728,7 +1722,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&self.base, &self.base,
display_list, display_list,
layout_context, layout_context,
StackingContextLayer::IfCanvas(self.layer_id(0)), StackingContextLayerNecessity::IfCanvas(self.layer_id(0)),
StackingContextCreationMode::Normal)) StackingContextCreationMode::Normal))
} else { } else {
DisplayListBuildingResult::Normal(display_list) DisplayListBuildingResult::Normal(display_list)
@ -1828,7 +1822,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
&self.base, &self.base,
display_list, display_list,
layout_context, layout_context,
StackingContextLayer::IfCanvas(self.layer_id(0)), StackingContextLayerNecessity::IfCanvas(self.layer_id(0)),
StackingContextCreationMode::Normal)) StackingContextCreationMode::Normal))
} else { } else {
DisplayListBuildingResult::Normal(display_list) DisplayListBuildingResult::Normal(display_list)

View file

@ -1033,22 +1033,23 @@ impl LayoutTask {
flow::mut_base(flow_ref::deref_mut(layout_root)) flow::mut_base(flow_ref::deref_mut(layout_root))
.display_list_building_result .display_list_building_result
.add_to(&mut *display_list); .add_to(&mut *display_list);
let paint_layer = PaintLayer::new(layout_root.layer_id(0),
root_background_color,
ScrollPolicy::Scrollable);
let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size); let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size);
let layer_id = layout_root.layer_id(0);
let stacking_context = Arc::new(StackingContext::new(display_list, let stacking_context = Arc::new(StackingContext::new(display_list,
&origin, &origin,
&origin, &origin,
0, 0,
filter::T::new(Vec::new()), filter::T::new(Vec::new()),
mix_blend_mode::T::normal, mix_blend_mode::T::normal,
Some(paint_layer),
Matrix4::identity(), Matrix4::identity(),
Matrix4::identity(), Matrix4::identity(),
true, true,
false)); false,
ScrollPolicy::Scrollable,
Some(layer_id)));
let paint_layer = PaintLayer::new(layer_id,
root_background_color,
stacking_context.clone());
if opts::get().dump_display_list { if opts::get().dump_display_list {
println!("#### start printing display list."); println!("#### start printing display list.");
@ -1058,13 +1059,13 @@ impl LayoutTask {
println!("{}", serde_json::to_string_pretty(&stacking_context).unwrap()); println!("{}", serde_json::to_string_pretty(&stacking_context).unwrap());
} }
rw_data.stacking_context = Some(stacking_context.clone()); rw_data.stacking_context = Some(stacking_context);
debug!("Layout done!"); debug!("Layout done!");
rw_data.epoch.next(); rw_data.epoch.next();
self.paint_chan self.paint_chan
.send(LayoutToPaintMsg::PaintInit(rw_data.epoch, stacking_context)) .send(LayoutToPaintMsg::PaintInit(rw_data.epoch, paint_layer))
.unwrap(); .unwrap();
} }
}); });

View file

@ -35,7 +35,7 @@ impl FrameTreeId {
} }
} }
#[derive(Clone, PartialEq, Eq, Copy, Hash, Deserialize, Serialize)] #[derive(Clone, PartialEq, Eq, Copy, Hash, Deserialize, Serialize, HeapSizeOf)]
pub struct LayerId(pub usize, pub u32); pub struct LayerId(pub usize, pub u32);
impl Debug for LayerId { impl Debug for LayerId {
@ -59,7 +59,7 @@ pub enum LayerKind {
} }
/// The scrolling policy of a layer. /// The scrolling policy of a layer.
#[derive(Clone, PartialEq, Eq, Copy, Deserialize, Serialize, Debug)] #[derive(Clone, PartialEq, Eq, Copy, Deserialize, Serialize, Debug, HeapSizeOf)]
pub enum ScrollPolicy { pub enum ScrollPolicy {
/// These layers scroll when the parent receives a scrolling message. /// These layers scroll when the parent receives a scrolling message.
Scrollable, Scrollable,