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.
This commit is contained in:
Martin Robinson 2023-05-16 09:18:03 +02:00
parent 0377a1853a
commit 4d3625ec80
No known key found for this signature in database
GPG key ID: D56AA4FA55EFE6F8
8 changed files with 85 additions and 79 deletions

View file

@ -662,31 +662,32 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
.send_transaction(self.webrender_document, txn); .send_transaction(self.webrender_document, txn);
}, },
WebrenderMsg::Layout(script_traits::WebrenderMsg::SendDisplayList( WebrenderMsg::Layout(script_traits::WebrenderMsg::SendDisplayList {
epoch, display_list_info,
size, content_size,
pipeline, display_list_descriptor,
size2, display_list_receiver,
receiver, }) => match display_list_receiver.recv() {
descriptor,
compositor_display_list_info,
)) => match receiver.recv() {
Ok(data) => { Ok(data) => {
self.waiting_on_pending_frame = true; self.waiting_on_pending_frame = true;
let details = self.pipeline_details(PipelineId::from_webrender(pipeline)); let pipeline_id = display_list_info.pipeline_id;
details.hit_test_items = compositor_display_list_info.hit_test_info; let details = self.pipeline_details(PipelineId::from_webrender(pipeline_id));
details.install_new_scroll_tree(compositor_display_list_info.scroll_tree); 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(); let mut txn = webrender_api::Transaction::new();
txn.set_display_list( txn.set_display_list(
epoch, display_list_info.epoch,
None, None,
size, display_list_info.viewport_size,
( (
pipeline, pipeline_id,
size2, content_size,
webrender_api::BuiltDisplayList::from_data(data, descriptor), webrender_api::BuiltDisplayList::from_data(
data,
display_list_descriptor,
),
), ),
true, true,
); );
@ -694,7 +695,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
self.webrender_api self.webrender_api
.send_transaction(self.webrender_document, txn); .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( WebrenderMsg::Layout(script_traits::WebrenderMsg::HitTest(

View file

@ -28,6 +28,12 @@ impl Epoch {
} }
} }
impl Into<webrender_api::Epoch> for Epoch {
fn into(self) -> webrender_api::Epoch {
webrender_api::Epoch(self.0)
}
}
/// A unique ID for every stacking context. /// A unique ID for every stacking context.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub struct StackingContextId( pub struct StackingContextId(

View file

@ -13,7 +13,7 @@ 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, self, ClipId, CommonItemProperties, DisplayItem as WrDisplayItem, DisplayListBuilder, Epoch,
PrimitiveFlags, PropertyBinding, PushStackingContextDisplayItem, RasterSpace, PrimitiveFlags, PropertyBinding, PushStackingContextDisplayItem, RasterSpace,
ReferenceFrameKind, SpaceAndClipInfo, SpatialId, StackingContext, ReferenceFrameKind, SpaceAndClipInfo, SpatialId, StackingContext,
}; };
@ -25,20 +25,11 @@ struct ClipScrollState {
} }
impl ClipScrollState { impl ClipScrollState {
fn new( fn new(size: usize, compositor_info: CompositorDisplayListInfo) -> Self {
size: usize,
content_size: LayoutSize,
viewport_size: LayoutSize,
pipeline_id: webrender_api::PipelineId,
) -> Self {
let mut state = ClipScrollState { let mut state = ClipScrollState {
clip_ids: vec![None; size], clip_ids: vec![None; size],
scroll_node_ids: vec![None; size], scroll_node_ids: vec![None; size],
compositor_info: CompositorDisplayListInfo::new( compositor_info,
viewport_size,
content_size,
pipeline_id,
),
}; };
// We need to register the WebRender root reference frame and root scroll node ids // 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[0] = Some(state.compositor_info.root_reference_frame_id);
state.scroll_node_ids[1] = Some(state.compositor_info.root_scroll_node_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(0, root_clip_id);
state.add_clip_node_mapping(1, root_clip_id); state.add_clip_node_mapping(1, root_clip_id);
@ -106,13 +97,17 @@ impl DisplayList {
&mut self, &mut self,
pipeline_id: PipelineId, pipeline_id: PipelineId,
viewport_size: LayoutSize, viewport_size: LayoutSize,
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( let mut state = ClipScrollState::new(
self.clip_scroll_nodes.len(), self.clip_scroll_nodes.len(),
self.bounds().size, CompositorDisplayListInfo::new(
viewport_size, viewport_size,
webrender_pipeline, self.bounds().size,
webrender_pipeline,
epoch,
),
); );
let mut builder = DisplayListBuilder::with_capacity( let mut builder = DisplayListBuilder::with_capacity(

View file

@ -70,6 +70,7 @@ impl DisplayList {
viewport_size: units::LayoutSize, viewport_size: units::LayoutSize,
content_size: units::LayoutSize, content_size: units::LayoutSize,
pipeline_id: wr::PipelineId, pipeline_id: wr::PipelineId,
epoch: wr::Epoch,
) -> Self { ) -> Self {
Self { Self {
wr: wr::DisplayListBuilder::new(pipeline_id, content_size), wr: wr::DisplayListBuilder::new(pipeline_id, content_size),
@ -77,6 +78,7 @@ impl DisplayList {
viewport_size, viewport_size,
content_size, content_size,
pipeline_id, pipeline_id,
epoch,
), ),
} }
} }

View file

@ -1069,26 +1069,22 @@ impl LayoutThread {
self.viewport_size.height.to_f32_px(), 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(); let mut epoch = self.epoch.get();
epoch.next(); epoch.next();
self.epoch.set(epoch); 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 // Observe notifications about rendered frames if needed right before
// sending the display list to WebRender in order to set time related // sending the display list to WebRender in order to set time related
// Progressive Web Metrics. // Progressive Web Metrics.
self.paint_time_metrics self.paint_time_metrics
.maybe_observe_paint_time(self, epoch, is_contentful.0); .maybe_observe_paint_time(self, epoch, is_contentful.0);
self.webrender_api.send_display_list( self.webrender_api
epoch, .send_display_list(compositor_info, builder.finalize());
viewport_size,
compositor_info,
builder.finalize(),
);
}, },
); );
} }

View file

@ -1264,6 +1264,10 @@ impl LayoutThread {
document.will_paint(); 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( let viewport_size = webrender_api::units::LayoutSize::from_untyped(Size2D::new(
self.viewport_size.width.to_f32_px(), self.viewport_size.width.to_f32_px(),
self.viewport_size.height.to_f32_px(), self.viewport_size.height.to_f32_px(),
@ -1272,6 +1276,7 @@ impl LayoutThread {
viewport_size, viewport_size,
fragment_tree.scrollable_overflow(), fragment_tree.scrollable_overflow(),
self.id.to_webrender(), self.id.to_webrender(),
epoch.into(),
); );
// `dump_serialized_display_list` doesn't actually print anything. It sets up // `dump_serialized_display_list` doesn't actually print anything. It sets up
@ -1296,22 +1301,14 @@ impl LayoutThread {
} }
debug!("Layout done!"); debug!("Layout done!");
let mut epoch = self.epoch.get();
epoch.next();
self.epoch.set(epoch);
// Observe notifications about rendered frames if needed right before // Observe notifications about rendered frames if needed right before
// sending the display list to WebRender in order to set time related // sending the display list to WebRender in order to set time related
// Progressive Web Metrics. // Progressive Web Metrics.
self.paint_time_metrics self.paint_time_metrics
.maybe_observe_paint_time(self, epoch, is_contentful); .maybe_observe_paint_time(self, epoch, is_contentful);
self.webrender_api.send_display_list( self.webrender_api
epoch, .send_display_list(display_list.compositor_info, display_list.wr.finalize());
viewport_size,
display_list.compositor_info,
display_list.wr.finalize(),
);
self.update_iframe_sizes(iframe_sizes); self.update_iframe_sizes(iframe_sizes);

View file

@ -7,7 +7,7 @@
use embedder_traits::Cursor; use embedder_traits::Cursor;
use webrender_api::{ use webrender_api::{
units::{LayoutSize, LayoutVector2D}, units::{LayoutSize, LayoutVector2D},
ExternalScrollId, ScrollLocation, ScrollSensitivity, SpatialId, Epoch, ExternalScrollId, PipelineId, ScrollLocation, ScrollSensitivity, SpatialId,
}; };
/// Information that Servo keeps alongside WebRender display items /// Information that Servo keeps alongside WebRender display items
@ -213,6 +213,15 @@ impl ScrollTree {
/// display lists sent to the compositor. /// display lists sent to the compositor.
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub struct CompositorDisplayListInfo { 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 /// An array of `HitTestInfo` which is used to store information
/// to assist the compositor to take various actions (set the cursor, /// to assist the compositor to take various actions (set the cursor,
/// scroll without layout) using a WebRender hit test result. /// scroll without layout) using a WebRender hit test result.
@ -237,7 +246,8 @@ impl CompositorDisplayListInfo {
pub fn new( pub fn new(
viewport_size: LayoutSize, viewport_size: LayoutSize,
content_size: LayoutSize, content_size: LayoutSize,
pipeline_id: webrender_api::PipelineId, pipeline_id: PipelineId,
epoch: Epoch,
) -> Self { ) -> Self {
let mut scroll_tree = ScrollTree::default(); let mut scroll_tree = ScrollTree::default();
let root_reference_frame_id = scroll_tree.add_scroll_tree_node( let root_reference_frame_id = scroll_tree.add_scroll_tree_node(
@ -257,6 +267,9 @@ impl CompositorDisplayListInfo {
); );
CompositorDisplayListInfo { CompositorDisplayListInfo {
pipeline_id,
viewport_size,
epoch,
hit_test_info: Default::default(), hit_test_info: Default::default(),
scroll_tree, scroll_tree,
root_reference_frame_id, root_reference_frame_id,

View file

@ -1132,15 +1132,16 @@ pub enum WebrenderMsg {
/// Perform a scroll operation. /// Perform a scroll operation.
SendScrollNode(LayoutPoint, ExternalScrollId, ScrollClamping), SendScrollNode(LayoutPoint, ExternalScrollId, ScrollClamping),
/// Inform WebRender of a new display list for the given pipeline. /// Inform WebRender of a new display list for the given pipeline.
SendDisplayList( SendDisplayList {
webrender_api::Epoch, /// The [CompositorDisplayListInfo] that describes the display list being sent.
LayoutSize, display_list_info: CompositorDisplayListInfo,
webrender_api::PipelineId, /// The content size of this display list as calculated by WebRender.
LayoutSize, content_size: LayoutSize,
ipc::IpcBytesReceiver, /// A descriptor of this display list used to construct this display list from raw data.
BuiltDisplayListDescriptor, display_list_descriptor: BuiltDisplayListDescriptor,
CompositorDisplayListInfo, /// 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 /// Perform a hit test operation. The result will be returned via
/// the provided channel sender. /// the provided channel sender.
HitTest( HitTest(
@ -1191,26 +1192,21 @@ impl WebrenderIpcSender {
/// Inform WebRender of a new display list for the given pipeline. /// Inform WebRender of a new display list for the given pipeline.
pub fn send_display_list( pub fn send_display_list(
&self, &self,
epoch: Epoch,
size: LayoutSize,
display_list_info: CompositorDisplayListInfo, 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 (display_list_data, display_list_descriptor) = list.into_data();
let (sender, receiver) = ipc::bytes_channel().unwrap(); let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap();
if let Err(e) = self.0.send(WebrenderMsg::SendDisplayList( if let Err(e) = self.0.send(WebrenderMsg::SendDisplayList {
webrender_api::Epoch(epoch.0),
size,
pipeline,
size2,
receiver,
descriptor,
display_list_info, display_list_info,
)) { content_size,
display_list_descriptor,
display_list_receiver,
}) {
warn!("Error sending display list: {}", e); 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); warn!("Error sending display data: {}", e);
} }
} }