mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Instead of exposing many different kinds of messages to the compositor that are routed through the constellation, expose a single message type which can be sent across IPC channels. In addition, this IPC channel and the route to the crossbeam channel with the compositor is created along with the `CompositorProxy`, simplifying what needs to be passed around during pipeline initialization. Previously, some image updates (from video) were sent over IPC with a special serialization routine and some were sent via crossbeam channels (canvas). Now all updates go over the IPC channel `IpcSharedMemory` is used to avoid serialization penalties. This should improve performance and reduce copies for video, but add a memory copy overhead for canvas. This will improve in the future when canvas renders directly into a texture. All-in-all this is a simplification which opens the path toward having a standard compositor API and reduces the number of duplicate messages and proxying that had to happen in libservo. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
30cbf01280
commit
9195344b75
28 changed files with 547 additions and 800 deletions
|
@ -16,8 +16,7 @@ use base::cross_process_instant::CrossProcessInstant;
|
|||
use base::id::{PipelineId, TopLevelBrowsingContextId, WebViewId};
|
||||
use base::{Epoch, WebRenderEpochToU16};
|
||||
use compositing_traits::{
|
||||
CompositionPipeline, CompositorMsg, CompositorReceiver, ConstellationMsg,
|
||||
ForwardedToCompositorMsg, SendableFrameTree,
|
||||
CompositionPipeline, CompositorMsg, CompositorReceiver, ConstellationMsg, SendableFrameTree,
|
||||
};
|
||||
use crossbeam_channel::Sender;
|
||||
use embedder_traits::Cursor;
|
||||
|
@ -51,8 +50,7 @@ use webrender_api::{
|
|||
};
|
||||
use webrender_traits::display_list::{HitTestInfo, ScrollTree};
|
||||
use webrender_traits::{
|
||||
CanvasToCompositorMsg, CompositorHitTestResult, FontToCompositorMsg, ImageUpdate,
|
||||
NetToCompositorMsg, RenderingContext, ScriptToCompositorMsg, SerializedImageUpdate,
|
||||
CompositorHitTestResult, CrossProcessCompositorMessage, ImageUpdate, RenderingContext,
|
||||
UntrustedNodeAddress,
|
||||
};
|
||||
|
||||
|
@ -653,29 +651,8 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
self.pending_paint_metrics.insert(pipeline_id, epoch);
|
||||
},
|
||||
|
||||
CompositorMsg::GetClientWindow(req) => {
|
||||
if let Err(e) = req.send(self.embedder_coordinates.window) {
|
||||
warn!("Sending response to get client window failed ({:?}).", e);
|
||||
}
|
||||
},
|
||||
|
||||
CompositorMsg::GetScreenSize(req) => {
|
||||
if let Err(e) = req.send(self.embedder_coordinates.screen) {
|
||||
warn!("Sending response to get screen size failed ({:?}).", e);
|
||||
}
|
||||
},
|
||||
|
||||
CompositorMsg::GetScreenAvailSize(req) => {
|
||||
if let Err(e) = req.send(self.embedder_coordinates.screen_avail) {
|
||||
warn!(
|
||||
"Sending response to get screen avail size failed ({:?}).",
|
||||
e
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
CompositorMsg::Forwarded(msg) => {
|
||||
self.handle_webrender_message(msg);
|
||||
CompositorMsg::CrossProcess(cross_proces_message) => {
|
||||
self.handle_cross_process_message(cross_proces_message);
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -685,11 +662,9 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
/// Accept messages from content processes that need to be relayed to the WebRender
|
||||
/// instance in the parent process.
|
||||
#[instrument(skip_all, fields(servo_profiling = true))]
|
||||
fn handle_webrender_message(&mut self, msg: ForwardedToCompositorMsg) {
|
||||
fn handle_cross_process_message(&mut self, msg: CrossProcessCompositorMessage) {
|
||||
match msg {
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::SendInitialTransaction(
|
||||
pipeline,
|
||||
)) => {
|
||||
CrossProcessCompositorMessage::SendInitialTransaction(pipeline) => {
|
||||
let mut txn = Transaction::new();
|
||||
txn.set_display_list(WebRenderEpoch(0), (pipeline, Default::default()));
|
||||
self.generate_frame(&mut txn, RenderReasons::SCENE);
|
||||
|
@ -697,11 +672,11 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::SendScrollNode(
|
||||
CrossProcessCompositorMessage::SendScrollNode(
|
||||
pipeline_id,
|
||||
point,
|
||||
external_scroll_id,
|
||||
)) => {
|
||||
) => {
|
||||
let pipeline_id = pipeline_id.into();
|
||||
let pipeline_details = match self.pipeline_details.get_mut(&pipeline_id) {
|
||||
Some(details) => details,
|
||||
|
@ -733,11 +708,11 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::SendDisplayList {
|
||||
CrossProcessCompositorMessage::SendDisplayList {
|
||||
display_list_info,
|
||||
display_list_descriptor,
|
||||
display_list_receiver,
|
||||
}) => {
|
||||
} => {
|
||||
// This must match the order from the sender, currently in `shared/script/lib.rs`.
|
||||
let items_data = match display_list_receiver.recv() {
|
||||
Ok(display_list_data) => display_list_data,
|
||||
|
@ -793,12 +768,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.send_transaction(self.webrender_document, transaction);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::HitTest(
|
||||
pipeline,
|
||||
point,
|
||||
flags,
|
||||
sender,
|
||||
)) => {
|
||||
CrossProcessCompositorMessage::HitTest(pipeline, point, flags, sender) => {
|
||||
// When a display list is sent to WebRender, it starts scene building in a
|
||||
// separate thread and then that display list is available for hit testing.
|
||||
// Without flushing scene building, any hit test we do might be done against
|
||||
|
@ -815,27 +785,20 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
let _ = sender.send(result);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::GenerateImageKey(sender)) |
|
||||
ForwardedToCompositorMsg::Net(NetToCompositorMsg::GenerateImageKey(sender)) => {
|
||||
CrossProcessCompositorMessage::GenerateImageKey(sender) => {
|
||||
let _ = sender.send(self.webrender_api.generate_image_key());
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::UpdateImages(updates)) => {
|
||||
CrossProcessCompositorMessage::UpdateImages(updates) => {
|
||||
let mut txn = Transaction::new();
|
||||
for update in updates {
|
||||
match update {
|
||||
SerializedImageUpdate::AddImage(key, desc, data) => {
|
||||
match data.to_image_data() {
|
||||
Ok(data) => txn.add_image(key, desc, data, None),
|
||||
Err(e) => warn!("error when sending image data: {:?}", e),
|
||||
}
|
||||
ImageUpdate::AddImage(key, desc, data) => {
|
||||
txn.add_image(key, desc, data.into(), None)
|
||||
},
|
||||
SerializedImageUpdate::DeleteImage(key) => txn.delete_image(key),
|
||||
SerializedImageUpdate::UpdateImage(key, desc, data) => {
|
||||
match data.to_image_data() {
|
||||
Ok(data) => txn.update_image(key, desc, data, &DirtyRect::All),
|
||||
Err(e) => warn!("error when sending image data: {:?}", e),
|
||||
}
|
||||
ImageUpdate::DeleteImage(key) => txn.delete_image(key),
|
||||
ImageUpdate::UpdateImage(key, desc, data) => {
|
||||
txn.update_image(key, desc, data.into(), &DirtyRect::All)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -843,27 +806,27 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::AddFont(
|
||||
font_key,
|
||||
data,
|
||||
index,
|
||||
)) => {
|
||||
CrossProcessCompositorMessage::AddFont(font_key, data, index) => {
|
||||
self.add_font(font_key, index, data);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::AddFontInstance(
|
||||
CrossProcessCompositorMessage::AddSystemFont(font_key, native_handle) => {
|
||||
let mut transaction = Transaction::new();
|
||||
transaction.add_native_font(font_key, native_handle);
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, transaction);
|
||||
},
|
||||
|
||||
CrossProcessCompositorMessage::AddFontInstance(
|
||||
font_instance_key,
|
||||
font_key,
|
||||
size,
|
||||
flags,
|
||||
)) => {
|
||||
) => {
|
||||
self.add_font_instance(font_instance_key, font_key, size, flags);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::RemoveFonts(
|
||||
keys,
|
||||
instance_keys,
|
||||
)) => {
|
||||
CrossProcessCompositorMessage::RemoveFonts(keys, instance_keys) => {
|
||||
let mut transaction = Transaction::new();
|
||||
|
||||
for instance in instance_keys.into_iter() {
|
||||
|
@ -877,18 +840,18 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.send_transaction(self.webrender_document, transaction);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Net(NetToCompositorMsg::AddImage(key, desc, data)) => {
|
||||
CrossProcessCompositorMessage::AddImage(key, desc, data) => {
|
||||
let mut txn = Transaction::new();
|
||||
txn.add_image(key, desc, data, None);
|
||||
txn.add_image(key, desc, data.into(), None);
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::GenerateKeys(
|
||||
CrossProcessCompositorMessage::GenerateFontKeys(
|
||||
number_of_font_keys,
|
||||
number_of_font_instance_keys,
|
||||
result_sender,
|
||||
)) => {
|
||||
) => {
|
||||
let font_keys = (0..number_of_font_keys)
|
||||
.map(|_| self.webrender_api.generate_font_key())
|
||||
.collect();
|
||||
|
@ -897,53 +860,23 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.collect();
|
||||
let _ = result_sender.send((font_keys, font_instance_keys));
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFontInstance(
|
||||
font_instance_key,
|
||||
font_key,
|
||||
size,
|
||||
flags,
|
||||
)) => {
|
||||
self.add_font_instance(font_instance_key, font_key, size, flags);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFont(
|
||||
font_key,
|
||||
index,
|
||||
data,
|
||||
)) => {
|
||||
self.add_font(font_key, index, data);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddSystemFont(
|
||||
font_key,
|
||||
native_handle,
|
||||
)) => {
|
||||
let mut transaction = Transaction::new();
|
||||
transaction.add_native_font(font_key, native_handle);
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, transaction);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Canvas(CanvasToCompositorMsg::GenerateKey(sender)) => {
|
||||
let _ = sender.send(self.webrender_api.generate_image_key());
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Canvas(CanvasToCompositorMsg::UpdateImages(updates)) => {
|
||||
let mut txn = Transaction::new();
|
||||
for update in updates {
|
||||
match update {
|
||||
ImageUpdate::AddImage(key, descriptor, data) => {
|
||||
txn.add_image(key, descriptor, data, None)
|
||||
},
|
||||
ImageUpdate::UpdateImage(key, descriptor, data) => {
|
||||
txn.update_image(key, descriptor, data, &DirtyRect::All)
|
||||
},
|
||||
ImageUpdate::DeleteImage(key) => txn.delete_image(key),
|
||||
}
|
||||
CrossProcessCompositorMessage::GetClientWindowRect(req) => {
|
||||
if let Err(e) = req.send(self.embedder_coordinates.window_rect) {
|
||||
warn!("Sending response to get client window failed ({:?}).", e);
|
||||
}
|
||||
},
|
||||
CrossProcessCompositorMessage::GetScreenSize(req) => {
|
||||
if let Err(e) = req.send(self.embedder_coordinates.screen_size) {
|
||||
warn!("Sending response to get screen size failed ({:?}).", e);
|
||||
}
|
||||
},
|
||||
CrossProcessCompositorMessage::GetAvailableScreenSize(req) => {
|
||||
if let Err(e) = req.send(self.embedder_coordinates.available_screen_size) {
|
||||
warn!(
|
||||
"Sending response to get screen avail size failed ({:?}).",
|
||||
e
|
||||
);
|
||||
}
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -968,23 +901,40 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
self.remove_pipeline_root_layer(pipeline_id);
|
||||
let _ = sender.send(());
|
||||
},
|
||||
CompositorMsg::Forwarded(ForwardedToCompositorMsg::Canvas(
|
||||
CanvasToCompositorMsg::GenerateKey(sender),
|
||||
CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GenerateImageKey(
|
||||
sender,
|
||||
)) => {
|
||||
let _ = sender.send(self.webrender_api.generate_image_key());
|
||||
},
|
||||
CompositorMsg::GetClientWindow(sender) => {
|
||||
if let Err(e) = sender.send(self.embedder_coordinates.window) {
|
||||
CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GenerateFontKeys(
|
||||
number_of_font_keys,
|
||||
number_of_font_instance_keys,
|
||||
result_sender,
|
||||
)) => {
|
||||
let font_keys = (0..number_of_font_keys)
|
||||
.map(|_| self.webrender_api.generate_font_key())
|
||||
.collect();
|
||||
let font_instance_keys = (0..number_of_font_instance_keys)
|
||||
.map(|_| self.webrender_api.generate_font_instance_key())
|
||||
.collect();
|
||||
let _ = result_sender.send((font_keys, font_instance_keys));
|
||||
},
|
||||
CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GetClientWindowRect(
|
||||
req,
|
||||
)) => {
|
||||
if let Err(e) = req.send(self.embedder_coordinates.window_rect) {
|
||||
warn!("Sending response to get client window failed ({:?}).", e);
|
||||
}
|
||||
},
|
||||
CompositorMsg::GetScreenSize(sender) => {
|
||||
if let Err(e) = sender.send(self.embedder_coordinates.screen) {
|
||||
CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GetScreenSize(req)) => {
|
||||
if let Err(e) = req.send(self.embedder_coordinates.screen_size) {
|
||||
warn!("Sending response to get screen size failed ({:?}).", e);
|
||||
}
|
||||
},
|
||||
CompositorMsg::GetScreenAvailSize(sender) => {
|
||||
if let Err(e) = sender.send(self.embedder_coordinates.screen_avail) {
|
||||
CompositorMsg::CrossProcess(CrossProcessCompositorMessage::GetAvailableScreenSize(
|
||||
req,
|
||||
)) => {
|
||||
if let Err(e) = req.send(self.embedder_coordinates.available_screen_size) {
|
||||
warn!(
|
||||
"Sending response to get screen avail size failed ({:?}).",
|
||||
e
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue