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);
},
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<Window: WindowMethods + ?Sized> IOCompositor<Window> {
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(

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.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub struct StackingContextId(

View file

@ -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,
CompositorDisplayListInfo::new(
viewport_size,
self.bounds().size,
webrender_pipeline,
epoch,
),
);
let mut builder = DisplayListBuilder::with_capacity(

View file

@ -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,
),
}
}

View file

@ -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());
},
);
}

View file

@ -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);

View file

@ -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,

View file

@ -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);
}
}