aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout_2020/display_list/gradient.rs8
-rw-r--r--components/layout_2020/display_list/mod.rs140
-rw-r--r--components/layout_2020/display_list/stacking_context.rs265
-rw-r--r--components/layout_2020/flow/root.rs61
-rw-r--r--components/layout_thread_2020/lib.rs30
5 files changed, 326 insertions, 178 deletions
diff --git a/components/layout_2020/display_list/gradient.rs b/components/layout_2020/display_list/gradient.rs
index 09f5be610c2..bc057330023 100644
--- a/components/layout_2020/display_list/gradient.rs
+++ b/components/layout_2020/display_list/gradient.rs
@@ -144,9 +144,9 @@ pub(super) fn build_linear(
let stops = fixup_stops(style, items, Length::new(gradient_line_length));
let linear_gradient = builder
- .wr
+ .wr()
.create_gradient(start_point, end_point, stops, extend_mode);
- builder.wr.push_gradient(
+ builder.wr().push_gradient(
&layer.common,
layer.bounds,
linear_gradient,
@@ -244,9 +244,9 @@ pub(super) fn build_radial(
let stops = fixup_stops(style, items, Length::new(gradient_line_length));
let radial_gradient = builder
- .wr
+ .wr()
.create_radial_gradient(center, radii, stops, extend_mode);
- builder.wr.push_radial_gradient(
+ builder.wr().push_radial_gradient(
&layer.common,
layer.bounds,
radial_gradient,
diff --git a/components/layout_2020/display_list/mod.rs b/components/layout_2020/display_list/mod.rs
index 79274277704..bd4a237fb59 100644
--- a/components/layout_2020/display_list/mod.rs
+++ b/components/layout_2020/display_list/mod.rs
@@ -10,6 +10,7 @@ use crate::fragments::{BoxFragment, Fragment, TextFragment};
use crate::geom::{PhysicalPoint, PhysicalRect};
use crate::replaced::IntrinsicSizes;
use crate::style_ext::ComputedValuesExt;
+use crate::FragmentTree;
use embedder_traits::Cursor;
use euclid::{Point2D, SideOffsets2D, Size2D};
use fnv::FnvHashMap;
@@ -32,7 +33,9 @@ use webrender_api::{self as wr, units};
mod background;
mod conversions;
mod gradient;
-pub mod stacking_context;
+mod stacking_context;
+
+pub use stacking_context::*;
#[derive(Clone, Copy)]
pub struct WebRenderImageInfo {
@@ -45,38 +48,99 @@ pub struct WebRenderImageInfo {
type ItemTag = (u64, u16);
type HitInfo = Option<ItemTag>;
-pub struct DisplayListBuilder<'a> {
- /// The current SpatialId and ClipId information for this `DisplayListBuilder`.
- current_space_and_clip: wr::SpaceAndClipInfo,
-
- element_for_canvas_background: OpaqueNode,
- pub context: &'a LayoutContext<'a>,
+/// Where the information that's used to build display lists is stored. This
+/// includes both a [wr::DisplayListBuilder] for building up WebRender-specific
+/// display list information and a [CompositorDisplayListInfo] used to store
+/// information used by the compositor, such as a compositor-side scroll tree.
+pub struct DisplayList {
+ /// The [wr::DisplayListBuilder] used to collect display list items.
pub wr: wr::DisplayListBuilder,
- pub compositor_info: CompositorDisplayListInfo,
- pub iframe_sizes: FnvHashMap<BrowsingContextId, Size2D<f32, CSSPixel>>,
- /// Contentful paint, for the purpose of
- /// https://w3c.github.io/paint-timing/#first-contentful-paint
- /// (i.e. the display list contains items of type text,
- /// image, non-white canvas or SVG). Used by metrics.
- pub is_contentful: bool,
+ /// The information about the WebRender display list that the compositor
+ /// consumes. This curerntly contains the out-of-band hit testing information
+ /// data structure that the compositor uses to map hit tests to information
+ /// about the item hit.
+ pub compositor_info: CompositorDisplayListInfo,
}
-impl<'a> DisplayListBuilder<'a> {
+impl DisplayList {
+ /// Create a new [DisplayList] given the dimensions of the layout and the WebRender
+ /// pipeline id.
+ ///
+ /// TODO(mrobinson): `_viewport_size` will eventually be used in the creation
+ /// of the compositor-side scroll tree.
pub fn new(
+ _viewport_size: units::LayoutSize,
+ content_size: units::LayoutSize,
pipeline_id: wr::PipelineId,
- context: &'a LayoutContext,
- fragment_tree: &crate::FragmentTree,
) -> Self {
Self {
- current_space_and_clip: wr::SpaceAndClipInfo::root_scroll(pipeline_id),
+ wr: wr::DisplayListBuilder::new(pipeline_id, content_size),
+ compositor_info: CompositorDisplayListInfo::default(),
+ }
+ }
+}
+
+pub(crate) struct DisplayListBuilder<'a> {
+ /// The current [wr::SpatialId] for this [DisplayListBuilder]. This allows
+ /// only passing the builder instead passing the containing
+ /// [stacking_context::StackingContextFragment] as an argument to display
+ /// list building functions.
+ current_spatial_id: wr::SpatialId,
+
+ /// The current [wr::ClipId] for this [DisplayListBuilder]. This allows
+ /// only passing the builder instead passing the containing
+ /// [stacking_context::StackingContextFragment] as an argument to display
+ /// list building functions.
+ current_clip_id: wr::ClipId,
+
+ /// The [OpaqueNode] handle to the node used to paint the page background
+ /// if the background was a canvas.
+ element_for_canvas_background: OpaqueNode,
+
+ /// A [LayoutContext] used to get information about the device pixel ratio
+ /// and get handles to WebRender images.
+ pub context: &'a LayoutContext<'a>,
+
+ /// The [DisplayList] used to collect display list items and metadata.
+ pub display_list: &'a mut DisplayList,
+
+ /// A recording of the sizes of iframes encountered when building this
+ /// display list. This information is forwarded to the layout thread for the
+ /// iframe so that its layout knows how large the initial containing block /
+ /// viewport is.
+ iframe_sizes: FnvHashMap<BrowsingContextId, Size2D<f32, CSSPixel>>,
+
+ /// Contentful paint i.e. whether the display list contains items of type
+ /// text, image, non-white canvas or SVG). Used by metrics.
+ /// See https://w3c.github.io/paint-timing/#first-contentful-paint.
+ is_contentful: bool,
+}
+
+impl DisplayList {
+ pub fn build<'a>(
+ &mut self,
+ context: &'a LayoutContext,
+ fragment_tree: &FragmentTree,
+ root_stacking_context: &StackingContext,
+ ) -> (FnvHashMap<BrowsingContextId, Size2D<f32, CSSPixel>>, bool) {
+ let mut builder = DisplayListBuilder {
+ current_spatial_id: wr::SpatialId::root_scroll_node(self.wr.pipeline_id),
+ current_clip_id: wr::ClipId::root(self.wr.pipeline_id),
element_for_canvas_background: fragment_tree.canvas_background.from_element,
is_contentful: false,
context,
- wr: wr::DisplayListBuilder::new(pipeline_id, fragment_tree.scrollable_overflow()),
- compositor_info: CompositorDisplayListInfo::default(),
+ display_list: self,
iframe_sizes: FnvHashMap::default(),
- }
+ };
+ fragment_tree.build_display_list(&mut builder, root_stacking_context);
+ (builder.iframe_sizes, builder.is_contentful)
+ }
+}
+
+impl<'a> DisplayListBuilder<'a> {
+ fn wr(&mut self) -> &mut wr::DisplayListBuilder {
+ &mut self.display_list.wr
}
fn common_properties(
@@ -89,8 +153,8 @@ impl<'a> DisplayListBuilder<'a> {
// for fragments that paint their entire border rectangle.
wr::CommonItemProperties {
clip_rect,
- spatial_id: self.current_space_and_clip.spatial_id,
- clip_id: self.current_space_and_clip.clip_id,
+ spatial_id: self.current_spatial_id,
+ clip_id: self.current_clip_id,
hit_info: None,
flags: style.get_webrender_primitive_flags(),
}
@@ -109,7 +173,7 @@ impl<'a> DisplayListBuilder<'a> {
return None;
}
- let hit_test_index = self.compositor_info.add_hit_test_info(
+ let hit_test_index = self.display_list.compositor_info.add_hit_test_info(
tag?.node.0 as u64,
Some(cursor(inherited_ui.cursor.keyword, auto_cursor)),
);
@@ -143,7 +207,7 @@ impl Fragment {
.translate(containing_block.origin.to_vector());
let common = builder.common_properties(rect.to_webrender(), &i.style);
- builder.wr.push_image(
+ builder.wr().push_image(
&common,
rect.to_webrender(),
image_rendering(i.style.get_inherited_box().image_rendering),
@@ -169,7 +233,7 @@ impl Fragment {
);
let common = builder.common_properties(rect.to_webrender(), &iframe.style);
- builder.wr.push_iframe(
+ builder.wr().push_iframe(
rect.to_webrender(),
common.clip_rect,
&wr::SpaceAndClipInfo {
@@ -248,7 +312,7 @@ impl Fragment {
}
// Text.
- builder.wr.push_text(
+ builder.wr().push_text(
&common,
rect.to_webrender(),
&glyphs,
@@ -287,7 +351,7 @@ impl Fragment {
if text_decoration_style == ComputedTextDecorationStyle::MozNone {
return;
}
- builder.wr.push_line(
+ builder.display_list.wr.push_line(
&builder.common_properties(rect, &fragment.parent_style),
&rect,
wavy_line_thickness,
@@ -448,7 +512,7 @@ impl<'a> BuilderForBoxFragment<'a> {
if let Some(clip_id) = self.border_edge_clip(builder) {
common.clip_id = clip_id
}
- builder.wr.push_hit_test(&common)
+ builder.wr().push_hit_test(&common)
}
}
@@ -473,7 +537,7 @@ impl<'a> BuilderForBoxFragment<'a> {
let layer_index = b.background_image.0.len() - 1;
let (bounds, common) = background::painting_area(self, &source, builder, layer_index);
builder
- .wr
+ .wr()
.push_rect(&common, *bounds, rgba(background_color))
}
@@ -550,7 +614,7 @@ impl<'a> BuilderForBoxFragment<'a> {
{
let image_rendering = image_rendering(style.clone_image_rendering());
if layer.repeat {
- builder.wr.push_repeating_image(
+ builder.wr().push_repeating_image(
&layer.common,
layer.bounds,
layer.tile_size,
@@ -561,7 +625,7 @@ impl<'a> BuilderForBoxFragment<'a> {
wr::ColorF::WHITE,
)
} else {
- builder.wr.push_image(
+ builder.wr().push_image(
&layer.common,
layer.bounds,
image_rendering,
@@ -620,7 +684,7 @@ impl<'a> BuilderForBoxFragment<'a> {
do_aa: true,
});
builder
- .wr
+ .wr()
.push_border(&common, self.border_rect, widths, details)
}
@@ -655,7 +719,7 @@ impl<'a> BuilderForBoxFragment<'a> {
do_aa: true,
});
builder
- .wr
+ .wr()
.push_border(&common, outline_rect, widths, details)
}
}
@@ -801,8 +865,12 @@ fn clip_for_radii(
if radii.is_zero() {
None
} else {
- Some(builder.wr.define_clip_rounded_rect(
- &builder.current_space_and_clip,
+ let parent_space_and_clip = wr::SpaceAndClipInfo {
+ spatial_id: builder.current_spatial_id,
+ clip_id: builder.current_clip_id,
+ };
+ Some(builder.wr().define_clip_rounded_rect(
+ &parent_space_and_clip,
wr::ComplexClipRegion {
rect,
radii,
diff --git a/components/layout_2020/display_list/stacking_context.rs b/components/layout_2020/display_list/stacking_context.rs
index 7f15a530863..e88c08c6c1a 100644
--- a/components/layout_2020/display_list/stacking_context.rs
+++ b/components/layout_2020/display_list/stacking_context.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use super::DisplayList;
use crate::cell::ArcRefCell;
use crate::display_list::conversions::ToWebRender;
use crate::display_list::DisplayListBuilder;
@@ -9,6 +10,7 @@ use crate::fragment_tree::ContainingBlockManager;
use crate::fragments::{AnonymousFragment, BoxFragment, Fragment};
use crate::geom::PhysicalRect;
use crate::style_ext::ComputedValuesExt;
+use crate::FragmentTree;
use euclid::default::Rect;
use servo_arc::Arc as ServoArc;
use std::cmp::Ordering;
@@ -24,30 +26,39 @@ use style::values::generics::box_::Perspective;
use style::values::generics::transform;
use style::values::specified::box_::DisplayOutside;
use webrender_api as wr;
-use webrender_api::units::{LayoutPoint, LayoutTransform, LayoutVector2D};
+use webrender_api::units::{LayoutPoint, LayoutRect, LayoutTransform, LayoutVector2D};
#[derive(Clone)]
pub(crate) struct ContainingBlock {
- /// The SpaceAndClipInfo that contains the children of the fragment that
- /// established this containing block.
- space_and_clip: wr::SpaceAndClipInfo,
+ /// The SpatialId of the spatial node that contains the children
+ /// of this containing block.
+ spatial_id: wr::SpatialId,
+
+ /// The WebRender ClipId to use for this children of this containing
+ /// block.
+ clip_id: wr::ClipId,
/// The physical rect of this containing block.
rect: PhysicalRect<Length>,
}
impl ContainingBlock {
- pub(crate) fn new(rect: &PhysicalRect<Length>, space_and_clip: wr::SpaceAndClipInfo) -> Self {
+ pub(crate) fn new(
+ rect: &PhysicalRect<Length>,
+ spatial_id: wr::SpatialId,
+ clip_id: wr::ClipId,
+ ) -> Self {
ContainingBlock {
- space_and_clip,
+ spatial_id,
+ clip_id,
rect: *rect,
}
}
pub(crate) fn new_replacing_rect(&self, rect: &PhysicalRect<Length>) -> Self {
ContainingBlock {
- space_and_clip: self.space_and_clip,
rect: *rect,
+ ..*self
}
}
}
@@ -62,8 +73,89 @@ pub(crate) enum StackingContextSection {
Outline,
}
+impl DisplayList {
+ pub fn build_stacking_context_tree(&mut self, fragment_tree: &FragmentTree) -> StackingContext {
+ let cb_for_non_fixed_descendants = ContainingBlock::new(
+ &fragment_tree.initial_containing_block,
+ wr::SpatialId::root_scroll_node(self.wr.pipeline_id),
+ wr::ClipId::root(self.wr.pipeline_id),
+ );
+ let cb_for_fixed_descendants = ContainingBlock::new(
+ &fragment_tree.initial_containing_block,
+ wr::SpatialId::root_reference_frame(self.wr.pipeline_id),
+ wr::ClipId::root(self.wr.pipeline_id),
+ );
+
+ // We need to specify all three containing blocks here, because absolute
+ // descdendants of the root cannot share the containing block we specify
+ // for fixed descendants. In this case, they need to have the spatial
+ // id of the root scroll frame, whereas fixed descendants need the
+ // spatial id of the root reference frame so that they do not scroll with
+ // page content.
+ let containing_block_info = ContainingBlockInfo {
+ for_non_absolute_descendants: &cb_for_non_fixed_descendants,
+ for_absolute_descendants: Some(&cb_for_non_fixed_descendants),
+ for_absolute_and_fixed_descendants: &cb_for_fixed_descendants,
+ };
+
+ let mut root_stacking_context = StackingContext::create_root(&self.wr);
+ for fragment in &fragment_tree.root_fragments {
+ fragment.borrow().build_stacking_context_tree(
+ fragment,
+ self,
+ &containing_block_info,
+ &mut root_stacking_context,
+ StackingContextBuildMode::SkipHoisted,
+ );
+ }
+ root_stacking_context.sort();
+ root_stacking_context
+ }
+
+ fn push_reference_frame(
+ &mut self,
+ origin: LayoutPoint,
+ parent_spatial_id: &wr::SpatialId,
+ transform_style: wr::TransformStyle,
+ transform: wr::PropertyBinding<LayoutTransform>,
+ kind: wr::ReferenceFrameKind,
+ ) -> wr::SpatialId {
+ self.wr
+ .push_reference_frame(origin, *parent_spatial_id, transform_style, transform, kind)
+ }
+
+ fn pop_reference_frame(&mut self) {
+ self.wr.pop_reference_frame();
+ }
+
+ fn define_scroll_frame(
+ &mut self,
+ parent_spatial_id: &wr::SpatialId,
+ parent_clip_id: &wr::ClipId,
+ external_id: Option<wr::ExternalScrollId>,
+ content_rect: LayoutRect,
+ clip_rect: LayoutRect,
+ scroll_sensitivity: wr::ScrollSensitivity,
+ external_scroll_offset: LayoutVector2D,
+ ) -> (wr::SpatialId, wr::ClipId) {
+ let new_space_and_clip = self.wr.define_scroll_frame(
+ &wr::SpaceAndClipInfo {
+ spatial_id: *parent_spatial_id,
+ clip_id: *parent_clip_id,
+ },
+ external_id,
+ content_rect,
+ clip_rect,
+ scroll_sensitivity,
+ external_scroll_offset,
+ );
+ (new_space_and_clip.spatial_id, new_space_and_clip.clip_id)
+ }
+}
+
pub(crate) struct StackingContextFragment {
- space_and_clip: wr::SpaceAndClipInfo,
+ spatial_id: wr::SpatialId,
+ clip_id: wr::ClipId,
section: StackingContextSection,
containing_block: PhysicalRect<Length>,
fragment: ArcRefCell<Fragment>,
@@ -71,7 +163,8 @@ pub(crate) struct StackingContextFragment {
impl StackingContextFragment {
fn build_display_list(&self, builder: &mut DisplayListBuilder) {
- builder.current_space_and_clip = self.space_and_clip;
+ builder.current_spatial_id = self.spatial_id;
+ builder.current_clip_id = self.clip_id;
self.fragment
.borrow()
.build_display_list(builder, &self.containing_block, self.section);
@@ -86,7 +179,7 @@ pub(crate) enum StackingContextType {
PseudoAtomicInline,
}
-pub(crate) struct StackingContext {
+pub struct StackingContext {
/// The spatial id of this fragment. This is used to properly handle
/// things like preserve-3d.
spatial_id: wr::SpatialId,
@@ -162,9 +255,9 @@ impl StackingContext {
});
}
- fn push_webrender_stacking_context_if_necessary<'a>(
+ fn push_webrender_stacking_context_if_necessary(
&self,
- builder: &'a mut DisplayListBuilder,
+ builder: &mut DisplayListBuilder,
) -> bool {
let style = match self.initializing_fragment_style.as_ref() {
Some(style) => style,
@@ -202,7 +295,7 @@ impl StackingContext {
// This will require additional tracking during layout
// before we start collecting stacking contexts so that
// information will be available when we reach this point.
- builder.wr.push_stacking_context(
+ builder.wr().push_stacking_context(
LayoutPoint::zero(), // origin
self.spatial_id,
style.get_webrender_primitive_flags(),
@@ -251,7 +344,10 @@ impl StackingContext {
if background_color.alpha > 0 {
let common = builder.common_properties(painting_area, &style);
let color = super::rgba(background_color);
- builder.wr.push_rect(&common, painting_area, color)
+ builder
+ .display_list
+ .wr
+ .push_rect(&common, painting_area, color)
}
// `background-color` was comparatively easy,
@@ -299,11 +395,10 @@ impl StackingContext {
Some(fragment_tree.canvas_background.root_element),
);
- // The root element may have a CSS transform,
- // and we want the canvas’ background image to be transformed.
- // To do so, take its `SpatialId` (but not its `ClipId`)
- builder.current_space_and_clip.spatial_id =
- first_stacking_context_fragment.space_and_clip.spatial_id;
+ // The root element may have a CSS transform, and we want the canvas’
+ // background image to be transformed. To do so, take its `SpatialId`
+ // (but not its `ClipId`)
+ builder.current_spatial_id = first_stacking_context_fragment.spatial_id;
// Now we need express the painting area rectangle in the local coordinate system,
// which differs from the top-level coordinate system based on…
@@ -393,7 +488,7 @@ impl StackingContext {
}
if pushed_context {
- builder.wr.pop_stacking_context();
+ builder.display_list.wr.pop_stacking_context();
}
}
}
@@ -408,7 +503,7 @@ impl Fragment {
pub(crate) fn build_stacking_context_tree(
&self,
fragment_ref: &ArcRefCell<Fragment>,
- wr: &mut wr::DisplayListBuilder,
+ display_list: &mut DisplayList,
containing_block_info: &ContainingBlockInfo,
stacking_context: &mut StackingContext,
mode: StackingContextBuildMode,
@@ -432,7 +527,7 @@ impl Fragment {
fragment.build_stacking_context_tree(
fragment_ref,
- wr,
+ display_list,
containing_block,
containing_block_info,
stacking_context,
@@ -447,7 +542,7 @@ impl Fragment {
fragment_ref.borrow().build_stacking_context_tree(
fragment_ref,
- wr,
+ display_list,
containing_block_info,
stacking_context,
StackingContextBuildMode::IncludeHoisted,
@@ -455,7 +550,7 @@ impl Fragment {
},
Fragment::Anonymous(fragment) => {
fragment.build_stacking_context_tree(
- wr,
+ display_list,
containing_block,
containing_block_info,
stacking_context,
@@ -464,7 +559,8 @@ impl Fragment {
Fragment::Text(_) | Fragment::Image(_) | Fragment::IFrame(_) => {
stacking_context.fragments.push(StackingContextFragment {
section: StackingContextSection::Content,
- space_and_clip: containing_block.space_and_clip,
+ spatial_id: containing_block.spatial_id,
+ clip_id: containing_block.clip_id,
containing_block: containing_block.rect,
fragment: fragment_ref.clone(),
});
@@ -516,14 +612,14 @@ impl BoxFragment {
fn build_stacking_context_tree(
&self,
fragment: &ArcRefCell<Fragment>,
- wr: &mut wr::DisplayListBuilder,
+ display_list: &mut DisplayList,
containing_block: &ContainingBlock,
containing_block_info: &ContainingBlockInfo,
parent_stacking_context: &mut StackingContext,
) {
self.build_stacking_context_tree_maybe_creating_reference_frame(
fragment,
- wr,
+ display_list,
containing_block,
containing_block_info,
parent_stacking_context,
@@ -533,7 +629,7 @@ impl BoxFragment {
fn build_stacking_context_tree_maybe_creating_reference_frame(
&self,
fragment: &ArcRefCell<Fragment>,
- wr: &mut wr::DisplayListBuilder,
+ display_list: &mut DisplayList,
containing_block: &ContainingBlock,
containing_block_info: &ContainingBlockInfo,
parent_stacking_context: &mut StackingContext,
@@ -544,7 +640,7 @@ impl BoxFragment {
None => {
return self.build_stacking_context_tree_maybe_creating_stacking_context(
fragment,
- wr,
+ display_list,
containing_block,
containing_block_info,
parent_stacking_context,
@@ -552,9 +648,9 @@ impl BoxFragment {
},
};
- let new_spatial_id = wr.push_reference_frame(
+ let new_spatial_id = display_list.push_reference_frame(
reference_frame_data.origin.to_webrender(),
- containing_block.space_and_clip.spatial_id,
+ &containing_block.spatial_id,
self.style.get_box().transform_style.to_webrender(),
wr::PropertyBinding::Value(reference_frame_data.transform),
reference_frame_data.kind,
@@ -576,29 +672,27 @@ impl BoxFragment {
&containing_block
.rect
.translate(-reference_frame_data.origin.to_vector()),
- wr::SpaceAndClipInfo {
- spatial_id: new_spatial_id,
- clip_id: containing_block.space_and_clip.clip_id,
- },
+ new_spatial_id,
+ containing_block.clip_id,
);
let new_containing_block_info =
containing_block_info.new_for_non_absolute_descendants(&adjusted_containing_block);
self.build_stacking_context_tree_maybe_creating_stacking_context(
fragment,
- wr,
+ display_list,
&adjusted_containing_block,
&new_containing_block_info,
parent_stacking_context,
);
- wr.pop_reference_frame();
+ display_list.pop_reference_frame();
}
fn build_stacking_context_tree_maybe_creating_stacking_context(
&self,
fragment: &ArcRefCell<Fragment>,
- wr: &mut wr::DisplayListBuilder,
+ display_list: &mut DisplayList,
containing_block: &ContainingBlock,
containing_block_info: &ContainingBlockInfo,
parent_stacking_context: &mut StackingContext,
@@ -608,7 +702,7 @@ impl BoxFragment {
None => {
self.build_stacking_context_tree_for_children(
fragment,
- wr,
+ display_list,
containing_block,
containing_block_info,
parent_stacking_context,
@@ -618,13 +712,13 @@ impl BoxFragment {
};
let mut child_stacking_context = StackingContext::new(
- containing_block.space_and_clip.spatial_id,
+ containing_block.spatial_id,
self.style.clone(),
context_type,
);
self.build_stacking_context_tree_for_children(
fragment,
- wr,
+ display_list,
containing_block,
containing_block_info,
&mut child_stacking_context,
@@ -647,30 +741,36 @@ impl BoxFragment {
.append(&mut stolen_children);
}
- fn build_stacking_context_tree_for_children<'a>(
- &'a self,
+ fn build_stacking_context_tree_for_children(
+ &self,
fragment: &ArcRefCell<Fragment>,
- wr: &mut wr::DisplayListBuilder,
+ display_list: &mut DisplayList,
containing_block: &ContainingBlock,
containing_block_info: &ContainingBlockInfo,
stacking_context: &mut StackingContext,
) {
- let mut new_space_and_clip = containing_block.space_and_clip;
- if let Some(new_clip_id) =
- self.build_clip_frame_if_necessary(wr, new_space_and_clip, &containing_block.rect)
- {
- new_space_and_clip.clip_id = new_clip_id;
+ let mut new_spatial_id = containing_block.spatial_id;
+ let mut new_clip_id = containing_block.clip_id;
+ if let Some(clip_id) = self.build_clip_frame_if_necessary(
+ display_list,
+ &new_spatial_id,
+ &new_clip_id,
+ &containing_block.rect,
+ ) {
+ new_clip_id = clip_id;
}
stacking_context.fragments.push(StackingContextFragment {
- space_and_clip: new_space_and_clip,
+ spatial_id: new_spatial_id,
+ clip_id: new_clip_id,
section: self.get_stacking_context_section(),
containing_block: containing_block.rect,
fragment: fragment.clone(),
});
if self.style.get_outline().outline_width.px() > 0.0 {
stacking_context.fragments.push(StackingContextFragment {
- space_and_clip: new_space_and_clip,
+ spatial_id: new_spatial_id,
+ clip_id: new_clip_id,
section: StackingContextSection::Outline,
containing_block: containing_block.rect,
fragment: fragment.clone(),
@@ -679,10 +779,14 @@ impl BoxFragment {
// We want to build the scroll frame after the background and border, because
// they shouldn't scroll with the rest of the box content.
- if let Some(scroll_space_and_clip) =
- self.build_scroll_frame_if_necessary(wr, new_space_and_clip, &containing_block.rect)
- {
- new_space_and_clip = scroll_space_and_clip;
+ if let Some((spatial_id, clip_id)) = self.build_scroll_frame_if_necessary(
+ display_list,
+ &new_spatial_id,
+ &new_clip_id,
+ &containing_block.rect,
+ ) {
+ new_spatial_id = spatial_id;
+ new_clip_id = clip_id;
}
let padding_rect = self
@@ -694,14 +798,10 @@ impl BoxFragment {
.to_physical(self.style.writing_mode, &containing_block.rect)
.translate(containing_block.rect.origin.to_vector());
- let for_absolute_descendants = ContainingBlock {
- rect: padding_rect,
- space_and_clip: new_space_and_clip,
- };
- let for_non_absolute_descendants = ContainingBlock {
- rect: content_rect,
- space_and_clip: new_space_and_clip,
- };
+ let for_absolute_descendants =
+ ContainingBlock::new(&padding_rect, new_spatial_id, new_clip_id);
+ let for_non_absolute_descendants =
+ ContainingBlock::new(&content_rect, new_spatial_id, new_clip_id);
// Create a new `ContainingBlockInfo` for descendants depending on
// whether or not this fragment establishes a containing block for
@@ -729,7 +829,7 @@ impl BoxFragment {
for child in &self.children {
child.borrow().build_stacking_context_tree(
child,
- wr,
+ display_list,
&new_containing_block_info,
stacking_context,
StackingContextBuildMode::SkipHoisted,
@@ -739,8 +839,9 @@ impl BoxFragment {
fn build_clip_frame_if_necessary(
&self,
- wr: &mut wr::DisplayListBuilder,
- current_space_and_clip: wr::SpaceAndClipInfo,
+ display_list: &mut DisplayList,
+ parent_spatial_id: &wr::SpatialId,
+ parent_clip_id: &wr::ClipId,
containing_block_rect: &PhysicalRect<Length>,
) -> Option<wr::ClipId> {
let position = self.style.get_box().position;
@@ -764,15 +865,22 @@ impl BoxFragment {
.translate(containing_block_rect.origin.to_vector())
.to_webrender();
- Some(wr.define_clip_rect(&current_space_and_clip, clip_rect))
+ Some(display_list.wr.define_clip_rect(
+ &wr::SpaceAndClipInfo {
+ spatial_id: *parent_spatial_id,
+ clip_id: *parent_clip_id,
+ },
+ clip_rect,
+ ))
}
- fn build_scroll_frame_if_necessary<'a>(
+ fn build_scroll_frame_if_necessary(
&self,
- wr: &mut wr::DisplayListBuilder,
- current_space_and_clip: wr::SpaceAndClipInfo,
+ display_list: &mut DisplayList,
+ parent_spatial_id: &wr::SpatialId,
+ parent_clip_id: &wr::ClipId,
containing_block_rect: &PhysicalRect<Length>,
- ) -> Option<wr::SpaceAndClipInfo> {
+ ) -> Option<(wr::SpatialId, wr::ClipId)> {
let overflow_x = self.style.get_box().overflow_x;
let overflow_y = self.style.get_box().overflow_y;
if overflow_x == ComputedOverflow::Visible && overflow_y == ComputedOverflow::Visible {
@@ -780,7 +888,10 @@ impl BoxFragment {
}
let tag = self.base.tag?;
- let external_id = wr::ExternalScrollId(tag.to_display_list_fragment_id(), wr.pipeline_id);
+ let external_id = wr::ExternalScrollId(
+ tag.to_display_list_fragment_id(),
+ display_list.wr.pipeline_id,
+ );
let sensitivity =
if ComputedOverflow::Hidden == overflow_x && ComputedOverflow::Hidden == overflow_y {
@@ -794,9 +905,11 @@ impl BoxFragment {
.to_physical(self.style.writing_mode, &containing_block_rect)
.translate(containing_block_rect.origin.to_vector())
.to_webrender();
+
Some(
- wr.define_scroll_frame(
- &current_space_and_clip,
+ display_list.define_scroll_frame(
+ parent_spatial_id,
+ parent_clip_id,
Some(external_id),
self.scrollable_overflow(&containing_block_rect)
.to_webrender(),
@@ -937,7 +1050,7 @@ impl BoxFragment {
impl AnonymousFragment {
fn build_stacking_context_tree(
&self,
- wr: &mut wr::DisplayListBuilder,
+ display_list: &mut DisplayList,
containing_block: &ContainingBlock,
containing_block_info: &ContainingBlockInfo,
stacking_context: &mut StackingContext,
@@ -953,7 +1066,7 @@ impl AnonymousFragment {
for child in &self.children {
child.borrow().build_stacking_context_tree(
child,
- wr,
+ display_list,
&new_containing_block_info,
stacking_context,
StackingContextBuildMode::SkipHoisted,
diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs
index f44b0c88159..5006b65a48b 100644
--- a/components/layout_2020/flow/root.rs
+++ b/components/layout_2020/flow/root.rs
@@ -4,9 +4,7 @@
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
-use crate::display_list::stacking_context::{
- ContainingBlock, ContainingBlockInfo, StackingContext, StackingContextBuildMode,
-};
+use crate::display_list::StackingContext;
use crate::dom::{LayoutBox, NodeExt};
use crate::dom_traversal::{iter_child_nodes, Contents, NodeAndStyleInfo};
use crate::flexbox::FlexLevelBox;
@@ -38,7 +36,6 @@ use style::dom::OpaqueNode;
use style::properties::ComputedValues;
use style::values::computed::Length;
use style_traits::CSSPixel;
-use webrender_api::{ClipId, SpaceAndClipInfo, SpatialId};
#[derive(Serialize)]
pub struct BoxTree {
@@ -60,7 +57,7 @@ pub struct FragmentTree {
/// * The first fragment is generated by the root element.
/// * There may be additional fragments generated by positioned boxes
/// that have the initial containing block.
- root_fragments: Vec<ArcRefCell<Fragment>>,
+ pub(crate) root_fragments: Vec<ArcRefCell<Fragment>>,
/// The scrollable overflow rectangle for the entire tree
/// https://drafts.csswg.org/css-overflow/#scrollable
@@ -384,58 +381,18 @@ impl BoxTree {
}
impl FragmentTree {
- pub fn build_display_list(&self, builder: &mut crate::display_list::DisplayListBuilder) {
- let stacking_context = self.build_stacking_context_tree(builder);
-
+ pub(crate) fn build_display_list(
+ &self,
+ builder: &mut crate::display_list::DisplayListBuilder,
+ root_stacking_context: &StackingContext,
+ ) {
// Paint the canvas’ background (if any) before/under everything else
- stacking_context.build_canvas_background_display_list(
+ root_stacking_context.build_canvas_background_display_list(
builder,
self,
&self.initial_containing_block,
);
-
- stacking_context.build_display_list(builder);
- }
-
- fn build_stacking_context_tree(
- &self,
- builder: &mut crate::display_list::DisplayListBuilder,
- ) -> StackingContext {
- let mut stacking_context = StackingContext::create_root(&builder.wr);
- let pipeline_id = builder.wr.pipeline_id;
- let cb_for_non_fixed_descendants = ContainingBlock::new(
- &self.initial_containing_block,
- SpaceAndClipInfo::root_scroll(pipeline_id),
- );
- let cb_for_fixed_descendants = ContainingBlock::new(
- &self.initial_containing_block,
- SpaceAndClipInfo {
- spatial_id: SpatialId::root_reference_frame(pipeline_id),
- clip_id: ClipId::root(pipeline_id),
- },
- );
-
- for fragment in &self.root_fragments {
- fragment.borrow().build_stacking_context_tree(
- fragment,
- &mut builder.wr,
- // We need to specify all three containing blocks here, because absolute
- // descdendants of the root cannot share the containing block we specify
- // for fixed descendants. In this case, they need to have the spatial
- // id of the root scroll frame, whereas fixed descendants need the
- // spatial id of the root reference frame so that they do not scroll with
- // page content.
- &ContainingBlockInfo {
- for_non_absolute_descendants: &cb_for_non_fixed_descendants,
- for_absolute_descendants: Some(&cb_for_non_fixed_descendants),
- for_absolute_and_fixed_descendants: &cb_for_fixed_descendants,
- },
- &mut stacking_context,
- StackingContextBuildMode::SkipHoisted,
- );
- }
- stacking_context.sort();
- stacking_context
+ root_stacking_context.build_display_list(builder);
}
pub fn print(&self) {
diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs
index 90c6f4da952..60b00075ddb 100644
--- a/components/layout_thread_2020/lib.rs
+++ b/components/layout_thread_2020/lib.rs
@@ -29,7 +29,7 @@ use gfx_traits::{node_id_from_scroll_id, Epoch};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
use layout::context::LayoutContext;
-use layout::display_list::{DisplayListBuilder, WebRenderImageInfo};
+use layout::display_list::{DisplayList, WebRenderImageInfo};
use layout::dom::DOMLayoutData;
use layout::layout_debug;
use layout::query::{
@@ -1268,8 +1268,15 @@ impl LayoutThread {
document.will_paint();
}
- let mut display_list =
- DisplayListBuilder::new(self.id.to_webrender(), context, &fragment_tree);
+ let viewport_size = webrender_api::units::LayoutSize::from_untyped(Size2D::new(
+ self.viewport_size.width.to_f32_px(),
+ self.viewport_size.height.to_f32_px(),
+ ));
+ let mut display_list = DisplayList::new(
+ viewport_size,
+ fragment_tree.scrollable_overflow(),
+ self.id.to_webrender(),
+ );
// `dump_serialized_display_list` doesn't actually print anything. It sets up
// the display list for printing the serialized version when `finalize()` is called.
@@ -1279,7 +1286,14 @@ impl LayoutThread {
display_list.wr.dump_serialized_display_list();
}
- fragment_tree.build_display_list(&mut display_list);
+ // Build the root stacking context. This turns the `FragmentTree` into a
+ // tree of fragments in CSS painting order and also creates all
+ // applicable spatial and clip nodes.
+ let root_stacking_context = display_list.build_stacking_context_tree(&fragment_tree);
+
+ // Build the rest of the display list which inclues all of the WebRender primitives.
+ let (iframe_sizes, is_contentful) =
+ display_list.build(context, &fragment_tree, &root_stacking_context);
if self.debug.dump_flow_tree {
fragment_tree.print();
@@ -1294,12 +1308,8 @@ impl LayoutThread {
// sending the display list to WebRender in order to set time related
// Progressive Web Metrics.
self.paint_time_metrics
- .maybe_observe_paint_time(self, epoch, display_list.is_contentful);
+ .maybe_observe_paint_time(self, epoch, is_contentful);
- let viewport_size = webrender_api::units::LayoutSize::from_untyped(Size2D::new(
- self.viewport_size.width.to_f32_px(),
- self.viewport_size.height.to_f32_px(),
- ));
self.webrender_api.send_display_list(
epoch,
viewport_size,
@@ -1307,7 +1317,7 @@ impl LayoutThread {
display_list.wr.finalize(),
);
- self.update_iframe_sizes(display_list.iframe_sizes);
+ self.update_iframe_sizes(iframe_sizes);
if self.debug.trace_layout {
layout_debug::end_trace(self.generation.get());