Use the WebRender clip chain API

The old clipping API has been removed from WebRender, so this switches
both legacy and new layout over to use the clip chain API in preparation
for the WebRender upgrade.
This commit is contained in:
Martin Robinson 2023-07-04 10:39:58 +02:00
parent 66abb1dfc4
commit 3c4328f3dc
No known key found for this signature in database
GPG key ID: D56AA4FA55EFE6F8
4 changed files with 165 additions and 114 deletions

View file

@ -2616,6 +2616,8 @@ impl BlockFlow {
clip: ClippingRegion::from_rect(border_box.to_layout()), clip: ClippingRegion::from_rect(border_box.to_layout()),
content_rect: LayoutRect::zero(), content_rect: LayoutRect::zero(),
node_type: ClipScrollNodeType::StickyFrame(sticky_frame_data), node_type: ClipScrollNodeType::StickyFrame(sticky_frame_data),
scroll_node_id: None,
clip_chain_id: None,
}); });
let new_clipping_and_scrolling = ClippingAndScrolling::simple(new_clip_scroll_index); let new_clipping_and_scrolling = ClippingAndScrolling::simple(new_clip_scroll_index);
@ -2683,6 +2685,8 @@ impl BlockFlow {
clip: clip, clip: clip,
content_rect: Rect::new(content_box.origin, content_size).to_layout(), content_rect: Rect::new(content_box.origin, content_size).to_layout(),
node_type: ClipScrollNodeType::ScrollFrame(sensitivity, external_id), node_type: ClipScrollNodeType::ScrollFrame(sensitivity, external_id),
scroll_node_id: None,
clip_chain_id: None,
}); });
let new_clipping_and_scrolling = ClippingAndScrolling::simple(new_clip_scroll_index); let new_clipping_and_scrolling = ClippingAndScrolling::simple(new_clip_scroll_index);
@ -2719,6 +2723,8 @@ impl BlockFlow {
clip: ClippingRegion::from_rect(clip_rect.to_layout()), clip: ClippingRegion::from_rect(clip_rect.to_layout()),
content_rect: LayoutRect::zero(), // content_rect isn't important for clips. content_rect: LayoutRect::zero(), // content_rect isn't important for clips.
node_type: ClipScrollNodeType::Clip(ClipType::Rect), node_type: ClipScrollNodeType::Clip(ClipType::Rect),
scroll_node_id: None,
clip_chain_id: None,
}); });
let new_indices = ClippingAndScrolling::new(new_index, new_index); let new_indices = ClippingAndScrolling::new(new_index, new_index);

View file

@ -18,6 +18,7 @@ use gfx_traits::print_tree::PrintTree;
use gfx_traits::{self, StackingContextId}; use gfx_traits::{self, StackingContextId};
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use net_traits::image::base::Image; use net_traits::image::base::Image;
use script_traits::compositor::ScrollTreeNodeId;
use servo_geometry::MaxRect; use servo_geometry::MaxRect;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::HashMap; use std::collections::HashMap;
@ -31,6 +32,7 @@ use webrender_api::{
FilterOp, GlyphInstance, GradientStop, ImageKey, MixBlendMode, PrimitiveFlags, FilterOp, GlyphInstance, GradientStop, ImageKey, MixBlendMode, PrimitiveFlags,
ScrollSensitivity, Shadow, SpatialId, StickyOffsetBounds, TransformStyle, ScrollSensitivity, Shadow, SpatialId, StickyOffsetBounds, TransformStyle,
}; };
use wr::ClipChainId;
pub use style::dom::OpaqueNode; pub use style::dom::OpaqueNode;
@ -369,6 +371,12 @@ pub struct ClipScrollNode {
/// The type of this ClipScrollNode. /// The type of this ClipScrollNode.
pub node_type: ClipScrollNodeType, pub node_type: ClipScrollNodeType,
/// The WebRender spatial id of this node assigned during WebRender conversion.
pub scroll_node_id: Option<ScrollTreeNodeId>,
/// The WebRender clip id of this node assigned during WebRender conversion.
pub clip_chain_id: Option<ClipChainId>,
} }
impl ClipScrollNode { impl ClipScrollNode {
@ -378,6 +386,8 @@ impl ClipScrollNode {
clip: ClippingRegion::from_rect(LayoutRect::zero()), clip: ClippingRegion::from_rect(LayoutRect::zero()),
content_rect: LayoutRect::zero(), content_rect: LayoutRect::zero(),
node_type: ClipScrollNodeType::Placeholder, node_type: ClipScrollNodeType::Placeholder,
scroll_node_id: None,
clip_chain_id: None,
} }
} }
@ -400,6 +410,8 @@ impl ClipScrollNode {
clip: ClippingRegion::from_rect(clip_rect), clip: ClippingRegion::from_rect(clip_rect),
content_rect: LayoutRect::zero(), // content_rect isn't important for clips. content_rect: LayoutRect::zero(), // content_rect isn't important for clips.
node_type: ClipScrollNodeType::Clip(ClipType::Rounded(complex_region)), node_type: ClipScrollNodeType::Clip(ClipType::Rounded(complex_region)),
scroll_node_id: None,
clip_chain_id: None,
} }
} }
} }

View file

@ -13,22 +13,24 @@ use msg::constellation_msg::PipelineId;
use script_traits::compositor::{CompositorDisplayListInfo, ScrollTreeNodeId, ScrollableNodeInfo}; use script_traits::compositor::{CompositorDisplayListInfo, ScrollTreeNodeId, ScrollableNodeInfo};
use webrender_api::units::{LayoutPoint, LayoutSize, LayoutVector2D}; use webrender_api::units::{LayoutPoint, LayoutSize, LayoutVector2D};
use webrender_api::{ use webrender_api::{
self, ClipId, CommonItemProperties, DisplayItem as WrDisplayItem, DisplayListBuilder, Epoch, self, ClipChainId, ClipId, CommonItemProperties, DisplayItem as WrDisplayItem,
PrimitiveFlags, PropertyBinding, PushStackingContextDisplayItem, RasterSpace, DisplayListBuilder, Epoch, PrimitiveFlags, PropertyBinding, PushStackingContextDisplayItem,
ReferenceFrameKind, SpaceAndClipInfo, SpatialId, StackingContext, RasterSpace, ReferenceFrameKind, SpaceAndClipInfo, SpatialId, StackingContext,
}; };
struct ClipScrollState { struct ClipScrollState<'a> {
clip_ids: Vec<Option<ClipId>>, clip_scroll_nodes: &'a mut Vec<ClipScrollNode>,
scroll_node_ids: Vec<Option<ScrollTreeNodeId>>,
compositor_info: CompositorDisplayListInfo, compositor_info: CompositorDisplayListInfo,
} }
impl ClipScrollState { impl<'a> ClipScrollState<'a> {
fn new(size: usize, compositor_info: CompositorDisplayListInfo) -> Self { fn new(
clip_scroll_nodes: &'a mut Vec<ClipScrollNode>,
compositor_info: CompositorDisplayListInfo,
builder: &mut DisplayListBuilder,
) -> Self {
let mut state = ClipScrollState { let mut state = ClipScrollState {
clip_ids: vec![None; size], clip_scroll_nodes,
scroll_node_ids: vec![None; size],
compositor_info, compositor_info,
}; };
@ -37,32 +39,38 @@ impl ClipScrollState {
// automatically. We also follow the "old" WebRender API for clip/scroll for now, // automatically. We also follow the "old" WebRender API for clip/scroll for now,
// hence both arrays are initialized based on FIRST_SPATIAL_NODE_INDEX, while // hence both arrays are initialized based on FIRST_SPATIAL_NODE_INDEX, while
// FIRST_CLIP_NODE_INDEX is not taken into account. // FIRST_CLIP_NODE_INDEX is not taken into account.
state.scroll_node_ids[0] = Some(state.compositor_info.root_reference_frame_id); state.clip_scroll_nodes[0].scroll_node_id =
state.scroll_node_ids[1] = Some(state.compositor_info.root_scroll_node_id); Some(state.compositor_info.root_reference_frame_id);
state.clip_scroll_nodes[1].scroll_node_id = Some(state.compositor_info.root_scroll_node_id);
let root_clip_id = ClipId::root(state.compositor_info.pipeline_id); let root_clip_chain =
state.add_clip_node_mapping(0, root_clip_id); builder.define_clip_chain(None, [ClipId::root(state.compositor_info.pipeline_id)]);
state.add_clip_node_mapping(1, root_clip_id); state.add_clip_node_mapping(0, root_clip_chain);
state.add_clip_node_mapping(1, root_clip_chain);
state state
} }
fn webrender_clip_id_for_index(&mut self, index: usize) -> ClipId { fn webrender_clip_id_for_index(&mut self, index: usize) -> ClipChainId {
self.clip_ids[index].expect("Tried to use WebRender parent ClipId before it was defined.") self.clip_scroll_nodes[index]
.clip_chain_id
.expect("Tried to access WebRender ClipId before definining it.")
} }
fn webrender_spatial_id_for_index(&mut self, index: usize) -> SpatialId { fn webrender_spatial_id_for_index(&mut self, index: usize) -> SpatialId {
self.scroll_node_ids[index] self.clip_scroll_nodes[index]
.scroll_node_id
.expect("Tried to use WebRender parent SpatialId before it was defined.") .expect("Tried to use WebRender parent SpatialId before it was defined.")
.spatial_id .spatial_id
} }
fn add_clip_node_mapping(&mut self, index: usize, webrender_id: ClipId) { fn add_clip_node_mapping(&mut self, index: usize, webrender_id: ClipChainId) {
self.clip_ids[index] = Some(webrender_id); self.clip_scroll_nodes[index].clip_chain_id = Some(webrender_id);
} }
fn scroll_node_id_from_index(&self, index: usize) -> ScrollTreeNodeId { fn scroll_node_id_from_index(&self, index: usize) -> ScrollTreeNodeId {
self.scroll_node_ids[index] self.clip_scroll_nodes[index]
.scroll_node_id
.expect("Tried to use WebRender parent SpatialId before it was defined.") .expect("Tried to use WebRender parent SpatialId before it was defined.")
} }
@ -74,15 +82,17 @@ impl ClipScrollState {
scroll_info: Option<ScrollableNodeInfo>, scroll_info: Option<ScrollableNodeInfo>,
) { ) {
let parent_scroll_node_id = parent_index.map(|index| self.scroll_node_id_from_index(index)); let parent_scroll_node_id = parent_index.map(|index| self.scroll_node_id_from_index(index));
self.scroll_node_ids[index] = Some(self.compositor_info.scroll_tree.add_scroll_tree_node( self.clip_scroll_nodes[index].scroll_node_id =
parent_scroll_node_id.as_ref(), Some(self.compositor_info.scroll_tree.add_scroll_tree_node(
spatial_id, parent_scroll_node_id.as_ref(),
scroll_info, spatial_id,
)); scroll_info,
));
} }
fn add_spatial_node_mapping_to_parent_index(&mut self, index: usize, parent_index: usize) { fn add_spatial_node_mapping_to_parent_index(&mut self, index: usize, parent_index: usize) {
self.scroll_node_ids[index] = self.scroll_node_ids[parent_index]; self.clip_scroll_nodes[index].scroll_node_id =
self.clip_scroll_nodes[parent_index].scroll_node_id
} }
} }
@ -100,27 +110,22 @@ impl DisplayList {
epoch: Epoch, epoch: Epoch,
) -> (DisplayListBuilder, CompositorDisplayListInfo, IsContentful) { ) -> (DisplayListBuilder, CompositorDisplayListInfo, IsContentful) {
let webrender_pipeline = pipeline_id.to_webrender(); let webrender_pipeline = pipeline_id.to_webrender();
let mut state = ClipScrollState::new(
self.clip_scroll_nodes.len(),
CompositorDisplayListInfo::new(
viewport_size,
self.bounds().size,
webrender_pipeline,
epoch,
),
);
let mut builder = DisplayListBuilder::with_capacity( let mut builder = DisplayListBuilder::with_capacity(
webrender_pipeline, webrender_pipeline,
self.bounds().size, self.bounds().size,
1024 * 1024, // 1 MB of space 1024 * 1024, // 1 MB of space
); );
let content_size = self.bounds().size;
let mut state = ClipScrollState::new(
&mut self.clip_scroll_nodes,
CompositorDisplayListInfo::new(viewport_size, content_size, webrender_pipeline, epoch),
&mut builder,
);
let mut is_contentful = IsContentful(false); let mut is_contentful = IsContentful(false);
for item in &mut self.list { for item in &mut self.list {
is_contentful.0 |= item is_contentful.0 |= item.convert_to_webrender(&mut state, &mut builder).0;
.convert_to_webrender(&self.clip_scroll_nodes, &mut state, &mut builder)
.0;
} }
(builder, state.compositor_info, is_contentful) (builder, state.compositor_info, is_contentful)
@ -130,7 +135,6 @@ impl DisplayList {
impl DisplayItem { impl DisplayItem {
fn convert_to_webrender( fn convert_to_webrender(
&mut self, &mut self,
clip_scroll_nodes: &[ClipScrollNode],
state: &mut ClipScrollState, state: &mut ClipScrollState,
builder: &mut DisplayListBuilder, builder: &mut DisplayListBuilder,
) -> IsContentful { ) -> IsContentful {
@ -165,7 +169,7 @@ impl DisplayItem {
CommonItemProperties { CommonItemProperties {
clip_rect: base.clip_rect, clip_rect: base.clip_rect,
spatial_id: current_scroll_node_id.spatial_id, spatial_id: current_scroll_node_id.spatial_id,
clip_id: current_clip_id, clip_id: ClipId::ClipChain(current_clip_id),
// TODO(gw): Make use of the WR backface visibility functionality. // TODO(gw): Make use of the WR backface visibility functionality.
flags: PrimitiveFlags::default(), flags: PrimitiveFlags::default(),
hit_info: tag, hit_info: tag,
@ -339,48 +343,54 @@ impl DisplayItem {
}, },
DisplayItem::DefineClipScrollNode(ref mut item) => { DisplayItem::DefineClipScrollNode(ref mut item) => {
let index = item.node_index.to_index(); let index = item.node_index.to_index();
let node = &clip_scroll_nodes[index]; let node = state.clip_scroll_nodes[index].clone();
let item_rect = node.clip.main; let item_rect = node.clip.main;
let parent_index = node.parent_index.to_index(); let parent_index = node.parent_index.to_index();
let parent_spatial_id = state.webrender_spatial_id_for_index(parent_index); let parent_spatial_id = state.webrender_spatial_id_for_index(parent_index);
let parent_clip_id = state.webrender_clip_id_for_index(parent_index); let parent_clip_chain_id = state.webrender_clip_id_for_index(parent_index);
let parent_space_and_clip_info = SpaceAndClipInfo {
clip_id: ClipId::root(state.compositor_info.pipeline_id),
spatial_id: parent_spatial_id,
};
match node.node_type { match node.node_type {
ClipScrollNodeType::Clip(clip_type) => { ClipScrollNodeType::Clip(clip_type) => {
let space_and_clip_info = SpaceAndClipInfo {
clip_id: parent_clip_id,
spatial_id: parent_spatial_id,
};
let clip_id = match clip_type { let clip_id = match clip_type {
ClipType::Rect => { ClipType::Rect => {
builder.define_clip_rect(&space_and_clip_info, item_rect) builder.define_clip_rect(&parent_space_and_clip_info, item_rect)
},
ClipType::Rounded(complex) => {
builder.define_clip_rounded_rect(&space_and_clip_info, complex)
}, },
ClipType::Rounded(complex) => builder
.define_clip_rounded_rect(&parent_space_and_clip_info, complex),
}; };
state.add_clip_node_mapping(index, clip_id); let clip_chain_id =
builder.define_clip_chain(Some(parent_clip_chain_id), [clip_id]);
state.add_clip_node_mapping(index, clip_chain_id);
state.add_spatial_node_mapping_to_parent_index(index, parent_index); state.add_spatial_node_mapping_to_parent_index(index, parent_index);
}, },
ClipScrollNodeType::ScrollFrame(scroll_sensitivity, external_id) => { ClipScrollNodeType::ScrollFrame(scroll_sensitivity, external_id) => {
let space_clip_info = builder.define_scroll_frame( let clip_id =
&SpaceAndClipInfo { builder.define_clip_rect(&parent_space_and_clip_info, item_rect);
clip_id: parent_clip_id, let clip_chain_id =
spatial_id: parent_spatial_id, builder.define_clip_chain(Some(parent_clip_chain_id), [clip_id]);
}, state.add_clip_node_mapping(index, clip_chain_id);
Some(external_id),
node.content_rect, let spatial_id = builder
item_rect, .define_scroll_frame(
scroll_sensitivity, &parent_space_and_clip_info,
LayoutVector2D::zero(), Some(external_id),
); node.content_rect,
item_rect,
scroll_sensitivity,
LayoutVector2D::zero(),
)
.spatial_id;
state.add_clip_node_mapping(index, space_clip_info.clip_id);
state.register_spatial_node( state.register_spatial_node(
index, index,
space_clip_info.spatial_id, spatial_id,
Some(parent_index), Some(parent_index),
Some(ScrollableNodeInfo { Some(ScrollableNodeInfo {
external_id, external_id,
@ -401,7 +411,7 @@ impl DisplayItem {
LayoutVector2D::zero(), LayoutVector2D::zero(),
); );
state.add_clip_node_mapping(index, parent_clip_id); state.add_clip_node_mapping(index, parent_clip_chain_id);
state.register_spatial_node(index, id, Some(current_scrolling_index), None); state.register_spatial_node(index, id, Some(current_scrolling_index), None);
}, },
ClipScrollNodeType::Placeholder => { ClipScrollNodeType::Placeholder => {

View file

@ -37,7 +37,7 @@ pub(crate) struct ContainingBlock {
/// The WebRender ClipId to use for this children of this containing /// The WebRender ClipId to use for this children of this containing
/// block. /// block.
clip_id: wr::ClipId, clip_chain_id: wr::ClipChainId,
/// The physical rect of this containing block. /// The physical rect of this containing block.
rect: PhysicalRect<Length>, rect: PhysicalRect<Length>,
@ -47,11 +47,11 @@ impl ContainingBlock {
pub(crate) fn new( pub(crate) fn new(
rect: &PhysicalRect<Length>, rect: &PhysicalRect<Length>,
scroll_node_id: ScrollTreeNodeId, scroll_node_id: ScrollTreeNodeId,
clip_id: wr::ClipId, clip_chain_id: wr::ClipChainId,
) -> Self { ) -> Self {
ContainingBlock { ContainingBlock {
scroll_node_id, scroll_node_id,
clip_id, clip_chain_id,
rect: *rect, rect: *rect,
} }
} }
@ -76,15 +76,19 @@ pub(crate) enum StackingContextSection {
impl DisplayList { impl DisplayList {
pub fn build_stacking_context_tree(&mut self, fragment_tree: &FragmentTree) -> StackingContext { pub fn build_stacking_context_tree(&mut self, fragment_tree: &FragmentTree) -> StackingContext {
let root_clip_chain_id = self
.wr
.define_clip_chain(None, [wr::ClipId::root(self.wr.pipeline_id)]);
let cb_for_non_fixed_descendants = ContainingBlock::new( let cb_for_non_fixed_descendants = ContainingBlock::new(
&fragment_tree.initial_containing_block, &fragment_tree.initial_containing_block,
self.compositor_info.root_scroll_node_id, self.compositor_info.root_scroll_node_id,
wr::ClipId::root(self.wr.pipeline_id), root_clip_chain_id,
); );
let cb_for_fixed_descendants = ContainingBlock::new( let cb_for_fixed_descendants = ContainingBlock::new(
&fragment_tree.initial_containing_block, &fragment_tree.initial_containing_block,
self.compositor_info.root_reference_frame_id, self.compositor_info.root_reference_frame_id,
wr::ClipId::root(self.wr.pipeline_id), root_clip_chain_id,
); );
// We need to specify all three containing blocks here, because absolute // We need to specify all three containing blocks here, because absolute
@ -142,27 +146,40 @@ impl DisplayList {
fn define_scroll_frame( fn define_scroll_frame(
&mut self, &mut self,
parent_scroll_node_id: &ScrollTreeNodeId, parent_scroll_node_id: &ScrollTreeNodeId,
parent_clip_id: &wr::ClipId, parent_clip_chain_id: &wr::ClipChainId,
external_id: wr::ExternalScrollId, external_id: wr::ExternalScrollId,
content_rect: LayoutRect, content_rect: LayoutRect,
clip_rect: LayoutRect, clip_rect: LayoutRect,
scroll_sensitivity: wr::ScrollSensitivity, scroll_sensitivity: wr::ScrollSensitivity,
external_scroll_offset: LayoutVector2D, external_scroll_offset: LayoutVector2D,
) -> (ScrollTreeNodeId, wr::ClipId) { ) -> (ScrollTreeNodeId, wr::ClipChainId) {
let new_space_and_clip = self.wr.define_scroll_frame( let parent_space_and_clip_info = wr::SpaceAndClipInfo {
&wr::SpaceAndClipInfo { spatial_id: parent_scroll_node_id.spatial_id,
spatial_id: parent_scroll_node_id.spatial_id, clip_id: wr::ClipId::root(self.wr.pipeline_id),
clip_id: *parent_clip_id, };
},
Some(external_id), let new_clip_id = self
content_rect, .wr
clip_rect, .define_clip_rect(&parent_space_and_clip_info, clip_rect);
scroll_sensitivity, let new_clip_chain_id = self
external_scroll_offset, .wr
); .define_clip_chain(Some(*parent_clip_chain_id), [new_clip_id]);
let new_spatial_id = self
.wr
.define_scroll_frame(
&parent_space_and_clip_info,
Some(external_id),
content_rect,
clip_rect,
scroll_sensitivity,
external_scroll_offset,
)
.spatial_id;
let new_scroll_node_id = self.compositor_info.scroll_tree.add_scroll_tree_node( let new_scroll_node_id = self.compositor_info.scroll_tree.add_scroll_tree_node(
Some(&parent_scroll_node_id), Some(&parent_scroll_node_id),
new_space_and_clip.spatial_id, new_spatial_id,
Some(ScrollableNodeInfo { Some(ScrollableNodeInfo {
external_id, external_id,
scrollable_size: content_rect.size - clip_rect.size, scrollable_size: content_rect.size - clip_rect.size,
@ -170,13 +187,13 @@ impl DisplayList {
offset: LayoutVector2D::zero(), offset: LayoutVector2D::zero(),
}), }),
); );
(new_scroll_node_id, new_space_and_clip.clip_id) (new_scroll_node_id, new_clip_chain_id)
} }
} }
pub(crate) struct StackingContextFragment { pub(crate) struct StackingContextFragment {
scroll_node_id: ScrollTreeNodeId, scroll_node_id: ScrollTreeNodeId,
clip_id: wr::ClipId, clip_chain_id: wr::ClipChainId,
section: StackingContextSection, section: StackingContextSection,
containing_block: PhysicalRect<Length>, containing_block: PhysicalRect<Length>,
fragment: ArcRefCell<Fragment>, fragment: ArcRefCell<Fragment>,
@ -185,7 +202,7 @@ pub(crate) struct StackingContextFragment {
impl StackingContextFragment { impl StackingContextFragment {
fn build_display_list(&self, builder: &mut DisplayListBuilder) { fn build_display_list(&self, builder: &mut DisplayListBuilder) {
builder.current_scroll_node_id = self.scroll_node_id; builder.current_scroll_node_id = self.scroll_node_id;
builder.current_clip_id = self.clip_id; builder.current_clip_id = wr::ClipId::ClipChain(self.clip_chain_id);
self.fragment self.fragment
.borrow() .borrow()
.build_display_list(builder, &self.containing_block, self.section); .build_display_list(builder, &self.containing_block, self.section);
@ -346,7 +363,7 @@ impl StackingContext {
LayoutPoint::zero(), // origin LayoutPoint::zero(), // origin
self.spatial_id, self.spatial_id,
style.get_webrender_primitive_flags(), style.get_webrender_primitive_flags(),
None, // clip_id None, // clip_chain_id
style.get_used_transform_style().to_webrender(), style.get_used_transform_style().to_webrender(),
effects.mix_blend_mode.to_webrender(), effects.mix_blend_mode.to_webrender(),
&filters, &filters,
@ -608,7 +625,7 @@ impl Fragment {
stacking_context.fragments.push(StackingContextFragment { stacking_context.fragments.push(StackingContextFragment {
section: StackingContextSection::Content, section: StackingContextSection::Content,
scroll_node_id: containing_block.scroll_node_id, scroll_node_id: containing_block.scroll_node_id,
clip_id: containing_block.clip_id, clip_chain_id: containing_block.clip_chain_id,
containing_block: containing_block.rect, containing_block: containing_block.rect,
fragment: fragment_ref.clone(), fragment: fragment_ref.clone(),
}); });
@ -721,7 +738,7 @@ impl BoxFragment {
.rect .rect
.translate(-reference_frame_data.origin.to_vector()), .translate(-reference_frame_data.origin.to_vector()),
new_spatial_id, new_spatial_id,
containing_block.clip_id, containing_block.clip_chain_id,
); );
let new_containing_block_info = let new_containing_block_info =
containing_block_info.new_for_non_absolute_descendants(&adjusted_containing_block); containing_block_info.new_for_non_absolute_descendants(&adjusted_containing_block);
@ -796,19 +813,19 @@ impl BoxFragment {
stacking_context: &mut StackingContext, stacking_context: &mut StackingContext,
) { ) {
let mut new_scroll_node_id = containing_block.scroll_node_id; let mut new_scroll_node_id = containing_block.scroll_node_id;
let mut new_clip_id = containing_block.clip_id; let mut new_clip_chain_id = containing_block.clip_chain_id;
if let Some(clip_id) = self.build_clip_frame_if_necessary( if let Some(clip_chain_id) = self.build_clip_frame_if_necessary(
display_list, display_list,
&new_scroll_node_id, &new_scroll_node_id,
&new_clip_id, &new_clip_chain_id,
&containing_block.rect, &containing_block.rect,
) { ) {
new_clip_id = clip_id; new_clip_chain_id = clip_chain_id;
} }
stacking_context.fragments.push(StackingContextFragment { stacking_context.fragments.push(StackingContextFragment {
scroll_node_id: new_scroll_node_id, scroll_node_id: new_scroll_node_id,
clip_id: new_clip_id, clip_chain_id: new_clip_chain_id,
section: self.get_stacking_context_section(), section: self.get_stacking_context_section(),
containing_block: containing_block.rect, containing_block: containing_block.rect,
fragment: fragment.clone(), fragment: fragment.clone(),
@ -816,7 +833,7 @@ impl BoxFragment {
if self.style.get_outline().outline_width.px() > 0.0 { if self.style.get_outline().outline_width.px() > 0.0 {
stacking_context.fragments.push(StackingContextFragment { stacking_context.fragments.push(StackingContextFragment {
scroll_node_id: new_scroll_node_id, scroll_node_id: new_scroll_node_id,
clip_id: new_clip_id, clip_chain_id: new_clip_chain_id,
section: StackingContextSection::Outline, section: StackingContextSection::Outline,
containing_block: containing_block.rect, containing_block: containing_block.rect,
fragment: fragment.clone(), fragment: fragment.clone(),
@ -825,14 +842,14 @@ impl BoxFragment {
// We want to build the scroll frame after the background and border, because // We want to build the scroll frame after the background and border, because
// they shouldn't scroll with the rest of the box content. // they shouldn't scroll with the rest of the box content.
if let Some((scroll_node_id, clip_id)) = self.build_scroll_frame_if_necessary( if let Some((scroll_node_id, clip_chain_id)) = self.build_scroll_frame_if_necessary(
display_list, display_list,
&new_scroll_node_id, &new_scroll_node_id,
&new_clip_id, &new_clip_chain_id,
&containing_block.rect, &containing_block.rect,
) { ) {
new_scroll_node_id = scroll_node_id; new_scroll_node_id = scroll_node_id;
new_clip_id = clip_id; new_clip_chain_id = clip_chain_id;
} }
let padding_rect = self let padding_rect = self
@ -845,9 +862,9 @@ impl BoxFragment {
.translate(containing_block.rect.origin.to_vector()); .translate(containing_block.rect.origin.to_vector());
let for_absolute_descendants = let for_absolute_descendants =
ContainingBlock::new(&padding_rect, new_scroll_node_id, new_clip_id); ContainingBlock::new(&padding_rect, new_scroll_node_id, new_clip_chain_id);
let for_non_absolute_descendants = let for_non_absolute_descendants =
ContainingBlock::new(&content_rect, new_scroll_node_id, new_clip_id); ContainingBlock::new(&content_rect, new_scroll_node_id, new_clip_chain_id);
// Create a new `ContainingBlockInfo` for descendants depending on // Create a new `ContainingBlockInfo` for descendants depending on
// whether or not this fragment establishes a containing block for // whether or not this fragment establishes a containing block for
@ -887,9 +904,9 @@ impl BoxFragment {
&self, &self,
display_list: &mut DisplayList, display_list: &mut DisplayList,
parent_scroll_node_id: &ScrollTreeNodeId, parent_scroll_node_id: &ScrollTreeNodeId,
parent_clip_id: &wr::ClipId, parent_clip_chain_id: &wr::ClipChainId,
containing_block_rect: &PhysicalRect<Length>, containing_block_rect: &PhysicalRect<Length>,
) -> Option<wr::ClipId> { ) -> Option<wr::ClipChainId> {
let position = self.style.get_box().position; let position = self.style.get_box().position;
// https://drafts.csswg.org/css2/#clipping // https://drafts.csswg.org/css2/#clipping
// The clip property applies only to absolutely positioned elements // The clip property applies only to absolutely positioned elements
@ -911,22 +928,28 @@ impl BoxFragment {
.translate(containing_block_rect.origin.to_vector()) .translate(containing_block_rect.origin.to_vector())
.to_webrender(); .to_webrender();
Some(display_list.wr.define_clip_rect( let parent_space_and_clip = &wr::SpaceAndClipInfo {
&wr::SpaceAndClipInfo { spatial_id: parent_scroll_node_id.spatial_id,
spatial_id: parent_scroll_node_id.spatial_id, clip_id: wr::ClipId::root(display_list.wr.pipeline_id),
clip_id: *parent_clip_id, };
},
clip_rect, let clip_id = display_list
)) .wr
.define_clip_rect(&parent_space_and_clip, clip_rect);
Some(
display_list
.wr
.define_clip_chain(Some(*parent_clip_chain_id), [clip_id]),
)
} }
fn build_scroll_frame_if_necessary( fn build_scroll_frame_if_necessary(
&self, &self,
display_list: &mut DisplayList, display_list: &mut DisplayList,
parent_scroll_node_id: &ScrollTreeNodeId, parent_scroll_node_id: &ScrollTreeNodeId,
parent_clip_id: &wr::ClipId, parent_clip_id: &wr::ClipChainId,
containing_block_rect: &PhysicalRect<Length>, containing_block_rect: &PhysicalRect<Length>,
) -> Option<(ScrollTreeNodeId, wr::ClipId)> { ) -> Option<(ScrollTreeNodeId, wr::ClipChainId)> {
let overflow_x = self.style.get_box().overflow_x; let overflow_x = self.style.get_box().overflow_x;
let overflow_y = self.style.get_box().overflow_y; let overflow_y = self.style.get_box().overflow_y;
if overflow_x == ComputedOverflow::Visible && overflow_y == ComputedOverflow::Visible { if overflow_x == ComputedOverflow::Visible && overflow_y == ComputedOverflow::Visible {