aboutsummaryrefslogtreecommitdiffstats
path: root/components/shared
diff options
context:
space:
mode:
authorMukilan Thiyagarajan <mukilan@igalia.com>2024-05-20 16:05:18 +0530
committerGitHub <noreply@github.com>2024-05-20 10:35:18 +0000
commit2af6fe0b30a275e5fd8a43eca4126d82639fbaa9 (patch)
tree2687a12c392b30cba7cdcd849133d0d382b79cbe /components/shared
parentc2076580f352f3c61f90969e03d78ada609935eb (diff)
downloadservo-2af6fe0b30a275e5fd8a43eca4126d82639fbaa9.tar.gz
servo-2af6fe0b30a275e5fd8a43eca4126d82639fbaa9.zip
compositor: Move WebRender-ish messages and types to `webrender_traits` (#32315)
* Move WebRender related types to `webrender_traits` This refactor moves several WebRender related types from `compositing_traits`, `script_traits` and `net_traits` crates to the `webrender_traits` crate. This change also moves the `Image` type and associated function out of `net_traits` and into the `pixels` crate. Co-authored-by: Martin Robinson <mrobinson@igalia.com> Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * Move `script_traits::WebrenderIpcSender` to `webrender_traits::WebRenderScriptApi` --------- Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Diffstat (limited to 'components/shared')
-rw-r--r--components/shared/compositing/Cargo.toml4
-rw-r--r--components/shared/compositing/lib.rs20
-rw-r--r--components/shared/net/Cargo.toml1
-rw-r--r--components/shared/net/image/base.rs121
-rw-r--r--components/shared/net/image_cache.rs18
-rw-r--r--components/shared/net/lib.rs43
-rw-r--r--components/shared/net/tests/image.rs28
-rw-r--r--components/shared/script/Cargo.toml1
-rw-r--r--components/shared/script/lib.rs259
-rw-r--r--components/shared/script/tests/compositor.rs6
-rw-r--r--components/shared/script_layout/Cargo.toml2
-rw-r--r--components/shared/script_layout/lib.rs5
-rw-r--r--components/shared/script_layout/wrapper_traits.rs2
-rw-r--r--components/shared/webrender/Cargo.toml7
-rw-r--r--components/shared/webrender/display_list.rs (renamed from components/shared/script/compositor.rs)0
-rw-r--r--components/shared/webrender/lib.rs324
16 files changed, 361 insertions, 480 deletions
diff --git a/components/shared/compositing/Cargo.toml b/components/shared/compositing/Cargo.toml
index aed9a0e3565..b454cae37fa 100644
--- a/components/shared/compositing/Cargo.toml
+++ b/components/shared/compositing/Cargo.toml
@@ -12,7 +12,6 @@ path = "lib.rs"
[dependencies]
base = { workspace = true }
-canvas = { path = "../../canvas" }
crossbeam-channel = { workspace = true }
embedder_traits = { workspace = true }
euclid = { workspace = true }
@@ -20,8 +19,9 @@ gfx_traits = { workspace = true }
ipc-channel = { workspace = true }
keyboard-types = { workspace = true }
log = { workspace = true }
-net_traits = { workspace = true }
+pixels = { path = '../../pixels' }
script_traits = { workspace = true }
servo_url = { path = "../../url" }
style_traits = { workspace = true }
webrender_api = { workspace = true }
+webrender_traits = { workspace = true }
diff --git a/components/shared/compositing/lib.rs b/components/shared/compositing/lib.rs
index 34c390cca85..171b0676c2d 100644
--- a/components/shared/compositing/lib.rs
+++ b/components/shared/compositing/lib.rs
@@ -10,23 +10,20 @@ use std::fmt::{Debug, Error, Formatter};
use base::id::{PipelineId, TopLevelBrowsingContextId};
use base::Epoch;
-use canvas::canvas_paint_thread::ImageUpdate;
pub use constellation_msg::ConstellationMsg;
use crossbeam_channel::{Receiver, Sender};
use embedder_traits::EventLoopWaker;
use euclid::Rect;
use ipc_channel::ipc::IpcSender;
use log::warn;
-use net_traits::image::base::Image;
-use net_traits::NetToCompositorMsg;
+use pixels::Image;
use script_traits::{
AnimationState, ConstellationControlMsg, EventResult, MouseButton, MouseEventType,
- ScriptToCompositorMsg,
};
use style_traits::CSSPixel;
use webrender_api::units::{DeviceIntPoint, DeviceIntSize, DeviceRect};
-use webrender_api::{
- self, FontInstanceFlags, FontInstanceKey, FontKey, ImageKey, NativeFontHandle,
+use webrender_traits::{
+ CanvasToCompositorMsg, FontToCompositorMsg, NetToCompositorMsg, ScriptToCompositorMsg,
};
/// Sends messages to the compositor.
@@ -140,17 +137,6 @@ pub struct CompositionPipeline {
pub script_chan: IpcSender<ConstellationControlMsg>,
}
-pub enum FontToCompositorMsg {
- AddFontInstance(FontKey, f32, FontInstanceFlags, Sender<FontInstanceKey>),
- AddFont(Sender<FontKey>, u32, ipc_channel::ipc::IpcBytesReceiver),
- AddSystemFont(Sender<FontKey>, NativeFontHandle),
-}
-
-pub enum CanvasToCompositorMsg {
- GenerateKey(Sender<ImageKey>),
- UpdateImages(Vec<ImageUpdate>),
-}
-
/// Messages forwarded by the Constellation to the Compositor.
pub enum ForwardedToCompositorMsg {
Layout(ScriptToCompositorMsg),
diff --git a/components/shared/net/Cargo.toml b/components/shared/net/Cargo.toml
index 73db752aba6..cf174100feb 100644
--- a/components/shared/net/Cargo.toml
+++ b/components/shared/net/Cargo.toml
@@ -39,3 +39,4 @@ servo_url = { path = "../../url" }
url = { workspace = true }
uuid = { workspace = true }
webrender_api = { workspace = true }
+webrender_traits = { workspace = true }
diff --git a/components/shared/net/image/base.rs b/components/shared/net/image/base.rs
deleted file mode 100644
index 66257012df2..00000000000
--- a/components/shared/net/image/base.rs
+++ /dev/null
@@ -1,121 +0,0 @@
-/* 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/. */
-
-use std::fmt;
-
-use image::ImageFormat;
-use ipc_channel::ipc::IpcSharedMemory;
-use log::debug;
-use malloc_size_of_derive::MallocSizeOf;
-use pixels::PixelFormat;
-use serde::{Deserialize, Serialize};
-use webrender_api::ImageKey;
-
-use crate::image_cache::CorsStatus;
-
-#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
-pub struct Image {
- pub width: u32,
- pub height: u32,
- pub format: PixelFormat,
- #[ignore_malloc_size_of = "Defined in ipc-channel"]
- pub bytes: IpcSharedMemory,
- #[ignore_malloc_size_of = "Defined in webrender_api"]
- pub id: Option<ImageKey>,
- pub cors_status: CorsStatus,
-}
-
-impl fmt::Debug for Image {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(
- f,
- "Image {{ width: {}, height: {}, format: {:?}, ..., id: {:?} }}",
- self.width, self.height, self.format, self.id
- )
- }
-}
-
-#[derive(Clone, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
-pub struct ImageMetadata {
- pub width: u32,
- pub height: u32,
-}
-
-// FIXME: Images must not be copied every frame. Instead we should atomically
-// reference count them.
-
-pub fn load_from_memory(buffer: &[u8], cors_status: CorsStatus) -> Option<Image> {
- if buffer.is_empty() {
- return None;
- }
-
- let image_fmt_result = detect_image_format(buffer);
- match image_fmt_result {
- Err(msg) => {
- debug!("{}", msg);
- None
- },
- Ok(_) => match image::load_from_memory(buffer) {
- Ok(image) => {
- let mut rgba = image.into_rgba8();
- pixels::rgba8_byte_swap_colors_inplace(&mut rgba);
- Some(Image {
- width: rgba.width(),
- height: rgba.height(),
- format: PixelFormat::BGRA8,
- bytes: IpcSharedMemory::from_bytes(&rgba),
- id: None,
- cors_status,
- })
- },
- Err(e) => {
- debug!("Image decoding error: {:?}", e);
- None
- },
- },
- }
-}
-
-// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img
-pub fn detect_image_format(buffer: &[u8]) -> Result<ImageFormat, &str> {
- if is_gif(buffer) {
- Ok(ImageFormat::Gif)
- } else if is_jpeg(buffer) {
- Ok(ImageFormat::Jpeg)
- } else if is_png(buffer) {
- Ok(ImageFormat::Png)
- } else if is_webp(buffer) {
- Ok(ImageFormat::WebP)
- } else if is_bmp(buffer) {
- Ok(ImageFormat::Bmp)
- } else if is_ico(buffer) {
- Ok(ImageFormat::Ico)
- } else {
- Err("Image Format Not Supported")
- }
-}
-
-fn is_gif(buffer: &[u8]) -> bool {
- buffer.starts_with(b"GIF87a") || buffer.starts_with(b"GIF89a")
-}
-
-fn is_jpeg(buffer: &[u8]) -> bool {
- buffer.starts_with(&[0xff, 0xd8, 0xff])
-}
-
-fn is_png(buffer: &[u8]) -> bool {
- buffer.starts_with(&[0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])
-}
-
-fn is_bmp(buffer: &[u8]) -> bool {
- buffer.starts_with(&[0x42, 0x4D])
-}
-
-fn is_ico(buffer: &[u8]) -> bool {
- buffer.starts_with(&[0x00, 0x00, 0x01, 0x00])
-}
-
-fn is_webp(buffer: &[u8]) -> bool {
- buffer.starts_with(b"RIFF") && buffer.len() >= 14 && &buffer[8..14] == b"WEBPVP"
-}
diff --git a/components/shared/net/image_cache.rs b/components/shared/net/image_cache.rs
index d1087bace63..317fd1b66ef 100644
--- a/components/shared/net/image_cache.rs
+++ b/components/shared/net/image_cache.rs
@@ -7,12 +7,13 @@ use std::sync::Arc;
use ipc_channel::ipc::IpcSender;
use log::debug;
use malloc_size_of_derive::MallocSizeOf;
+use pixels::{Image, ImageMetadata};
use serde::{Deserialize, Serialize};
use servo_url::{ImmutableOrigin, ServoUrl};
+use webrender_traits::WebRenderNetApi;
-use crate::image::base::{Image, ImageMetadata};
use crate::request::CorsSettings;
-use crate::{FetchResponseMsg, WebrenderIpcSender};
+use crate::FetchResponseMsg;
// ======================================================================
// Aux structs and enums.
@@ -98,7 +99,7 @@ pub enum ImageCacheResult {
}
pub trait ImageCache: Sync + Send {
- fn new(webrender_api: WebrenderIpcSender) -> Self
+ fn new(webrender_api: WebRenderNetApi) -> Self
where
Self: Sized;
@@ -140,14 +141,3 @@ pub trait ImageCache: Sync + Send {
/// Inform the image cache about a response for a pending request.
fn notify_pending_response(&self, id: PendingImageId, action: FetchResponseMsg);
}
-
-/// Whether this response passed any CORS checks, and is thus safe to read from
-/// in cross-origin environments.
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
-pub enum CorsStatus {
- /// The response is either same-origin or cross-origin but passed CORS checks.
- Safe,
- /// The response is cross-origin and did not pass CORS checks. It is unsafe
- /// to expose pixel data to the requesting environment.
- Unsafe,
-}
diff --git a/components/shared/net/lib.rs b/components/shared/net/lib.rs
index 436ccf5d645..595d47c7b06 100644
--- a/components/shared/net/lib.rs
+++ b/components/shared/net/lib.rs
@@ -16,7 +16,6 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
use ipc_channel::Error as IpcError;
use lazy_static::lazy_static;
-use log::warn;
use malloc_size_of::malloc_size_of_is_0;
use malloc_size_of_derive::MallocSizeOf;
use mime::Mime;
@@ -25,7 +24,6 @@ use rustls::Certificate;
use serde::{Deserialize, Serialize};
use servo_rand::RngCore;
use servo_url::{ImmutableOrigin, ServoUrl};
-use webrender_api::{ImageData, ImageDescriptor, ImageKey};
use crate::filemanager_thread::FileManagerThreadMsg;
use crate::request::{Request, RequestBuilder};
@@ -41,15 +39,6 @@ pub mod request;
pub mod response;
pub mod storage_thread;
-/// Image handling.
-///
-/// It may be surprising that this goes in the network crate as opposed to the graphics crate.
-/// However, image handling is generally very integrated with the network stack (especially where
-/// caching is involved) and as a result it must live in here.
-pub mod image {
- pub mod base;
-}
-
/// An implementation of the [Fetch specification](https://fetch.spec.whatwg.org/)
pub mod fetch {
pub mod headers;
@@ -829,38 +818,6 @@ pub fn http_percent_encode(bytes: &[u8]) -> String {
percent_encoding::percent_encode(bytes, HTTP_VALUE).to_string()
}
-#[derive(Deserialize, Serialize)]
-pub enum NetToCompositorMsg {
- AddImage(ImageKey, ImageDescriptor, ImageData),
- GenerateImageKey(IpcSender<ImageKey>),
-}
-
-#[derive(Clone, Deserialize, Serialize)]
-pub struct WebrenderIpcSender(IpcSender<NetToCompositorMsg>);
-
-impl WebrenderIpcSender {
- pub fn new(sender: IpcSender<NetToCompositorMsg>) -> Self {
- Self(sender)
- }
-
- pub fn generate_image_key(&self) -> ImageKey {
- let (sender, receiver) = ipc::channel().unwrap();
- self.0
- .send(NetToCompositorMsg::GenerateImageKey(sender))
- .expect("error sending image key generation");
- receiver.recv().expect("error receiving image key result")
- }
-
- pub fn add_image(&self, key: ImageKey, descriptor: ImageDescriptor, data: ImageData) {
- if let Err(e) = self
- .0
- .send(NetToCompositorMsg::AddImage(key, descriptor, data))
- {
- warn!("Error sending image update: {}", e);
- }
- }
-}
-
lazy_static! {
pub static ref PRIVILEGED_SECRET: u32 = servo_rand::ServoRng::default().next_u32();
}
diff --git a/components/shared/net/tests/image.rs b/components/shared/net/tests/image.rs
deleted file mode 100644
index a4963702b57..00000000000
--- a/components/shared/net/tests/image.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 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/. */
-
-use net_traits::image::base::detect_image_format;
-
-#[test]
-fn test_supported_images() {
- let gif1 = [b'G', b'I', b'F', b'8', b'7', b'a'];
- let gif2 = [b'G', b'I', b'F', b'8', b'9', b'a'];
- let jpeg = [0xff, 0xd8, 0xff];
- let png = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
- let webp = [
- b'R', b'I', b'F', b'F', 0x01, 0x02, 0x03, 0x04, b'W', b'E', b'B', b'P', b'V', b'P',
- ];
- let bmp = [0x42, 0x4D];
- let ico = [0x00, 0x00, 0x01, 0x00];
- let junk_format = [0x01, 0x02, 0x03, 0x04, 0x05];
-
- assert!(detect_image_format(&gif1).is_ok());
- assert!(detect_image_format(&gif2).is_ok());
- assert!(detect_image_format(&jpeg).is_ok());
- assert!(detect_image_format(&png).is_ok());
- assert!(detect_image_format(&webp).is_ok());
- assert!(detect_image_format(&bmp).is_ok());
- assert!(detect_image_format(&ico).is_ok());
- assert!(detect_image_format(&junk_format).is_err());
-}
diff --git a/components/shared/script/Cargo.toml b/components/shared/script/Cargo.toml
index f95a0ffdcc9..6b3a2384d41 100644
--- a/components/shared/script/Cargo.toml
+++ b/components/shared/script/Cargo.toml
@@ -44,4 +44,5 @@ uuid = { workspace = true }
webdriver = { workspace = true }
webgpu = { path = "../../webgpu" }
webrender_api = { workspace = true }
+webrender_traits = { workspace = true }
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
diff --git a/components/shared/script/lib.rs b/components/shared/script/lib.rs
index 2f9822d2711..16f1e07710d 100644
--- a/components/shared/script/lib.rs
+++ b/components/shared/script/lib.rs
@@ -9,7 +9,6 @@
#![deny(missing_docs)]
#![deny(unsafe_code)]
-pub mod compositor;
mod script_msg;
pub mod serializable;
pub mod transferable;
@@ -29,14 +28,13 @@ use base::Epoch;
use bitflags::bitflags;
use bluetooth_traits::BluetoothRequest;
use canvas_traits::webgl::WebGLPipeline;
-use compositor::ScrollTreeNodeId;
use crossbeam_channel::{RecvTimeoutError, Sender};
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
-use embedder_traits::{CompositorEventVariant, Cursor};
+use embedder_traits::CompositorEventVariant;
use euclid::default::Point2D;
use euclid::{Length, Rect, Scale, Size2D, UnknownUnit, Vector2D};
use http::{HeaderMap, Method};
-use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
+use ipc_channel::ipc::{IpcReceiver, IpcSender};
use ipc_channel::Error as IpcError;
use keyboard_types::webdriver::Event as WebDriverInputEvent;
use keyboard_types::{CompositionEvent, KeyboardEvent};
@@ -45,25 +43,21 @@ use log::warn;
use malloc_size_of::malloc_size_of_is_0;
use malloc_size_of_derive::MallocSizeOf;
use media::WindowGLContext;
-use net_traits::image::base::Image;
use net_traits::image_cache::ImageCache;
use net_traits::request::{Referrer, RequestBody};
use net_traits::storage_thread::StorageType;
use net_traits::{FetchResponseMsg, ReferrerPolicy, ResourceThreads};
-use pixels::PixelFormat;
+use pixels::{Image, PixelFormat};
use profile_traits::{mem, time as profile_time};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use servo_atoms::Atom;
use servo_url::{ImmutableOrigin, ServoUrl};
use style_traits::{CSSPixel, SpeculativePainter};
use webgpu::WebGPUMsg;
-use webrender_api::units::{DeviceIntSize, DevicePixel, DevicePoint, LayoutPixel, LayoutPoint};
-use webrender_api::{
- BuiltDisplayList, BuiltDisplayListDescriptor, DocumentId, ExternalImageData, ExternalScrollId,
- HitTestFlags, ImageData, ImageDescriptor, ImageKey, PipelineId as WebRenderPipelineId,
-};
+use webrender_api::units::{DeviceIntSize, DevicePixel, LayoutPixel};
+use webrender_api::{DocumentId, ExternalScrollId, ImageKey};
+use webrender_traits::{UntrustedNodeAddress as WebRenderUntrustedNodeAddress, WebRenderScriptApi};
-use crate::compositor::CompositorDisplayListInfo;
pub use crate::script_msg::{
DOMMessage, EventResult, HistoryEntryReplacement, IFrameSizeMsg, Job, JobError, JobResult,
JobResultValue, JobType, LayoutMsg, LogEntry, SWManagerMsg, SWManagerSenders, ScopeThings,
@@ -83,6 +77,12 @@ malloc_size_of_is_0!(UntrustedNodeAddress);
#[allow(unsafe_code)]
unsafe impl Send for UntrustedNodeAddress {}
+impl From<WebRenderUntrustedNodeAddress> for UntrustedNodeAddress {
+ fn from(o: WebRenderUntrustedNodeAddress) -> Self {
+ UntrustedNodeAddress(o.0 as *const c_void)
+ }
+}
+
impl From<style_traits::dom::OpaqueNode> for UntrustedNodeAddress {
fn from(o: style_traits::dom::OpaqueNode) -> Self {
UntrustedNodeAddress(o.0 as *const c_void)
@@ -691,7 +691,7 @@ pub struct InitialScriptState {
/// The Webrender document ID associated with this thread.
pub webrender_document: DocumentId,
/// FIXME(victor): The Webrender API sender in this constellation's pipeline
- pub webrender_api_sender: WebrenderIpcSender,
+ pub webrender_api_sender: WebRenderScriptApi,
/// Application window's GL Context for Media player
pub player_context: WindowGLContext,
}
@@ -1093,239 +1093,6 @@ impl From<i32> for MediaSessionActionType {
}
}
-/// The result of a hit test in the compositor.
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct CompositorHitTestResult {
- /// The pipeline id of the resulting item.
- pub pipeline_id: PipelineId,
-
- /// The hit test point in the item's viewport.
- pub point_in_viewport: euclid::default::Point2D<f32>,
-
- /// The hit test point relative to the item itself.
- pub point_relative_to_item: euclid::default::Point2D<f32>,
-
- /// The node address of the hit test result.
- pub node: UntrustedNodeAddress,
-
- /// The cursor that should be used when hovering the item hit by the hit test.
- pub cursor: Option<Cursor>,
-
- /// The scroll tree node associated with this hit test item.
- pub scroll_tree_node: ScrollTreeNodeId,
-}
-
-/// The set of WebRender operations that can be initiated by the content process.
-#[derive(Deserialize, Serialize)]
-pub enum ScriptToCompositorMsg {
- /// Inform WebRender of the existence of this pipeline.
- SendInitialTransaction(WebRenderPipelineId),
- /// Perform a scroll operation.
- SendScrollNode(WebRenderPipelineId, LayoutPoint, ExternalScrollId),
- /// Inform WebRender of a new display list for the given pipeline.
- SendDisplayList {
- /// The [CompositorDisplayListInfo] that describes the display list being sent.
- display_list_info: CompositorDisplayListInfo,
- /// A descriptor of this display list used to construct this display list from raw data.
- display_list_descriptor: BuiltDisplayListDescriptor,
- /// An [ipc::IpcBytesReceiver] used to send the raw data of the display list.
- display_list_receiver: ipc::IpcBytesReceiver,
- },
- /// Perform a hit test operation. The result will be returned via
- /// the provided channel sender.
- HitTest(
- Option<WebRenderPipelineId>,
- DevicePoint,
- HitTestFlags,
- IpcSender<Vec<CompositorHitTestResult>>,
- ),
- /// Create a new image key. The result will be returned via the
- /// provided channel sender.
- GenerateImageKey(IpcSender<ImageKey>),
- /// Perform a resource update operation.
- UpdateImages(Vec<SerializedImageUpdate>),
-}
-
-#[derive(Clone, Deserialize, Serialize)]
-/// A mechanism to communicate with the parent process' WebRender instance.
-pub struct WebrenderIpcSender(IpcSender<ScriptToCompositorMsg>);
-
-impl WebrenderIpcSender {
- /// Create a new WebrenderIpcSender object that wraps the provided channel sender.
- pub fn new(sender: IpcSender<ScriptToCompositorMsg>) -> Self {
- Self(sender)
- }
-
- /// Inform WebRender of the existence of this pipeline.
- pub fn send_initial_transaction(&self, pipeline: WebRenderPipelineId) {
- if let Err(e) = self
- .0
- .send(ScriptToCompositorMsg::SendInitialTransaction(pipeline))
- {
- warn!("Error sending initial transaction: {}", e);
- }
- }
-
- /// Perform a scroll operation.
- pub fn send_scroll_node(
- &self,
- pipeline_id: WebRenderPipelineId,
- point: LayoutPoint,
- scroll_id: ExternalScrollId,
- ) {
- if let Err(e) = self.0.send(ScriptToCompositorMsg::SendScrollNode(
- pipeline_id,
- point,
- scroll_id,
- )) {
- warn!("Error sending scroll node: {}", e);
- }
- }
-
- /// Inform WebRender of a new display list for the given pipeline.
- pub fn send_display_list(
- &self,
- display_list_info: CompositorDisplayListInfo,
- list: BuiltDisplayList,
- ) {
- 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(ScriptToCompositorMsg::SendDisplayList {
- display_list_info,
- display_list_descriptor,
- display_list_receiver,
- }) {
- warn!("Error sending display list: {}", e);
- }
-
- if let Err(error) = display_list_sender.send(&display_list_data.items_data) {
- warn!("Error sending display list items: {}", error);
- }
- if let Err(error) = display_list_sender.send(&display_list_data.cache_data) {
- warn!("Error sending display list cache data: {}", error);
- }
- if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) {
- warn!("Error sending display spatial tree: {}", error);
- }
- }
-
- /// Perform a hit test operation. Blocks until the operation is complete and
- /// and a result is available.
- pub fn hit_test(
- &self,
- pipeline: Option<WebRenderPipelineId>,
- point: DevicePoint,
- flags: HitTestFlags,
- ) -> Vec<CompositorHitTestResult> {
- let (sender, receiver) = ipc::channel().unwrap();
- self.0
- .send(ScriptToCompositorMsg::HitTest(
- pipeline, point, flags, sender,
- ))
- .expect("error sending hit test");
- receiver.recv().expect("error receiving hit test result")
- }
-
- /// 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(ScriptToCompositorMsg::GenerateImageKey(sender))
- .ok()?;
- receiver.recv().ok()
- }
-
- /// Perform a resource update operation.
- pub fn update_images(&self, updates: Vec<ImageUpdate>) {
- let mut senders = Vec::new();
- // Convert `ImageUpdate` to `SerializedImageUpdate` because `ImageData` may contain large
- // byes. With this conversion, we send `IpcBytesReceiver` instead and use it to send the
- // actual bytes.
- let updates = updates
- .into_iter()
- .map(|update| match update {
- ImageUpdate::AddImage(k, d, data) => {
- let data = match data {
- ImageData::Raw(r) => {
- let (sender, receiver) = ipc::bytes_channel().unwrap();
- senders.push((sender, r));
- SerializedImageData::Raw(receiver)
- },
- ImageData::External(e) => SerializedImageData::External(e),
- };
- SerializedImageUpdate::AddImage(k, d, data)
- },
- ImageUpdate::DeleteImage(k) => SerializedImageUpdate::DeleteImage(k),
- ImageUpdate::UpdateImage(k, d, data) => {
- let data = match data {
- ImageData::Raw(r) => {
- let (sender, receiver) = ipc::bytes_channel().unwrap();
- senders.push((sender, r));
- SerializedImageData::Raw(receiver)
- },
- ImageData::External(e) => SerializedImageData::External(e),
- };
- SerializedImageUpdate::UpdateImage(k, d, data)
- },
- })
- .collect();
-
- if let Err(e) = self.0.send(ScriptToCompositorMsg::UpdateImages(updates)) {
- warn!("error sending image updates: {}", e);
- }
-
- senders.into_iter().for_each(|(tx, data)| {
- if let Err(e) = tx.send(&data) {
- warn!("error sending image data: {}", e);
- }
- });
- }
-}
-
-#[derive(Deserialize, Serialize)]
-/// Serializable image updates that must be performed by WebRender.
-pub enum ImageUpdate {
- /// Register a new image.
- AddImage(ImageKey, ImageDescriptor, ImageData),
- /// Delete a previously registered image registration.
- DeleteImage(ImageKey),
- /// Update an existing image registration.
- UpdateImage(ImageKey, ImageDescriptor, ImageData),
-}
-
-#[derive(Deserialize, Serialize)]
-/// Serialized `ImageUpdate`.
-pub enum SerializedImageUpdate {
- /// Register a new image.
- AddImage(ImageKey, ImageDescriptor, SerializedImageData),
- /// Delete a previously registered image registration.
- DeleteImage(ImageKey),
- /// Update an existing image registration.
- UpdateImage(ImageKey, ImageDescriptor, SerializedImageData),
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-/// Serialized `ImageData`. It contains IPC byte channel receiver to prevent from loading bytes too
-/// slow.
-pub enum SerializedImageData {
- /// A simple series of bytes, provided by the embedding and owned by WebRender.
- /// The format is stored out-of-band, currently in ImageDescriptor.
- Raw(ipc::IpcBytesReceiver),
- /// An image owned by the embedding, and referenced by WebRender. This may
- /// take the form of a texture or a heap-allocated buffer.
- External(ExternalImageData),
-}
-
-impl SerializedImageData {
- /// Convert to ``ImageData`.
- pub fn to_image_data(&self) -> Result<ImageData, ipc::IpcError> {
- match self {
- SerializedImageData::Raw(rx) => rx.recv().map(ImageData::new),
- SerializedImageData::External(image) => Ok(ImageData::External(*image)),
- }
- }
-}
-
#[derive(
Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize,
)]
diff --git a/components/shared/script/tests/compositor.rs b/components/shared/script/tests/compositor.rs
index 289f4ffebf1..ee3fd72ad49 100644
--- a/components/shared/script/tests/compositor.rs
+++ b/components/shared/script/tests/compositor.rs
@@ -3,11 +3,11 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use euclid::Size2D;
-use script_traits::compositor::{
- ScrollSensitivity, ScrollTree, ScrollTreeNodeId, ScrollableNodeInfo,
-};
use webrender_api::units::LayoutVector2D;
use webrender_api::{ExternalScrollId, PipelineId, ScrollLocation, SpatialId};
+use webrender_traits::display_list::{
+ ScrollSensitivity, ScrollTree, ScrollTreeNodeId, ScrollableNodeInfo,
+};
fn add_mock_scroll_node(tree: &mut ScrollTree) -> ScrollTreeNodeId {
let pipeline_id = PipelineId(0, 0);
diff --git a/components/shared/script_layout/Cargo.toml b/components/shared/script_layout/Cargo.toml
index 57c4059b859..803a247bc2d 100644
--- a/components/shared/script_layout/Cargo.toml
+++ b/components/shared/script_layout/Cargo.toml
@@ -26,6 +26,7 @@ malloc_size_of = { workspace = true }
malloc_size_of_derive = { workspace = true }
metrics = { path = "../../metrics" }
net_traits = { workspace = true }
+pixels = { path = "../../pixels" }
profile_traits = { workspace = true }
range = { path = "../../range" }
script_traits = { workspace = true }
@@ -37,3 +38,4 @@ servo_url = { path = "../../url" }
style = { workspace = true }
style_traits = { workspace = true }
webrender_api = { workspace = true }
+webrender_traits = { workspace = true }
diff --git a/components/shared/script_layout/lib.rs b/components/shared/script_layout/lib.rs
index 7c1f4ee2162..d07a009af0e 100644
--- a/components/shared/script_layout/lib.rs
+++ b/components/shared/script_layout/lib.rs
@@ -33,7 +33,7 @@ use profile_traits::mem::Report;
use profile_traits::time;
use script_traits::{
ConstellationControlMsg, InitialScriptState, LayoutControlMsg, LayoutMsg, LoadData, Painter,
- ScrollState, UntrustedNodeAddress, WebrenderIpcSender, WindowSizeData,
+ ScrollState, UntrustedNodeAddress, WindowSizeData,
};
use serde::{Deserialize, Serialize};
use servo_arc::Arc as ServoArc;
@@ -51,6 +51,7 @@ use style::stylesheets::Stylesheet;
use style::Atom;
use style_traits::CSSPixel;
use webrender_api::ImageKey;
+use webrender_traits::WebRenderScriptApi;
pub type GenericLayoutData = dyn Any + Send + Sync;
@@ -165,7 +166,7 @@ pub struct LayoutConfig {
pub image_cache: Arc<dyn ImageCache>,
pub font_cache_thread: FontCacheThread,
pub time_profiler_chan: time::ProfilerChan,
- pub webrender_api_sender: WebrenderIpcSender,
+ pub webrender_api_sender: WebRenderScriptApi,
pub paint_time_metrics: PaintTimeMetrics,
pub window_size: WindowSizeData,
}
diff --git a/components/shared/script_layout/wrapper_traits.rs b/components/shared/script_layout/wrapper_traits.rs
index 0adb51be244..399c8bd3362 100644
--- a/components/shared/script_layout/wrapper_traits.rs
+++ b/components/shared/script_layout/wrapper_traits.rs
@@ -12,7 +12,7 @@ use atomic_refcell::AtomicRef;
use base::id::{BrowsingContextId, PipelineId};
use gfx_traits::ByteIndex;
use html5ever::{local_name, namespace_url, ns, LocalName, Namespace};
-use net_traits::image::base::{Image, ImageMetadata};
+use pixels::{Image, ImageMetadata};
use range::Range;
use servo_arc::Arc;
use servo_url::ServoUrl;
diff --git a/components/shared/webrender/Cargo.toml b/components/shared/webrender/Cargo.toml
index f078b96101d..158872b0494 100644
--- a/components/shared/webrender/Cargo.toml
+++ b/components/shared/webrender/Cargo.toml
@@ -11,5 +11,12 @@ name = "webrender_traits"
path = "lib.rs"
[dependencies]
+base = { workspace = true }
+crossbeam-channel = { workspace = true }
+embedder_traits = { workspace = true }
euclid = { workspace = true }
+ipc-channel = { workspace = true }
+log = { workspace = true }
+libc = { workspace = true }
webrender_api = { workspace = true }
+serde = { workspace = true }
diff --git a/components/shared/script/compositor.rs b/components/shared/webrender/display_list.rs
index e66c3bf8227..e66c3bf8227 100644
--- a/components/shared/script/compositor.rs
+++ b/components/shared/webrender/display_list.rs
diff --git a/components/shared/webrender/lib.rs b/components/shared/webrender/lib.rs
index 8af3a17b609..d4883d150e4 100644
--- a/components/shared/webrender/lib.rs
+++ b/components/shared/webrender/lib.rs
@@ -4,14 +4,26 @@
#![deny(unsafe_code)]
+pub mod display_list;
+
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
+use base::id::PipelineId;
+use crossbeam_channel::Sender;
+use display_list::{CompositorDisplayListInfo, ScrollTreeNodeId};
+use embedder_traits::Cursor;
use euclid::default::Size2D;
-use webrender_api::units::TexelRect;
+use ipc_channel::ipc::{self, IpcBytesReceiver, IpcSender};
+use libc::c_void;
+use log::warn;
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
+use webrender_api::units::{DevicePoint, LayoutPoint, TexelRect};
use webrender_api::{
- ExternalImage, ExternalImageHandler, ExternalImageId, ExternalImageSource, FontInstanceFlags,
- FontInstanceKey, FontKey, NativeFontHandle,
+ BuiltDisplayList, BuiltDisplayListDescriptor, ExternalImage, ExternalImageData,
+ ExternalImageHandler, ExternalImageId, ExternalImageSource, ExternalScrollId,
+ FontInstanceFlags, FontInstanceKey, FontKey, HitTestFlags, ImageData, ImageDescriptor,
+ ImageKey, NativeFontHandle, PipelineId as WebRenderPipelineId,
};
/// This trait is used as a bridge between the different GL clients
@@ -178,3 +190,309 @@ pub trait WebRenderFontApi {
fn add_font(&self, data: Arc<Vec<u8>>, index: u32) -> FontKey;
fn add_system_font(&self, handle: NativeFontHandle) -> FontKey;
}
+
+pub enum CanvasToCompositorMsg {
+ GenerateKey(Sender<ImageKey>),
+ UpdateImages(Vec<ImageUpdate>),
+}
+
+pub enum FontToCompositorMsg {
+ AddFontInstance(FontKey, f32, FontInstanceFlags, Sender<FontInstanceKey>),
+ AddFont(Sender<FontKey>, u32, IpcBytesReceiver),
+ AddSystemFont(Sender<FontKey>, NativeFontHandle),
+}
+
+#[derive(Deserialize, Serialize)]
+pub enum NetToCompositorMsg {
+ AddImage(ImageKey, ImageDescriptor, ImageData),
+ GenerateImageKey(IpcSender<ImageKey>),
+}
+
+/// The set of WebRender operations that can be initiated by the content process.
+#[derive(Deserialize, Serialize)]
+pub enum ScriptToCompositorMsg {
+ /// Inform WebRender of the existence of this pipeline.
+ SendInitialTransaction(WebRenderPipelineId),
+ /// Perform a scroll operation.
+ SendScrollNode(WebRenderPipelineId, LayoutPoint, ExternalScrollId),
+ /// Inform WebRender of a new display list for the given pipeline.
+ SendDisplayList {
+ /// The [CompositorDisplayListInfo] that describes the display list being sent.
+ display_list_info: CompositorDisplayListInfo,
+ /// A descriptor of this display list used to construct this display list from raw data.
+ display_list_descriptor: BuiltDisplayListDescriptor,
+ /// An [ipc::IpcBytesReceiver] used to send the raw data of the display list.
+ display_list_receiver: ipc::IpcBytesReceiver,
+ },
+ /// Perform a hit test operation. The result will be returned via
+ /// the provided channel sender.
+ HitTest(
+ Option<WebRenderPipelineId>,
+ DevicePoint,
+ HitTestFlags,
+ IpcSender<Vec<CompositorHitTestResult>>,
+ ),
+ /// Create a new image key. The result will be returned via the
+ /// provided channel sender.
+ GenerateImageKey(IpcSender<ImageKey>),
+ /// Perform a resource update operation.
+ UpdateImages(Vec<SerializedImageUpdate>),
+}
+
+/// A mechanism to send messages from networking to the WebRender instance.
+#[derive(Clone, Deserialize, Serialize)]
+pub struct WebRenderNetApi(IpcSender<NetToCompositorMsg>);
+
+impl WebRenderNetApi {
+ pub fn new(sender: IpcSender<NetToCompositorMsg>) -> Self {
+ Self(sender)
+ }
+
+ pub fn generate_image_key(&self) -> ImageKey {
+ let (sender, receiver) = ipc::channel().unwrap();
+ self.0
+ .send(NetToCompositorMsg::GenerateImageKey(sender))
+ .expect("error sending image key generation");
+ receiver.recv().expect("error receiving image key result")
+ }
+
+ pub fn add_image(&self, key: ImageKey, descriptor: ImageDescriptor, data: ImageData) {
+ if let Err(e) = self
+ .0
+ .send(NetToCompositorMsg::AddImage(key, descriptor, data))
+ {
+ warn!("Error sending image update: {}", e);
+ }
+ }
+}
+
+/// A mechanism to send messages from ScriptThread to the parent process' WebRender instance.
+#[derive(Clone, Deserialize, Serialize)]
+pub struct WebRenderScriptApi(IpcSender<ScriptToCompositorMsg>);
+
+impl WebRenderScriptApi {
+ /// Create a new WebrenderIpcSender object that wraps the provided channel sender.
+ pub fn new(sender: IpcSender<ScriptToCompositorMsg>) -> Self {
+ Self(sender)
+ }
+
+ /// Inform WebRender of the existence of this pipeline.
+ pub fn send_initial_transaction(&self, pipeline: WebRenderPipelineId) {
+ if let Err(e) = self
+ .0
+ .send(ScriptToCompositorMsg::SendInitialTransaction(pipeline))
+ {
+ warn!("Error sending initial transaction: {}", e);
+ }
+ }
+
+ /// Perform a scroll operation.
+ pub fn send_scroll_node(
+ &self,
+ pipeline_id: WebRenderPipelineId,
+ point: LayoutPoint,
+ scroll_id: ExternalScrollId,
+ ) {
+ if let Err(e) = self.0.send(ScriptToCompositorMsg::SendScrollNode(
+ pipeline_id,
+ point,
+ scroll_id,
+ )) {
+ warn!("Error sending scroll node: {}", e);
+ }
+ }
+
+ /// Inform WebRender of a new display list for the given pipeline.
+ pub fn send_display_list(
+ &self,
+ display_list_info: CompositorDisplayListInfo,
+ list: BuiltDisplayList,
+ ) {
+ 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(ScriptToCompositorMsg::SendDisplayList {
+ display_list_info,
+ display_list_descriptor,
+ display_list_receiver,
+ }) {
+ warn!("Error sending display list: {}", e);
+ }
+
+ if let Err(error) = display_list_sender.send(&display_list_data.items_data) {
+ warn!("Error sending display list items: {}", error);
+ }
+ if let Err(error) = display_list_sender.send(&display_list_data.cache_data) {
+ warn!("Error sending display list cache data: {}", error);
+ }
+ if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) {
+ warn!("Error sending display spatial tree: {}", error);
+ }
+ }
+
+ /// Perform a hit test operation. Blocks until the operation is complete and
+ /// and a result is available.
+ pub fn hit_test(
+ &self,
+ pipeline: Option<WebRenderPipelineId>,
+ point: DevicePoint,
+ flags: HitTestFlags,
+ ) -> Vec<CompositorHitTestResult> {
+ let (sender, receiver) = ipc::channel().unwrap();
+ self.0
+ .send(ScriptToCompositorMsg::HitTest(
+ pipeline, point, flags, sender,
+ ))
+ .expect("error sending hit test");
+ receiver.recv().expect("error receiving hit test result")
+ }
+
+ /// 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(ScriptToCompositorMsg::GenerateImageKey(sender))
+ .ok()?;
+ receiver.recv().ok()
+ }
+
+ /// Perform a resource update operation.
+ pub fn update_images(&self, updates: Vec<ImageUpdate>) {
+ let mut senders = Vec::new();
+ // Convert `ImageUpdate` to `SerializedImageUpdate` because `ImageData` may contain large
+ // byes. With this conversion, we send `IpcBytesReceiver` instead and use it to send the
+ // actual bytes.
+ let updates = updates
+ .into_iter()
+ .map(|update| match update {
+ ImageUpdate::AddImage(k, d, data) => {
+ let data = match data {
+ ImageData::Raw(r) => {
+ let (sender, receiver) = ipc::bytes_channel().unwrap();
+ senders.push((sender, r));
+ SerializedImageData::Raw(receiver)
+ },
+ ImageData::External(e) => SerializedImageData::External(e),
+ };
+ SerializedImageUpdate::AddImage(k, d, data)
+ },
+ ImageUpdate::DeleteImage(k) => SerializedImageUpdate::DeleteImage(k),
+ ImageUpdate::UpdateImage(k, d, data) => {
+ let data = match data {
+ ImageData::Raw(r) => {
+ let (sender, receiver) = ipc::bytes_channel().unwrap();
+ senders.push((sender, r));
+ SerializedImageData::Raw(receiver)
+ },
+ ImageData::External(e) => SerializedImageData::External(e),
+ };
+ SerializedImageUpdate::UpdateImage(k, d, data)
+ },
+ })
+ .collect();
+
+ if let Err(e) = self.0.send(ScriptToCompositorMsg::UpdateImages(updates)) {
+ warn!("error sending image updates: {}", e);
+ }
+
+ senders.into_iter().for_each(|(tx, data)| {
+ if let Err(e) = tx.send(&data) {
+ warn!("error sending image data: {}", e);
+ }
+ });
+ }
+}
+
+#[derive(Deserialize, Serialize)]
+/// Serializable image updates that must be performed by WebRender.
+pub enum ImageUpdate {
+ /// Register a new image.
+ AddImage(ImageKey, ImageDescriptor, ImageData),
+ /// Delete a previously registered image registration.
+ DeleteImage(ImageKey),
+ /// Update an existing image registration.
+ UpdateImage(ImageKey, ImageDescriptor, ImageData),
+}
+
+#[derive(Deserialize, Serialize)]
+/// Serialized `ImageUpdate`.
+pub enum SerializedImageUpdate {
+ /// Register a new image.
+ AddImage(ImageKey, ImageDescriptor, SerializedImageData),
+ /// Delete a previously registered image registration.
+ DeleteImage(ImageKey),
+ /// Update an existing image registration.
+ UpdateImage(ImageKey, ImageDescriptor, SerializedImageData),
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+/// Serialized `ImageData`. It contains IPC byte channel receiver to prevent from loading bytes too
+/// slow.
+pub enum SerializedImageData {
+ /// A simple series of bytes, provided by the embedding and owned by WebRender.
+ /// The format is stored out-of-band, currently in ImageDescriptor.
+ Raw(ipc::IpcBytesReceiver),
+ /// An image owned by the embedding, and referenced by WebRender. This may
+ /// take the form of a texture or a heap-allocated buffer.
+ External(ExternalImageData),
+}
+
+impl SerializedImageData {
+ /// Convert to ``ImageData`.
+ pub fn to_image_data(&self) -> Result<ImageData, ipc::IpcError> {
+ match self {
+ SerializedImageData::Raw(rx) => rx.recv().map(ImageData::new),
+ SerializedImageData::External(image) => Ok(ImageData::External(*image)),
+ }
+ }
+}
+
+/// The address of a node. Layout sends these back. They must be validated via
+/// `from_untrusted_node_address` before they can be used, because we do not trust layout.
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub struct UntrustedNodeAddress(pub *const c_void);
+
+#[allow(unsafe_code)]
+unsafe impl Send for UntrustedNodeAddress {}
+
+impl Serialize for UntrustedNodeAddress {
+ fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
+ (self.0 as usize).serialize(s)
+ }
+}
+
+impl<'de> Deserialize<'de> for UntrustedNodeAddress {
+ fn deserialize<D: Deserializer<'de>>(d: D) -> Result<UntrustedNodeAddress, D::Error> {
+ let value: usize = Deserialize::deserialize(d)?;
+ Ok(UntrustedNodeAddress::from_id(value))
+ }
+}
+
+impl UntrustedNodeAddress {
+ /// Creates an `UntrustedNodeAddress` from the given pointer address value.
+ #[inline]
+ pub fn from_id(id: usize) -> UntrustedNodeAddress {
+ UntrustedNodeAddress(id as *const c_void)
+ }
+}
+
+/// The result of a hit test in the compositor.
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct CompositorHitTestResult {
+ /// The pipeline id of the resulting item.
+ pub pipeline_id: PipelineId,
+
+ /// The hit test point in the item's viewport.
+ pub point_in_viewport: euclid::default::Point2D<f32>,
+
+ /// The hit test point relative to the item itself.
+ pub point_relative_to_item: euclid::default::Point2D<f32>,
+
+ /// The node address of the hit test result.
+ pub node: UntrustedNodeAddress,
+
+ /// The cursor that should be used when hovering the item hit by the hit test.
+ pub cursor: Option<Cursor>,
+
+ /// The scroll tree node associated with this hit test item.
+ pub scroll_tree_node: ScrollTreeNodeId,
+}