diff --git a/Cargo.lock b/Cargo.lock index 6b5d8de6c27..dcf80f1c9cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1454,6 +1454,7 @@ dependencies = [ "backtrace", "base", "bluetooth_traits", + "canvas", "canvas_traits", "compositing_traits", "constellation_traits", @@ -4846,7 +4847,6 @@ dependencies = [ "bincode", "bluetooth", "bluetooth_traits", - "canvas", "canvas_traits", "compositing", "compositing_traits", diff --git a/components/constellation/Cargo.toml b/components/constellation/Cargo.toml index c1a0249828a..634166d1050 100644 --- a/components/constellation/Cargo.toml +++ b/components/constellation/Cargo.toml @@ -23,6 +23,7 @@ background_hang_monitor_api = { workspace = true } backtrace = { workspace = true } base = { workspace = true } bluetooth_traits = { workspace = true, optional = true } +canvas = { path = "../canvas" } canvas_traits = { workspace = true } compositing_traits = { workspace = true } constellation_traits = { workspace = true } diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 29d3c656b53..616fb10b288 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -85,6 +85,7 @@ //! See use std::borrow::ToOwned; +use std::cell::OnceCell; use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet, VecDeque}; use std::marker::PhantomData; @@ -105,6 +106,7 @@ use base::id::{ }; #[cfg(feature = "bluetooth")] use bluetooth_traits::BluetoothRequest; +use canvas::canvas_paint_thread::CanvasPaintThread; use canvas_traits::ConstellationCanvasMsg; use canvas_traits::canvas::{CanvasId, CanvasMsg}; use canvas_traits::webgl::WebGLThreads; @@ -425,10 +427,8 @@ pub struct Constellation { /// The XR device registry webxr_registry: Option, - /// A channel through which messages can be sent to the canvas paint thread. - canvas_sender: Sender, - - canvas_ipc_sender: IpcSender, + /// Lazily initialized channels for canvas paint thread. + canvas: OnceCell<(Sender, IpcSender)>, /// Navigation requests from script awaiting approval from the embedder. pending_approval_navigations: PendingApprovalNavigations, @@ -584,8 +584,6 @@ where random_pipeline_closure_probability: Option, random_pipeline_closure_seed: Option, hard_fail: bool, - canvas_create_sender: Sender, - canvas_ipc_sender: IpcSender, ) -> Sender { let (compositor_sender, compositor_receiver) = unbounded(); @@ -707,8 +705,7 @@ where }), webgl_threads: state.webgl_threads, webxr_registry: state.webxr_registry, - canvas_sender: canvas_create_sender, - canvas_ipc_sender, + canvas: OnceCell::new(), pending_approval_navigations: HashMap::new(), pressed_mouse_buttons: 0, active_keyboard_modifiers: Modifiers::empty(), @@ -2665,14 +2662,16 @@ where } } - debug!("Exiting Canvas Paint thread."); - let (canvas_exit_sender, canvas_exit_receiver) = unbounded(); - if let Err(e) = self - .canvas_sender - .send(ConstellationCanvasMsg::Exit(canvas_exit_sender)) - { - warn!("Exit Canvas Paint thread failed ({})", e); - } + let canvas_exit_receiver = if let Some((canvas_sender, _)) = self.canvas.get() { + debug!("Exiting Canvas Paint thread."); + let (canvas_exit_sender, canvas_exit_receiver) = unbounded(); + if let Err(e) = canvas_sender.send(ConstellationCanvasMsg::Exit(canvas_exit_sender)) { + warn!("Exit Canvas Paint thread failed ({})", e); + } + Some(canvas_exit_receiver) + } else { + None + }; debug!("Exiting WebGPU threads."); #[cfg(feature = "webgpu")] @@ -2714,7 +2713,9 @@ where // Wait for the canvas thread to exit before shutting down the font service, as // canvas might still be using the system font service before shutting down. - let _ = canvas_exit_receiver.recv(); + if let Some(canvas_exit_receiver) = canvas_exit_receiver { + let _ = canvas_exit_receiver.recv(); + } debug!("Exiting the system font service thread."); self.system_font_service.exit(); @@ -4493,8 +4494,11 @@ where response_sender: IpcSender<(IpcSender, CanvasId, ImageKey)>, ) { let (canvas_data_sender, canvas_data_receiver) = unbounded(); + let (canvas_sender, canvas_ipc_sender) = self + .canvas + .get_or_init(|| self.create_canvas_paint_thread()); - if let Err(e) = self.canvas_sender.send(ConstellationCanvasMsg::Create { + if let Err(e) = canvas_sender.send(ConstellationCanvasMsg::Create { sender: canvas_data_sender, size, }) { @@ -4504,8 +4508,7 @@ where Ok(canvas_data) => canvas_data, Err(e) => return warn!("Create canvas paint thread id response failed ({})", e), }; - if let Err(e) = response_sender.send((self.canvas_ipc_sender.clone(), canvas_id, image_key)) - { + if let Err(e) = response_sender.send((canvas_ipc_sender.clone(), canvas_id, image_key)) { warn!("Create canvas paint thread response failed ({})", e); } } @@ -5745,4 +5748,12 @@ where warn!("Could not sent paint metric event to pipeline: {pipeline_id:?}: {error:?}"); } } + + fn create_canvas_paint_thread(&self) -> (Sender, IpcSender) { + CanvasPaintThread::start( + self.compositor_proxy.cross_process_compositor_api.clone(), + self.system_font_service.clone(), + self.public_resource_threads.clone(), + ) + } } diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index db9864ff9b0..ab7b977ad14 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -69,7 +69,6 @@ base = { workspace = true } bincode = { workspace = true } bluetooth = { path = "../bluetooth", optional = true } bluetooth_traits = { workspace = true, optional = true } -canvas = { path = "../canvas" } webgl = { path = "../webgl", default-features = false } canvas_traits = { workspace = true } compositing = { path = "../compositing" } diff --git a/components/servo/lib.rs b/components/servo/lib.rs index d26777a38d5..3b9be5bc011 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -39,7 +39,6 @@ use base::id::{PipelineNamespace, PipelineNamespaceId}; use bluetooth::BluetoothThreadFactory; #[cfg(feature = "bluetooth")] use bluetooth_traits::BluetoothRequest; -use canvas::canvas_paint_thread::CanvasPaintThread; use canvas_traits::webgl::{GlType, WebGLThreads}; use clipboard_delegate::StringRequest; pub use compositing::WebRenderDebugOption; @@ -115,7 +114,7 @@ use webview::WebViewInner; #[cfg(feature = "webxr")] pub use webxr; pub use { - background_hang_monitor, base, canvas, canvas_traits, devtools, devtools_traits, euclid, fonts, + background_hang_monitor, base, canvas_traits, devtools, devtools_traits, euclid, fonts, ipc_channel, layout_api, media, net, net_traits, profile, profile_traits, script, script_traits, servo_config as config, servo_config, servo_geometry, servo_url, style, style_traits, webrender_api, @@ -1095,12 +1094,6 @@ fn create_constellation( .to_proxy(), ); - let (canvas_create_sender, canvas_ipc_sender) = CanvasPaintThread::start( - compositor_proxy.cross_process_compositor_api.clone(), - system_font_service.clone(), - public_resource_threads.clone(), - ); - let initial_state = InitialConstellationState { compositor_proxy, embedder_proxy, @@ -1133,8 +1126,6 @@ fn create_constellation( opts.random_pipeline_closure_probability, opts.random_pipeline_closure_seed, opts.hard_fail, - canvas_create_sender, - canvas_ipc_sender, ) }