diff options
author | Martin Robinson <mrobinson@igalia.com> | 2023-10-05 19:47:39 +0200 |
---|---|---|
committer | Martin Robinson <mrobinson@igalia.com> | 2023-11-03 15:38:18 +0000 |
commit | f4d3af296c05260dfbb3deea4f8fa400cb6887d3 (patch) | |
tree | 169db2cc68e01a755b30500dd525f1a2ec2da861 /components/shared/webrender | |
parent | 863529d9622c68f0a9535225237eb5e5c5b8c757 (diff) | |
download | servo-f4d3af296c05260dfbb3deea4f8fa400cb6887d3.tar.gz servo-f4d3af296c05260dfbb3deea4f8fa400cb6887d3.zip |
Move `*_traits` and other shared types to `shared`
This is the start of the organization of types that are in their own
crates in order to break dependency cycles between other crates. The
idea here is that putting these packages into their own directory is the
first step toward cleaning them up. They have grown organically and it
is difficult to explain to new folks where to put new shared types. Many
of these crates contain more than traits or don't contain traits at all.
Notably, `script_traits` isn't touched because it is vendored from
Gecko. Eventually this will move to `third_party`.
Diffstat (limited to 'components/shared/webrender')
-rw-r--r-- | components/shared/webrender/Cargo.toml | 15 | ||||
-rw-r--r-- | components/shared/webrender/lib.rs | 179 |
2 files changed, 194 insertions, 0 deletions
diff --git a/components/shared/webrender/Cargo.toml b/components/shared/webrender/Cargo.toml new file mode 100644 index 00000000000..f078b96101d --- /dev/null +++ b/components/shared/webrender/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "webrender_traits" +version = "0.0.1" +authors = ["The Servo Project Developers"] +license = "MPL-2.0" +edition = "2018" +publish = false + +[lib] +name = "webrender_traits" +path = "lib.rs" + +[dependencies] +euclid = { workspace = true } +webrender_api = { workspace = true } diff --git a/components/shared/webrender/lib.rs b/components/shared/webrender/lib.rs new file mode 100644 index 00000000000..8e48d94e439 --- /dev/null +++ b/components/shared/webrender/lib.rs @@ -0,0 +1,179 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#![deny(unsafe_code)] + +use std::collections::HashMap; +use std::sync::{Arc, Mutex}; + +use euclid::default::Size2D; +use webrender_api::units::TexelRect; +use webrender_api::{ + ExternalImage, ExternalImageHandler, ExternalImageId, ExternalImageSource, ImageRendering, +}; + +/// This trait is used as a bridge between the different GL clients +/// in Servo that handles WebRender ExternalImages and the WebRender +/// ExternalImageHandler API. +// +/// This trait is used to notify lock/unlock messages and get the +/// required info that WR needs. +pub trait WebrenderExternalImageApi { + fn lock(&mut self, id: u64) -> (WebrenderImageSource, Size2D<i32>); + fn unlock(&mut self, id: u64); +} + +pub enum WebrenderImageSource<'a> { + TextureHandle(u32), + Raw(&'a [u8]), +} + +/// Type of Webrender External Image Handler. +pub enum WebrenderImageHandlerType { + WebGL, + Media, + WebGPU, +} + +/// List of Webrender external images to be shared among all external image +/// consumers (WebGL, Media, WebGPU). +/// It ensures that external image identifiers are unique. +pub struct WebrenderExternalImageRegistry { + /// Map of all generated external images. + external_images: HashMap<ExternalImageId, WebrenderImageHandlerType>, + /// Id generator for the next external image identifier. + next_image_id: u64, +} + +impl WebrenderExternalImageRegistry { + pub fn new() -> Self { + Self { + external_images: HashMap::new(), + next_image_id: 0, + } + } + + pub fn next_id(&mut self, handler_type: WebrenderImageHandlerType) -> ExternalImageId { + self.next_image_id += 1; + let key = ExternalImageId(self.next_image_id); + self.external_images.insert(key, handler_type); + key + } + + pub fn remove(&mut self, key: &ExternalImageId) { + self.external_images.remove(key); + } + + pub fn get(&self, key: &ExternalImageId) -> Option<&WebrenderImageHandlerType> { + self.external_images.get(key) + } +} + +/// WebRender External Image Handler implementation. +pub struct WebrenderExternalImageHandlers { + /// WebGL handler. + webgl_handler: Option<Box<dyn WebrenderExternalImageApi>>, + /// Media player handler. + media_handler: Option<Box<dyn WebrenderExternalImageApi>>, + /// WebGPU handler. + webgpu_handler: Option<Box<dyn WebrenderExternalImageApi>>, + /// Webrender external images. + external_images: Arc<Mutex<WebrenderExternalImageRegistry>>, +} + +impl WebrenderExternalImageHandlers { + pub fn new() -> (Self, Arc<Mutex<WebrenderExternalImageRegistry>>) { + let external_images = Arc::new(Mutex::new(WebrenderExternalImageRegistry::new())); + ( + Self { + webgl_handler: None, + media_handler: None, + webgpu_handler: None, + external_images: external_images.clone(), + }, + external_images, + ) + } + + pub fn set_handler( + &mut self, + handler: Box<dyn WebrenderExternalImageApi>, + handler_type: WebrenderImageHandlerType, + ) { + match handler_type { + WebrenderImageHandlerType::WebGL => self.webgl_handler = Some(handler), + WebrenderImageHandlerType::Media => self.media_handler = Some(handler), + WebrenderImageHandlerType::WebGPU => self.webgpu_handler = Some(handler), + } + } +} + +impl ExternalImageHandler for WebrenderExternalImageHandlers { + /// Lock the external image. Then, WR could start to read the + /// image content. + /// The WR client should not change the image content until the + /// unlock() call. + fn lock( + &mut self, + key: ExternalImageId, + _channel_index: u8, + _rendering: ImageRendering, + ) -> ExternalImage { + let external_images = self.external_images.lock().unwrap(); + let handler_type = external_images + .get(&key) + .expect("Tried to get unknown external image"); + match handler_type { + WebrenderImageHandlerType::WebGL => { + let (source, size) = self.webgl_handler.as_mut().unwrap().lock(key.0); + let texture_id = match source { + WebrenderImageSource::TextureHandle(b) => b, + _ => panic!("Wrong type"), + }; + ExternalImage { + uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0), + source: ExternalImageSource::NativeTexture(texture_id), + } + }, + WebrenderImageHandlerType::Media => { + let (source, size) = self.media_handler.as_mut().unwrap().lock(key.0); + let texture_id = match source { + WebrenderImageSource::TextureHandle(b) => b, + _ => panic!("Wrong type"), + }; + ExternalImage { + uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0), + source: ExternalImageSource::NativeTexture(texture_id), + } + }, + WebrenderImageHandlerType::WebGPU => { + let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0); + let buffer = match source { + WebrenderImageSource::Raw(b) => b, + _ => panic!("Wrong type"), + }; + ExternalImage { + uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0), + source: ExternalImageSource::RawData(buffer), + } + }, + } + } + + /// Unlock the external image. The WR should not read the image + /// content after this call. + fn unlock(&mut self, key: ExternalImageId, _channel_index: u8) { + let external_images = self.external_images.lock().unwrap(); + let handler_type = external_images + .get(&key) + .expect("Tried to get unknown external image"); + match handler_type { + WebrenderImageHandlerType::WebGL => self.webgl_handler.as_mut().unwrap().unlock(key.0), + WebrenderImageHandlerType::Media => self.media_handler.as_mut().unwrap().unlock(key.0), + WebrenderImageHandlerType::WebGPU => { + self.webgpu_handler.as_mut().unwrap().unlock(key.0) + }, + }; + } +} |