compositing: Send CompositorDisplayListInfo as bytes to compositor (#36484)

`CompositorDisplayListInfo` is a large data structure that scales with
the size of the display list. Serializing it onto the Compositor's IPC
channel can cause deadlocks. This change serializes it with bincode and
sends it alongside the rest of the serialized display list information
on the IPC `bytes_channel`. This should prevent deadlocks when the
compositor API is unified.

Testing: This is covered by existing WPT tests.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2025-04-12 22:01:22 +02:00 committed by GitHub
parent 084fe007a1
commit 5f0f457ac3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 27 additions and 8 deletions

2
Cargo.lock generated
View file

@ -1089,6 +1089,7 @@ name = "compositing"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"base", "base",
"bincode",
"bitflags 2.9.0", "bitflags 2.9.0",
"compositing_traits", "compositing_traits",
"constellation_traits", "constellation_traits",
@ -1120,6 +1121,7 @@ name = "compositing_traits"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"base", "base",
"bincode",
"crossbeam-channel", "crossbeam-channel",
"dpi", "dpi",
"embedder_traits", "embedder_traits",

View file

@ -19,6 +19,7 @@ webxr = ["dep:webxr"]
[dependencies] [dependencies]
base = { workspace = true } base = { workspace = true }
bincode = { workspace = true }
bitflags = { workspace = true } bitflags = { workspace = true }
compositing_traits = { workspace = true } compositing_traits = { workspace = true }
constellation_traits = { workspace = true } constellation_traits = { workspace = true }

View file

@ -16,7 +16,7 @@ use base::cross_process_instant::CrossProcessInstant;
use base::id::{PipelineId, WebViewId}; use base::id::{PipelineId, WebViewId};
use base::{Epoch, WebRenderEpochToU16}; use base::{Epoch, WebRenderEpochToU16};
use bitflags::bitflags; use bitflags::bitflags;
use compositing_traits::display_list::{HitTestInfo, ScrollTree}; use compositing_traits::display_list::{CompositorDisplayListInfo, HitTestInfo, ScrollTree};
use compositing_traits::rendering_context::RenderingContext; use compositing_traits::rendering_context::RenderingContext;
use compositing_traits::{ use compositing_traits::{
CompositionPipeline, CompositorMsg, CompositorReceiver, CrossProcessCompositorMessage, CompositionPipeline, CompositorMsg, CompositorReceiver, CrossProcessCompositorMessage,
@ -740,11 +740,23 @@ impl IOCompositor {
CrossProcessCompositorMessage::SendDisplayList { CrossProcessCompositorMessage::SendDisplayList {
webview_id, webview_id,
display_list_info,
display_list_descriptor, display_list_descriptor,
display_list_receiver, display_list_receiver,
} => { } => {
// This must match the order from the sender, currently in `shared/script/lib.rs`. // This must match the order from the sender, currently in `shared/script/lib.rs`.
let display_list_info = match display_list_receiver.recv() {
Ok(display_list_info) => display_list_info,
Err(error) => {
return warn!("Could not receive display list info: {error}");
},
};
let display_list_info: CompositorDisplayListInfo =
match bincode::deserialize(&display_list_info) {
Ok(display_list_info) => display_list_info,
Err(error) => {
return warn!("Could not deserialize display list info: {error}");
},
};
let items_data = match display_list_receiver.recv() { let items_data = match display_list_receiver.recv() {
Ok(display_list_data) => display_list_data, Ok(display_list_data) => display_list_data,
Err(error) => { Err(error) => {

View file

@ -16,6 +16,7 @@ no-wgl = ["surfman/sm-angle-default"]
[dependencies] [dependencies]
base = { workspace = true } base = { workspace = true }
bincode = { workspace = true }
crossbeam-channel = { workspace = true } crossbeam-channel = { workspace = true }
dpi = { version = "0.1" } dpi = { version = "0.1" }
embedder_traits = { workspace = true } embedder_traits = { workspace = true }

View file

@ -147,8 +147,6 @@ pub enum CrossProcessCompositorMessage {
SendDisplayList { SendDisplayList {
/// The [`WebViewId`] that this display list belongs to. /// The [`WebViewId`] that this display list belongs to.
webview_id: WebViewId, webview_id: WebViewId,
/// The [CompositorDisplayListInfo] that describes the display list being sent.
display_list_info: Box<CompositorDisplayListInfo>,
/// A descriptor of this display list used to construct this display list from raw data. /// A descriptor of this display list used to construct this display list from raw data.
display_list_descriptor: BuiltDisplayListDescriptor, display_list_descriptor: BuiltDisplayListDescriptor,
/// An [ipc::IpcBytesReceiver] used to send the raw data of the display list. /// An [ipc::IpcBytesReceiver] used to send the raw data of the display list.
@ -275,21 +273,26 @@ impl CrossProcessCompositorApi {
let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap(); let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap();
if let Err(e) = self.0.send(CrossProcessCompositorMessage::SendDisplayList { if let Err(e) = self.0.send(CrossProcessCompositorMessage::SendDisplayList {
webview_id, webview_id,
display_list_info: Box::new(display_list_info),
display_list_descriptor, display_list_descriptor,
display_list_receiver, display_list_receiver,
}) { }) {
warn!("Error sending display list: {}", e); warn!("Error sending display list: {}", e);
} }
let display_list_info_serialized =
bincode::serialize(&display_list_info).unwrap_or_default();
if let Err(error) = display_list_sender.send(&display_list_info_serialized) {
warn!("Error sending display list info: {error}");
}
if let Err(error) = display_list_sender.send(&display_list_data.items_data) { if let Err(error) = display_list_sender.send(&display_list_data.items_data) {
warn!("Error sending display list items: {}", error); warn!("Error sending display list items: {error}");
} }
if let Err(error) = display_list_sender.send(&display_list_data.cache_data) { if let Err(error) = display_list_sender.send(&display_list_data.cache_data) {
warn!("Error sending display list cache data: {}", error); warn!("Error sending display list cache data: {error}");
} }
if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) { if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) {
warn!("Error sending display spatial tree: {}", error); warn!("Error sending display spatial tree: {error}");
} }
} }