mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +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
|
@ -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"] }
|
||||
|
|
|
@ -1,334 +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/. */
|
||||
|
||||
//! Defines data structures which are consumed by the Compositor.
|
||||
|
||||
use embedder_traits::Cursor;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use webrender_api::units::{LayoutSize, LayoutVector2D};
|
||||
use webrender_api::{Epoch, ExternalScrollId, PipelineId, ScrollLocation, SpatialId};
|
||||
|
||||
/// The scroll sensitivity of a scroll node ie whether it can be scrolled due to input event and
|
||||
/// script events or only script events.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum ScrollSensitivity {
|
||||
/// This node can be scrolled by input and script events.
|
||||
ScriptAndInputEvents,
|
||||
/// This node can only be scrolled by script events.
|
||||
Script,
|
||||
}
|
||||
|
||||
/// Information that Servo keeps alongside WebRender display items
|
||||
/// in order to add more context to hit test results.
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct HitTestInfo {
|
||||
/// The id of the node of this hit test item.
|
||||
pub node: u64,
|
||||
|
||||
/// The cursor of this node's hit test item.
|
||||
pub cursor: Option<Cursor>,
|
||||
|
||||
/// The id of the [ScrollTree] associated with this hit test item.
|
||||
pub scroll_tree_node: ScrollTreeNodeId,
|
||||
}
|
||||
|
||||
/// An id for a ScrollTreeNode in the ScrollTree. This contains both the index
|
||||
/// to the node in the tree's array of nodes as well as the corresponding SpatialId
|
||||
/// for the SpatialNode in the WebRender display list.
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ScrollTreeNodeId {
|
||||
/// The index of this scroll tree node in the tree's array of nodes.
|
||||
pub index: usize,
|
||||
|
||||
/// The WebRender spatial id of this scroll tree node.
|
||||
pub spatial_id: SpatialId,
|
||||
}
|
||||
|
||||
/// Data stored for nodes in the [ScrollTree] that actually scroll,
|
||||
/// as opposed to reference frames and sticky nodes which do not.
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct ScrollableNodeInfo {
|
||||
/// The external scroll id of this node, used to track
|
||||
/// it between successive re-layouts.
|
||||
pub external_id: ExternalScrollId,
|
||||
|
||||
/// Amount that this `ScrollableNode` can scroll in both directions.
|
||||
pub scrollable_size: LayoutSize,
|
||||
|
||||
/// Whether this `ScrollableNode` is sensitive to input events.
|
||||
pub scroll_sensitivity: ScrollSensitivity,
|
||||
|
||||
/// The current offset of this scroll node.
|
||||
pub offset: LayoutVector2D,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
/// A node in a tree of scroll nodes. This may either be a scrollable
|
||||
/// node which responds to scroll events or a non-scrollable one.
|
||||
pub struct ScrollTreeNode {
|
||||
/// The index of the parent of this node in the tree. If this is
|
||||
/// None then this is the root node.
|
||||
pub parent: Option<ScrollTreeNodeId>,
|
||||
|
||||
/// Scrolling data which will not be None if this is a scrolling node.
|
||||
pub scroll_info: Option<ScrollableNodeInfo>,
|
||||
}
|
||||
|
||||
impl ScrollTreeNode {
|
||||
/// Get the external id of this node.
|
||||
pub fn external_id(&self) -> Option<ExternalScrollId> {
|
||||
self.scroll_info.as_ref().map(|info| info.external_id)
|
||||
}
|
||||
|
||||
/// Get the offset id of this node if it applies.
|
||||
pub fn offset(&self) -> Option<LayoutVector2D> {
|
||||
self.scroll_info.as_ref().map(|info| info.offset)
|
||||
}
|
||||
|
||||
/// Set the offset for this node, returns false if this was a
|
||||
/// non-scrolling node for which you cannot set the offset.
|
||||
pub fn set_offset(&mut self, new_offset: LayoutVector2D) -> bool {
|
||||
match self.scroll_info {
|
||||
Some(ref mut info) => {
|
||||
info.offset = new_offset;
|
||||
true
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Scroll this node given a WebRender ScrollLocation. Returns a tuple that can
|
||||
/// be used to scroll an individual WebRender scroll frame if the operation
|
||||
/// actually changed an offset.
|
||||
pub fn scroll(
|
||||
&mut self,
|
||||
scroll_location: ScrollLocation,
|
||||
) -> Option<(ExternalScrollId, LayoutVector2D)> {
|
||||
let info = match self.scroll_info {
|
||||
Some(ref mut data) => data,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
if info.scroll_sensitivity != ScrollSensitivity::ScriptAndInputEvents {
|
||||
return None;
|
||||
}
|
||||
|
||||
let delta = match scroll_location {
|
||||
ScrollLocation::Delta(delta) => delta,
|
||||
ScrollLocation::Start => {
|
||||
if info.offset.y.round() >= 0.0 {
|
||||
// Nothing to do on this layer.
|
||||
return None;
|
||||
}
|
||||
|
||||
info.offset.y = 0.0;
|
||||
return Some((info.external_id, info.offset));
|
||||
},
|
||||
ScrollLocation::End => {
|
||||
let end_pos = -info.scrollable_size.height;
|
||||
if info.offset.y.round() <= end_pos {
|
||||
// Nothing to do on this layer.
|
||||
return None;
|
||||
}
|
||||
|
||||
info.offset.y = end_pos;
|
||||
return Some((info.external_id, info.offset));
|
||||
},
|
||||
};
|
||||
|
||||
let scrollable_width = info.scrollable_size.width;
|
||||
let scrollable_height = info.scrollable_size.height;
|
||||
let original_layer_scroll_offset = info.offset;
|
||||
|
||||
if scrollable_width > 0. {
|
||||
info.offset.x = (info.offset.x + delta.x).min(0.0).max(-scrollable_width);
|
||||
}
|
||||
|
||||
if scrollable_height > 0. {
|
||||
info.offset.y = (info.offset.y + delta.y).min(0.0).max(-scrollable_height);
|
||||
}
|
||||
|
||||
if info.offset != original_layer_scroll_offset {
|
||||
Some((info.external_id, info.offset))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A tree of spatial nodes, which mirrors the spatial nodes in the WebRender
|
||||
/// display list, except these are used to scrolling in the compositor so that
|
||||
/// new offsets can be sent to WebRender.
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
pub struct ScrollTree {
|
||||
/// A list of compositor-side scroll nodes that describe the tree
|
||||
/// of WebRender spatial nodes, used by the compositor to scroll the
|
||||
/// contents of the display list.
|
||||
pub nodes: Vec<ScrollTreeNode>,
|
||||
}
|
||||
|
||||
impl ScrollTree {
|
||||
/// Add a scroll node to this ScrollTree returning the id of the new node.
|
||||
pub fn add_scroll_tree_node(
|
||||
&mut self,
|
||||
parent: Option<&ScrollTreeNodeId>,
|
||||
spatial_id: SpatialId,
|
||||
scroll_info: Option<ScrollableNodeInfo>,
|
||||
) -> ScrollTreeNodeId {
|
||||
self.nodes.push(ScrollTreeNode {
|
||||
parent: parent.cloned(),
|
||||
scroll_info,
|
||||
});
|
||||
ScrollTreeNodeId {
|
||||
index: self.nodes.len() - 1,
|
||||
spatial_id,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a mutable reference to the node with the given index.
|
||||
pub fn get_node_mut(&mut self, id: &ScrollTreeNodeId) -> &mut ScrollTreeNode {
|
||||
&mut self.nodes[id.index]
|
||||
}
|
||||
|
||||
/// Get an immutable reference to the node with the given index.
|
||||
pub fn get_node(&mut self, id: &ScrollTreeNodeId) -> &ScrollTreeNode {
|
||||
&self.nodes[id.index]
|
||||
}
|
||||
|
||||
/// Scroll the given scroll node on this scroll tree. If the node cannot be scrolled,
|
||||
/// because it isn't a scrollable node or it's already scrolled to the maximum scroll
|
||||
/// extent, try to scroll an ancestor of this node. Returns the node scrolled and the
|
||||
/// new offset if a scroll was performed, otherwise returns None.
|
||||
pub fn scroll_node_or_ancestor(
|
||||
&mut self,
|
||||
scroll_node_id: &ScrollTreeNodeId,
|
||||
scroll_location: ScrollLocation,
|
||||
) -> Option<(ExternalScrollId, LayoutVector2D)> {
|
||||
let parent = {
|
||||
let node = &mut self.get_node_mut(scroll_node_id);
|
||||
let result = node.scroll(scroll_location);
|
||||
if result.is_some() {
|
||||
return result;
|
||||
}
|
||||
node.parent
|
||||
};
|
||||
|
||||
parent.and_then(|parent| self.scroll_node_or_ancestor(&parent, scroll_location))
|
||||
}
|
||||
|
||||
/// Given an [`ExternalScrollId`] and an offset, update the scroll offset of the scroll node
|
||||
/// with the given id.
|
||||
pub fn set_scroll_offsets_for_node_with_external_scroll_id(
|
||||
&mut self,
|
||||
external_scroll_id: ExternalScrollId,
|
||||
offset: LayoutVector2D,
|
||||
) -> bool {
|
||||
for node in self.nodes.iter_mut() {
|
||||
match node.scroll_info {
|
||||
Some(ref mut scroll_info) if scroll_info.external_id == external_scroll_id => {
|
||||
scroll_info.offset = offset;
|
||||
return true;
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// A data structure which stores compositor-side information about
|
||||
/// display lists sent to the compositor.
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct CompositorDisplayListInfo {
|
||||
/// The WebRender [PipelineId] of this display list.
|
||||
pub pipeline_id: PipelineId,
|
||||
|
||||
/// The size of the viewport that this display list renders into.
|
||||
pub viewport_size: LayoutSize,
|
||||
|
||||
/// The size of this display list's content.
|
||||
pub content_size: LayoutSize,
|
||||
|
||||
/// The epoch of the display list.
|
||||
pub epoch: Epoch,
|
||||
|
||||
/// An array of `HitTestInfo` which is used to store information
|
||||
/// to assist the compositor to take various actions (set the cursor,
|
||||
/// scroll without layout) using a WebRender hit test result.
|
||||
pub hit_test_info: Vec<HitTestInfo>,
|
||||
|
||||
/// A ScrollTree used by the compositor to scroll the contents of the
|
||||
/// display list.
|
||||
pub scroll_tree: ScrollTree,
|
||||
|
||||
/// The `ScrollTreeNodeId` of the root reference frame of this info's scroll
|
||||
/// tree.
|
||||
pub root_reference_frame_id: ScrollTreeNodeId,
|
||||
|
||||
/// The `ScrollTreeNodeId` of the topmost scrolling frame of this info's scroll
|
||||
/// tree.
|
||||
pub root_scroll_node_id: ScrollTreeNodeId,
|
||||
}
|
||||
|
||||
impl CompositorDisplayListInfo {
|
||||
/// Create a new CompositorDisplayListInfo with the root reference frame
|
||||
/// and scroll frame already added to the scroll tree.
|
||||
pub fn new(
|
||||
viewport_size: LayoutSize,
|
||||
content_size: LayoutSize,
|
||||
pipeline_id: PipelineId,
|
||||
epoch: Epoch,
|
||||
root_scroll_sensitivity: ScrollSensitivity,
|
||||
) -> Self {
|
||||
let mut scroll_tree = ScrollTree::default();
|
||||
let root_reference_frame_id = scroll_tree.add_scroll_tree_node(
|
||||
None,
|
||||
SpatialId::root_reference_frame(pipeline_id),
|
||||
None,
|
||||
);
|
||||
let root_scroll_node_id = scroll_tree.add_scroll_tree_node(
|
||||
Some(&root_reference_frame_id),
|
||||
SpatialId::root_scroll_node(pipeline_id),
|
||||
Some(ScrollableNodeInfo {
|
||||
external_id: ExternalScrollId(0, pipeline_id),
|
||||
scrollable_size: content_size - viewport_size,
|
||||
scroll_sensitivity: root_scroll_sensitivity,
|
||||
offset: LayoutVector2D::zero(),
|
||||
}),
|
||||
);
|
||||
|
||||
CompositorDisplayListInfo {
|
||||
pipeline_id,
|
||||
viewport_size,
|
||||
content_size,
|
||||
epoch,
|
||||
hit_test_info: Default::default(),
|
||||
scroll_tree,
|
||||
root_reference_frame_id,
|
||||
root_scroll_node_id,
|
||||
}
|
||||
}
|
||||
|
||||
/// Add or re-use a duplicate HitTestInfo entry in this `CompositorHitTestInfo`
|
||||
/// and return the index.
|
||||
pub fn add_hit_test_info(
|
||||
&mut self,
|
||||
node: u64,
|
||||
cursor: Option<Cursor>,
|
||||
scroll_tree_node: ScrollTreeNodeId,
|
||||
) -> usize {
|
||||
if let Some(last) = self.hit_test_info.last() {
|
||||
if node == last.node && cursor == last.cursor {
|
||||
return self.hit_test_info.len() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
self.hit_test_info.push(HitTestInfo {
|
||||
node,
|
||||
cursor,
|
||||
scroll_tree_node,
|
||||
});
|
||||
self.hit_test_info.len() - 1
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue