diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 08b269e3950..4c58b269ca0 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::{ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey}; -use webrender_traits::{CrossProcessCompositorApi, ImageUpdate, SerializableImageData}; +use webrender_api::{ImageData, ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey}; +use webrender_traits::ImageUpdate; -use crate::canvas_paint_thread::AntialiasMode; +use crate::canvas_paint_thread::{AntialiasMode, WebrenderApi}; 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>, - compositor_api: CrossProcessCompositorApi, + webrender_api: Box, 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, - compositor_api: CrossProcessCompositorApi, + webrender_api: Box, 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![], - compositor_api, + webrender_api, image_key: None, old_image_key: None, very_old_image_key: None, @@ -1279,9 +1279,8 @@ impl<'a> CanvasData<'a> { offset: 0, flags: ImageDescriptorFlags::empty(), }; - let data = SerializableImageData::Raw(IpcSharedMemory::from_bytes( - &self.drawtarget.snapshot_data_owned(), - )); + let data = self.drawtarget.snapshot_data_owned(); + let data = ImageData::Raw(Arc::new(data)); let mut updates = vec![]; @@ -1291,7 +1290,7 @@ impl<'a> CanvasData<'a> { updates.push(ImageUpdate::UpdateImage(image_key, descriptor, data)); }, None => { - let Some(key) = self.compositor_api.generate_image_key() else { + let Some(key) = self.webrender_api.generate_key() else { return; }; updates.push(ImageUpdate::AddImage(key, descriptor, data)); @@ -1306,7 +1305,7 @@ impl<'a> CanvasData<'a> { updates.push(ImageUpdate::DeleteImage(image_key)); } - self.compositor_api.update_images(updates); + self.webrender_api.update_images(updates); let data = CanvasImageData { image_key: self.image_key.unwrap(), @@ -1427,7 +1426,7 @@ impl<'a> Drop for CanvasData<'a> { updates.push(ImageUpdate::DeleteImage(image_key)); } - self.compositor_api.update_images(updates); + self.webrender_api.update_images(updates); } } diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index 7b3500e1290..5fec02a2b7a 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -16,7 +16,8 @@ use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::router::ROUTER; use log::warn; use net_traits::ResourceThreads; -use webrender_traits::CrossProcessCompositorApi; +use webrender_api::ImageKey; +use webrender_traits::{ImageUpdate, WebRenderScriptApi}; use crate::canvas_data::*; @@ -25,26 +26,36 @@ 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, - compositor_api: CrossProcessCompositorApi, + webrender_api: Box, font_context: Arc, } impl<'a> CanvasPaintThread<'a> { fn new( - compositor_api: CrossProcessCompositorApi, + webrender_api: Box, 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), - compositor_api: compositor_api.clone(), + webrender_api, font_context: Arc::new(FontContext::new( system_font_service, - compositor_api, + webrender_script_api, resource_threads, )), } @@ -53,7 +64,7 @@ impl<'a> CanvasPaintThread<'a> { /// Creates a new `CanvasPaintThread` and returns an `IpcSender` to /// communicate with it. pub fn start( - compositor_api: CrossProcessCompositorApi, + webrender_api: Box, system_font_service: Arc, resource_threads: ResourceThreads, ) -> (Sender, IpcSender) { @@ -64,7 +75,7 @@ impl<'a> CanvasPaintThread<'a> { .name("Canvas".to_owned()) .spawn(move || { let mut canvas_paint_thread = CanvasPaintThread::new( - compositor_api, system_font_service, resource_threads); + webrender_api, system_font_service, resource_threads); loop { select! { recv(msg_receiver) -> msg => { @@ -130,7 +141,7 @@ impl<'a> CanvasPaintThread<'a> { let canvas_data = CanvasData::new( size, - self.compositor_api.clone(), + self.webrender_api.clone(), antialias, self.font_context.clone(), ); diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index c258b692c84..db94d658760 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -16,7 +16,8 @@ use base::cross_process_instant::CrossProcessInstant; use base::id::{PipelineId, TopLevelBrowsingContextId, WebViewId}; use base::{Epoch, WebRenderEpochToU16}; use compositing_traits::{ - CompositionPipeline, CompositorMsg, CompositorReceiver, ConstellationMsg, SendableFrameTree, + CompositionPipeline, CompositorMsg, CompositorReceiver, ConstellationMsg, + ForwardedToCompositorMsg, SendableFrameTree, }; use crossbeam_channel::Sender; use embedder_traits::Cursor; @@ -50,7 +51,8 @@ use webrender_api::{ }; use webrender_traits::display_list::{HitTestInfo, ScrollTree}; use webrender_traits::{ - CompositorHitTestResult, CrossProcessCompositorMessage, ImageUpdate, RenderingContext, + CanvasToCompositorMsg, CompositorHitTestResult, FontToCompositorMsg, ImageUpdate, + NetToCompositorMsg, RenderingContext, ScriptToCompositorMsg, SerializedImageUpdate, UntrustedNodeAddress, }; @@ -651,8 +653,29 @@ impl IOCompositor { self.pending_paint_metrics.insert(pipeline_id, epoch); }, - CompositorMsg::CrossProcess(cross_proces_message) => { - self.handle_cross_process_message(cross_proces_message); + 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); }, } @@ -662,9 +685,11 @@ impl IOCompositor { /// Accept messages from content processes that need to be relayed to the WebRender /// instance in the parent process. #[tracing::instrument(skip(self), fields(servo_profiling = true))] - fn handle_cross_process_message(&mut self, msg: CrossProcessCompositorMessage) { + fn handle_webrender_message(&mut self, msg: ForwardedToCompositorMsg) { match msg { - CrossProcessCompositorMessage::SendInitialTransaction(pipeline) => { + ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::SendInitialTransaction( + pipeline, + )) => { let mut txn = Transaction::new(); txn.set_display_list(WebRenderEpoch(0), (pipeline, Default::default())); self.generate_frame(&mut txn, RenderReasons::SCENE); @@ -672,11 +697,11 @@ impl IOCompositor { .send_transaction(self.webrender_document, txn); }, - CrossProcessCompositorMessage::SendScrollNode( + ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::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, @@ -708,11 +733,11 @@ impl IOCompositor { .send_transaction(self.webrender_document, txn); }, - CrossProcessCompositorMessage::SendDisplayList { + ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::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, @@ -768,7 +793,12 @@ impl IOCompositor { .send_transaction(self.webrender_document, transaction); }, - CrossProcessCompositorMessage::HitTest(pipeline, point, flags, sender) => { + ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::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 @@ -785,20 +815,27 @@ impl IOCompositor { let _ = sender.send(result); }, - CrossProcessCompositorMessage::GenerateImageKey(sender) => { + ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::GenerateImageKey(sender)) | + ForwardedToCompositorMsg::Net(NetToCompositorMsg::GenerateImageKey(sender)) => { let _ = sender.send(self.webrender_api.generate_image_key()); }, - CrossProcessCompositorMessage::UpdateImages(updates) => { + ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::UpdateImages(updates)) => { let mut txn = Transaction::new(); for update in updates { match update { - ImageUpdate::AddImage(key, desc, data) => { - txn.add_image(key, desc, data.into(), None) + 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::DeleteImage(key) => txn.delete_image(key), - ImageUpdate::UpdateImage(key, desc, data) => { - txn.update_image(key, desc, data.into(), &DirtyRect::All) + 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), + } }, } } @@ -806,27 +843,27 @@ impl IOCompositor { .send_transaction(self.webrender_document, txn); }, - CrossProcessCompositorMessage::AddFont(font_key, data, index) => { + ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::AddFont( + font_key, + data, + index, + )) => { self.add_font(font_key, index, data); }, - 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( + ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::AddFontInstance( font_instance_key, font_key, size, flags, - ) => { + )) => { self.add_font_instance(font_instance_key, font_key, size, flags); }, - CrossProcessCompositorMessage::RemoveFonts(keys, instance_keys) => { + ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::RemoveFonts( + keys, + instance_keys, + )) => { let mut transaction = Transaction::new(); for instance in instance_keys.into_iter() { @@ -840,18 +877,18 @@ impl IOCompositor { .send_transaction(self.webrender_document, transaction); }, - CrossProcessCompositorMessage::AddImage(key, desc, data) => { + ForwardedToCompositorMsg::Net(NetToCompositorMsg::AddImage(key, desc, data)) => { let mut txn = Transaction::new(); - txn.add_image(key, desc, data.into(), None); + txn.add_image(key, desc, data, None); self.webrender_api .send_transaction(self.webrender_document, txn); }, - CrossProcessCompositorMessage::GenerateFontKeys( + ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::GenerateKeys( 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(); @@ -860,23 +897,53 @@ impl IOCompositor { .collect(); let _ = result_sender.send((font_keys, font_instance_keys)); }, - CrossProcessCompositorMessage::GetClientWindowRect(req) => { - if let Err(e) = req.send(self.embedder_coordinates.window_rect) { - warn!("Sending response to get client window failed ({:?}).", e); - } + + ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFontInstance( + font_instance_key, + font_key, + size, + flags, + )) => { + self.add_font_instance(font_instance_key, font_key, size, flags); }, - CrossProcessCompositorMessage::GetScreenSize(req) => { - if let Err(e) = req.send(self.embedder_coordinates.screen_size) { - warn!("Sending response to get screen size failed ({:?}).", e); - } + + ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFont( + font_key, + index, + data, + )) => { + self.add_font(font_key, index, data); }, - 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 - ); + + 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), + } } + self.webrender_api + .send_transaction(self.webrender_document, txn); }, } } @@ -901,40 +968,23 @@ impl IOCompositor { self.remove_pipeline_root_layer(pipeline_id); let _ = sender.send(()); }, - CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GenerateImageKey( - sender, + CompositorMsg::Forwarded(ForwardedToCompositorMsg::Canvas( + CanvasToCompositorMsg::GenerateKey(sender), )) => { let _ = sender.send(self.webrender_api.generate_image_key()); }, - 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) { + CompositorMsg::GetClientWindow(sender) => { + if let Err(e) = sender.send(self.embedder_coordinates.window) { warn!("Sending response to get client window failed ({:?}).", e); } }, - CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GetScreenSize(req)) => { - if let Err(e) = req.send(self.embedder_coordinates.screen_size) { + CompositorMsg::GetScreenSize(sender) => { + if let Err(e) = sender.send(self.embedder_coordinates.screen) { warn!("Sending response to get screen size failed ({:?}).", e); } }, - CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GetAvailableScreenSize( - req, - )) => { - if let Err(e) = req.send(self.embedder_coordinates.available_screen_size) { + CompositorMsg::GetScreenAvailSize(sender) => { + if let Err(e) = sender.send(self.embedder_coordinates.screen_avail) { warn!( "Sending response to get screen avail size failed ({:?}).", e diff --git a/components/compositing/tracing.rs b/components/compositing/tracing.rs index 0b4e4ceaa35..7a53d6f9b84 100644 --- a/components/compositing/tracing.rs +++ b/components/compositing/tracing.rs @@ -48,7 +48,10 @@ mod from_constellation { Self::LoadComplete(..) => target!("LoadComplete"), Self::WebDriverMouseButtonEvent(..) => target!("WebDriverMouseButtonEvent"), Self::WebDriverMouseMoveEvent(..) => target!("WebDriverMouseMoveEvent"), - Self::CrossProcess(_) => target!("CrossProcess"), + Self::GetClientWindow(..) => target!("GetClientWindow"), + Self::GetScreenSize(..) => target!("GetScreenSize"), + Self::GetScreenAvailSize(..) => target!("GetScreenAvailSize"), + Self::Forwarded(..) => target!("Forwarded"), } } } diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index 86771d115ac..d1cf9866d01 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_size: DeviceIntSize, + pub screen: DeviceIntSize, /// Size of the available screen space (screen without toolbars and docks). - pub available_screen_size: DeviceIntSize, - /// Position and size of the native window. - pub window_rect: DeviceIntRect, + pub screen_avail: DeviceIntSize, + /// Size of the native window. + pub window: (DeviceIntSize, DeviceIntPoint), /// 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_size: screen, - available_screen_size: screen, - window_rect: DeviceIntRect::from_origin_and_size(pos, viewport), + screen, + screen_avail: screen, + window: (viewport, pos), framebuffer: viewport, viewport: DeviceIntRect::from_origin_and_size(pos, viewport), }; diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 74452717cfa..4765f651425 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -108,7 +108,8 @@ use canvas_traits::canvas::{CanvasId, CanvasMsg}; use canvas_traits::webgl::WebGLThreads; use canvas_traits::ConstellationCanvasMsg; use compositing_traits::{ - CompositorMsg, CompositorProxy, ConstellationMsg as FromCompositorMsg, SendableFrameTree, + CompositorMsg, CompositorProxy, ConstellationMsg as FromCompositorMsg, + ForwardedToCompositorMsg, SendableFrameTree, }; use crossbeam_channel::{after, never, select, unbounded, Receiver, Sender}; use devtools_traits::{ @@ -156,7 +157,7 @@ use webgpu::swapchain::WGPUImageMap; use webgpu::{self, WebGPU, WebGPURequest, WebGPUResponse}; use webrender::{RenderApi, RenderApiSender}; use webrender_api::DocumentId; -use webrender_traits::WebrenderExternalImageRegistry; +use webrender_traits::{WebRenderNetApi, WebRenderScriptApi, WebrenderExternalImageRegistry}; use crate::browsingcontext::{ AllBrowsingContextsIterator, BrowsingContext, FullyActiveBrowsingContextsIterator, @@ -391,6 +392,14 @@ 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, @@ -497,7 +506,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 in-process. + /// A channel through which messages can be sent to the compositor. pub compositor_proxy: CompositorProxy, /// A channel to the developer tools, if applicable. @@ -696,6 +705,35 @@ 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, @@ -750,6 +788,8 @@ 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(), @@ -1013,6 +1053,8 @@ 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 @@ -1709,6 +1751,18 @@ 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 3f5887fa6ed..b646e581200 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -43,7 +43,6 @@ 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}; @@ -184,6 +183,12 @@ 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, @@ -288,11 +293,9 @@ 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, @@ -495,7 +498,8 @@ pub struct UnprivilegedPipelineContent { opts: Opts, prefs: HashMap, pipeline_namespace_id: PipelineNamespaceId, - cross_process_compositor_api: CrossProcessCompositorApi, + webrender_api_sender: webrender_traits::WebRenderScriptApi, + webrender_image_api_sender: webrender_traits::WebRenderNetApi, webrender_document: DocumentId, webgl_chan: Option, webxr_registry: webxr_api::Registry, @@ -514,9 +518,7 @@ impl UnprivilegedPipelineContent { // Idempotent in single-process mode. PipelineNamespace::set_installer_sender(self.namespace_request_sender); - let image_cache = Arc::new(ImageCacheImpl::new( - self.cross_process_compositor_api.clone(), - )); + let image_cache = Arc::new(ImageCacheImpl::new(self.webrender_image_api_sender.clone())); let (content_process_shutdown_chan, content_process_shutdown_port) = unbounded(); STF::create( InitialScriptState { @@ -543,7 +545,7 @@ impl UnprivilegedPipelineContent { webgl_chan: self.webgl_chan, webxr_registry: self.webxr_registry, webrender_document: self.webrender_document, - compositor_api: self.cross_process_compositor_api.clone(), + webrender_api_sender: self.webrender_api_sender.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 c3e87104457..46335012d03 100644 --- a/components/constellation/tracing.rs +++ b/components/constellation/tracing.rs @@ -181,6 +181,9 @@ 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 8c7aafbb984..093c5775169 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::CrossProcessCompositorApi; +use webrender_traits::{ScriptToCompositorMsg, WebRenderScriptApi}; 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. - compositor_api: ReentrantMutex, + webrender_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, - compositor_api: CrossProcessCompositorApi, + webrender_api: WebRenderScriptApi, resource_threads: ResourceThreads, ) -> Self { #[allow(clippy::default_constructed_unit_structs)] Self { system_font_service_proxy, resource_threads: ReentrantMutex::new(resource_threads.core_thread), - compositor_api: ReentrantMutex::new(compositor_api), + webrender_api: ReentrantMutex::new(webrender_api), fonts: Default::default(), resolved_font_groups: Default::default(), web_fonts: Arc::new(RwLock::default()), @@ -323,11 +323,15 @@ impl FontContext { .entry(identifier.clone()) .or_insert_with(|| { let font_key = self.system_font_service_proxy.generate_font_key(); - self.compositor_api.lock().add_font( - font_key, - font_data.as_ipc_shared_memory(), - identifier.index(), - ); + let _ = self + .webrender_api + .lock() + .sender() + .send(ScriptToCompositorMsg::AddFont( + font_key, + font_data.as_ipc_shared_memory(), + identifier.index(), + )); font_key }); @@ -337,11 +341,13 @@ impl FontContext { .entry((font_key, pt_size)) .or_insert_with(|| { let font_instance_key = self.system_font_service_proxy.generate_font_instance_key(); - self.compositor_api.lock().add_font_instance( - font_instance_key, - font_key, - pt_size.to_f32_px(), - flags, + let _ = self.webrender_api.lock().sender().send( + ScriptToCompositorMsg::AddFontInstance( + 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 bacaf88fb92..36130c5ed8b 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::{span, Level}; use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey}; -use webrender_traits::CrossProcessCompositorApi; +use webrender_traits::WebRenderFontApi; use crate::font::FontDescriptor; use crate::font_store::FontStore; @@ -97,7 +97,7 @@ struct ResolvedGenericFontFamilies { pub struct SystemFontService { port: IpcReceiver, local_families: FontStore, - compositor_api: CrossProcessCompositorApi, + webrender_api: Box, webrender_fonts: HashMap, font_instances: HashMap<(FontKey, Au), FontInstanceKey>, generic_fonts: ResolvedGenericFontFamilies, @@ -129,7 +129,7 @@ impl SystemFontServiceProxySender { } impl SystemFontService { - pub fn spawn(compositor_api: CrossProcessCompositorApi) -> SystemFontServiceProxySender { + pub fn spawn(webrender_api: Box) -> 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(), - compositor_api, + webrender_api, webrender_fonts: HashMap::new(), font_instances: HashMap::new(), generic_fonts: Default::default(), @@ -198,7 +198,7 @@ impl SystemFontService { const FREE_FONT_KEYS_BATCH_SIZE: usize = 20; const FREE_FONT_INSTANCE_KEYS_BATCH_SIZE: usize = 20; - let (mut new_font_keys, mut new_font_instance_keys) = self.compositor_api.fetch_font_keys( + let (mut new_font_keys, mut new_font_instance_keys) = self.webrender_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(), ); @@ -281,7 +281,7 @@ impl SystemFontService { ) -> FontInstanceKey { self.fetch_new_keys(); - let compositor_api = &self.compositor_api; + let webrender_font_api = &self.webrender_api; let webrender_fonts = &mut self.webrender_fonts; let font_data = self.local_families.get_or_initialize_font_data(&identifier); @@ -296,12 +296,12 @@ impl SystemFontService { // this for those platforms. #[cfg(target_os = "macos")] if let FontIdentifier::Local(local_font_identifier) = identifier { - compositor_api + webrender_font_api .add_system_font(font_key, local_font_identifier.native_font_handle()); return font_key; } - compositor_api.add_font( + webrender_font_api.add_font( font_key, font_data.as_ipc_shared_memory(), identifier.index(), @@ -314,7 +314,7 @@ impl SystemFontService { .entry((font_key, pt_size)) .or_insert_with(|| { let font_instance_key = self.free_font_instance_keys.pop().unwrap(); - compositor_api.add_font_instance( + webrender_font_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 42e7bbf8c74..036bcde7aec 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::CrossProcessCompositorApi; +use webrender_traits::WebRenderScriptApi; 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_compositor_api = CrossProcessCompositorApi::dummy(); + let mock_webrender_api = WebRenderScriptApi::dummy(); let proxy_clone = Arc::new(system_font_service_proxy.to_sender().to_proxy()); Self { - context: FontContext::new(proxy_clone, mock_compositor_api, mock_resource_threads), + context: FontContext::new(proxy_clone, mock_webrender_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 0934685473a..75c1c331afc 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::CrossProcessCompositorApi; +use webrender_traits::WebRenderScriptApi; /// Information needed by layout. pub struct LayoutThread { @@ -170,8 +170,8 @@ pub struct LayoutThread { /// The executors for paint worklets. registered_painters: RegisteredPaintersImpl, - /// Cross-process access to the compositor API. - compositor_api: CrossProcessCompositorApi, + /// Webrender interface. + webrender_api: WebRenderScriptApi, /// 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.compositor_api, + config.webrender_api_sender, 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.compositor_api + self.webrender_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 - .compositor_api + .webrender_api .hit_test(Some(self.id.into()), client_point, flags); results.iter().map(|result| result.node.into()).collect() @@ -562,12 +562,12 @@ impl LayoutThread { resource_threads: ResourceThreads, system_font_service: Arc, time_profiler_chan: profile_time::ProfilerChan, - compositor_api: CrossProcessCompositorApi, + webrender_api: WebRenderScriptApi, paint_time_metrics: PaintTimeMetrics, window_size: WindowSizeData, ) -> LayoutThread { // Let webrender know about this pipeline by sending an empty display list. - compositor_api.send_initial_transaction(id.into()); + webrender_api.send_initial_transaction(id.into()); let mut font = Font::initial_values(); let default_font_size = pref!(fonts.default_size); @@ -579,7 +579,7 @@ impl LayoutThread { let font_context = Arc::new(FontContext::new( system_font_service, - compositor_api.clone(), + webrender_api.clone(), resource_threads, )); let device = Device::new( @@ -611,7 +611,7 @@ impl LayoutThread { Au::from_f32_px(window_size.initial_viewport.width), Au::from_f32_px(window_size.initial_viewport.height), ), - compositor_api, + webrender_api, stylist: Stylist::new(device, QuirksMode::NoQuirks), display_list: Default::default(), indexable_text: Default::default(), @@ -936,13 +936,13 @@ impl LayoutThread { self.paint_time_metrics .maybe_observe_paint_time(self, epoch, is_contentful.0); - self.compositor_api + self.webrender_api .send_display_list(compositor_info, builder.end().1); let (keys, instance_keys) = self .font_context .collect_unused_webrender_resources(false /* all */); - self.compositor_api + self.webrender_api .remove_unused_font_resources(keys, instance_keys) }, ); @@ -1185,7 +1185,7 @@ impl LayoutThread { .insert(state.scroll_id, state.scroll_offset); let point = Point2D::new(-state.scroll_offset.x, -state.scroll_offset.y); - self.compositor_api.send_scroll_node( + self.webrender_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 d3e9320ad0b..070ad845fdb 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -92,7 +92,7 @@ use tracing::{span, Level}; use url::Url; use webrender_api::units::LayoutPixel; use webrender_api::{units, ExternalScrollId, HitTestFlags}; -use webrender_traits::CrossProcessCompositorApi; +use webrender_traits::WebRenderScriptApi; /// Information needed by layout. pub struct LayoutThread { @@ -151,8 +151,8 @@ pub struct LayoutThread { /// The executors for paint worklets. registered_painters: RegisteredPaintersImpl, - /// Cross-process access to the Compositor API. - compositor_api: CrossProcessCompositorApi, + /// Webrender interface. + webrender_api: WebRenderScriptApi, /// 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.compositor_api, + config.webrender_api_sender, 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.compositor_api + self.webrender_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 - .compositor_api + .webrender_api .hit_test(Some(self.id.into()), client_point, flags); results.iter().map(|result| result.node.into()).collect() @@ -504,12 +504,12 @@ impl LayoutThread { resource_threads: ResourceThreads, system_font_service: Arc, time_profiler_chan: profile_time::ProfilerChan, - compositor_api: CrossProcessCompositorApi, + webrender_api_sender: WebRenderScriptApi, paint_time_metrics: PaintTimeMetrics, window_size: WindowSizeData, ) -> LayoutThread { // Let webrender know about this pipeline by sending an empty display list. - compositor_api.send_initial_transaction(id.into()); + webrender_api_sender.send_initial_transaction(id.into()); let mut font = Font::initial_values(); let default_font_size = pref!(fonts.default_size); @@ -523,7 +523,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, - compositor_api.clone(), + webrender_api_sender.clone(), resource_threads, )); let device = Device::new( @@ -555,7 +555,7 @@ impl LayoutThread { Au::from_f32_px(window_size.initial_viewport.width), Au::from_f32_px(window_size.initial_viewport.height), ), - compositor_api, + webrender_api: webrender_api_sender, scroll_offsets: Default::default(), stylist: Stylist::new(device, QuirksMode::NoQuirks), webrender_image_cache: Default::default(), @@ -864,7 +864,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.compositor_api.send_scroll_node( + self.webrender_api.send_scroll_node( self.id.into(), units::LayoutPoint::from_untyped(point), state.scroll_id, @@ -954,13 +954,13 @@ impl LayoutThread { .maybe_observe_paint_time(self, epoch, is_contentful); if reflow_goal.needs_display() { - self.compositor_api + self.webrender_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.compositor_api + self.webrender_api .remove_unused_font_resources(keys, instance_keys) } diff --git a/components/net/image_cache.rs b/components/net/image_cache.rs index dfaa6e4e07e..2f0968f3aa4 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, IpcSharedMemory}; +use ipc_channel::ipc::IpcSender; 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::{ImageDescriptor, ImageDescriptorFlags, ImageFormat}; -use webrender_traits::{CrossProcessCompositorApi, SerializableImageData}; +use webrender_api::{ImageData, ImageDescriptor, ImageDescriptorFlags, ImageFormat}; +use webrender_traits::WebRenderNetApi; 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(compositor_api: &CrossProcessCompositorApi, data: &[u8]) -> Arc { +fn get_placeholder_image(webrender_api: &WebRenderNetApi, data: &[u8]) -> Arc { let mut image = load_from_memory(data, CorsStatus::Unsafe).unwrap(); - set_webrender_image_key(compositor_api, &mut image); + set_webrender_image_key(webrender_api, &mut image); Arc::new(image) } -fn set_webrender_image_key(compositor_api: &CrossProcessCompositorApi, image: &mut Image) { +fn set_webrender_image_key(webrender_api: &WebRenderNetApi, image: &mut Image) { if image.id.is_some() { return; } @@ -82,11 +82,10 @@ fn set_webrender_image_key(compositor_api: &CrossProcessCompositorApi, image: &m offset: 0, flags, }; - 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); - } + 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); } // ====================================================================== @@ -329,8 +328,8 @@ struct ImageCacheStore { // The URL used for the placeholder image placeholder_url: ServoUrl, - // Cross-process compositor API instance. - compositor_api: CrossProcessCompositorApi, + // Webrender API instance. + webrender_api: WebRenderNetApi, } impl ImageCacheStore { @@ -344,7 +343,7 @@ impl ImageCacheStore { match load_result { LoadResult::Loaded(ref mut image) => { - set_webrender_image_key(&self.compositor_api, image) + set_webrender_image_key(&self.webrender_api, image) }, LoadResult::PlaceholderLoaded(..) | LoadResult::None => {}, } @@ -417,7 +416,7 @@ pub struct ImageCacheImpl { } impl ImageCache for ImageCacheImpl { - fn new(compositor_api: CrossProcessCompositorApi) -> ImageCacheImpl { + fn new(webrender_api: WebRenderNetApi) -> ImageCacheImpl { debug!("New image cache"); let rippy_data = resources::read_bytes(Resource::RippyPNG); @@ -432,9 +431,9 @@ impl ImageCache for ImageCacheImpl { store: Arc::new(Mutex::new(ImageCacheStore { pending_loads: AllPendingLoads::new(), completed_loads: HashMap::new(), - placeholder_image: get_placeholder_image(&compositor_api, &rippy_data), + placeholder_image: get_placeholder_image(&webrender_api, &rippy_data), placeholder_url: ServoUrl::parse("chrome://resources/rippy.png").unwrap(), - compositor_api, + webrender_api, })), thread_pool: CoreResourceThreadPool::new(thread_count), } diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 04d388cf9a3..3e57b4e2645 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::{self, IpcSharedMemory}; +use ipc_channel::ipc; 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, ImageDescriptor, - ImageDescriptorFlags, ImageFormat, ImageKey, + ExternalImageData, ExternalImageId, ExternalImageType, ImageBufferKind, ImageData, + ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey, }; -use webrender_traits::{CrossProcessCompositorApi, ImageUpdate, SerializableImageData}; +use webrender_traits::{ImageUpdate, WebRenderScriptApi}; use crate::document_loader::{LoadBlocker, LoadType}; use crate::dom::attr::Attr; @@ -156,7 +156,7 @@ impl FrameHolder { pub struct MediaFrameRenderer { player_id: Option, - compositor_api: CrossProcessCompositorApi, + api: WebRenderScriptApi, current_frame: Option<(ImageKey, i32, i32)>, old_frame: Option, very_old_frame: Option, @@ -165,10 +165,10 @@ pub struct MediaFrameRenderer { } impl MediaFrameRenderer { - fn new(compositor_api: CrossProcessCompositorApi) -> Self { + fn new(render_api_sender: WebRenderScriptApi) -> Self { Self { player_id: None, - compositor_api, + api: render_api_sender, current_frame: None, old_frame: None, very_old_frame: None, @@ -213,7 +213,7 @@ impl VideoFrameRenderer for MediaFrameRenderer { updates.push(ImageUpdate::UpdateImage( *image_key, descriptor, - SerializableImageData::Raw(IpcSharedMemory::from_bytes(&frame.get_data())), + ImageData::Raw(frame.get_data()), )); } @@ -228,7 +228,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.compositor_api.generate_image_key() else { + let Some(new_image_key) = self.api.generate_image_key() else { return; }; @@ -244,13 +244,13 @@ impl VideoFrameRenderer for MediaFrameRenderer { ImageBufferKind::Texture2D }; - SerializableImageData::External(ExternalImageData { + ImageData::External(ExternalImageData { id: ExternalImageId(self.player_id.unwrap()), channel_index: 0, image_type: ExternalImageType::TextureHandle(texture_target), }) } else { - SerializableImageData::Raw(IpcSharedMemory::from_bytes(&frame.get_data())) + ImageData::Raw(frame.get_data()) }; self.current_frame_holder @@ -260,7 +260,7 @@ impl VideoFrameRenderer for MediaFrameRenderer { updates.push(ImageUpdate::AddImage(new_image_key, descriptor, image_data)); }, None => { - let Some(image_key) = self.compositor_api.generate_image_key() else { + let Some(image_key) = self.api.generate_image_key() else { return; }; self.current_frame = Some((image_key, frame.get_width(), frame.get_height())); @@ -272,13 +272,13 @@ impl VideoFrameRenderer for MediaFrameRenderer { ImageBufferKind::Texture2D }; - SerializableImageData::External(ExternalImageData { + ImageData::External(ExternalImageData { id: ExternalImageId(self.player_id.unwrap()), channel_index: 0, image_type: ExternalImageType::TextureHandle(texture_target), }) } else { - SerializableImageData::Raw(IpcSharedMemory::from_bytes(&frame.get_data())) + ImageData::Raw(frame.get_data()) }; self.current_frame_holder = Some(FrameHolder::new(frame)); @@ -286,7 +286,7 @@ impl VideoFrameRenderer for MediaFrameRenderer { updates.push(ImageUpdate::AddImage(image_key, descriptor, image_data)); }, } - self.compositor_api.update_images(updates); + self.api.update_images(updates); } } @@ -445,7 +445,7 @@ impl HTMLMediaElement { in_flight_play_promises_queue: Default::default(), player: Default::default(), video_renderer: Arc::new(Mutex::new(MediaFrameRenderer::new( - document.window().compositor_api().clone(), + document.window().get_webrender_api_sender(), ))), audio_renderer: Default::default(), show_poster: Cell::new(true), diff --git a/components/script/dom/screen.rs b/components/script/dom/screen.rs index d7ce8b6b4be..fcbd84fd061 100644 --- a/components/script/dom/screen.rs +++ b/components/script/dom/screen.rs @@ -5,14 +5,16 @@ 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] @@ -37,9 +39,9 @@ impl Screen { let (send, recv) = ipc::channel::(self.global().time_profiler_chan().clone()).unwrap(); self.window - .compositor_api() - .sender() - .send(CrossProcessCompositorMessage::GetScreenSize(send)) + .upcast::() + .script_to_constellation_chan() + .send(ScriptMsg::GetScreenSize(send)) .unwrap(); let dpr = self.window.device_pixel_ratio(); let screen = recv.recv().unwrap_or(Size2D::zero()); @@ -50,9 +52,9 @@ impl Screen { let (send, recv) = ipc::channel::(self.global().time_profiler_chan().clone()).unwrap(); self.window - .compositor_api() - .sender() - .send(CrossProcessCompositorMessage::GetAvailableScreenSize(send)) + .upcast::() + .script_to_constellation_chan() + .send(ScriptMsg::GetScreenAvailSize(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 73a63e435db..1622eecc896 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::{DeviceIntRect, LayoutPixel}; +use webrender_api::units::{DeviceIntPoint, DeviceIntSize, LayoutPixel}; use webrender_api::{DocumentId, ExternalScrollId}; -use webrender_traits::CrossProcessCompositorApi; +use webrender_traits::WebRenderScriptApi; 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, - /// Cross-process access to the compositor. + /// Webrender API Sender #[ignore_malloc_size_of = "Wraps an IpcSender"] #[no_trace] - compositor_api: CrossProcessCompositorApi, + webrender_api_sender: WebRenderScriptApi, /// 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 compositor_api(&self) -> &CrossProcessCompositorApi { - &self.compositor_api + pub fn get_webrender_api_sender(&self) -> WebRenderScriptApi { + self.webrender_api_sender.clone() } pub fn get_userscripts_path(&self) -> Option { @@ -1773,16 +1773,14 @@ impl Window { fn client_window(&self) -> (Size2D, Point2D) { let timer_profile_chan = self.global().time_profiler_chan().clone(); - 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 (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 dpr = self.device_pixel_ratio(); ( - (rect.size().to_f32() / dpr).to_u32(), - (rect.min.to_f32() / dpr).to_i32(), + (size.to_f32() / dpr).to_u32(), + (point.to_f32() / dpr).to_i32(), ) } @@ -2550,7 +2548,7 @@ impl Window { webxr_registry: webxr_api::Registry, microtask_queue: Rc, webrender_document: DocumentId, - compositor_api: CrossProcessCompositorApi, + webrender_api_sender: WebRenderScriptApi, relayout_event: bool, prepare_for_screenshot: bool, unminify_js: bool, @@ -2635,7 +2633,7 @@ impl Window { paint_worklet: Default::default(), webrender_document, exists_mut_observer: Cell::new(false), - compositor_api, + webrender_api_sender, 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 1e45f4e54d9..6da64d32786 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::CrossProcessCompositorApi; +use webrender_traits::WebRenderScriptApi; use crate::document_loader::DocumentLoader; use crate::dom::bindings::cell::DomRefCell; @@ -669,9 +669,9 @@ pub struct ScriptThread { #[no_trace] webrender_document: DocumentId, - /// Cross-process access to the compositor's API. + /// Webrender API sender. #[no_trace] - compositor_api: CrossProcessCompositorApi, + webrender_api_sender: WebRenderScriptApi, /// 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, - compositor_api: state.compositor_api, + webrender_api_sender: state.webrender_api_sender, 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(), - compositor_api: self.compositor_api.clone(), + webrender_api_sender: self.webrender_api_sender.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.compositor_api.clone(), + self.webrender_api_sender.clone(), self.relayout_event, self.prepare_for_screenshot, self.unminify_js, diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 19956ed5055..99947da8cad 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -28,13 +28,15 @@ pub use base::id::TopLevelBrowsingContextId; use base::id::{PipelineNamespace, PipelineNamespaceId}; use bluetooth::BluetoothThreadFactory; use bluetooth_traits::BluetoothRequest; -use canvas::canvas_paint_thread::CanvasPaintThread; +use canvas::canvas_paint_thread::{self, 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}; +use compositing_traits::{ + CompositorMsg, CompositorProxy, CompositorReceiver, ConstellationMsg, ForwardedToCompositorMsg, +}; #[cfg(all( not(target_os = "windows"), not(target_os = "ios"), @@ -64,8 +66,7 @@ use fonts::SystemFontService; use gaol::sandbox::{ChildSandbox, ChildSandboxMethods}; pub use gleam::gl; use gleam::gl::RENDERER; -use ipc_channel::ipc::{self, IpcSender}; -use ipc_channel::router::ROUTER; +use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory}; #[cfg(feature = "layout_2013")] pub use layout_thread_2013; use log::{error, trace, warn, Log, Metadata, Record}; @@ -90,10 +91,13 @@ 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, FramePublishId}; +use webrender_api::{ + ColorF, DocumentId, FontInstanceFlags, FontInstanceKey, FontKey, FramePublishId, ImageKey, + NativeFontHandle, +}; use webrender_traits::{ - CrossProcessCompositorApi, RenderingContext, WebrenderExternalImageHandlers, - WebrenderExternalImageRegistry, WebrenderImageHandlerType, + CanvasToCompositorMsg, FontToCompositorMsg, ImageUpdate, RenderingContext, WebRenderFontApi, + WebrenderExternalImageHandlers, WebrenderExternalImageRegistry, WebrenderImageHandlerType, }; pub use { background_hang_monitor, base, bluetooth, bluetooth_traits, canvas, canvas_traits, compositing, @@ -975,24 +979,9 @@ 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 }, @@ -1054,11 +1043,14 @@ fn create_constellation( ); let system_font_service = Arc::new( - SystemFontService::spawn(compositor_proxy.cross_process_compositor_api.clone()).to_proxy(), + SystemFontService::spawn(Box::new(WebRenderFontApiCompositorProxy( + compositor_proxy.clone(), + ))) + .to_proxy(), ); let (canvas_create_sender, canvas_ipc_sender) = CanvasPaintThread::start( - compositor_proxy.cross_process_compositor_api.clone(), + Box::new(CanvasWebrenderApi(compositor_proxy.clone())), system_font_service.clone(), public_resource_threads.clone(), ); @@ -1102,6 +1094,82 @@ 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 f4afdc211b2..e3c0c079037 100644 --- a/components/shared/compositing/lib.rs +++ b/components/shared/compositing/lib.rs @@ -21,18 +21,15 @@ use script_traits::{ AnimationState, ConstellationControlMsg, EventResult, MouseButton, MouseEventType, }; use style_traits::CSSPixel; -use webrender_api::units::DeviceRect; +use webrender_api::units::{DeviceIntPoint, DeviceIntSize, DeviceRect}; use webrender_api::DocumentId; -use webrender_traits::{CrossProcessCompositorApi, CrossProcessCompositorMessage}; +use webrender_traits::{ + CanvasToCompositorMsg, FontToCompositorMsg, NetToCompositorMsg, ScriptToCompositorMsg, +}; /// 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, } @@ -45,6 +42,15 @@ 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, @@ -108,9 +114,16 @@ 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. - CrossProcess(CrossProcessCompositorMessage), + Forwarded(ForwardedToCompositorMsg), } pub struct SendableFrameTree { @@ -126,6 +139,27 @@ 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 { @@ -149,7 +183,10 @@ impl Debug for CompositorMsg { CompositorMsg::LoadComplete(..) => write!(f, "LoadComplete"), CompositorMsg::WebDriverMouseButtonEvent(..) => write!(f, "WebDriverMouseButtonEvent"), CompositorMsg::WebDriverMouseMoveEvent(..) => write!(f, "WebDriverMouseMoveEvent"), - CompositorMsg::CrossProcess(..) => write!(f, "CrossProcess"), + CompositorMsg::GetClientWindow(..) => write!(f, "GetClientWindow"), + CompositorMsg::GetScreenSize(..) => write!(f, "GetScreenSize"), + CompositorMsg::GetScreenAvailSize(..) => write!(f, "GetScreenAvailSize"), + CompositorMsg::Forwarded(..) => write!(f, "Webrender"), } } } diff --git a/components/shared/net/image_cache.rs b/components/shared/net/image_cache.rs index c587eab13b3..317fd1b66ef 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::CrossProcessCompositorApi; +use webrender_traits::WebRenderNetApi; use crate::request::CorsSettings; use crate::FetchResponseMsg; @@ -99,7 +99,7 @@ pub enum ImageCacheResult { } pub trait ImageCache: Sync + Send { - fn new(compositor_api: CrossProcessCompositorApi) -> Self + fn new(webrender_api: WebRenderNetApi) -> Self where Self: Sized; diff --git a/components/shared/script/lib.rs b/components/shared/script/lib.rs index c3bb72156b4..1ab9e518731 100644 --- a/components/shared/script/lib.rs +++ b/components/shared/script/lib.rs @@ -58,9 +58,7 @@ use style_traits::{CSSPixel, SpeculativePainter}; use webgpu::WebGPUMsg; use webrender_api::units::{DeviceIntSize, DevicePixel, LayoutPixel}; use webrender_api::{DocumentId, ExternalScrollId, ImageKey}; -use webrender_traits::{ - CrossProcessCompositorApi, UntrustedNodeAddress as WebRenderUntrustedNodeAddress, -}; +use webrender_traits::{UntrustedNodeAddress as WebRenderUntrustedNodeAddress, WebRenderScriptApi}; pub use crate::script_msg::{ DOMMessage, EventResult, HistoryEntryReplacement, IFrameSizeMsg, Job, JobError, JobResult, @@ -661,8 +659,8 @@ pub struct InitialScriptState { pub webxr_registry: webxr_api::Registry, /// The Webrender document ID associated with this thread. pub webrender_document: DocumentId, - /// Access to the compositor across a process boundary. - pub compositor_api: CrossProcessCompositorApi, + /// FIXME(victor): The Webrender API sender in this constellation's pipeline + pub webrender_api_sender: WebRenderScriptApi, /// 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 5689395ef32..ee8e8da1386 100644 --- a/components/shared/script/script_msg.rs +++ b/components/shared/script/script_msg.rs @@ -24,6 +24,7 @@ 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, @@ -244,6 +245,12 @@ 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), @@ -311,6 +318,9 @@ 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 228fd03556e..1ad180411d3 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::CrossProcessCompositorApi; +use webrender_traits::WebRenderScriptApi; 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 compositor_api: CrossProcessCompositorApi, + pub webrender_api_sender: WebRenderScriptApi, pub paint_time_metrics: PaintTimeMetrics, pub window_size: WindowSizeData, } diff --git a/components/shared/webrender/lib.rs b/components/shared/webrender/lib.rs index 94949b81e9b..58580175e7d 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::{DeviceIntRect, DeviceIntSize, DevicePoint, LayoutPoint, TexelRect}; +use webrender_api::units::{DevicePoint, LayoutPoint, TexelRect}; use webrender_api::{ BuiltDisplayList, BuiltDisplayListDescriptor, ExternalImage, ExternalImageData, ExternalImageHandler, ExternalImageId, ExternalImageSource, ExternalScrollId, @@ -29,261 +29,6 @@ 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: CompositorDisplayListInfo, - /// 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, - 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. @@ -438,34 +183,304 @@ 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: CompositorDisplayListInfo, + /// 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, + 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, SerializableImageData), + AddImage(ImageKey, ImageDescriptor, ImageData), /// Delete a previously registered image registration. DeleteImage(ImageKey), /// Update an existing image registration. - UpdateImage(ImageKey, ImageDescriptor, SerializableImageData), + 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), } #[derive(Debug, Deserialize, Serialize)] /// Serialized `ImageData`. It contains IPC byte channel receiver to prevent from loading bytes too /// slow. -pub enum SerializableImageData { +pub enum SerializedImageData { /// A simple series of bytes, provided by the embedding and owned by WebRender. /// The format is stored out-of-band, currently in ImageDescriptor. - Raw(IpcSharedMemory), + Raw(ipc::IpcBytesReceiver), /// 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 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), +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)), } } } diff --git a/ports/servoshell/desktop/headed_window.rs b/ports/servoshell/desktop/headed_window.rs index a58ef788fcd..911e60d9caf 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_rect: DeviceIntRect::from_origin_and_size(window_origin, window_size), - screen_size: screen, + window: (window_size, window_origin), + screen, // FIXME: Winit doesn't have API for available size. Fallback to screen size - available_screen_size: screen, + screen_avail: screen, hidpi_factor: self.hidpi_factor(), } } diff --git a/ports/servoshell/desktop/headless_window.rs b/ports/servoshell/desktop/headless_window.rs index be058b6598b..421332d9b50 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_rect: DeviceIntRect::from_origin_and_size(Point2D::zero(), size), - screen_size: size, - available_screen_size: size, + window: (size, Point2D::zero()), + screen: size, + screen_avail: size, hidpi_factor: dpr, } } diff --git a/ports/servoshell/egl/servo_glue.rs b/ports/servoshell/egl/servo_glue.rs index cc4f30667fd..b5739f2ba50 100644 --- a/ports/servoshell/egl/servo_glue.rs +++ b/ports/servoshell/egl/servo_glue.rs @@ -25,7 +25,6 @@ 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}; @@ -694,9 +693,9 @@ impl WindowMethods for ServoWindowCallbacks { EmbedderCoordinates { viewport: coords.viewport.to_box2d(), framebuffer: coords.framebuffer, - window_rect: DeviceIntRect::from_origin_and_size(Point2D::zero(), coords.viewport.size), - screen_size: coords.viewport.size, - available_screen_size: coords.viewport.size, + window: (coords.viewport.size, Point2D::new(0, 0)), + screen: coords.viewport.size, + screen_avail: coords.viewport.size, hidpi_factor: Scale::new(self.density), } }