diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 4c58b269ca0..08b269e3950 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -22,10 +22,10 @@ use style::color::AbsoluteColor; use style::properties::style_structs::Font as FontStyleStruct; use unicode_script::Script; use webrender_api::units::{DeviceIntSize, RectExt as RectExt_}; -use webrender_api::{ImageData, ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey}; -use webrender_traits::ImageUpdate; +use webrender_api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey}; +use webrender_traits::{CrossProcessCompositorApi, ImageUpdate, SerializableImageData}; -use crate::canvas_paint_thread::{AntialiasMode, WebrenderApi}; +use crate::canvas_paint_thread::AntialiasMode; use crate::raqote_backend::Repetition; /// The canvas data stores a state machine for the current status of @@ -428,7 +428,7 @@ pub struct CanvasData<'a> { path_state: Option, state: CanvasPaintState<'a>, saved_states: Vec>, - webrender_api: Box, + compositor_api: CrossProcessCompositorApi, image_key: Option, /// An old webrender image key that can be deleted when the next epoch ends. old_image_key: Option, @@ -444,7 +444,7 @@ fn create_backend() -> Box { impl<'a> CanvasData<'a> { pub fn new( size: Size2D, - webrender_api: Box, + compositor_api: CrossProcessCompositorApi, antialias: AntialiasMode, font_context: Arc, ) -> CanvasData<'a> { @@ -456,7 +456,7 @@ impl<'a> CanvasData<'a> { path_state: None, state: CanvasPaintState::new(antialias), saved_states: vec![], - webrender_api, + compositor_api, image_key: None, old_image_key: None, very_old_image_key: None, @@ -1279,8 +1279,9 @@ impl<'a> CanvasData<'a> { offset: 0, flags: ImageDescriptorFlags::empty(), }; - let data = self.drawtarget.snapshot_data_owned(); - let data = ImageData::Raw(Arc::new(data)); + let data = SerializableImageData::Raw(IpcSharedMemory::from_bytes( + &self.drawtarget.snapshot_data_owned(), + )); let mut updates = vec![]; @@ -1290,7 +1291,7 @@ impl<'a> CanvasData<'a> { updates.push(ImageUpdate::UpdateImage(image_key, descriptor, data)); }, None => { - let Some(key) = self.webrender_api.generate_key() else { + let Some(key) = self.compositor_api.generate_image_key() else { return; }; updates.push(ImageUpdate::AddImage(key, descriptor, data)); @@ -1305,7 +1306,7 @@ impl<'a> CanvasData<'a> { updates.push(ImageUpdate::DeleteImage(image_key)); } - self.webrender_api.update_images(updates); + self.compositor_api.update_images(updates); let data = CanvasImageData { image_key: self.image_key.unwrap(), @@ -1426,7 +1427,7 @@ impl<'a> Drop for CanvasData<'a> { updates.push(ImageUpdate::DeleteImage(image_key)); } - self.webrender_api.update_images(updates); + self.compositor_api.update_images(updates); } } diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index 5fec02a2b7a..7b3500e1290 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -16,8 +16,7 @@ use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::router::ROUTER; use log::warn; use net_traits::ResourceThreads; -use webrender_api::ImageKey; -use webrender_traits::{ImageUpdate, WebRenderScriptApi}; +use webrender_traits::CrossProcessCompositorApi; use crate::canvas_data::*; @@ -26,36 +25,26 @@ pub enum AntialiasMode { None, } -pub trait WebrenderApi { - /// Attempt to generate an [`ImageKey`], returning `None` in case of failure. - fn generate_key(&self) -> Option; - fn update_images(&self, updates: Vec); - fn clone(&self) -> Box; -} - pub struct CanvasPaintThread<'a> { canvases: HashMap>, next_canvas_id: CanvasId, - webrender_api: Box, + compositor_api: CrossProcessCompositorApi, font_context: Arc, } impl<'a> CanvasPaintThread<'a> { fn new( - webrender_api: Box, + compositor_api: CrossProcessCompositorApi, system_font_service: Arc, resource_threads: ResourceThreads, ) -> CanvasPaintThread<'a> { - // This is only used for web fonts and currently canvas never uses web fonts. - let webrender_script_api = WebRenderScriptApi::dummy(); - CanvasPaintThread { canvases: HashMap::new(), next_canvas_id: CanvasId(0), - webrender_api, + compositor_api: compositor_api.clone(), font_context: Arc::new(FontContext::new( system_font_service, - webrender_script_api, + compositor_api, resource_threads, )), } @@ -64,7 +53,7 @@ impl<'a> CanvasPaintThread<'a> { /// Creates a new `CanvasPaintThread` and returns an `IpcSender` to /// communicate with it. pub fn start( - webrender_api: Box, + compositor_api: CrossProcessCompositorApi, system_font_service: Arc, resource_threads: ResourceThreads, ) -> (Sender, IpcSender) { @@ -75,7 +64,7 @@ impl<'a> CanvasPaintThread<'a> { .name("Canvas".to_owned()) .spawn(move || { let mut canvas_paint_thread = CanvasPaintThread::new( - webrender_api, system_font_service, resource_threads); + compositor_api, system_font_service, resource_threads); loop { select! { recv(msg_receiver) -> msg => { @@ -141,7 +130,7 @@ impl<'a> CanvasPaintThread<'a> { let canvas_data = CanvasData::new( size, - self.webrender_api.clone(), + self.compositor_api.clone(), antialias, self.font_context.clone(), ); diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 8d31ce9a32c..eb0eb08096f 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -16,8 +16,7 @@ use base::cross_process_instant::CrossProcessInstant; use base::id::{PipelineId, TopLevelBrowsingContextId, WebViewId}; use base::{Epoch, WebRenderEpochToU16}; use compositing_traits::{ - CompositionPipeline, CompositorMsg, CompositorReceiver, ConstellationMsg, - ForwardedToCompositorMsg, SendableFrameTree, + CompositionPipeline, CompositorMsg, CompositorReceiver, ConstellationMsg, SendableFrameTree, }; use crossbeam_channel::Sender; use embedder_traits::Cursor; @@ -51,8 +50,7 @@ use webrender_api::{ }; use webrender_traits::display_list::{HitTestInfo, ScrollTree}; use webrender_traits::{ - CanvasToCompositorMsg, CompositorHitTestResult, FontToCompositorMsg, ImageUpdate, - NetToCompositorMsg, RenderingContext, ScriptToCompositorMsg, SerializedImageUpdate, + CompositorHitTestResult, CrossProcessCompositorMessage, ImageUpdate, RenderingContext, UntrustedNodeAddress, }; @@ -653,29 +651,8 @@ impl IOCompositor { self.pending_paint_metrics.insert(pipeline_id, epoch); }, - CompositorMsg::GetClientWindow(req) => { - if let Err(e) = req.send(self.embedder_coordinates.window) { - warn!("Sending response to get client window failed ({:?}).", e); - } - }, - - CompositorMsg::GetScreenSize(req) => { - if let Err(e) = req.send(self.embedder_coordinates.screen) { - warn!("Sending response to get screen size failed ({:?}).", e); - } - }, - - CompositorMsg::GetScreenAvailSize(req) => { - if let Err(e) = req.send(self.embedder_coordinates.screen_avail) { - warn!( - "Sending response to get screen avail size failed ({:?}).", - e - ); - } - }, - - CompositorMsg::Forwarded(msg) => { - self.handle_webrender_message(msg); + CompositorMsg::CrossProcess(cross_proces_message) => { + self.handle_cross_process_message(cross_proces_message); }, } @@ -685,11 +662,9 @@ impl IOCompositor { /// Accept messages from content processes that need to be relayed to the WebRender /// instance in the parent process. #[instrument(skip_all, fields(servo_profiling = true))] - fn handle_webrender_message(&mut self, msg: ForwardedToCompositorMsg) { + fn handle_cross_process_message(&mut self, msg: CrossProcessCompositorMessage) { match msg { - ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::SendInitialTransaction( - pipeline, - )) => { + CrossProcessCompositorMessage::SendInitialTransaction(pipeline) => { let mut txn = Transaction::new(); txn.set_display_list(WebRenderEpoch(0), (pipeline, Default::default())); self.generate_frame(&mut txn, RenderReasons::SCENE); @@ -697,11 +672,11 @@ impl IOCompositor { .send_transaction(self.webrender_document, txn); }, - ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::SendScrollNode( + CrossProcessCompositorMessage::SendScrollNode( pipeline_id, point, external_scroll_id, - )) => { + ) => { let pipeline_id = pipeline_id.into(); let pipeline_details = match self.pipeline_details.get_mut(&pipeline_id) { Some(details) => details, @@ -733,11 +708,11 @@ impl IOCompositor { .send_transaction(self.webrender_document, txn); }, - ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::SendDisplayList { + CrossProcessCompositorMessage::SendDisplayList { display_list_info, display_list_descriptor, display_list_receiver, - }) => { + } => { // This must match the order from the sender, currently in `shared/script/lib.rs`. let items_data = match display_list_receiver.recv() { Ok(display_list_data) => display_list_data, @@ -793,12 +768,7 @@ impl IOCompositor { .send_transaction(self.webrender_document, transaction); }, - ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::HitTest( - pipeline, - point, - flags, - sender, - )) => { + CrossProcessCompositorMessage::HitTest(pipeline, point, flags, sender) => { // When a display list is sent to WebRender, it starts scene building in a // separate thread and then that display list is available for hit testing. // Without flushing scene building, any hit test we do might be done against @@ -815,27 +785,20 @@ impl IOCompositor { let _ = sender.send(result); }, - ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::GenerateImageKey(sender)) | - ForwardedToCompositorMsg::Net(NetToCompositorMsg::GenerateImageKey(sender)) => { + CrossProcessCompositorMessage::GenerateImageKey(sender) => { let _ = sender.send(self.webrender_api.generate_image_key()); }, - ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::UpdateImages(updates)) => { + CrossProcessCompositorMessage::UpdateImages(updates) => { let mut txn = Transaction::new(); for update in updates { match update { - SerializedImageUpdate::AddImage(key, desc, data) => { - match data.to_image_data() { - Ok(data) => txn.add_image(key, desc, data, None), - Err(e) => warn!("error when sending image data: {:?}", e), - } + ImageUpdate::AddImage(key, desc, data) => { + txn.add_image(key, desc, data.into(), None) }, - SerializedImageUpdate::DeleteImage(key) => txn.delete_image(key), - SerializedImageUpdate::UpdateImage(key, desc, data) => { - match data.to_image_data() { - Ok(data) => txn.update_image(key, desc, data, &DirtyRect::All), - Err(e) => warn!("error when sending image data: {:?}", e), - } + ImageUpdate::DeleteImage(key) => txn.delete_image(key), + ImageUpdate::UpdateImage(key, desc, data) => { + txn.update_image(key, desc, data.into(), &DirtyRect::All) }, } } @@ -843,27 +806,27 @@ impl IOCompositor { .send_transaction(self.webrender_document, txn); }, - ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::AddFont( - font_key, - data, - index, - )) => { + CrossProcessCompositorMessage::AddFont(font_key, data, index) => { self.add_font(font_key, index, data); }, - ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::AddFontInstance( + CrossProcessCompositorMessage::AddSystemFont(font_key, native_handle) => { + let mut transaction = Transaction::new(); + transaction.add_native_font(font_key, native_handle); + self.webrender_api + .send_transaction(self.webrender_document, transaction); + }, + + CrossProcessCompositorMessage::AddFontInstance( font_instance_key, font_key, size, flags, - )) => { + ) => { self.add_font_instance(font_instance_key, font_key, size, flags); }, - ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::RemoveFonts( - keys, - instance_keys, - )) => { + CrossProcessCompositorMessage::RemoveFonts(keys, instance_keys) => { let mut transaction = Transaction::new(); for instance in instance_keys.into_iter() { @@ -877,18 +840,18 @@ impl IOCompositor { .send_transaction(self.webrender_document, transaction); }, - ForwardedToCompositorMsg::Net(NetToCompositorMsg::AddImage(key, desc, data)) => { + CrossProcessCompositorMessage::AddImage(key, desc, data) => { let mut txn = Transaction::new(); - txn.add_image(key, desc, data, None); + txn.add_image(key, desc, data.into(), None); self.webrender_api .send_transaction(self.webrender_document, txn); }, - ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::GenerateKeys( + CrossProcessCompositorMessage::GenerateFontKeys( number_of_font_keys, number_of_font_instance_keys, result_sender, - )) => { + ) => { let font_keys = (0..number_of_font_keys) .map(|_| self.webrender_api.generate_font_key()) .collect(); @@ -897,53 +860,23 @@ impl IOCompositor { .collect(); let _ = result_sender.send((font_keys, font_instance_keys)); }, - - ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFontInstance( - font_instance_key, - font_key, - size, - flags, - )) => { - self.add_font_instance(font_instance_key, font_key, size, flags); - }, - - ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFont( - font_key, - index, - data, - )) => { - self.add_font(font_key, index, data); - }, - - ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddSystemFont( - font_key, - native_handle, - )) => { - let mut transaction = Transaction::new(); - transaction.add_native_font(font_key, native_handle); - self.webrender_api - .send_transaction(self.webrender_document, transaction); - }, - - ForwardedToCompositorMsg::Canvas(CanvasToCompositorMsg::GenerateKey(sender)) => { - let _ = sender.send(self.webrender_api.generate_image_key()); - }, - - ForwardedToCompositorMsg::Canvas(CanvasToCompositorMsg::UpdateImages(updates)) => { - let mut txn = Transaction::new(); - for update in updates { - match update { - ImageUpdate::AddImage(key, descriptor, data) => { - txn.add_image(key, descriptor, data, None) - }, - ImageUpdate::UpdateImage(key, descriptor, data) => { - txn.update_image(key, descriptor, data, &DirtyRect::All) - }, - ImageUpdate::DeleteImage(key) => txn.delete_image(key), - } + CrossProcessCompositorMessage::GetClientWindowRect(req) => { + if let Err(e) = req.send(self.embedder_coordinates.window_rect) { + warn!("Sending response to get client window failed ({:?}).", e); + } + }, + CrossProcessCompositorMessage::GetScreenSize(req) => { + if let Err(e) = req.send(self.embedder_coordinates.screen_size) { + warn!("Sending response to get screen size failed ({:?}).", e); + } + }, + CrossProcessCompositorMessage::GetAvailableScreenSize(req) => { + if let Err(e) = req.send(self.embedder_coordinates.available_screen_size) { + warn!( + "Sending response to get screen avail size failed ({:?}).", + e + ); } - self.webrender_api - .send_transaction(self.webrender_document, txn); }, } } @@ -968,23 +901,40 @@ impl IOCompositor { self.remove_pipeline_root_layer(pipeline_id); let _ = sender.send(()); }, - CompositorMsg::Forwarded(ForwardedToCompositorMsg::Canvas( - CanvasToCompositorMsg::GenerateKey(sender), + CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GenerateImageKey( + sender, )) => { let _ = sender.send(self.webrender_api.generate_image_key()); }, - CompositorMsg::GetClientWindow(sender) => { - if let Err(e) = sender.send(self.embedder_coordinates.window) { + CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GenerateFontKeys( + number_of_font_keys, + number_of_font_instance_keys, + result_sender, + )) => { + let font_keys = (0..number_of_font_keys) + .map(|_| self.webrender_api.generate_font_key()) + .collect(); + let font_instance_keys = (0..number_of_font_instance_keys) + .map(|_| self.webrender_api.generate_font_instance_key()) + .collect(); + let _ = result_sender.send((font_keys, font_instance_keys)); + }, + CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GetClientWindowRect( + req, + )) => { + if let Err(e) = req.send(self.embedder_coordinates.window_rect) { warn!("Sending response to get client window failed ({:?}).", e); } }, - CompositorMsg::GetScreenSize(sender) => { - if let Err(e) = sender.send(self.embedder_coordinates.screen) { + CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GetScreenSize(req)) => { + if let Err(e) = req.send(self.embedder_coordinates.screen_size) { warn!("Sending response to get screen size failed ({:?}).", e); } }, - CompositorMsg::GetScreenAvailSize(sender) => { - if let Err(e) = sender.send(self.embedder_coordinates.screen_avail) { + CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GetAvailableScreenSize( + req, + )) => { + if let Err(e) = req.send(self.embedder_coordinates.available_screen_size) { warn!( "Sending response to get screen avail size failed ({:?}).", e diff --git a/components/compositing/tracing.rs b/components/compositing/tracing.rs index 7a53d6f9b84..0b4e4ceaa35 100644 --- a/components/compositing/tracing.rs +++ b/components/compositing/tracing.rs @@ -48,10 +48,7 @@ mod from_constellation { Self::LoadComplete(..) => target!("LoadComplete"), Self::WebDriverMouseButtonEvent(..) => target!("WebDriverMouseButtonEvent"), Self::WebDriverMouseMoveEvent(..) => target!("WebDriverMouseMoveEvent"), - Self::GetClientWindow(..) => target!("GetClientWindow"), - Self::GetScreenSize(..) => target!("GetScreenSize"), - Self::GetScreenAvailSize(..) => target!("GetScreenAvailSize"), - Self::Forwarded(..) => target!("Forwarded"), + Self::CrossProcess(_) => target!("CrossProcess"), } } } diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index d1cf9866d01..86771d115ac 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -241,11 +241,11 @@ pub struct EmbedderCoordinates { /// The pixel density of the display. pub hidpi_factor: Scale, /// Size of the screen. - pub screen: DeviceIntSize, + pub screen_size: DeviceIntSize, /// Size of the available screen space (screen without toolbars and docks). - pub screen_avail: DeviceIntSize, - /// Size of the native window. - pub window: (DeviceIntSize, DeviceIntPoint), + pub available_screen_size: DeviceIntSize, + /// Position and size of the native window. + pub window_rect: DeviceIntRect, /// Size of the GL buffer in the window. pub framebuffer: DeviceIntSize, /// Coordinates of the document within the framebuffer. @@ -290,9 +290,9 @@ mod test { let screen = Size2D::new(1080, 720); let coordinates = EmbedderCoordinates { hidpi_factor: Scale::new(1.), - screen, - screen_avail: screen, - window: (viewport, pos), + screen_size: screen, + available_screen_size: screen, + window_rect: DeviceIntRect::from_origin_and_size(pos, viewport), framebuffer: viewport, viewport: DeviceIntRect::from_origin_and_size(pos, viewport), }; diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 83a4ab186ff..cb2138cc8ac 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -108,8 +108,7 @@ use canvas_traits::canvas::{CanvasId, CanvasMsg}; use canvas_traits::webgl::WebGLThreads; use canvas_traits::ConstellationCanvasMsg; use compositing_traits::{ - CompositorMsg, CompositorProxy, ConstellationMsg as FromCompositorMsg, - ForwardedToCompositorMsg, SendableFrameTree, + CompositorMsg, CompositorProxy, ConstellationMsg as FromCompositorMsg, SendableFrameTree, }; use crossbeam_channel::{after, never, select, unbounded, Receiver, Sender}; use devtools_traits::{ @@ -157,7 +156,7 @@ use webgpu::swapchain::WGPUImageMap; use webgpu::{self, WebGPU, WebGPURequest, WebGPUResponse}; use webrender::{RenderApi, RenderApiSender}; use webrender_api::DocumentId; -use webrender_traits::{WebRenderNetApi, WebRenderScriptApi, WebrenderExternalImageRegistry}; +use webrender_traits::WebrenderExternalImageRegistry; use crate::browsingcontext::{ AllBrowsingContextsIterator, BrowsingContext, FullyActiveBrowsingContextsIterator, @@ -392,14 +391,6 @@ pub struct Constellation { /// Webrender related objects required by WebGPU threads webrender_wgpu: WebrenderWGPU, - /// A channel for content processes to send messages that will - /// be relayed to the WebRender thread. - webrender_api_ipc_sender: WebRenderScriptApi, - - /// A channel for content process image caches to send messages - /// that will be relayed to the WebRender thread. - webrender_image_api_sender: WebRenderNetApi, - /// A map of message-port Id to info. message_ports: HashMap, @@ -506,7 +497,7 @@ pub struct InitialConstellationState { /// A channel through which messages can be sent to the embedder. pub embedder_proxy: EmbedderProxy, - /// A channel through which messages can be sent to the compositor. + /// A channel through which messages can be sent to the compositor in-process. pub compositor_proxy: CompositorProxy, /// A channel to the developer tools, if applicable. @@ -705,35 +696,6 @@ where // Zero is reserved for the embedder. PipelineNamespace::install(PipelineNamespaceId(1)); - let (webrender_ipc_sender, webrender_ipc_receiver) = - ipc::channel().expect("ipc channel failure"); - let (webrender_image_ipc_sender, webrender_image_ipc_receiver) = - ipc::channel().expect("ipc channel failure"); - - let compositor_proxy = state.compositor_proxy.clone(); - ROUTER.add_route( - webrender_ipc_receiver.to_opaque(), - Box::new(move |message| { - compositor_proxy.send(CompositorMsg::Forwarded( - ForwardedToCompositorMsg::Layout( - message.to().expect("conversion failure"), - ), - )); - }), - ); - - let compositor_proxy = state.compositor_proxy.clone(); - ROUTER.add_route( - webrender_image_ipc_receiver.to_opaque(), - Box::new(move |message| { - compositor_proxy.send(CompositorMsg::Forwarded( - ForwardedToCompositorMsg::Net( - message.to().expect("conversion failure"), - ), - )); - }), - ); - let webrender_wgpu = WebrenderWGPU { webrender_api: state.webrender_api_sender.create_api(), webrender_external_images: state.webrender_external_images, @@ -788,8 +750,6 @@ where scheduler_receiver, document_states: HashMap::new(), webrender_document: state.webrender_document, - webrender_api_ipc_sender: WebRenderScriptApi::new(webrender_ipc_sender), - webrender_image_api_sender: WebRenderNetApi::new(webrender_image_ipc_sender), webrender_wgpu, shutting_down: false, handled_warnings: VecDeque::new(), @@ -1053,8 +1013,6 @@ where event_loop, load_data, prev_throttled: throttled, - webrender_api_sender: self.webrender_api_ipc_sender.clone(), - webrender_image_api_sender: self.webrender_image_api_sender.clone(), webrender_document: self.webrender_document, webgl_chan: self .webgl_threads @@ -1751,18 +1709,6 @@ where response_sender.send(true).unwrap_or_default(); }, - FromScriptMsg::GetClientWindow(response_sender) => { - self.compositor_proxy - .send(CompositorMsg::GetClientWindow(response_sender)); - }, - FromScriptMsg::GetScreenSize(response_sender) => { - self.compositor_proxy - .send(CompositorMsg::GetScreenSize(response_sender)); - }, - FromScriptMsg::GetScreenAvailSize(response_sender) => { - self.compositor_proxy - .send(CompositorMsg::GetScreenAvailSize(response_sender)); - }, FromScriptMsg::LogEntry(thread_name, entry) => { self.handle_log_entry(Some(source_top_ctx_id), thread_name, entry); }, diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs index b646e581200..3f5887fa6ed 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -43,6 +43,7 @@ use servo_config::prefs; use servo_config::prefs::PrefValue; use servo_url::ServoUrl; use webrender_api::DocumentId; +use webrender_traits::CrossProcessCompositorApi; use crate::event_loop::EventLoop; use crate::sandboxing::{spawn_multiprocess, UnprivilegedContent}; @@ -183,12 +184,6 @@ pub struct InitialPipelineState { /// compositor threads after spawning a pipeline. pub prev_throttled: bool, - /// Webrender api. - pub webrender_image_api_sender: webrender_traits::WebRenderNetApi, - - /// Webrender api. - pub webrender_api_sender: webrender_traits::WebRenderScriptApi, - /// The ID of the document processed by this script thread. pub webrender_document: DocumentId, @@ -293,9 +288,11 @@ impl Pipeline { opts: (*opts::get()).clone(), prefs: prefs::pref_map().iter().collect(), pipeline_namespace_id: state.pipeline_namespace_id, - webrender_api_sender: state.webrender_api_sender, - webrender_image_api_sender: state.webrender_image_api_sender, webrender_document: state.webrender_document, + cross_process_compositor_api: state + .compositor_proxy + .cross_process_compositor_api + .clone(), webgl_chan: state.webgl_chan, webxr_registry: state.webxr_registry, player_context: state.player_context, @@ -498,8 +495,7 @@ pub struct UnprivilegedPipelineContent { opts: Opts, prefs: HashMap, pipeline_namespace_id: PipelineNamespaceId, - webrender_api_sender: webrender_traits::WebRenderScriptApi, - webrender_image_api_sender: webrender_traits::WebRenderNetApi, + cross_process_compositor_api: CrossProcessCompositorApi, webrender_document: DocumentId, webgl_chan: Option, webxr_registry: webxr_api::Registry, @@ -518,7 +514,9 @@ impl UnprivilegedPipelineContent { // Idempotent in single-process mode. PipelineNamespace::set_installer_sender(self.namespace_request_sender); - let image_cache = Arc::new(ImageCacheImpl::new(self.webrender_image_api_sender.clone())); + let image_cache = Arc::new(ImageCacheImpl::new( + self.cross_process_compositor_api.clone(), + )); let (content_process_shutdown_chan, content_process_shutdown_port) = unbounded(); STF::create( InitialScriptState { @@ -545,7 +543,7 @@ impl UnprivilegedPipelineContent { webgl_chan: self.webgl_chan, webxr_registry: self.webxr_registry, webrender_document: self.webrender_document, - webrender_api_sender: self.webrender_api_sender.clone(), + compositor_api: self.cross_process_compositor_api.clone(), player_context: self.player_context.clone(), inherited_secure_context: self.load_data.inherited_secure_context, }, diff --git a/components/constellation/tracing.rs b/components/constellation/tracing.rs index 46335012d03..c3e87104457 100644 --- a/components/constellation/tracing.rs +++ b/components/constellation/tracing.rs @@ -181,9 +181,6 @@ mod from_script { Self::PipelineExited => target!("PipelineExited"), Self::ForwardDOMMessage(..) => target!("ForwardDOMMessage"), Self::ScheduleJob(..) => target!("ScheduleJob"), - Self::GetClientWindow(..) => target!("GetClientWindow"), - Self::GetScreenSize(..) => target!("GetScreenSize"), - Self::GetScreenAvailSize(..) => target!("GetScreenAvailSize"), Self::MediaSessionEvent(..) => target!("MediaSessionEvent"), Self::RequestAdapter(..) => target!("RequestAdapter"), Self::GetWebGPUChan(..) => target!("GetWebGPUChan"), diff --git a/components/fonts/font_context.rs b/components/fonts/font_context.rs index c229a607596..82672bff209 100644 --- a/components/fonts/font_context.rs +++ b/components/fonts/font_context.rs @@ -30,7 +30,7 @@ use style::values::computed::font::{FamilyName, FontFamilyNameSyntax, SingleFont use style::Atom; use url::Url; use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey}; -use webrender_traits::{ScriptToCompositorMsg, WebRenderScriptApi}; +use webrender_traits::CrossProcessCompositorApi; use crate::font::{ Font, FontDescriptor, FontFamilyDescriptor, FontGroup, FontRef, FontSearchScope, @@ -52,7 +52,7 @@ pub struct FontContext { resource_threads: ReentrantMutex, /// A sender that can send messages and receive replies from the compositor. - webrender_api: ReentrantMutex, + compositor_api: ReentrantMutex, /// The actual instances of fonts ie a [`FontTemplate`] combined with a size and /// other font properties, along with the font data and a platform font instance. @@ -100,14 +100,14 @@ impl MallocSizeOf for FontContext { impl FontContext { pub fn new( system_font_service_proxy: Arc, - webrender_api: WebRenderScriptApi, + compositor_api: CrossProcessCompositorApi, resource_threads: ResourceThreads, ) -> Self { #[allow(clippy::default_constructed_unit_structs)] Self { system_font_service_proxy, resource_threads: ReentrantMutex::new(resource_threads.core_thread), - webrender_api: ReentrantMutex::new(webrender_api), + compositor_api: ReentrantMutex::new(compositor_api), fonts: Default::default(), resolved_font_groups: Default::default(), web_fonts: Arc::new(RwLock::default()), @@ -321,15 +321,11 @@ impl FontContext { .entry(identifier.clone()) .or_insert_with(|| { let font_key = self.system_font_service_proxy.generate_font_key(); - let _ = self - .webrender_api - .lock() - .sender() - .send(ScriptToCompositorMsg::AddFont( - font_key, - font_data.as_ipc_shared_memory(), - identifier.index(), - )); + self.compositor_api.lock().add_font( + font_key, + font_data.as_ipc_shared_memory(), + identifier.index(), + ); font_key }); @@ -339,13 +335,11 @@ impl FontContext { .entry((font_key, pt_size)) .or_insert_with(|| { let font_instance_key = self.system_font_service_proxy.generate_font_instance_key(); - let _ = self.webrender_api.lock().sender().send( - ScriptToCompositorMsg::AddFontInstance( - font_instance_key, - font_key, - pt_size.to_f32_px(), - flags, - ), + self.compositor_api.lock().add_font_instance( + font_instance_key, + font_key, + pt_size.to_f32_px(), + flags, ); font_instance_key }); diff --git a/components/fonts/system_font_service.rs b/components/fonts/system_font_service.rs index 90009f29c93..3b62d468671 100644 --- a/components/fonts/system_font_service.rs +++ b/components/fonts/system_font_service.rs @@ -27,7 +27,7 @@ use style::values::specified::FontStretch as SpecifiedFontStretch; use style::Atom; use tracing::{instrument, span, Level}; use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey}; -use webrender_traits::WebRenderFontApi; +use webrender_traits::CrossProcessCompositorApi; use crate::font::FontDescriptor; use crate::font_store::FontStore; @@ -97,7 +97,7 @@ struct ResolvedGenericFontFamilies { pub struct SystemFontService { port: IpcReceiver, local_families: FontStore, - webrender_api: Box, + compositor_api: CrossProcessCompositorApi, webrender_fonts: HashMap, font_instances: HashMap<(FontKey, Au), FontInstanceKey>, generic_fonts: ResolvedGenericFontFamilies, @@ -129,7 +129,7 @@ impl SystemFontServiceProxySender { } impl SystemFontService { - pub fn spawn(webrender_api: Box) -> SystemFontServiceProxySender { + pub fn spawn(compositor_api: CrossProcessCompositorApi) -> SystemFontServiceProxySender { let (sender, receiver) = ipc::channel().unwrap(); thread::Builder::new() @@ -139,7 +139,7 @@ impl SystemFontService { let mut cache = SystemFontService { port: receiver, local_families: Default::default(), - webrender_api, + compositor_api, webrender_fonts: HashMap::new(), font_instances: HashMap::new(), generic_fonts: Default::default(), @@ -204,7 +204,7 @@ impl SystemFontService { const FREE_FONT_KEYS_BATCH_SIZE: usize = 40; const FREE_FONT_INSTANCE_KEYS_BATCH_SIZE: usize = 40; - let (mut new_font_keys, mut new_font_instance_keys) = self.webrender_api.fetch_font_keys( + let (mut new_font_keys, mut new_font_instance_keys) = self.compositor_api.fetch_font_keys( FREE_FONT_KEYS_BATCH_SIZE - self.free_font_keys.len(), FREE_FONT_INSTANCE_KEYS_BATCH_SIZE - self.free_font_instance_keys.len(), ); @@ -290,7 +290,7 @@ impl SystemFontService { ) -> FontInstanceKey { self.fetch_new_keys(); - let webrender_font_api = &self.webrender_api; + let compositor_api = &self.compositor_api; let webrender_fonts = &mut self.webrender_fonts; let font_data = self.local_families.get_or_initialize_font_data(&identifier); @@ -305,12 +305,12 @@ impl SystemFontService { // this for those platforms. #[cfg(target_os = "macos")] if let FontIdentifier::Local(local_font_identifier) = identifier { - webrender_font_api + compositor_api .add_system_font(font_key, local_font_identifier.native_font_handle()); return font_key; } - webrender_font_api.add_font( + compositor_api.add_font( font_key, font_data.as_ipc_shared_memory(), identifier.index(), @@ -323,7 +323,7 @@ impl SystemFontService { .entry((font_key, pt_size)) .or_insert_with(|| { let font_instance_key = self.free_font_instance_keys.pop().unwrap(); - webrender_font_api.add_font_instance( + compositor_api.add_font_instance( font_instance_key, font_key, pt_size.to_f32_px(), diff --git a/components/fonts/tests/font_context.rs b/components/fonts/tests/font_context.rs index 036bcde7aec..42e7bbf8c74 100644 --- a/components/fonts/tests/font_context.rs +++ b/components/fonts/tests/font_context.rs @@ -33,7 +33,7 @@ use style::values::computed::{FontLanguageOverride, XLang}; use style::values::generics::font::LineHeight; use style::ArcSlice; use webrender_api::{FontInstanceKey, FontKey, IdNamespace}; -use webrender_traits::WebRenderScriptApi; +use webrender_traits::CrossProcessCompositorApi; struct TestContext { context: FontContext, @@ -47,11 +47,11 @@ impl TestContext { let (core_sender, _) = ipc::channel().unwrap(); let (storage_sender, _) = ipc::channel().unwrap(); let mock_resource_threads = ResourceThreads::new(core_sender, storage_sender); - let mock_webrender_api = WebRenderScriptApi::dummy(); + let mock_compositor_api = CrossProcessCompositorApi::dummy(); let proxy_clone = Arc::new(system_font_service_proxy.to_sender().to_proxy()); Self { - context: FontContext::new(proxy_clone, mock_webrender_api, mock_resource_threads), + context: FontContext::new(proxy_clone, mock_compositor_api, mock_resource_threads), system_font_service, system_font_service_proxy, } diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 3f7abcb9c2b..7a6ad0ae7a8 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -105,7 +105,7 @@ use style_traits::{CSSPixel, DevicePixel, SpeculativePainter}; use time_03::Duration; use url::Url; use webrender_api::{units, ColorF, HitTestFlags}; -use webrender_traits::WebRenderScriptApi; +use webrender_traits::CrossProcessCompositorApi; /// Information needed by layout. pub struct LayoutThread { @@ -170,8 +170,8 @@ pub struct LayoutThread { /// The executors for paint worklets. registered_painters: RegisteredPaintersImpl, - /// Webrender interface. - webrender_api: WebRenderScriptApi, + /// Cross-process access to the compositor API. + compositor_api: CrossProcessCompositorApi, /// Paint time metrics. paint_time_metrics: PaintTimeMetrics, @@ -201,7 +201,7 @@ impl LayoutFactory for LayoutFactoryImpl { config.resource_threads, config.system_font_service, config.time_profiler_chan, - config.webrender_api_sender, + config.compositor_api, config.paint_time_metrics, config.window_size, )) @@ -249,7 +249,7 @@ impl Drop for LayoutThread { let (keys, instance_keys) = self .font_context .collect_unused_webrender_resources(true /* all */); - self.webrender_api + self.compositor_api .remove_unused_font_resources(keys, instance_keys) } } @@ -359,7 +359,7 @@ impl Layout for LayoutThread { let client_point = units::DevicePoint::from_untyped(point); let results = self - .webrender_api + .compositor_api .hit_test(Some(self.id.into()), client_point, flags); results.iter().map(|result| result.node.into()).collect() @@ -563,12 +563,12 @@ impl LayoutThread { resource_threads: ResourceThreads, system_font_service: Arc, time_profiler_chan: profile_time::ProfilerChan, - webrender_api: WebRenderScriptApi, + compositor_api: CrossProcessCompositorApi, paint_time_metrics: PaintTimeMetrics, window_size: WindowSizeData, ) -> LayoutThread { // Let webrender know about this pipeline by sending an empty display list. - webrender_api.send_initial_transaction(id.into()); + compositor_api.send_initial_transaction(id.into()); let mut font = Font::initial_values(); let default_font_size = pref!(fonts.default_size); @@ -580,7 +580,7 @@ impl LayoutThread { let font_context = Arc::new(FontContext::new( system_font_service, - webrender_api.clone(), + compositor_api.clone(), resource_threads, )); let device = Device::new( @@ -612,7 +612,7 @@ impl LayoutThread { Au::from_f32_px(window_size.initial_viewport.width), Au::from_f32_px(window_size.initial_viewport.height), ), - webrender_api, + compositor_api, stylist: Stylist::new(device, QuirksMode::NoQuirks), display_list: Default::default(), indexable_text: Default::default(), @@ -937,13 +937,13 @@ impl LayoutThread { self.paint_time_metrics .maybe_observe_paint_time(self, epoch, is_contentful.0); - self.webrender_api + self.compositor_api .send_display_list(compositor_info, builder.end().1); let (keys, instance_keys) = self .font_context .collect_unused_webrender_resources(false /* all */); - self.webrender_api + self.compositor_api .remove_unused_font_resources(keys, instance_keys) }, ); @@ -1186,7 +1186,7 @@ impl LayoutThread { .insert(state.scroll_id, state.scroll_offset); let point = Point2D::new(-state.scroll_offset.x, -state.scroll_offset.y); - self.webrender_api.send_scroll_node( + self.compositor_api.send_scroll_node( self.id.into(), units::LayoutPoint::from_untyped(point), state.scroll_id, diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index 1637e330f50..2a730f7deeb 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -92,7 +92,7 @@ use tracing::{instrument, span, Level}; use url::Url; use webrender_api::units::LayoutPixel; use webrender_api::{units, ExternalScrollId, HitTestFlags}; -use webrender_traits::WebRenderScriptApi; +use webrender_traits::CrossProcessCompositorApi; /// Information needed by layout. pub struct LayoutThread { @@ -151,8 +151,8 @@ pub struct LayoutThread { /// The executors for paint worklets. registered_painters: RegisteredPaintersImpl, - /// Webrender interface. - webrender_api: WebRenderScriptApi, + /// Cross-process access to the Compositor API. + compositor_api: CrossProcessCompositorApi, /// Paint time metrics. paint_time_metrics: PaintTimeMetrics, @@ -179,7 +179,7 @@ impl LayoutFactory for LayoutFactoryImpl { config.resource_threads, config.system_font_service, config.time_profiler_chan, - config.webrender_api_sender, + config.compositor_api, config.paint_time_metrics, config.window_size, )) @@ -228,7 +228,7 @@ impl Drop for LayoutThread { let (keys, instance_keys) = self .font_context .collect_unused_webrender_resources(true /* all */); - self.webrender_api + self.compositor_api .remove_unused_font_resources(keys, instance_keys) } } @@ -333,7 +333,7 @@ impl Layout for LayoutThread { let client_point = units::DevicePoint::from_untyped(point); let results = self - .webrender_api + .compositor_api .hit_test(Some(self.id.into()), client_point, flags); results.iter().map(|result| result.node.into()).collect() @@ -506,12 +506,12 @@ impl LayoutThread { resource_threads: ResourceThreads, system_font_service: Arc, time_profiler_chan: profile_time::ProfilerChan, - webrender_api_sender: WebRenderScriptApi, + compositor_api: CrossProcessCompositorApi, paint_time_metrics: PaintTimeMetrics, window_size: WindowSizeData, ) -> LayoutThread { // Let webrender know about this pipeline by sending an empty display list. - webrender_api_sender.send_initial_transaction(id.into()); + compositor_api.send_initial_transaction(id.into()); let mut font = Font::initial_values(); let default_font_size = pref!(fonts.default_size); @@ -525,7 +525,7 @@ impl LayoutThread { // but it will be set correctly when the initial reflow takes place. let font_context = Arc::new(FontContext::new( system_font_service, - webrender_api_sender.clone(), + compositor_api.clone(), resource_threads, )); let device = Device::new( @@ -557,7 +557,7 @@ impl LayoutThread { Au::from_f32_px(window_size.initial_viewport.width), Au::from_f32_px(window_size.initial_viewport.height), ), - webrender_api: webrender_api_sender, + compositor_api, scroll_offsets: Default::default(), stylist: Stylist::new(device, QuirksMode::NoQuirks), webrender_image_cache: Default::default(), @@ -868,7 +868,7 @@ impl LayoutThread { .borrow_mut() .insert(state.scroll_id, state.scroll_offset); let point = Point2D::new(-state.scroll_offset.x, -state.scroll_offset.y); - self.webrender_api.send_scroll_node( + self.compositor_api.send_scroll_node( self.id.into(), units::LayoutPoint::from_untyped(point), state.scroll_id, @@ -958,13 +958,13 @@ impl LayoutThread { .maybe_observe_paint_time(self, epoch, is_contentful); if reflow_goal.needs_display() { - self.webrender_api + self.compositor_api .send_display_list(display_list.compositor_info, display_list.wr.end().1); let (keys, instance_keys) = self .font_context .collect_unused_webrender_resources(false /* all */); - self.webrender_api + self.compositor_api .remove_unused_font_resources(keys, instance_keys) } diff --git a/components/net/image_cache.rs b/components/net/image_cache.rs index 2f0968f3aa4..dfaa6e4e07e 100644 --- a/components/net/image_cache.rs +++ b/components/net/image_cache.rs @@ -10,7 +10,7 @@ use std::{mem, thread}; use embedder_traits::resources::{self, Resource}; use imsz::imsz_from_reader; -use ipc_channel::ipc::IpcSender; +use ipc_channel::ipc::{IpcSender, IpcSharedMemory}; use log::{debug, warn}; use net_traits::image_cache::{ ImageCache, ImageCacheResult, ImageOrMetadataAvailable, ImageResponder, ImageResponse, @@ -21,8 +21,8 @@ use net_traits::{FetchMetadata, FetchResponseMsg, FilteredMetadata, NetworkError use pixels::{load_from_memory, CorsStatus, Image, ImageMetadata, PixelFormat}; use servo_url::{ImmutableOrigin, ServoUrl}; use webrender_api::units::DeviceIntSize; -use webrender_api::{ImageData, ImageDescriptor, ImageDescriptorFlags, ImageFormat}; -use webrender_traits::WebRenderNetApi; +use webrender_api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat}; +use webrender_traits::{CrossProcessCompositorApi, SerializableImageData}; use crate::resource_thread::CoreResourceThreadPool; @@ -45,13 +45,13 @@ fn decode_bytes_sync(key: LoadKey, bytes: &[u8], cors: CorsStatus) -> DecoderMsg DecoderMsg { key, image } } -fn get_placeholder_image(webrender_api: &WebRenderNetApi, data: &[u8]) -> Arc { +fn get_placeholder_image(compositor_api: &CrossProcessCompositorApi, data: &[u8]) -> Arc { let mut image = load_from_memory(data, CorsStatus::Unsafe).unwrap(); - set_webrender_image_key(webrender_api, &mut image); + set_webrender_image_key(compositor_api, &mut image); Arc::new(image) } -fn set_webrender_image_key(webrender_api: &WebRenderNetApi, image: &mut Image) { +fn set_webrender_image_key(compositor_api: &CrossProcessCompositorApi, image: &mut Image) { if image.id.is_some() { return; } @@ -82,10 +82,11 @@ fn set_webrender_image_key(webrender_api: &WebRenderNetApi, image: &mut Image) { offset: 0, flags, }; - let data = ImageData::new(bytes); - let image_key = webrender_api.generate_image_key(); - webrender_api.add_image(image_key, descriptor, data); - image.id = Some(image_key); + if let Some(image_key) = compositor_api.generate_image_key() { + let data = SerializableImageData::Raw(IpcSharedMemory::from_bytes(&bytes)); + compositor_api.add_image(image_key, descriptor, data); + image.id = Some(image_key); + } } // ====================================================================== @@ -328,8 +329,8 @@ struct ImageCacheStore { // The URL used for the placeholder image placeholder_url: ServoUrl, - // Webrender API instance. - webrender_api: WebRenderNetApi, + // Cross-process compositor API instance. + compositor_api: CrossProcessCompositorApi, } impl ImageCacheStore { @@ -343,7 +344,7 @@ impl ImageCacheStore { match load_result { LoadResult::Loaded(ref mut image) => { - set_webrender_image_key(&self.webrender_api, image) + set_webrender_image_key(&self.compositor_api, image) }, LoadResult::PlaceholderLoaded(..) | LoadResult::None => {}, } @@ -416,7 +417,7 @@ pub struct ImageCacheImpl { } impl ImageCache for ImageCacheImpl { - fn new(webrender_api: WebRenderNetApi) -> ImageCacheImpl { + fn new(compositor_api: CrossProcessCompositorApi) -> ImageCacheImpl { debug!("New image cache"); let rippy_data = resources::read_bytes(Resource::RippyPNG); @@ -431,9 +432,9 @@ impl ImageCache for ImageCacheImpl { store: Arc::new(Mutex::new(ImageCacheStore { pending_loads: AllPendingLoads::new(), completed_loads: HashMap::new(), - placeholder_image: get_placeholder_image(&webrender_api, &rippy_data), + placeholder_image: get_placeholder_image(&compositor_api, &rippy_data), placeholder_url: ServoUrl::parse("chrome://resources/rippy.png").unwrap(), - webrender_api, + compositor_api, })), thread_pool: CoreResourceThreadPool::new(thread_count), } diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 72657e5e3eb..89b1eebac78 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -17,7 +17,7 @@ use headers::{ContentLength, ContentRange, HeaderMapExt}; use html5ever::{local_name, namespace_url, ns, LocalName, Prefix}; use http::header::{self, HeaderMap, HeaderValue}; use http::StatusCode; -use ipc_channel::ipc; +use ipc_channel::ipc::{self, IpcSharedMemory}; use ipc_channel::router::ROUTER; use js::jsapi::JSAutoRealm; use media::{glplayer_channel, GLPlayerMsg, GLPlayerMsgForward, WindowGLContext}; @@ -35,10 +35,10 @@ use servo_media::player::{PlaybackState, Player, PlayerError, PlayerEvent, SeekL use servo_media::{ClientContextId, ServoMedia, SupportsMediaType}; use servo_url::ServoUrl; use webrender_api::{ - ExternalImageData, ExternalImageId, ExternalImageType, ImageBufferKind, ImageData, - ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey, + ExternalImageData, ExternalImageId, ExternalImageType, ImageBufferKind, ImageDescriptor, + ImageDescriptorFlags, ImageFormat, ImageKey, }; -use webrender_traits::{ImageUpdate, WebRenderScriptApi}; +use webrender_traits::{CrossProcessCompositorApi, ImageUpdate, SerializableImageData}; use crate::document_loader::{LoadBlocker, LoadType}; use crate::dom::attr::Attr; @@ -157,7 +157,7 @@ impl FrameHolder { pub struct MediaFrameRenderer { player_id: Option, - api: WebRenderScriptApi, + compositor_api: CrossProcessCompositorApi, current_frame: Option<(ImageKey, i32, i32)>, old_frame: Option, very_old_frame: Option, @@ -166,10 +166,10 @@ pub struct MediaFrameRenderer { } impl MediaFrameRenderer { - fn new(render_api_sender: WebRenderScriptApi) -> Self { + fn new(compositor_api: CrossProcessCompositorApi) -> Self { Self { player_id: None, - api: render_api_sender, + compositor_api, current_frame: None, old_frame: None, very_old_frame: None, @@ -214,7 +214,7 @@ impl VideoFrameRenderer for MediaFrameRenderer { updates.push(ImageUpdate::UpdateImage( *image_key, descriptor, - ImageData::Raw(frame.get_data()), + SerializableImageData::Raw(IpcSharedMemory::from_bytes(&frame.get_data())), )); } @@ -229,7 +229,7 @@ impl VideoFrameRenderer for MediaFrameRenderer { Some((ref mut image_key, ref mut width, ref mut height)) => { self.old_frame = Some(*image_key); - let Some(new_image_key) = self.api.generate_image_key() else { + let Some(new_image_key) = self.compositor_api.generate_image_key() else { return; }; @@ -245,13 +245,13 @@ impl VideoFrameRenderer for MediaFrameRenderer { ImageBufferKind::Texture2D }; - ImageData::External(ExternalImageData { + SerializableImageData::External(ExternalImageData { id: ExternalImageId(self.player_id.unwrap()), channel_index: 0, image_type: ExternalImageType::TextureHandle(texture_target), }) } else { - ImageData::Raw(frame.get_data()) + SerializableImageData::Raw(IpcSharedMemory::from_bytes(&frame.get_data())) }; self.current_frame_holder @@ -261,7 +261,7 @@ impl VideoFrameRenderer for MediaFrameRenderer { updates.push(ImageUpdate::AddImage(new_image_key, descriptor, image_data)); }, None => { - let Some(image_key) = self.api.generate_image_key() else { + let Some(image_key) = self.compositor_api.generate_image_key() else { return; }; self.current_frame = Some((image_key, frame.get_width(), frame.get_height())); @@ -273,13 +273,13 @@ impl VideoFrameRenderer for MediaFrameRenderer { ImageBufferKind::Texture2D }; - ImageData::External(ExternalImageData { + SerializableImageData::External(ExternalImageData { id: ExternalImageId(self.player_id.unwrap()), channel_index: 0, image_type: ExternalImageType::TextureHandle(texture_target), }) } else { - ImageData::Raw(frame.get_data()) + SerializableImageData::Raw(IpcSharedMemory::from_bytes(&frame.get_data())) }; self.current_frame_holder = Some(FrameHolder::new(frame)); @@ -287,7 +287,7 @@ impl VideoFrameRenderer for MediaFrameRenderer { updates.push(ImageUpdate::AddImage(image_key, descriptor, image_data)); }, } - self.api.update_images(updates); + self.compositor_api.update_images(updates); } } @@ -446,7 +446,7 @@ impl HTMLMediaElement { in_flight_play_promises_queue: Default::default(), player: Default::default(), video_renderer: Arc::new(Mutex::new(MediaFrameRenderer::new( - document.window().get_webrender_api_sender(), + document.window().compositor_api().clone(), ))), audio_renderer: Default::default(), show_poster: Cell::new(true), diff --git a/components/script/dom/screen.rs b/components/script/dom/screen.rs index fcbd84fd061..d7ce8b6b4be 100644 --- a/components/script/dom/screen.rs +++ b/components/script/dom/screen.rs @@ -5,16 +5,14 @@ use dom_struct::dom_struct; use euclid::Size2D; use profile_traits::ipc; -use script_traits::ScriptMsg; use style_traits::CSSPixel; use webrender_api::units::DeviceIntSize; +use webrender_traits::CrossProcessCompositorMessage; use crate::dom::bindings::codegen::Bindings::ScreenBinding::ScreenMethods; -use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; -use crate::dom::globalscope::GlobalScope; use crate::dom::window::Window; #[dom_struct] @@ -39,9 +37,9 @@ impl Screen { let (send, recv) = ipc::channel::(self.global().time_profiler_chan().clone()).unwrap(); self.window - .upcast::() - .script_to_constellation_chan() - .send(ScriptMsg::GetScreenSize(send)) + .compositor_api() + .sender() + .send(CrossProcessCompositorMessage::GetScreenSize(send)) .unwrap(); let dpr = self.window.device_pixel_ratio(); let screen = recv.recv().unwrap_or(Size2D::zero()); @@ -52,9 +50,9 @@ impl Screen { let (send, recv) = ipc::channel::(self.global().time_profiler_chan().clone()).unwrap(); self.window - .upcast::() - .script_to_constellation_chan() - .send(ScriptMsg::GetScreenAvailSize(send)) + .compositor_api() + .sender() + .send(CrossProcessCompositorMessage::GetAvailableScreenSize(send)) .unwrap(); let dpr = self.window.device_pixel_ratio(); let screen = recv.recv().unwrap_or(Size2D::zero()); diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 1622eecc896..73a63e435db 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -76,9 +76,9 @@ use style::str::HTML_SPACE_CHARACTERS; use style::stylesheets::{CssRuleType, Origin, UrlExtraData}; use style_traits::{CSSPixel, DevicePixel, ParsingMode}; use url::Position; -use webrender_api::units::{DeviceIntPoint, DeviceIntSize, LayoutPixel}; +use webrender_api::units::{DeviceIntRect, LayoutPixel}; use webrender_api::{DocumentId, ExternalScrollId}; -use webrender_traits::WebRenderScriptApi; +use webrender_traits::CrossProcessCompositorApi; use super::bindings::codegen::Bindings::MessagePortBinding::StructuredSerializeOptions; use super::bindings::trace::HashMapTracedValues; @@ -312,10 +312,10 @@ pub struct Window { /// Flag to identify whether mutation observers are present(true)/absent(false) exists_mut_observer: Cell, - /// Webrender API Sender + /// Cross-process access to the compositor. #[ignore_malloc_size_of = "Wraps an IpcSender"] #[no_trace] - webrender_api_sender: WebRenderScriptApi, + compositor_api: CrossProcessCompositorApi, /// Indicate whether a SetDocumentStatus message has been sent after a reflow is complete. /// It is used to avoid sending idle message more than once, which is unneccessary. @@ -526,8 +526,8 @@ impl Window { self.add_pending_reflow(); } - pub fn get_webrender_api_sender(&self) -> WebRenderScriptApi { - self.webrender_api_sender.clone() + pub fn compositor_api(&self) -> &CrossProcessCompositorApi { + &self.compositor_api } pub fn get_userscripts_path(&self) -> Option { @@ -1773,14 +1773,16 @@ impl Window { fn client_window(&self) -> (Size2D, Point2D) { let timer_profile_chan = self.global().time_profiler_chan().clone(); - let (send, recv) = - ProfiledIpc::channel::<(DeviceIntSize, DeviceIntPoint)>(timer_profile_chan).unwrap(); - self.send_to_constellation(ScriptMsg::GetClientWindow(send)); - let (size, point) = recv.recv().unwrap_or((Size2D::zero(), Point2D::zero())); + let (send, recv) = ProfiledIpc::channel::(timer_profile_chan).unwrap(); + let _ = self + .compositor_api + .sender() + .send(webrender_traits::CrossProcessCompositorMessage::GetClientWindowRect(send)); + let rect = recv.recv().unwrap_or_default(); let dpr = self.device_pixel_ratio(); ( - (size.to_f32() / dpr).to_u32(), - (point.to_f32() / dpr).to_i32(), + (rect.size().to_f32() / dpr).to_u32(), + (rect.min.to_f32() / dpr).to_i32(), ) } @@ -2548,7 +2550,7 @@ impl Window { webxr_registry: webxr_api::Registry, microtask_queue: Rc, webrender_document: DocumentId, - webrender_api_sender: WebRenderScriptApi, + compositor_api: CrossProcessCompositorApi, relayout_event: bool, prepare_for_screenshot: bool, unminify_js: bool, @@ -2633,7 +2635,7 @@ impl Window { paint_worklet: Default::default(), webrender_document, exists_mut_observer: Cell::new(false), - webrender_api_sender, + compositor_api, has_sent_idle_message: Cell::new(false), relayout_event, prepare_for_screenshot, diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index e170dfcaa9d..daea4ce4cfd 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -95,7 +95,7 @@ use style::thread_state::{self, ThreadState}; use url::Position; use webgpu::{WebGPUDevice, WebGPUMsg}; use webrender_api::DocumentId; -use webrender_traits::WebRenderScriptApi; +use webrender_traits::CrossProcessCompositorApi; use crate::document_loader::DocumentLoader; use crate::dom::bindings::cell::DomRefCell; @@ -669,9 +669,9 @@ pub struct ScriptThread { #[no_trace] webrender_document: DocumentId, - /// Webrender API sender. + /// Cross-process access to the compositor's API. #[no_trace] - webrender_api_sender: WebRenderScriptApi, + compositor_api: CrossProcessCompositorApi, /// Periodically print out on which events script threads spend their processing time. profile_script_events: bool, @@ -1399,7 +1399,7 @@ impl ScriptThread { custom_element_reaction_stack: CustomElementReactionStack::new(), webrender_document: state.webrender_document, - webrender_api_sender: state.webrender_api_sender, + compositor_api: state.compositor_api, profile_script_events: opts.debug.profile_script_events, print_pwm: opts.print_pwm, @@ -3661,7 +3661,7 @@ impl ScriptThread { system_font_service: self.system_font_service.clone(), resource_threads: self.resource_threads.clone(), time_profiler_chan: self.time_profiler_chan.clone(), - webrender_api_sender: self.webrender_api_sender.clone(), + compositor_api: self.compositor_api.clone(), paint_time_metrics, window_size: incomplete.window_size, }; @@ -3692,7 +3692,7 @@ impl ScriptThread { self.webxr_registry.clone(), self.microtask_queue.clone(), self.webrender_document, - self.webrender_api_sender.clone(), + self.compositor_api.clone(), self.relayout_event, self.prepare_for_screenshot, self.unminify_js, diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 99947da8cad..19956ed5055 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -28,15 +28,13 @@ pub use base::id::TopLevelBrowsingContextId; use base::id::{PipelineNamespace, PipelineNamespaceId}; use bluetooth::BluetoothThreadFactory; use bluetooth_traits::BluetoothRequest; -use canvas::canvas_paint_thread::{self, CanvasPaintThread}; +use canvas::canvas_paint_thread::CanvasPaintThread; use canvas::WebGLComm; use canvas_traits::webgl::WebGLThreads; use compositing::webview::UnknownWebView; use compositing::windowing::{EmbedderEvent, EmbedderMethods, WindowMethods}; use compositing::{CompositeTarget, IOCompositor, InitialCompositorState, ShutdownState}; -use compositing_traits::{ - CompositorMsg, CompositorProxy, CompositorReceiver, ConstellationMsg, ForwardedToCompositorMsg, -}; +use compositing_traits::{CompositorMsg, CompositorProxy, CompositorReceiver, ConstellationMsg}; #[cfg(all( not(target_os = "windows"), not(target_os = "ios"), @@ -66,7 +64,8 @@ use fonts::SystemFontService; use gaol::sandbox::{ChildSandbox, ChildSandboxMethods}; pub use gleam::gl; use gleam::gl::RENDERER; -use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory}; +use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::router::ROUTER; #[cfg(feature = "layout_2013")] pub use layout_thread_2013; use log::{error, trace, warn, Log, Metadata, Record}; @@ -91,13 +90,10 @@ use surfman::{GLApi, GLVersion}; use surfman::{NativeConnection, NativeContext}; use webgpu::swapchain::WGPUImageMap; use webrender::{RenderApiSender, ShaderPrecacheFlags, UploadMethod, ONE_TIME_USAGE_HINT}; -use webrender_api::{ - ColorF, DocumentId, FontInstanceFlags, FontInstanceKey, FontKey, FramePublishId, ImageKey, - NativeFontHandle, -}; +use webrender_api::{ColorF, DocumentId, FramePublishId}; use webrender_traits::{ - CanvasToCompositorMsg, FontToCompositorMsg, ImageUpdate, RenderingContext, WebRenderFontApi, - WebrenderExternalImageHandlers, WebrenderExternalImageRegistry, WebrenderImageHandlerType, + CrossProcessCompositorApi, RenderingContext, WebrenderExternalImageHandlers, + WebrenderExternalImageRegistry, WebrenderImageHandlerType, }; pub use { background_hang_monitor, base, bluetooth, bluetooth_traits, canvas, canvas_traits, compositing, @@ -979,9 +975,24 @@ fn create_compositor_channel( event_loop_waker: Box, ) -> (CompositorProxy, CompositorReceiver) { let (sender, receiver) = unbounded(); + + let (compositor_ipc_sender, compositor_ipc_receiver) = + ipc::channel().expect("ipc channel failure"); + let sender_clone = sender.clone(); + ROUTER.add_route( + compositor_ipc_receiver.to_opaque(), + Box::new(move |message| { + let _ = sender_clone.send(CompositorMsg::CrossProcess( + message.to().expect("Could not convert Compositor message"), + )); + }), + ); + let cross_process_compositor_api = CrossProcessCompositorApi(compositor_ipc_sender); + ( CompositorProxy { sender, + cross_process_compositor_api, event_loop_waker, }, CompositorReceiver { receiver }, @@ -1043,14 +1054,11 @@ fn create_constellation( ); let system_font_service = Arc::new( - SystemFontService::spawn(Box::new(WebRenderFontApiCompositorProxy( - compositor_proxy.clone(), - ))) - .to_proxy(), + SystemFontService::spawn(compositor_proxy.cross_process_compositor_api.clone()).to_proxy(), ); let (canvas_create_sender, canvas_ipc_sender) = CanvasPaintThread::start( - Box::new(CanvasWebrenderApi(compositor_proxy.clone())), + compositor_proxy.cross_process_compositor_api.clone(), system_font_service.clone(), public_resource_threads.clone(), ); @@ -1094,82 +1102,6 @@ fn create_constellation( ) } -struct WebRenderFontApiCompositorProxy(CompositorProxy); - -impl WebRenderFontApi for WebRenderFontApiCompositorProxy { - fn add_font_instance( - &self, - font_instance_key: FontInstanceKey, - font_key: FontKey, - size: f32, - flags: FontInstanceFlags, - ) { - self.0.send(CompositorMsg::Forwarded( - ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFontInstance( - font_instance_key, - font_key, - size, - flags, - )), - )); - } - - fn add_font(&self, font_key: FontKey, data: Arc, index: u32) { - self.0.send(CompositorMsg::Forwarded( - ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFont( - font_key, index, data, - )), - )); - } - - fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) { - self.0.send(CompositorMsg::Forwarded( - ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddSystemFont( - font_key, handle, - )), - )); - } - - fn fetch_font_keys( - &self, - number_of_font_keys: usize, - number_of_font_instance_keys: usize, - ) -> (Vec, Vec) { - let (sender, receiver) = unbounded(); - self.0.send(CompositorMsg::Forwarded( - ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::GenerateKeys( - number_of_font_keys, - number_of_font_instance_keys, - sender, - )), - )); - receiver.recv().unwrap() - } -} - -#[derive(Clone)] -struct CanvasWebrenderApi(CompositorProxy); - -impl canvas_paint_thread::WebrenderApi for CanvasWebrenderApi { - fn generate_key(&self) -> Option { - let (sender, receiver) = unbounded(); - self.0 - .send(CompositorMsg::Forwarded(ForwardedToCompositorMsg::Canvas( - CanvasToCompositorMsg::GenerateKey(sender), - ))); - receiver.recv().ok() - } - fn update_images(&self, updates: Vec) { - self.0 - .send(CompositorMsg::Forwarded(ForwardedToCompositorMsg::Canvas( - CanvasToCompositorMsg::UpdateImages(updates), - ))); - } - fn clone(&self) -> Box { - Box::new(::clone(self)) - } -} - // A logger that logs to two downstream loggers. // This should probably be in the log crate. struct BothLogger(Log1, Log2); diff --git a/components/shared/compositing/lib.rs b/components/shared/compositing/lib.rs index e3c0c079037..f4afdc211b2 100644 --- a/components/shared/compositing/lib.rs +++ b/components/shared/compositing/lib.rs @@ -21,15 +21,18 @@ use script_traits::{ AnimationState, ConstellationControlMsg, EventResult, MouseButton, MouseEventType, }; use style_traits::CSSPixel; -use webrender_api::units::{DeviceIntPoint, DeviceIntSize, DeviceRect}; +use webrender_api::units::DeviceRect; use webrender_api::DocumentId; -use webrender_traits::{ - CanvasToCompositorMsg, FontToCompositorMsg, NetToCompositorMsg, ScriptToCompositorMsg, -}; +use webrender_traits::{CrossProcessCompositorApi, CrossProcessCompositorMessage}; /// Sends messages to the compositor. +#[derive(Clone)] pub struct CompositorProxy { pub sender: Sender, + /// Access to [`Self::sender`] that is possible to send across an IPC + /// channel. These messages are routed via the router thread to + /// [`Self::sender`]. + pub cross_process_compositor_api: CrossProcessCompositorApi, pub event_loop_waker: Box, } @@ -42,15 +45,6 @@ impl CompositorProxy { } } -impl Clone for CompositorProxy { - fn clone(&self) -> CompositorProxy { - CompositorProxy { - sender: self.sender.clone(), - event_loop_waker: self.event_loop_waker.clone(), - } - } -} - /// The port that the compositor receives messages on. pub struct CompositorReceiver { pub receiver: Receiver, @@ -114,16 +108,9 @@ pub enum CompositorMsg { /// WebDriver mouse move event WebDriverMouseMoveEvent(f32, f32), - /// Get Window Informations size and position. - GetClientWindow(IpcSender<(DeviceIntSize, DeviceIntPoint)>), - /// Get screen size. - GetScreenSize(IpcSender), - /// Get screen available size. - GetScreenAvailSize(IpcSender), - /// Messages forwarded to the compositor by the constellation from other crates. These /// messages are mainly passed on from the compositor to WebRender. - Forwarded(ForwardedToCompositorMsg), + CrossProcess(CrossProcessCompositorMessage), } pub struct SendableFrameTree { @@ -139,27 +126,6 @@ pub struct CompositionPipeline { pub script_chan: IpcSender, } -/// Messages forwarded by the Constellation to the Compositor. -pub enum ForwardedToCompositorMsg { - Layout(ScriptToCompositorMsg), - Net(NetToCompositorMsg), - SystemFontService(FontToCompositorMsg), - Canvas(CanvasToCompositorMsg), -} - -impl Debug for ForwardedToCompositorMsg { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { - match self { - ForwardedToCompositorMsg::Layout(_) => write!(f, "Layout(ScriptToCompositorMsg)"), - ForwardedToCompositorMsg::Net(_) => write!(f, "Net(NetToCompositorMsg)"), - ForwardedToCompositorMsg::SystemFontService(_) => { - write!(f, "SystemFontService(FontToCompositorMsg)") - }, - ForwardedToCompositorMsg::Canvas(_) => write!(f, "Canvas(CanvasToCompositorMsg)"), - } - } -} - impl Debug for CompositorMsg { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { match *self { @@ -183,10 +149,7 @@ impl Debug for CompositorMsg { CompositorMsg::LoadComplete(..) => write!(f, "LoadComplete"), CompositorMsg::WebDriverMouseButtonEvent(..) => write!(f, "WebDriverMouseButtonEvent"), CompositorMsg::WebDriverMouseMoveEvent(..) => write!(f, "WebDriverMouseMoveEvent"), - CompositorMsg::GetClientWindow(..) => write!(f, "GetClientWindow"), - CompositorMsg::GetScreenSize(..) => write!(f, "GetScreenSize"), - CompositorMsg::GetScreenAvailSize(..) => write!(f, "GetScreenAvailSize"), - CompositorMsg::Forwarded(..) => write!(f, "Webrender"), + CompositorMsg::CrossProcess(..) => write!(f, "CrossProcess"), } } } diff --git a/components/shared/net/image_cache.rs b/components/shared/net/image_cache.rs index 317fd1b66ef..c587eab13b3 100644 --- a/components/shared/net/image_cache.rs +++ b/components/shared/net/image_cache.rs @@ -10,7 +10,7 @@ use malloc_size_of_derive::MallocSizeOf; use pixels::{Image, ImageMetadata}; use serde::{Deserialize, Serialize}; use servo_url::{ImmutableOrigin, ServoUrl}; -use webrender_traits::WebRenderNetApi; +use webrender_traits::CrossProcessCompositorApi; use crate::request::CorsSettings; use crate::FetchResponseMsg; @@ -99,7 +99,7 @@ pub enum ImageCacheResult { } pub trait ImageCache: Sync + Send { - fn new(webrender_api: WebRenderNetApi) -> Self + fn new(compositor_api: CrossProcessCompositorApi) -> Self where Self: Sized; diff --git a/components/shared/script/lib.rs b/components/shared/script/lib.rs index 1ab9e518731..c3bb72156b4 100644 --- a/components/shared/script/lib.rs +++ b/components/shared/script/lib.rs @@ -58,7 +58,9 @@ use style_traits::{CSSPixel, SpeculativePainter}; use webgpu::WebGPUMsg; use webrender_api::units::{DeviceIntSize, DevicePixel, LayoutPixel}; use webrender_api::{DocumentId, ExternalScrollId, ImageKey}; -use webrender_traits::{UntrustedNodeAddress as WebRenderUntrustedNodeAddress, WebRenderScriptApi}; +use webrender_traits::{ + CrossProcessCompositorApi, UntrustedNodeAddress as WebRenderUntrustedNodeAddress, +}; pub use crate::script_msg::{ DOMMessage, EventResult, HistoryEntryReplacement, IFrameSizeMsg, Job, JobError, JobResult, @@ -659,8 +661,8 @@ pub struct InitialScriptState { pub webxr_registry: webxr_api::Registry, /// The Webrender document ID associated with this thread. pub webrender_document: DocumentId, - /// FIXME(victor): The Webrender API sender in this constellation's pipeline - pub webrender_api_sender: WebRenderScriptApi, + /// Access to the compositor across a process boundary. + pub compositor_api: CrossProcessCompositorApi, /// Application window's GL Context for Media player pub player_context: WindowGLContext, } diff --git a/components/shared/script/script_msg.rs b/components/shared/script/script_msg.rs index ee8e8da1386..5689395ef32 100644 --- a/components/shared/script/script_msg.rs +++ b/components/shared/script/script_msg.rs @@ -24,7 +24,6 @@ use serde::{Deserialize, Serialize}; use servo_url::{ImmutableOrigin, ServoUrl}; use style_traits::CSSPixel; use webgpu::{wgc, WebGPU, WebGPUResponse}; -use webrender_api::units::{DeviceIntPoint, DeviceIntSize}; use crate::{ AnimationState, AuxiliaryBrowsingContextLoadInfo, BroadcastMsg, DocumentState, @@ -245,12 +244,6 @@ pub enum ScriptMsg { ForwardDOMMessage(DOMMessage, ServoUrl), /// ScheduleJob(Job), - /// Get Window Informations size and position - GetClientWindow(IpcSender<(DeviceIntSize, DeviceIntPoint)>), - /// Get the screen size (pixel) - GetScreenSize(IpcSender), - /// Get the available screen size (pixel) - GetScreenAvailSize(IpcSender), /// Notifies the constellation about media session events /// (i.e. when there is metadata for the active media session, playback state changes...). MediaSessionEvent(PipelineId, MediaSessionEvent), @@ -318,9 +311,6 @@ impl fmt::Debug for ScriptMsg { PipelineExited => "PipelineExited", ForwardDOMMessage(..) => "ForwardDOMMessage", ScheduleJob(..) => "ScheduleJob", - GetClientWindow(..) => "GetClientWindow", - GetScreenSize(..) => "GetScreenSize", - GetScreenAvailSize(..) => "GetScreenAvailSize", MediaSessionEvent(..) => "MediaSessionEvent", RequestAdapter(..) => "RequestAdapter", GetWebGPUChan(..) => "GetWebGPUChan", diff --git a/components/shared/script_layout/lib.rs b/components/shared/script_layout/lib.rs index 1ad180411d3..228fd03556e 100644 --- a/components/shared/script_layout/lib.rs +++ b/components/shared/script_layout/lib.rs @@ -53,7 +53,7 @@ use style::stylesheets::Stylesheet; use style::Atom; use style_traits::CSSPixel; use webrender_api::ImageKey; -use webrender_traits::WebRenderScriptApi; +use webrender_traits::CrossProcessCompositorApi; pub type GenericLayoutData = dyn Any + Send + Sync; @@ -177,7 +177,7 @@ pub struct LayoutConfig { pub resource_threads: ResourceThreads, pub system_font_service: Arc, pub time_profiler_chan: time::ProfilerChan, - pub webrender_api_sender: WebRenderScriptApi, + pub compositor_api: CrossProcessCompositorApi, pub paint_time_metrics: PaintTimeMetrics, pub window_size: WindowSizeData, } diff --git a/components/shared/webrender/lib.rs b/components/shared/webrender/lib.rs index 3e51e6bc6ea..807c8909d61 100644 --- a/components/shared/webrender/lib.rs +++ b/components/shared/webrender/lib.rs @@ -7,11 +7,11 @@ pub mod display_list; pub mod rendering_context; +use core::fmt; use std::collections::HashMap; use std::sync::{Arc, Mutex}; use base::id::PipelineId; -use crossbeam_channel::Sender; use display_list::{CompositorDisplayListInfo, ScrollTreeNodeId}; use embedder_traits::Cursor; use euclid::default::Size2D; @@ -19,7 +19,7 @@ use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory}; use libc::c_void; use log::warn; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use webrender_api::units::{DevicePoint, LayoutPoint, TexelRect}; +use webrender_api::units::{DeviceIntRect, DeviceIntSize, DevicePoint, LayoutPoint, TexelRect}; use webrender_api::{ BuiltDisplayList, BuiltDisplayListDescriptor, ExternalImage, ExternalImageData, ExternalImageHandler, ExternalImageId, ExternalImageSource, ExternalScrollId, @@ -29,6 +29,261 @@ use webrender_api::{ pub use crate::rendering_context::RenderingContext; +#[derive(Deserialize, Serialize)] +pub enum CrossProcessCompositorMessage { + /// Inform WebRender of the existence of this pipeline. + SendInitialTransaction(WebRenderPipelineId), + /// Perform a scroll operation. + SendScrollNode(WebRenderPipelineId, LayoutPoint, ExternalScrollId), + /// Inform WebRender of a new display list for the given pipeline. + SendDisplayList { + /// The [CompositorDisplayListInfo] that describes the display list being sent. + display_list_info: Box, + /// 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( + Option, + DevicePoint, + HitTestFlags, + IpcSender>, + ), + /// Create a new image key. The result will be returned via the + /// provided channel sender. + GenerateImageKey(IpcSender), + /// Add an image with the given data and `ImageKey`. + AddImage(ImageKey, ImageDescriptor, SerializableImageData), + /// Perform a resource update operation. + UpdateImages(Vec), + + /// Generate a new batch of font keys which can be used to allocate + /// keys asynchronously. + GenerateFontKeys( + usize, + usize, + IpcSender<(Vec, Vec)>, + ), + /// Add a font with the given data and font key. + AddFont(FontKey, Arc, u32), + /// Add a system font with the given font key and handle. + AddSystemFont(FontKey, NativeFontHandle), + /// Add an instance of a font with the given instance key. + AddFontInstance(FontInstanceKey, FontKey, f32, FontInstanceFlags), + /// Remove the given font resources from our WebRender instance. + RemoveFonts(Vec, Vec), + + /// Get the client window size and position. + GetClientWindowRect(IpcSender), + /// Get the size of the screen that the client window inhabits. + GetScreenSize(IpcSender), + /// Get the available screen size (without toolbars and docks) for the screen + /// the client window inhabits. + GetAvailableScreenSize(IpcSender), +} + +impl fmt::Debug for CrossProcessCompositorMessage { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::AddImage(..) => f.write_str("AddImage"), + Self::GenerateFontKeys(..) => f.write_str("GenerateFontKeys"), + Self::AddSystemFont(..) => f.write_str("AddSystemFont"), + Self::SendInitialTransaction(..) => f.write_str("SendInitialTransaction"), + Self::SendScrollNode(..) => f.write_str("SendScrollNode"), + Self::SendDisplayList { .. } => f.write_str("SendDisplayList"), + Self::HitTest(..) => f.write_str("HitTest"), + Self::GenerateImageKey(..) => f.write_str("GenerateImageKey"), + Self::UpdateImages(..) => f.write_str("UpdateImages"), + Self::RemoveFonts(..) => f.write_str("RemoveFonts"), + Self::AddFontInstance(..) => f.write_str("AddFontInstance"), + Self::AddFont(..) => f.write_str("AddFont"), + Self::GetClientWindowRect(..) => f.write_str("GetClientWindowRect"), + Self::GetScreenSize(..) => f.write_str("GetScreenSize"), + Self::GetAvailableScreenSize(..) => f.write_str("GetAvailableScreenSize"), + } + } +} + +/// A mechanism to send messages from ScriptThread to the parent process' WebRender instance. +#[derive(Clone, Deserialize, Serialize)] +pub struct CrossProcessCompositorApi(pub IpcSender); + +impl CrossProcessCompositorApi { + /// Create a new [`CrossProcessCompositorApi`] struct that does not have a listener on the other + /// end to use for unit testing. + pub fn dummy() -> Self { + let (sender, _) = ipc::channel().unwrap(); + Self(sender) + } + + /// Get the sender for this proxy. + pub fn sender(&self) -> &IpcSender { + &self.0 + } + + /// Inform WebRender of the existence of this pipeline. + pub fn send_initial_transaction(&self, pipeline: WebRenderPipelineId) { + if let Err(e) = self + .0 + .send(CrossProcessCompositorMessage::SendInitialTransaction( + pipeline, + )) + { + warn!("Error sending initial transaction: {}", e); + } + } + + /// Perform a scroll operation. + pub fn send_scroll_node( + &self, + pipeline_id: WebRenderPipelineId, + point: LayoutPoint, + scroll_id: ExternalScrollId, + ) { + if let Err(e) = self.0.send(CrossProcessCompositorMessage::SendScrollNode( + pipeline_id, + point, + scroll_id, + )) { + warn!("Error sending scroll node: {}", e); + } + } + + /// Inform WebRender of a new display list for the given pipeline. + pub fn send_display_list( + &self, + display_list_info: CompositorDisplayListInfo, + list: BuiltDisplayList, + ) { + 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(CrossProcessCompositorMessage::SendDisplayList { + display_list_info: Box::new(display_list_info), + display_list_descriptor, + display_list_receiver, + }) { + warn!("Error sending display list: {}", e); + } + + if let Err(error) = display_list_sender.send(&display_list_data.items_data) { + warn!("Error sending display list items: {}", error); + } + if let Err(error) = display_list_sender.send(&display_list_data.cache_data) { + warn!("Error sending display list cache data: {}", error); + } + if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) { + warn!("Error sending display spatial tree: {}", error); + } + } + + /// Perform a hit test operation. Blocks until the operation is complete and + /// and a result is available. + pub fn hit_test( + &self, + pipeline: Option, + point: DevicePoint, + flags: HitTestFlags, + ) -> Vec { + let (sender, receiver) = ipc::channel().unwrap(); + self.0 + .send(CrossProcessCompositorMessage::HitTest( + pipeline, point, flags, sender, + )) + .expect("error sending hit test"); + receiver.recv().expect("error receiving hit test result") + } + + /// Create a new image key. Blocks until the key is available. + pub fn generate_image_key(&self) -> Option { + let (sender, receiver) = ipc::channel().unwrap(); + self.0 + .send(CrossProcessCompositorMessage::GenerateImageKey(sender)) + .ok()?; + receiver.recv().ok() + } + + pub fn add_image( + &self, + key: ImageKey, + descriptor: ImageDescriptor, + data: SerializableImageData, + ) { + if let Err(e) = self.0.send(CrossProcessCompositorMessage::AddImage( + key, descriptor, data, + )) { + warn!("Error sending image update: {}", e); + } + } + + /// Perform an image resource update operation. + pub fn update_images(&self, updates: Vec) { + if let Err(e) = self + .0 + .send(CrossProcessCompositorMessage::UpdateImages(updates)) + { + warn!("error sending image updates: {}", e); + } + } + + pub fn remove_unused_font_resources( + &self, + keys: Vec, + instance_keys: Vec, + ) { + if keys.is_empty() && instance_keys.is_empty() { + return; + } + let _ = self.0.send(CrossProcessCompositorMessage::RemoveFonts( + keys, + instance_keys, + )); + } + + pub fn add_font_instance( + &self, + font_instance_key: FontInstanceKey, + font_key: FontKey, + size: f32, + flags: FontInstanceFlags, + ) { + let _x = self.0.send(CrossProcessCompositorMessage::AddFontInstance( + font_instance_key, + font_key, + size, + flags, + )); + } + + pub fn add_font(&self, font_key: FontKey, data: Arc, index: u32) { + let _ = self.0.send(CrossProcessCompositorMessage::AddFont( + font_key, data, index, + )); + } + + pub fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) { + let _ = self.0.send(CrossProcessCompositorMessage::AddSystemFont( + font_key, handle, + )); + } + + pub fn fetch_font_keys( + &self, + number_of_font_keys: usize, + number_of_font_instance_keys: usize, + ) -> (Vec, Vec) { + let (sender, receiver) = ipc_channel::ipc::channel().expect("Could not create IPC channel"); + let _ = self.0.send(CrossProcessCompositorMessage::GenerateFontKeys( + number_of_font_keys, + number_of_font_instance_keys, + sender, + )); + receiver.recv().unwrap() + } +} + /// This trait is used as a bridge between the different GL clients /// in Servo that handles WebRender ExternalImages and the WebRender /// ExternalImageHandler API. @@ -183,303 +438,34 @@ impl ExternalImageHandler for WebrenderExternalImageHandlers { } } -pub trait WebRenderFontApi { - fn add_font_instance( - &self, - font_instance_key: FontInstanceKey, - font_key: FontKey, - size: f32, - flags: FontInstanceFlags, - ); - fn add_font(&self, font_key: FontKey, data: Arc, index: u32); - fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle); - fn fetch_font_keys( - &self, - number_of_font_keys: usize, - number_of_font_instance_keys: usize, - ) -> (Vec, Vec); -} - -pub enum CanvasToCompositorMsg { - GenerateKey(Sender), - UpdateImages(Vec), -} - -pub enum FontToCompositorMsg { - GenerateKeys(usize, usize, Sender<(Vec, Vec)>), - AddFontInstance(FontInstanceKey, FontKey, f32, FontInstanceFlags), - AddFont(FontKey, u32, Arc), - AddSystemFont(FontKey, NativeFontHandle), -} - -#[derive(Deserialize, Serialize)] -pub enum NetToCompositorMsg { - AddImage(ImageKey, ImageDescriptor, ImageData), - GenerateImageKey(IpcSender), -} - -/// The set of WebRender operations that can be initiated by the content process. -#[derive(Deserialize, Serialize)] -pub enum ScriptToCompositorMsg { - /// Inform WebRender of the existence of this pipeline. - SendInitialTransaction(WebRenderPipelineId), - /// Perform a scroll operation. - SendScrollNode(WebRenderPipelineId, LayoutPoint, ExternalScrollId), - /// Inform WebRender of a new display list for the given pipeline. - SendDisplayList { - /// The [CompositorDisplayListInfo] that describes the display list being sent. - display_list_info: Box, - /// 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( - Option, - DevicePoint, - HitTestFlags, - IpcSender>, - ), - /// Create a new image key. The result will be returned via the - /// provided channel sender. - GenerateImageKey(IpcSender), - /// Perform a resource update operation. - UpdateImages(Vec), - /// Remove the given font resources from our WebRender instance. - RemoveFonts(Vec, Vec), - AddFontInstance(FontInstanceKey, FontKey, f32, FontInstanceFlags), - AddFont(FontKey, Arc, u32), -} - -/// A mechanism to send messages from networking to the WebRender instance. -#[derive(Clone, Deserialize, Serialize)] -pub struct WebRenderNetApi(IpcSender); - -impl WebRenderNetApi { - pub fn new(sender: IpcSender) -> Self { - Self(sender) - } - - pub fn generate_image_key(&self) -> ImageKey { - let (sender, receiver) = ipc::channel().unwrap(); - self.0 - .send(NetToCompositorMsg::GenerateImageKey(sender)) - .expect("error sending image key generation"); - receiver.recv().expect("error receiving image key result") - } - - pub fn add_image(&self, key: ImageKey, descriptor: ImageDescriptor, data: ImageData) { - if let Err(e) = self - .0 - .send(NetToCompositorMsg::AddImage(key, descriptor, data)) - { - warn!("Error sending image update: {}", e); - } - } -} - -/// A mechanism to send messages from ScriptThread to the parent process' WebRender instance. -#[derive(Clone, Deserialize, Serialize)] -pub struct WebRenderScriptApi(IpcSender); - -impl WebRenderScriptApi { - /// Create a new [`WebRenderScriptApi`] object that wraps the provided channel sender. - pub fn new(sender: IpcSender) -> Self { - Self(sender) - } - - /// Create a new [`WebRenderScriptApi`] object that does not have a listener on the - /// other end. - pub fn dummy() -> Self { - let (sender, _) = ipc::channel().unwrap(); - Self::new(sender) - } - - /// Get the sender for this proxy. - pub fn sender(&self) -> &IpcSender { - &self.0 - } - - /// Inform WebRender of the existence of this pipeline. - pub fn send_initial_transaction(&self, pipeline: WebRenderPipelineId) { - if let Err(e) = self - .0 - .send(ScriptToCompositorMsg::SendInitialTransaction(pipeline)) - { - warn!("Error sending initial transaction: {}", e); - } - } - - /// Perform a scroll operation. - pub fn send_scroll_node( - &self, - pipeline_id: WebRenderPipelineId, - point: LayoutPoint, - scroll_id: ExternalScrollId, - ) { - if let Err(e) = self.0.send(ScriptToCompositorMsg::SendScrollNode( - pipeline_id, - point, - scroll_id, - )) { - warn!("Error sending scroll node: {}", e); - } - } - - /// Inform WebRender of a new display list for the given pipeline. - pub fn send_display_list( - &self, - display_list_info: CompositorDisplayListInfo, - list: BuiltDisplayList, - ) { - 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(ScriptToCompositorMsg::SendDisplayList { - display_list_info: Box::new(display_list_info), - display_list_descriptor, - display_list_receiver, - }) { - warn!("Error sending display list: {}", e); - } - if let Err(error) = display_list_sender.send(&display_list_data.items_data) { - warn!("Error sending display list items: {}", error); - } - if let Err(error) = display_list_sender.send(&display_list_data.cache_data) { - warn!("Error sending display list cache data: {}", error); - } - if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) { - warn!("Error sending display spatial tree: {}", error); - } - } - - /// Perform a hit test operation. Blocks until the operation is complete and - /// and a result is available. - pub fn hit_test( - &self, - pipeline: Option, - point: DevicePoint, - flags: HitTestFlags, - ) -> Vec { - let (sender, receiver) = ipc::channel().unwrap(); - self.0 - .send(ScriptToCompositorMsg::HitTest( - pipeline, point, flags, sender, - )) - .expect("error sending hit test"); - receiver.recv().expect("error receiving hit test result") - } - - /// Create a new image key. Blocks until the key is available. - pub fn generate_image_key(&self) -> Option { - let (sender, receiver) = ipc::channel().unwrap(); - self.0 - .send(ScriptToCompositorMsg::GenerateImageKey(sender)) - .ok()?; - receiver.recv().ok() - } - - /// Perform a resource update operation. - pub fn update_images(&self, updates: Vec) { - let mut senders = Vec::new(); - // Convert `ImageUpdate` to `SerializedImageUpdate` because `ImageData` may contain large - // byes. With this conversion, we send `IpcBytesReceiver` instead and use it to send the - // actual bytes. - let updates = updates - .into_iter() - .map(|update| match update { - ImageUpdate::AddImage(k, d, data) => { - let data = match data { - ImageData::Raw(r) => { - let (sender, receiver) = ipc::bytes_channel().unwrap(); - senders.push((sender, r)); - SerializedImageData::Raw(receiver) - }, - ImageData::External(e) => SerializedImageData::External(e), - }; - SerializedImageUpdate::AddImage(k, d, data) - }, - ImageUpdate::DeleteImage(k) => SerializedImageUpdate::DeleteImage(k), - ImageUpdate::UpdateImage(k, d, data) => { - let data = match data { - ImageData::Raw(r) => { - let (sender, receiver) = ipc::bytes_channel().unwrap(); - senders.push((sender, r)); - SerializedImageData::Raw(receiver) - }, - ImageData::External(e) => SerializedImageData::External(e), - }; - SerializedImageUpdate::UpdateImage(k, d, data) - }, - }) - .collect(); - - if let Err(e) = self.0.send(ScriptToCompositorMsg::UpdateImages(updates)) { - warn!("error sending image updates: {}", e); - } - - senders.into_iter().for_each(|(tx, data)| { - if let Err(e) = tx.send(&data) { - warn!("error sending image data: {}", e); - } - }); - } - - pub fn remove_unused_font_resources( - &self, - keys: Vec, - instance_keys: Vec, - ) { - if keys.is_empty() && instance_keys.is_empty() { - return; - } - let _ = self - .0 - .send(ScriptToCompositorMsg::RemoveFonts(keys, instance_keys)); - } -} - #[derive(Deserialize, Serialize)] /// Serializable image updates that must be performed by WebRender. pub enum ImageUpdate { /// Register a new image. - AddImage(ImageKey, ImageDescriptor, ImageData), + AddImage(ImageKey, ImageDescriptor, SerializableImageData), /// Delete a previously registered image registration. DeleteImage(ImageKey), /// Update an existing image registration. - UpdateImage(ImageKey, ImageDescriptor, ImageData), -} - -#[derive(Deserialize, Serialize)] -/// Serialized `ImageUpdate`. -pub enum SerializedImageUpdate { - /// Register a new image. - AddImage(ImageKey, ImageDescriptor, SerializedImageData), - /// Delete a previously registered image registration. - DeleteImage(ImageKey), - /// Update an existing image registration. - UpdateImage(ImageKey, ImageDescriptor, SerializedImageData), + UpdateImage(ImageKey, ImageDescriptor, SerializableImageData), } #[derive(Debug, Deserialize, Serialize)] /// Serialized `ImageData`. It contains IPC byte channel receiver to prevent from loading bytes too /// slow. -pub enum SerializedImageData { +pub enum SerializableImageData { /// A simple series of bytes, provided by the embedding and owned by WebRender. /// The format is stored out-of-band, currently in ImageDescriptor. - Raw(ipc::IpcBytesReceiver), + Raw(IpcSharedMemory), /// An image owned by the embedding, and referenced by WebRender. This may /// take the form of a texture or a heap-allocated buffer. External(ExternalImageData), } -impl SerializedImageData { - /// Convert to ``ImageData`. - pub fn to_image_data(&self) -> Result { - match self { - SerializedImageData::Raw(rx) => rx.recv().map(ImageData::new), - SerializedImageData::External(image) => Ok(ImageData::External(*image)), +impl From for ImageData { + fn from(value: SerializableImageData) -> Self { + match value { + SerializableImageData::Raw(shared_memory) => ImageData::new(shared_memory.to_vec()), + SerializableImageData::External(image) => ImageData::External(image), } } } diff --git a/ports/servoshell/desktop/headed_window.rs b/ports/servoshell/desktop/headed_window.rs index 911e60d9caf..a58ef788fcd 100644 --- a/ports/servoshell/desktop/headed_window.rs +++ b/ports/servoshell/desktop/headed_window.rs @@ -536,10 +536,10 @@ impl WindowMethods for Window { EmbedderCoordinates { viewport, framebuffer: viewport.size(), - window: (window_size, window_origin), - screen, + window_rect: DeviceIntRect::from_origin_and_size(window_origin, window_size), + screen_size: screen, // FIXME: Winit doesn't have API for available size. Fallback to screen size - screen_avail: screen, + available_screen_size: screen, hidpi_factor: self.hidpi_factor(), } } diff --git a/ports/servoshell/desktop/headless_window.rs b/ports/servoshell/desktop/headless_window.rs index 421332d9b50..be058b6598b 100644 --- a/ports/servoshell/desktop/headless_window.rs +++ b/ports/servoshell/desktop/headless_window.rs @@ -167,9 +167,9 @@ impl WindowMethods for Window { EmbedderCoordinates { viewport, framebuffer: size, - window: (size, Point2D::zero()), - screen: size, - screen_avail: size, + window_rect: DeviceIntRect::from_origin_and_size(Point2D::zero(), size), + screen_size: size, + available_screen_size: size, hidpi_factor: dpr, } } diff --git a/ports/servoshell/egl/servo_glue.rs b/ports/servoshell/egl/servo_glue.rs index b5739f2ba50..cc4f30667fd 100644 --- a/ports/servoshell/egl/servo_glue.rs +++ b/ports/servoshell/egl/servo_glue.rs @@ -25,6 +25,7 @@ use servo::script_traits::{ }; use servo::servo_url::ServoUrl; use servo::style_traits::DevicePixel; +use servo::webrender_api::units::DeviceIntRect; use servo::webrender_api::ScrollLocation; use servo::webrender_traits::RenderingContext; use servo::{gl, Servo, TopLevelBrowsingContextId}; @@ -693,9 +694,9 @@ impl WindowMethods for ServoWindowCallbacks { EmbedderCoordinates { viewport: coords.viewport.to_box2d(), framebuffer: coords.framebuffer, - window: (coords.viewport.size, Point2D::new(0, 0)), - screen: coords.viewport.size, - screen_avail: coords.viewport.size, + window_rect: DeviceIntRect::from_origin_and_size(Point2D::zero(), coords.viewport.size), + screen_size: coords.viewport.size, + available_screen_size: coords.viewport.size, hidpi_factor: Scale::new(self.density), } }