diff options
author | Martin Robinson <mrobinson@igalia.com> | 2023-07-04 10:39:58 +0200 |
---|---|---|
committer | Martin Robinson <mrobinson@igalia.com> | 2023-07-04 11:24:00 +0200 |
commit | 3c4328f3dc987f64e8b2d762c7cda5e8eb87f328 (patch) | |
tree | 4d94b676c9edc92623c8c89e4e62ff68451aa22a /components/layout/display_list | |
parent | 66abb1dfc49ab1067b7a3d7bc2d40b772f949bcd (diff) | |
download | servo-3c4328f3dc987f64e8b2d762c7cda5e8eb87f328.tar.gz servo-3c4328f3dc987f64e8b2d762c7cda5e8eb87f328.zip |
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.
Diffstat (limited to 'components/layout/display_list')
-rw-r--r-- | components/layout/display_list/builder.rs | 6 | ||||
-rw-r--r-- | components/layout/display_list/items.rs | 12 | ||||
-rw-r--r-- | components/layout/display_list/webrender_helpers.rs | 144 |
3 files changed, 95 insertions, 67 deletions
diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs index 1b53ac90249..e6b16710d22 100644 --- a/components/layout/display_list/builder.rs +++ b/components/layout/display_list/builder.rs @@ -2616,6 +2616,8 @@ impl BlockFlow { clip: ClippingRegion::from_rect(border_box.to_layout()), content_rect: LayoutRect::zero(), 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); @@ -2683,6 +2685,8 @@ impl BlockFlow { clip: clip, content_rect: Rect::new(content_box.origin, content_size).to_layout(), 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); @@ -2719,6 +2723,8 @@ impl BlockFlow { clip: ClippingRegion::from_rect(clip_rect.to_layout()), content_rect: LayoutRect::zero(), // content_rect isn't important for clips. node_type: ClipScrollNodeType::Clip(ClipType::Rect), + scroll_node_id: None, + clip_chain_id: None, }); let new_indices = ClippingAndScrolling::new(new_index, new_index); diff --git a/components/layout/display_list/items.rs b/components/layout/display_list/items.rs index 4b8a5cf1a5e..b1de022d819 100644 --- a/components/layout/display_list/items.rs +++ b/components/layout/display_list/items.rs @@ -18,6 +18,7 @@ use gfx_traits::print_tree::PrintTree; use gfx_traits::{self, StackingContextId}; use msg::constellation_msg::PipelineId; use net_traits::image::base::Image; +use script_traits::compositor::ScrollTreeNodeId; use servo_geometry::MaxRect; use std::cmp::Ordering; use std::collections::HashMap; @@ -31,6 +32,7 @@ use webrender_api::{ FilterOp, GlyphInstance, GradientStop, ImageKey, MixBlendMode, PrimitiveFlags, ScrollSensitivity, Shadow, SpatialId, StickyOffsetBounds, TransformStyle, }; +use wr::ClipChainId; pub use style::dom::OpaqueNode; @@ -369,6 +371,12 @@ pub struct ClipScrollNode { /// The type of this ClipScrollNode. 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 { @@ -378,6 +386,8 @@ impl ClipScrollNode { clip: ClippingRegion::from_rect(LayoutRect::zero()), content_rect: LayoutRect::zero(), node_type: ClipScrollNodeType::Placeholder, + scroll_node_id: None, + clip_chain_id: None, } } @@ -400,6 +410,8 @@ impl ClipScrollNode { clip: ClippingRegion::from_rect(clip_rect), content_rect: LayoutRect::zero(), // content_rect isn't important for clips. node_type: ClipScrollNodeType::Clip(ClipType::Rounded(complex_region)), + scroll_node_id: None, + clip_chain_id: None, } } } diff --git a/components/layout/display_list/webrender_helpers.rs b/components/layout/display_list/webrender_helpers.rs index d84ce7739b7..9489eb357cd 100644 --- a/components/layout/display_list/webrender_helpers.rs +++ b/components/layout/display_list/webrender_helpers.rs @@ -13,22 +13,24 @@ use msg::constellation_msg::PipelineId; use script_traits::compositor::{CompositorDisplayListInfo, ScrollTreeNodeId, ScrollableNodeInfo}; use webrender_api::units::{LayoutPoint, LayoutSize, LayoutVector2D}; use webrender_api::{ - self, ClipId, CommonItemProperties, DisplayItem as WrDisplayItem, DisplayListBuilder, Epoch, - PrimitiveFlags, PropertyBinding, PushStackingContextDisplayItem, RasterSpace, - ReferenceFrameKind, SpaceAndClipInfo, SpatialId, StackingContext, + self, ClipChainId, ClipId, CommonItemProperties, DisplayItem as WrDisplayItem, + DisplayListBuilder, Epoch, PrimitiveFlags, PropertyBinding, PushStackingContextDisplayItem, + RasterSpace, ReferenceFrameKind, SpaceAndClipInfo, SpatialId, StackingContext, }; -struct ClipScrollState { - clip_ids: Vec<Option<ClipId>>, - scroll_node_ids: Vec<Option<ScrollTreeNodeId>>, +struct ClipScrollState<'a> { + clip_scroll_nodes: &'a mut Vec<ClipScrollNode>, compositor_info: CompositorDisplayListInfo, } -impl ClipScrollState { - fn new(size: usize, compositor_info: CompositorDisplayListInfo) -> Self { +impl<'a> ClipScrollState<'a> { + fn new( + clip_scroll_nodes: &'a mut Vec<ClipScrollNode>, + compositor_info: CompositorDisplayListInfo, + builder: &mut DisplayListBuilder, + ) -> Self { let mut state = ClipScrollState { - clip_ids: vec![None; size], - scroll_node_ids: vec![None; size], + clip_scroll_nodes, compositor_info, }; @@ -37,32 +39,38 @@ impl ClipScrollState { // 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 // FIRST_CLIP_NODE_INDEX is not taken into account. - state.scroll_node_ids[0] = Some(state.compositor_info.root_reference_frame_id); - state.scroll_node_ids[1] = Some(state.compositor_info.root_scroll_node_id); + state.clip_scroll_nodes[0].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); - state.add_clip_node_mapping(0, root_clip_id); - state.add_clip_node_mapping(1, root_clip_id); + let root_clip_chain = + builder.define_clip_chain(None, [ClipId::root(state.compositor_info.pipeline_id)]); + state.add_clip_node_mapping(0, root_clip_chain); + state.add_clip_node_mapping(1, root_clip_chain); state } - fn webrender_clip_id_for_index(&mut self, index: usize) -> ClipId { - self.clip_ids[index].expect("Tried to use WebRender parent ClipId before it was defined.") + fn webrender_clip_id_for_index(&mut self, index: usize) -> ClipChainId { + 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 { - self.scroll_node_ids[index] + self.clip_scroll_nodes[index] + .scroll_node_id .expect("Tried to use WebRender parent SpatialId before it was defined.") .spatial_id } - fn add_clip_node_mapping(&mut self, index: usize, webrender_id: ClipId) { - self.clip_ids[index] = Some(webrender_id); + fn add_clip_node_mapping(&mut self, index: usize, webrender_id: ClipChainId) { + self.clip_scroll_nodes[index].clip_chain_id = Some(webrender_id); } 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.") } @@ -74,15 +82,17 @@ impl ClipScrollState { scroll_info: Option<ScrollableNodeInfo>, ) { 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( - parent_scroll_node_id.as_ref(), - spatial_id, - scroll_info, - )); + self.clip_scroll_nodes[index].scroll_node_id = + Some(self.compositor_info.scroll_tree.add_scroll_tree_node( + parent_scroll_node_id.as_ref(), + spatial_id, + scroll_info, + )); } 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, ) -> (DisplayListBuilder, CompositorDisplayListInfo, IsContentful) { 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( webrender_pipeline, self.bounds().size, 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); for item in &mut self.list { - is_contentful.0 |= item - .convert_to_webrender(&self.clip_scroll_nodes, &mut state, &mut builder) - .0; + is_contentful.0 |= item.convert_to_webrender(&mut state, &mut builder).0; } (builder, state.compositor_info, is_contentful) @@ -130,7 +135,6 @@ impl DisplayList { impl DisplayItem { fn convert_to_webrender( &mut self, - clip_scroll_nodes: &[ClipScrollNode], state: &mut ClipScrollState, builder: &mut DisplayListBuilder, ) -> IsContentful { @@ -165,7 +169,7 @@ impl DisplayItem { CommonItemProperties { clip_rect: base.clip_rect, 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. flags: PrimitiveFlags::default(), hit_info: tag, @@ -339,48 +343,54 @@ impl DisplayItem { }, DisplayItem::DefineClipScrollNode(ref mut item) => { 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 parent_index = node.parent_index.to_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 { 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 { ClipType::Rect => { - builder.define_clip_rect(&space_and_clip_info, item_rect) - }, - ClipType::Rounded(complex) => { - builder.define_clip_rounded_rect(&space_and_clip_info, complex) + builder.define_clip_rect(&parent_space_and_clip_info, item_rect) }, + 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); }, ClipScrollNodeType::ScrollFrame(scroll_sensitivity, external_id) => { - let space_clip_info = builder.define_scroll_frame( - &SpaceAndClipInfo { - clip_id: parent_clip_id, - spatial_id: parent_spatial_id, - }, - Some(external_id), - node.content_rect, - item_rect, - scroll_sensitivity, - LayoutVector2D::zero(), - ); + let clip_id = + builder.define_clip_rect(&parent_space_and_clip_info, item_rect); + let clip_chain_id = + builder.define_clip_chain(Some(parent_clip_chain_id), [clip_id]); + state.add_clip_node_mapping(index, clip_chain_id); + + let spatial_id = builder + .define_scroll_frame( + &parent_space_and_clip_info, + 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( index, - space_clip_info.spatial_id, + spatial_id, Some(parent_index), Some(ScrollableNodeInfo { external_id, @@ -401,7 +411,7 @@ impl DisplayItem { 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); }, ClipScrollNodeType::Placeholder => { |