mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
compositor: Unify the cross process and in-process API (#36443)
Because there used to be two traits exposing messages to the compositor, there were two kinds of messages that could be sent: 1. In-process messages from the `Constellation` 2. Cross-process messages from other parts of Servo Now these two types of messages can be unified into one type. With that done the compositor can simply keep a single `IpcReceiver` for all messages, instead of having to set up a route for the cross-process messsages. This decreases overhead of cross proceses messages a bit, but more importantly solves an issue where Servo would rely on the compositor's cross-process message route after the `Constellation` had called `ROUTER.shutdown()`. This is part of #36442. Testing: This is covered by existing WPT tests. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
5f0f457ac3
commit
4c55104b36
8 changed files with 95 additions and 215 deletions
|
@ -7,7 +7,6 @@
|
|||
use std::fmt::{Debug, Error, Formatter};
|
||||
|
||||
use base::id::{PipelineId, WebViewId};
|
||||
use crossbeam_channel::{Receiver, Sender};
|
||||
use embedder_traits::{
|
||||
AnimationState, EventLoopWaker, MouseButton, MouseButtonAction, TouchEventResult,
|
||||
};
|
||||
|
@ -22,7 +21,6 @@ use webrender_api::DocumentId;
|
|||
pub mod display_list;
|
||||
pub mod rendering_context;
|
||||
|
||||
use core::fmt;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
|
@ -43,11 +41,7 @@ use webrender_api::{
|
|||
/// Sends messages to the compositor.
|
||||
#[derive(Clone)]
|
||||
pub struct CompositorProxy {
|
||||
pub sender: Sender<CompositorMsg>,
|
||||
/// 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 sender: IpcSender<CompositorMsg>,
|
||||
pub event_loop_waker: Box<dyn EventLoopWaker>,
|
||||
}
|
||||
|
||||
|
@ -58,24 +52,14 @@ impl CompositorProxy {
|
|||
}
|
||||
self.event_loop_waker.wake();
|
||||
}
|
||||
}
|
||||
|
||||
/// The port that the compositor receives messages on.
|
||||
pub struct CompositorReceiver {
|
||||
pub receiver: Receiver<CompositorMsg>,
|
||||
}
|
||||
|
||||
impl CompositorReceiver {
|
||||
pub fn try_recv_compositor_msg(&mut self) -> Option<CompositorMsg> {
|
||||
self.receiver.try_recv().ok()
|
||||
}
|
||||
pub fn recv_compositor_msg(&mut self) -> CompositorMsg {
|
||||
self.receiver.recv().unwrap()
|
||||
pub fn cross_process_compositor_api(&self) -> CrossProcessCompositorApi {
|
||||
CrossProcessCompositorApi(self.sender.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Messages from (or via) the constellation thread to the compositor.
|
||||
#[derive(IntoStaticStr)]
|
||||
#[derive(Deserialize, IntoStaticStr, Serialize)]
|
||||
pub enum CompositorMsg {
|
||||
/// Alerts the compositor that the given pipeline has changed whether it is running animations.
|
||||
ChangeRunningAnimationsState(WebViewId, PipelineId, AnimationState),
|
||||
|
@ -108,32 +92,6 @@ pub enum CompositorMsg {
|
|||
/// WebDriver mouse move event
|
||||
WebDriverMouseMoveEvent(WebViewId, f32, f32),
|
||||
|
||||
/// Messages forwarded to the compositor by the constellation from other crates. These
|
||||
/// messages are mainly passed on from the compositor to WebRender.
|
||||
CrossProcess(CrossProcessCompositorMessage),
|
||||
}
|
||||
|
||||
pub struct SendableFrameTree {
|
||||
pub pipeline: CompositionPipeline,
|
||||
pub children: Vec<SendableFrameTree>,
|
||||
}
|
||||
|
||||
/// The subset of the pipeline that is needed for layer composition.
|
||||
#[derive(Clone)]
|
||||
pub struct CompositionPipeline {
|
||||
pub id: PipelineId,
|
||||
pub webview_id: WebViewId,
|
||||
}
|
||||
|
||||
impl Debug for CompositorMsg {
|
||||
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
|
||||
let string: &'static str = self.into();
|
||||
write!(formatter, "{string}")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum CrossProcessCompositorMessage {
|
||||
/// Inform WebRender of the existence of this pipeline.
|
||||
SendInitialTransaction(WebRenderPipelineId),
|
||||
/// Perform a scroll operation.
|
||||
|
@ -193,31 +151,29 @@ pub enum CrossProcessCompositorMessage {
|
|||
GetAvailableScreenSize(WebViewId, IpcSender<DeviceIndependentIntSize>),
|
||||
}
|
||||
|
||||
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"),
|
||||
}
|
||||
impl Debug for CompositorMsg {
|
||||
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
|
||||
let string: &'static str = self.into();
|
||||
write!(formatter, "{string}")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct SendableFrameTree {
|
||||
pub pipeline: CompositionPipeline,
|
||||
pub children: Vec<SendableFrameTree>,
|
||||
}
|
||||
|
||||
/// The subset of the pipeline that is needed for layer composition.
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct CompositionPipeline {
|
||||
pub id: PipelineId,
|
||||
pub webview_id: WebViewId,
|
||||
}
|
||||
|
||||
/// A mechanism to send messages from ScriptThread to the parent process' WebRender instance.
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct CrossProcessCompositorApi(pub IpcSender<CrossProcessCompositorMessage>);
|
||||
pub struct CrossProcessCompositorApi(pub IpcSender<CompositorMsg>);
|
||||
|
||||
impl CrossProcessCompositorApi {
|
||||
/// Create a new [`CrossProcessCompositorApi`] struct that does not have a listener on the other
|
||||
|
@ -228,18 +184,13 @@ impl CrossProcessCompositorApi {
|
|||
}
|
||||
|
||||
/// Get the sender for this proxy.
|
||||
pub fn sender(&self) -> &IpcSender<CrossProcessCompositorMessage> {
|
||||
pub fn sender(&self) -> &IpcSender<CompositorMsg> {
|
||||
&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,
|
||||
))
|
||||
{
|
||||
if let Err(e) = self.0.send(CompositorMsg::SendInitialTransaction(pipeline)) {
|
||||
warn!("Error sending initial transaction: {}", e);
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +203,7 @@ impl CrossProcessCompositorApi {
|
|||
point: LayoutPoint,
|
||||
scroll_id: ExternalScrollId,
|
||||
) {
|
||||
if let Err(e) = self.0.send(CrossProcessCompositorMessage::SendScrollNode(
|
||||
if let Err(e) = self.0.send(CompositorMsg::SendScrollNode(
|
||||
webview_id,
|
||||
pipeline_id,
|
||||
point,
|
||||
|
@ -271,7 +222,7 @@ impl CrossProcessCompositorApi {
|
|||
) {
|
||||
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 {
|
||||
if let Err(e) = self.0.send(CompositorMsg::SendDisplayList {
|
||||
webview_id,
|
||||
display_list_descriptor,
|
||||
display_list_receiver,
|
||||
|
@ -306,9 +257,7 @@ impl CrossProcessCompositorApi {
|
|||
) -> Vec<CompositorHitTestResult> {
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
self.0
|
||||
.send(CrossProcessCompositorMessage::HitTest(
|
||||
pipeline, point, flags, sender,
|
||||
))
|
||||
.send(CompositorMsg::HitTest(pipeline, point, flags, sender))
|
||||
.expect("error sending hit test");
|
||||
receiver.recv().expect("error receiving hit test result")
|
||||
}
|
||||
|
@ -316,9 +265,7 @@ impl CrossProcessCompositorApi {
|
|||
/// Create a new image key. Blocks until the key is available.
|
||||
pub fn generate_image_key(&self) -> Option<ImageKey> {
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
self.0
|
||||
.send(CrossProcessCompositorMessage::GenerateImageKey(sender))
|
||||
.ok()?;
|
||||
self.0.send(CompositorMsg::GenerateImageKey(sender)).ok()?;
|
||||
receiver.recv().ok()
|
||||
}
|
||||
|
||||
|
@ -328,19 +275,14 @@ impl CrossProcessCompositorApi {
|
|||
descriptor: ImageDescriptor,
|
||||
data: SerializableImageData,
|
||||
) {
|
||||
if let Err(e) = self.0.send(CrossProcessCompositorMessage::AddImage(
|
||||
key, descriptor, data,
|
||||
)) {
|
||||
if let Err(e) = self.0.send(CompositorMsg::AddImage(key, descriptor, data)) {
|
||||
warn!("Error sending image update: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform an image resource update operation.
|
||||
pub fn update_images(&self, updates: Vec<ImageUpdate>) {
|
||||
if let Err(e) = self
|
||||
.0
|
||||
.send(CrossProcessCompositorMessage::UpdateImages(updates))
|
||||
{
|
||||
if let Err(e) = self.0.send(CompositorMsg::UpdateImages(updates)) {
|
||||
warn!("error sending image updates: {}", e);
|
||||
}
|
||||
}
|
||||
|
@ -353,10 +295,7 @@ impl CrossProcessCompositorApi {
|
|||
if keys.is_empty() && instance_keys.is_empty() {
|
||||
return;
|
||||
}
|
||||
let _ = self.0.send(CrossProcessCompositorMessage::RemoveFonts(
|
||||
keys,
|
||||
instance_keys,
|
||||
));
|
||||
let _ = self.0.send(CompositorMsg::RemoveFonts(keys, instance_keys));
|
||||
}
|
||||
|
||||
pub fn add_font_instance(
|
||||
|
@ -366,7 +305,7 @@ impl CrossProcessCompositorApi {
|
|||
size: f32,
|
||||
flags: FontInstanceFlags,
|
||||
) {
|
||||
let _x = self.0.send(CrossProcessCompositorMessage::AddFontInstance(
|
||||
let _x = self.0.send(CompositorMsg::AddFontInstance(
|
||||
font_instance_key,
|
||||
font_key,
|
||||
size,
|
||||
|
@ -375,15 +314,11 @@ impl CrossProcessCompositorApi {
|
|||
}
|
||||
|
||||
pub fn add_font(&self, font_key: FontKey, data: Arc<IpcSharedMemory>, index: u32) {
|
||||
let _ = self.0.send(CrossProcessCompositorMessage::AddFont(
|
||||
font_key, data, index,
|
||||
));
|
||||
let _ = self.0.send(CompositorMsg::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,
|
||||
));
|
||||
let _ = self.0.send(CompositorMsg::AddSystemFont(font_key, handle));
|
||||
}
|
||||
|
||||
pub fn fetch_font_keys(
|
||||
|
@ -392,7 +327,7 @@ impl CrossProcessCompositorApi {
|
|||
number_of_font_instance_keys: usize,
|
||||
) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
|
||||
let (sender, receiver) = ipc_channel::ipc::channel().expect("Could not create IPC channel");
|
||||
let _ = self.0.send(CrossProcessCompositorMessage::GenerateFontKeys(
|
||||
let _ = self.0.send(CompositorMsg::GenerateFontKeys(
|
||||
number_of_font_keys,
|
||||
number_of_font_instance_keys,
|
||||
sender,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue