mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
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>
This commit is contained in:
parent
c2076580f3
commit
2af6fe0b30
53 changed files with 666 additions and 617 deletions
|
@ -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 }
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -39,3 +39,4 @@ servo_url = { path = "../../url" }
|
|||
url = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
webrender_api = { workspace = true }
|
||||
webrender_traits = { workspace = true }
|
||||
|
|
|
@ -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"
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
|
@ -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"] }
|
||||
|
|
|
@ -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,
|
||||
)]
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue