compositor: Create a single cross-process compositor API (#33619) (#33660)

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:
Martin Robinson 2024-10-09 10:30:24 -07:00 committed by GitHub
parent 30cbf01280
commit 9195344b75
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 547 additions and 800 deletions

View file

@ -10,7 +10,7 @@ use std::{mem, thread};
use embedder_traits::resources::{self, Resource};
use imsz::imsz_from_reader;
use ipc_channel::ipc::IpcSender;
use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
use log::{debug, warn};
use net_traits::image_cache::{
ImageCache, ImageCacheResult, ImageOrMetadataAvailable, ImageResponder, ImageResponse,
@ -21,8 +21,8 @@ use net_traits::{FetchMetadata, FetchResponseMsg, FilteredMetadata, NetworkError
use pixels::{load_from_memory, CorsStatus, Image, ImageMetadata, PixelFormat};
use servo_url::{ImmutableOrigin, ServoUrl};
use webrender_api::units::DeviceIntSize;
use webrender_api::{ImageData, ImageDescriptor, ImageDescriptorFlags, ImageFormat};
use webrender_traits::WebRenderNetApi;
use webrender_api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat};
use webrender_traits::{CrossProcessCompositorApi, SerializableImageData};
use crate::resource_thread::CoreResourceThreadPool;
@ -45,13 +45,13 @@ fn decode_bytes_sync(key: LoadKey, bytes: &[u8], cors: CorsStatus) -> DecoderMsg
DecoderMsg { key, image }
}
fn get_placeholder_image(webrender_api: &WebRenderNetApi, data: &[u8]) -> Arc<Image> {
fn get_placeholder_image(compositor_api: &CrossProcessCompositorApi, data: &[u8]) -> Arc<Image> {
let mut image = load_from_memory(data, CorsStatus::Unsafe).unwrap();
set_webrender_image_key(webrender_api, &mut image);
set_webrender_image_key(compositor_api, &mut image);
Arc::new(image)
}
fn set_webrender_image_key(webrender_api: &WebRenderNetApi, image: &mut Image) {
fn set_webrender_image_key(compositor_api: &CrossProcessCompositorApi, image: &mut Image) {
if image.id.is_some() {
return;
}
@ -82,10 +82,11 @@ fn set_webrender_image_key(webrender_api: &WebRenderNetApi, image: &mut Image) {
offset: 0,
flags,
};
let data = ImageData::new(bytes);
let image_key = webrender_api.generate_image_key();
webrender_api.add_image(image_key, descriptor, data);
image.id = Some(image_key);
if let Some(image_key) = compositor_api.generate_image_key() {
let data = SerializableImageData::Raw(IpcSharedMemory::from_bytes(&bytes));
compositor_api.add_image(image_key, descriptor, data);
image.id = Some(image_key);
}
}
// ======================================================================
@ -328,8 +329,8 @@ struct ImageCacheStore {
// The URL used for the placeholder image
placeholder_url: ServoUrl,
// Webrender API instance.
webrender_api: WebRenderNetApi,
// Cross-process compositor API instance.
compositor_api: CrossProcessCompositorApi,
}
impl ImageCacheStore {
@ -343,7 +344,7 @@ impl ImageCacheStore {
match load_result {
LoadResult::Loaded(ref mut image) => {
set_webrender_image_key(&self.webrender_api, image)
set_webrender_image_key(&self.compositor_api, image)
},
LoadResult::PlaceholderLoaded(..) | LoadResult::None => {},
}
@ -416,7 +417,7 @@ pub struct ImageCacheImpl {
}
impl ImageCache for ImageCacheImpl {
fn new(webrender_api: WebRenderNetApi) -> ImageCacheImpl {
fn new(compositor_api: CrossProcessCompositorApi) -> ImageCacheImpl {
debug!("New image cache");
let rippy_data = resources::read_bytes(Resource::RippyPNG);
@ -431,9 +432,9 @@ impl ImageCache for ImageCacheImpl {
store: Arc::new(Mutex::new(ImageCacheStore {
pending_loads: AllPendingLoads::new(),
completed_loads: HashMap::new(),
placeholder_image: get_placeholder_image(&webrender_api, &rippy_data),
placeholder_image: get_placeholder_image(&compositor_api, &rippy_data),
placeholder_url: ServoUrl::parse("chrome://resources/rippy.png").unwrap(),
webrender_api,
compositor_api,
})),
thread_pool: CoreResourceThreadPool::new(thread_count),
}