From 4d3625ec80853191be324dd179e5015d1a862fee Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Tue, 16 May 2023 09:18:03 +0200 Subject: [PATCH] Clean up and document the `send_display_list` interface This moves more members to the CompositorDisplayListInfo struct, which now holds all miscellaneous, non-WebRender data when sending display lists. It also documents what each things sent with a display list does. --- components/compositing/compositor.rs | 37 ++++++++-------- components/gfx_traits/lib.rs | 6 +++ .../layout/display_list/webrender_helpers.rs | 27 +++++------- components/layout_2020/display_list/mod.rs | 2 + components/layout_thread/lib.rs | 16 +++---- components/layout_thread_2020/lib.rs | 17 ++++---- components/script_traits/compositor.rs | 17 +++++++- components/script_traits/lib.rs | 42 +++++++++---------- 8 files changed, 85 insertions(+), 79 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index b1ac1dfd3c9..5079fdd1bd7 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -662,31 +662,32 @@ impl IOCompositor { .send_transaction(self.webrender_document, txn); }, - WebrenderMsg::Layout(script_traits::WebrenderMsg::SendDisplayList( - epoch, - size, - pipeline, - size2, - receiver, - descriptor, - compositor_display_list_info, - )) => match receiver.recv() { + WebrenderMsg::Layout(script_traits::WebrenderMsg::SendDisplayList { + display_list_info, + content_size, + display_list_descriptor, + display_list_receiver, + }) => match display_list_receiver.recv() { Ok(data) => { self.waiting_on_pending_frame = true; - let details = self.pipeline_details(PipelineId::from_webrender(pipeline)); - details.hit_test_items = compositor_display_list_info.hit_test_info; - details.install_new_scroll_tree(compositor_display_list_info.scroll_tree); + let pipeline_id = display_list_info.pipeline_id; + let details = self.pipeline_details(PipelineId::from_webrender(pipeline_id)); + details.hit_test_items = display_list_info.hit_test_info; + details.install_new_scroll_tree(display_list_info.scroll_tree); let mut txn = webrender_api::Transaction::new(); txn.set_display_list( - epoch, + display_list_info.epoch, None, - size, + display_list_info.viewport_size, ( - pipeline, - size2, - webrender_api::BuiltDisplayList::from_data(data, descriptor), + pipeline_id, + content_size, + webrender_api::BuiltDisplayList::from_data( + data, + display_list_descriptor, + ), ), true, ); @@ -694,7 +695,7 @@ impl IOCompositor { self.webrender_api .send_transaction(self.webrender_document, txn); }, - Err(e) => warn!("error receiving display data: {:?}", e), + Err(e) => warn!("error receiving display list data: {e:?}"), }, WebrenderMsg::Layout(script_traits::WebrenderMsg::HitTest( diff --git a/components/gfx_traits/lib.rs b/components/gfx_traits/lib.rs index a7d447dfded..a7fae65f87e 100644 --- a/components/gfx_traits/lib.rs +++ b/components/gfx_traits/lib.rs @@ -28,6 +28,12 @@ impl Epoch { } } +impl Into for Epoch { + fn into(self) -> webrender_api::Epoch { + webrender_api::Epoch(self.0) + } +} + /// A unique ID for every stacking context. #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub struct StackingContextId( diff --git a/components/layout/display_list/webrender_helpers.rs b/components/layout/display_list/webrender_helpers.rs index a34905be136..d84ce7739b7 100644 --- a/components/layout/display_list/webrender_helpers.rs +++ b/components/layout/display_list/webrender_helpers.rs @@ -13,7 +13,7 @@ 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, + self, ClipId, CommonItemProperties, DisplayItem as WrDisplayItem, DisplayListBuilder, Epoch, PrimitiveFlags, PropertyBinding, PushStackingContextDisplayItem, RasterSpace, ReferenceFrameKind, SpaceAndClipInfo, SpatialId, StackingContext, }; @@ -25,20 +25,11 @@ struct ClipScrollState { } impl ClipScrollState { - fn new( - size: usize, - content_size: LayoutSize, - viewport_size: LayoutSize, - pipeline_id: webrender_api::PipelineId, - ) -> Self { + fn new(size: usize, compositor_info: CompositorDisplayListInfo) -> Self { let mut state = ClipScrollState { clip_ids: vec![None; size], scroll_node_ids: vec![None; size], - compositor_info: CompositorDisplayListInfo::new( - viewport_size, - content_size, - pipeline_id, - ), + compositor_info, }; // We need to register the WebRender root reference frame and root scroll node ids @@ -49,7 +40,7 @@ impl ClipScrollState { 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); - let root_clip_id = ClipId::root(pipeline_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); @@ -106,13 +97,17 @@ impl DisplayList { &mut self, pipeline_id: PipelineId, viewport_size: LayoutSize, + epoch: Epoch, ) -> (DisplayListBuilder, CompositorDisplayListInfo, IsContentful) { let webrender_pipeline = pipeline_id.to_webrender(); let mut state = ClipScrollState::new( self.clip_scroll_nodes.len(), - self.bounds().size, - viewport_size, - webrender_pipeline, + CompositorDisplayListInfo::new( + viewport_size, + self.bounds().size, + webrender_pipeline, + epoch, + ), ); let mut builder = DisplayListBuilder::with_capacity( diff --git a/components/layout_2020/display_list/mod.rs b/components/layout_2020/display_list/mod.rs index 1e097730bd7..46636064045 100644 --- a/components/layout_2020/display_list/mod.rs +++ b/components/layout_2020/display_list/mod.rs @@ -70,6 +70,7 @@ impl DisplayList { viewport_size: units::LayoutSize, content_size: units::LayoutSize, pipeline_id: wr::PipelineId, + epoch: wr::Epoch, ) -> Self { Self { wr: wr::DisplayListBuilder::new(pipeline_id, content_size), @@ -77,6 +78,7 @@ impl DisplayList { viewport_size, content_size, pipeline_id, + epoch, ), } } diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index a6b57778185..1fbc41cab06 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -1069,26 +1069,22 @@ impl LayoutThread { self.viewport_size.height.to_f32_px(), ); - // TODO: Avoid the temporary conversion and build webrender sc/dl directly! - let (builder, compositor_info, is_contentful) = - display_list.convert_to_webrender(self.id, viewport_size); - let mut epoch = self.epoch.get(); epoch.next(); self.epoch.set(epoch); + // TODO: Avoid the temporary conversion and build webrender sc/dl directly! + let (builder, compositor_info, is_contentful) = + display_list.convert_to_webrender(self.id, viewport_size, epoch.into()); + // Observe notifications about rendered frames if needed right before // 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, is_contentful.0); - self.webrender_api.send_display_list( - epoch, - viewport_size, - compositor_info, - builder.finalize(), - ); + self.webrender_api + .send_display_list(compositor_info, builder.finalize()); }, ); } diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index b2392e441a1..06675f0fe3b 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -1264,6 +1264,10 @@ impl LayoutThread { document.will_paint(); } + let mut epoch = self.epoch.get(); + epoch.next(); + self.epoch.set(epoch); + 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(), @@ -1272,6 +1276,7 @@ impl LayoutThread { viewport_size, fragment_tree.scrollable_overflow(), self.id.to_webrender(), + epoch.into(), ); // `dump_serialized_display_list` doesn't actually print anything. It sets up @@ -1296,22 +1301,14 @@ impl LayoutThread { } debug!("Layout done!"); - let mut epoch = self.epoch.get(); - epoch.next(); - self.epoch.set(epoch); - // Observe notifications about rendered frames if needed right before // 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, is_contentful); - self.webrender_api.send_display_list( - epoch, - viewport_size, - display_list.compositor_info, - display_list.wr.finalize(), - ); + self.webrender_api + .send_display_list(display_list.compositor_info, display_list.wr.finalize()); self.update_iframe_sizes(iframe_sizes); diff --git a/components/script_traits/compositor.rs b/components/script_traits/compositor.rs index 00255ee2efb..1707f4a3fe2 100644 --- a/components/script_traits/compositor.rs +++ b/components/script_traits/compositor.rs @@ -7,7 +7,7 @@ use embedder_traits::Cursor; use webrender_api::{ units::{LayoutSize, LayoutVector2D}, - ExternalScrollId, ScrollLocation, ScrollSensitivity, SpatialId, + Epoch, ExternalScrollId, PipelineId, ScrollLocation, ScrollSensitivity, SpatialId, }; /// Information that Servo keeps alongside WebRender display items @@ -213,6 +213,15 @@ impl ScrollTree { /// display lists sent to the compositor. #[derive(Debug, Deserialize, Serialize)] pub struct CompositorDisplayListInfo { + /// The WebRender [PipelineId] of this display list. + pub pipeline_id: PipelineId, + + /// The size of the viewport that this display list renders into. + pub viewport_size: LayoutSize, + + /// The epoch of the display list. + pub epoch: Epoch, + /// An array of `HitTestInfo` which is used to store information /// to assist the compositor to take various actions (set the cursor, /// scroll without layout) using a WebRender hit test result. @@ -237,7 +246,8 @@ impl CompositorDisplayListInfo { pub fn new( viewport_size: LayoutSize, content_size: LayoutSize, - pipeline_id: webrender_api::PipelineId, + pipeline_id: PipelineId, + epoch: Epoch, ) -> Self { let mut scroll_tree = ScrollTree::default(); let root_reference_frame_id = scroll_tree.add_scroll_tree_node( @@ -257,6 +267,9 @@ impl CompositorDisplayListInfo { ); CompositorDisplayListInfo { + pipeline_id, + viewport_size, + epoch, hit_test_info: Default::default(), scroll_tree, root_reference_frame_id, diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 90be1e44910..838a699a3be 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -1132,15 +1132,16 @@ pub enum WebrenderMsg { /// Perform a scroll operation. SendScrollNode(LayoutPoint, ExternalScrollId, ScrollClamping), /// Inform WebRender of a new display list for the given pipeline. - SendDisplayList( - webrender_api::Epoch, - LayoutSize, - webrender_api::PipelineId, - LayoutSize, - ipc::IpcBytesReceiver, - BuiltDisplayListDescriptor, - CompositorDisplayListInfo, - ), + SendDisplayList { + /// The [CompositorDisplayListInfo] that describes the display list being sent. + display_list_info: CompositorDisplayListInfo, + /// The content size of this display list as calculated by WebRender. + content_size: LayoutSize, + /// A descriptor of this display list used to construct this display list from raw data. + display_list_descriptor: BuiltDisplayListDescriptor, + /// An [ipc::IpcBytesReceiver] used to send the raw data of the display list. + display_list_receiver: ipc::IpcBytesReceiver, + }, /// Perform a hit test operation. The result will be returned via /// the provided channel sender. HitTest( @@ -1191,26 +1192,21 @@ impl WebrenderIpcSender { /// Inform WebRender of a new display list for the given pipeline. pub fn send_display_list( &self, - epoch: Epoch, - size: LayoutSize, display_list_info: CompositorDisplayListInfo, - (pipeline, size2, list): (webrender_api::PipelineId, LayoutSize, BuiltDisplayList), + (_, content_size, list): (webrender_api::PipelineId, LayoutSize, BuiltDisplayList), ) { - let (data, descriptor) = list.into_data(); - let (sender, receiver) = ipc::bytes_channel().unwrap(); - if let Err(e) = self.0.send(WebrenderMsg::SendDisplayList( - webrender_api::Epoch(epoch.0), - size, - pipeline, - size2, - receiver, - descriptor, + let (display_list_data, display_list_descriptor) = list.into_data(); + let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap(); + if let Err(e) = self.0.send(WebrenderMsg::SendDisplayList { display_list_info, - )) { + content_size, + display_list_descriptor, + display_list_receiver, + }) { warn!("Error sending display list: {}", e); } - if let Err(e) = sender.send(&data) { + if let Err(e) = display_list_sender.send(&display_list_data) { warn!("Error sending display data: {}", e); } }