mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01: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
|
@ -22,10 +22,10 @@ use style::color::AbsoluteColor;
|
|||
use style::properties::style_structs::Font as FontStyleStruct;
|
||||
use unicode_script::Script;
|
||||
use webrender_api::units::{DeviceIntSize, RectExt as RectExt_};
|
||||
use webrender_api::{ImageData, ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey};
|
||||
use webrender_traits::ImageUpdate;
|
||||
use webrender_api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey};
|
||||
use webrender_traits::{CrossProcessCompositorApi, ImageUpdate, SerializableImageData};
|
||||
|
||||
use crate::canvas_paint_thread::{AntialiasMode, WebrenderApi};
|
||||
use crate::canvas_paint_thread::AntialiasMode;
|
||||
use crate::raqote_backend::Repetition;
|
||||
|
||||
/// The canvas data stores a state machine for the current status of
|
||||
|
@ -428,7 +428,7 @@ pub struct CanvasData<'a> {
|
|||
path_state: Option<PathState>,
|
||||
state: CanvasPaintState<'a>,
|
||||
saved_states: Vec<CanvasPaintState<'a>>,
|
||||
webrender_api: Box<dyn WebrenderApi>,
|
||||
compositor_api: CrossProcessCompositorApi,
|
||||
image_key: Option<ImageKey>,
|
||||
/// An old webrender image key that can be deleted when the next epoch ends.
|
||||
old_image_key: Option<ImageKey>,
|
||||
|
@ -444,7 +444,7 @@ fn create_backend() -> Box<dyn Backend> {
|
|||
impl<'a> CanvasData<'a> {
|
||||
pub fn new(
|
||||
size: Size2D<u64>,
|
||||
webrender_api: Box<dyn WebrenderApi>,
|
||||
compositor_api: CrossProcessCompositorApi,
|
||||
antialias: AntialiasMode,
|
||||
font_context: Arc<FontContext>,
|
||||
) -> CanvasData<'a> {
|
||||
|
@ -456,7 +456,7 @@ impl<'a> CanvasData<'a> {
|
|||
path_state: None,
|
||||
state: CanvasPaintState::new(antialias),
|
||||
saved_states: vec![],
|
||||
webrender_api,
|
||||
compositor_api,
|
||||
image_key: None,
|
||||
old_image_key: None,
|
||||
very_old_image_key: None,
|
||||
|
@ -1279,8 +1279,9 @@ impl<'a> CanvasData<'a> {
|
|||
offset: 0,
|
||||
flags: ImageDescriptorFlags::empty(),
|
||||
};
|
||||
let data = self.drawtarget.snapshot_data_owned();
|
||||
let data = ImageData::Raw(Arc::new(data));
|
||||
let data = SerializableImageData::Raw(IpcSharedMemory::from_bytes(
|
||||
&self.drawtarget.snapshot_data_owned(),
|
||||
));
|
||||
|
||||
let mut updates = vec![];
|
||||
|
||||
|
@ -1290,7 +1291,7 @@ impl<'a> CanvasData<'a> {
|
|||
updates.push(ImageUpdate::UpdateImage(image_key, descriptor, data));
|
||||
},
|
||||
None => {
|
||||
let Some(key) = self.webrender_api.generate_key() else {
|
||||
let Some(key) = self.compositor_api.generate_image_key() else {
|
||||
return;
|
||||
};
|
||||
updates.push(ImageUpdate::AddImage(key, descriptor, data));
|
||||
|
@ -1305,7 +1306,7 @@ impl<'a> CanvasData<'a> {
|
|||
updates.push(ImageUpdate::DeleteImage(image_key));
|
||||
}
|
||||
|
||||
self.webrender_api.update_images(updates);
|
||||
self.compositor_api.update_images(updates);
|
||||
|
||||
let data = CanvasImageData {
|
||||
image_key: self.image_key.unwrap(),
|
||||
|
@ -1426,7 +1427,7 @@ impl<'a> Drop for CanvasData<'a> {
|
|||
updates.push(ImageUpdate::DeleteImage(image_key));
|
||||
}
|
||||
|
||||
self.webrender_api.update_images(updates);
|
||||
self.compositor_api.update_images(updates);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,7 @@ use ipc_channel::ipc::{self, IpcSender};
|
|||
use ipc_channel::router::ROUTER;
|
||||
use log::warn;
|
||||
use net_traits::ResourceThreads;
|
||||
use webrender_api::ImageKey;
|
||||
use webrender_traits::{ImageUpdate, WebRenderScriptApi};
|
||||
use webrender_traits::CrossProcessCompositorApi;
|
||||
|
||||
use crate::canvas_data::*;
|
||||
|
||||
|
@ -26,36 +25,26 @@ pub enum AntialiasMode {
|
|||
None,
|
||||
}
|
||||
|
||||
pub trait WebrenderApi {
|
||||
/// Attempt to generate an [`ImageKey`], returning `None` in case of failure.
|
||||
fn generate_key(&self) -> Option<ImageKey>;
|
||||
fn update_images(&self, updates: Vec<ImageUpdate>);
|
||||
fn clone(&self) -> Box<dyn WebrenderApi>;
|
||||
}
|
||||
|
||||
pub struct CanvasPaintThread<'a> {
|
||||
canvases: HashMap<CanvasId, CanvasData<'a>>,
|
||||
next_canvas_id: CanvasId,
|
||||
webrender_api: Box<dyn WebrenderApi>,
|
||||
compositor_api: CrossProcessCompositorApi,
|
||||
font_context: Arc<FontContext>,
|
||||
}
|
||||
|
||||
impl<'a> CanvasPaintThread<'a> {
|
||||
fn new(
|
||||
webrender_api: Box<dyn WebrenderApi>,
|
||||
compositor_api: CrossProcessCompositorApi,
|
||||
system_font_service: Arc<SystemFontServiceProxy>,
|
||||
resource_threads: ResourceThreads,
|
||||
) -> CanvasPaintThread<'a> {
|
||||
// This is only used for web fonts and currently canvas never uses web fonts.
|
||||
let webrender_script_api = WebRenderScriptApi::dummy();
|
||||
|
||||
CanvasPaintThread {
|
||||
canvases: HashMap::new(),
|
||||
next_canvas_id: CanvasId(0),
|
||||
webrender_api,
|
||||
compositor_api: compositor_api.clone(),
|
||||
font_context: Arc::new(FontContext::new(
|
||||
system_font_service,
|
||||
webrender_script_api,
|
||||
compositor_api,
|
||||
resource_threads,
|
||||
)),
|
||||
}
|
||||
|
@ -64,7 +53,7 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
/// Creates a new `CanvasPaintThread` and returns an `IpcSender` to
|
||||
/// communicate with it.
|
||||
pub fn start(
|
||||
webrender_api: Box<dyn WebrenderApi + Send>,
|
||||
compositor_api: CrossProcessCompositorApi,
|
||||
system_font_service: Arc<SystemFontServiceProxy>,
|
||||
resource_threads: ResourceThreads,
|
||||
) -> (Sender<ConstellationCanvasMsg>, IpcSender<CanvasMsg>) {
|
||||
|
@ -75,7 +64,7 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
.name("Canvas".to_owned())
|
||||
.spawn(move || {
|
||||
let mut canvas_paint_thread = CanvasPaintThread::new(
|
||||
webrender_api, system_font_service, resource_threads);
|
||||
compositor_api, system_font_service, resource_threads);
|
||||
loop {
|
||||
select! {
|
||||
recv(msg_receiver) -> msg => {
|
||||
|
@ -141,7 +130,7 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
|
||||
let canvas_data = CanvasData::new(
|
||||
size,
|
||||
self.webrender_api.clone(),
|
||||
self.compositor_api.clone(),
|
||||
antialias,
|
||||
self.font_context.clone(),
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue