mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00: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
28
Cargo.lock
generated
28
Cargo.lock
generated
|
@ -879,6 +879,7 @@ dependencies = [
|
|||
"toml 0.5.11",
|
||||
"webrender",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
"webxr",
|
||||
]
|
||||
|
||||
|
@ -887,7 +888,6 @@ name = "compositing_traits"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"base",
|
||||
"canvas",
|
||||
"crossbeam-channel",
|
||||
"embedder_traits",
|
||||
"euclid",
|
||||
|
@ -895,11 +895,12 @@ dependencies = [
|
|||
"ipc-channel",
|
||||
"keyboard-types",
|
||||
"log",
|
||||
"net_traits",
|
||||
"pixels",
|
||||
"script_traits",
|
||||
"servo_url",
|
||||
"style_traits",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3239,6 +3240,7 @@ dependencies = [
|
|||
"malloc_size_of_derive",
|
||||
"net_traits",
|
||||
"parking_lot",
|
||||
"pixels",
|
||||
"profile_traits",
|
||||
"range",
|
||||
"rayon",
|
||||
|
@ -3258,6 +3260,7 @@ dependencies = [
|
|||
"unicode-bidi",
|
||||
"unicode-script",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
"xi-unicode",
|
||||
]
|
||||
|
||||
|
@ -3284,6 +3287,7 @@ dependencies = [
|
|||
"log",
|
||||
"net_traits",
|
||||
"parking_lot",
|
||||
"pixels",
|
||||
"quickcheck",
|
||||
"range",
|
||||
"rayon",
|
||||
|
@ -3301,6 +3305,7 @@ dependencies = [
|
|||
"unicode-segmentation",
|
||||
"url",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
"xi-unicode",
|
||||
]
|
||||
|
||||
|
@ -3342,6 +3347,7 @@ dependencies = [
|
|||
"time 0.1.45",
|
||||
"url",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3378,6 +3384,7 @@ dependencies = [
|
|||
"style_traits",
|
||||
"url",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4026,6 +4033,7 @@ dependencies = [
|
|||
"uuid",
|
||||
"webpki-roots",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4058,6 +4066,7 @@ dependencies = [
|
|||
"url",
|
||||
"uuid",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4527,9 +4536,13 @@ name = "pixels"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"euclid",
|
||||
"image",
|
||||
"ipc-channel",
|
||||
"log",
|
||||
"malloc_size_of",
|
||||
"malloc_size_of_derive",
|
||||
"serde",
|
||||
"webrender_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5123,6 +5136,7 @@ dependencies = [
|
|||
"webdriver",
|
||||
"webgpu",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
"webxr-api",
|
||||
"xml5ever",
|
||||
]
|
||||
|
@ -5146,6 +5160,7 @@ dependencies = [
|
|||
"malloc_size_of_derive",
|
||||
"metrics",
|
||||
"net_traits",
|
||||
"pixels",
|
||||
"profile_traits",
|
||||
"range",
|
||||
"script_traits",
|
||||
|
@ -5157,6 +5172,7 @@ dependencies = [
|
|||
"style",
|
||||
"style_traits",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5206,6 +5222,7 @@ dependencies = [
|
|||
"webdriver",
|
||||
"webgpu",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
"webxr-api",
|
||||
]
|
||||
|
||||
|
@ -7186,7 +7203,14 @@ dependencies = [
|
|||
name = "webrender_traits"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"base",
|
||||
"crossbeam-channel",
|
||||
"embedder_traits",
|
||||
"euclid",
|
||||
"ipc-channel",
|
||||
"libc",
|
||||
"log",
|
||||
"serde",
|
||||
"webrender_api",
|
||||
]
|
||||
|
||||
|
|
|
@ -26,8 +26,9 @@ use style::values::computed::font;
|
|||
use style_traits::values::ToCss;
|
||||
use webrender_api::units::{DeviceIntSize, RectExt as RectExt_};
|
||||
use webrender_api::{ImageData, ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey};
|
||||
use webrender_traits::ImageUpdate;
|
||||
|
||||
use crate::canvas_paint_thread::{AntialiasMode, ImageUpdate, WebrenderApi};
|
||||
use crate::canvas_paint_thread::{AntialiasMode, WebrenderApi};
|
||||
use crate::raqote_backend::Repetition;
|
||||
|
||||
/// The canvas data stores a state machine for the current status of
|
||||
|
@ -1082,13 +1083,13 @@ impl<'a> CanvasData<'a> {
|
|||
match self.image_key {
|
||||
Some(image_key) => {
|
||||
debug!("Updating image {:?}.", image_key);
|
||||
updates.push(ImageUpdate::Update(image_key, descriptor, data));
|
||||
updates.push(ImageUpdate::UpdateImage(image_key, descriptor, data));
|
||||
},
|
||||
None => {
|
||||
let Some(key) = self.webrender_api.generate_key() else {
|
||||
return;
|
||||
};
|
||||
updates.push(ImageUpdate::Add(key, descriptor, data));
|
||||
updates.push(ImageUpdate::AddImage(key, descriptor, data));
|
||||
self.image_key = Some(key);
|
||||
debug!("New image {:?}.", self.image_key);
|
||||
},
|
||||
|
@ -1097,7 +1098,7 @@ impl<'a> CanvasData<'a> {
|
|||
if let Some(image_key) =
|
||||
mem::replace(&mut self.very_old_image_key, self.old_image_key.take())
|
||||
{
|
||||
updates.push(ImageUpdate::Delete(image_key));
|
||||
updates.push(ImageUpdate::DeleteImage(image_key));
|
||||
}
|
||||
|
||||
self.webrender_api.update_images(updates);
|
||||
|
@ -1215,10 +1216,10 @@ impl<'a> Drop for CanvasData<'a> {
|
|||
fn drop(&mut self) {
|
||||
let mut updates = vec![];
|
||||
if let Some(image_key) = self.old_image_key.take() {
|
||||
updates.push(ImageUpdate::Delete(image_key));
|
||||
updates.push(ImageUpdate::DeleteImage(image_key));
|
||||
}
|
||||
if let Some(image_key) = self.very_old_image_key.take() {
|
||||
updates.push(ImageUpdate::Delete(image_key));
|
||||
updates.push(ImageUpdate::DeleteImage(image_key));
|
||||
}
|
||||
|
||||
self.webrender_api.update_images(updates);
|
||||
|
|
|
@ -16,7 +16,8 @@ use gfx::font_context::FontContext;
|
|||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use ipc_channel::router::ROUTER;
|
||||
use log::warn;
|
||||
use webrender_api::{ImageData, ImageDescriptor, ImageKey};
|
||||
use webrender_api::ImageKey;
|
||||
use webrender_traits::ImageUpdate;
|
||||
|
||||
use crate::canvas_data::*;
|
||||
|
||||
|
@ -25,12 +26,6 @@ pub enum AntialiasMode {
|
|||
None,
|
||||
}
|
||||
|
||||
pub enum ImageUpdate {
|
||||
Add(ImageKey, ImageDescriptor, ImageData),
|
||||
Update(ImageKey, ImageDescriptor, ImageData),
|
||||
Delete(ImageKey),
|
||||
}
|
||||
|
||||
pub trait WebrenderApi {
|
||||
/// Attempt to generate an [`ImageKey`], returning `None` in case of failure.
|
||||
fn generate_key(&self) -> Option<ImageKey>;
|
||||
|
|
|
@ -43,6 +43,7 @@ style_traits = { workspace = true }
|
|||
time = { workspace = true }
|
||||
webrender = { workspace = true }
|
||||
webrender_api = { workspace = true }
|
||||
webrender_traits = { workspace = true }
|
||||
webxr = { git = "https://github.com/servo/webxr" }
|
||||
|
||||
[build-dependencies]
|
||||
|
|
|
@ -13,10 +13,9 @@ use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
|||
|
||||
use base::id::{PipelineId, TopLevelBrowsingContextId, WebViewId};
|
||||
use base::{Epoch, WebRenderEpochToU16};
|
||||
use canvas::canvas_paint_thread::ImageUpdate;
|
||||
use compositing_traits::{
|
||||
CanvasToCompositorMsg, CompositionPipeline, CompositorMsg, CompositorReceiver,
|
||||
ConstellationMsg, FontToCompositorMsg, ForwardedToCompositorMsg, SendableFrameTree,
|
||||
CompositionPipeline, CompositorMsg, CompositorReceiver, ConstellationMsg,
|
||||
ForwardedToCompositorMsg, SendableFrameTree,
|
||||
};
|
||||
use crossbeam_channel::Sender;
|
||||
use embedder_traits::Cursor;
|
||||
|
@ -27,16 +26,13 @@ use image::{DynamicImage, ImageFormat};
|
|||
use ipc_channel::ipc;
|
||||
use libc::c_void;
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use net_traits::image::base::Image;
|
||||
use net_traits::image_cache::CorsStatus;
|
||||
use pixels::PixelFormat;
|
||||
use pixels::{CorsStatus, Image, PixelFormat};
|
||||
use profile_traits::time::{self as profile_time, profile, ProfilerCategory};
|
||||
use script_traits::compositor::{HitTestInfo, ScrollTree};
|
||||
use script_traits::CompositorEvent::{MouseButtonEvent, MouseMoveEvent, TouchEvent, WheelEvent};
|
||||
use script_traits::{
|
||||
AnimationState, AnimationTickType, CompositorHitTestResult, ConstellationControlMsg,
|
||||
LayoutControlMsg, MouseButton, MouseEventType, ScrollState, TouchEventType, TouchId,
|
||||
UntrustedNodeAddress, WheelDelta, WindowSizeData, WindowSizeType,
|
||||
AnimationState, AnimationTickType, ConstellationControlMsg, LayoutControlMsg, MouseButton,
|
||||
MouseEventType, ScrollState, TouchEventType, TouchId, WheelDelta, WindowSizeData,
|
||||
WindowSizeType,
|
||||
};
|
||||
use servo_geometry::{DeviceIndependentPixel, FramebufferUintLength};
|
||||
use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor};
|
||||
|
@ -51,6 +47,11 @@ use webrender_api::{
|
|||
PropertyBinding, ReferenceFrameKind, RenderReasons, SampledScrollOffset, ScrollLocation,
|
||||
SpaceAndClipInfo, SpatialId, SpatialTreeItemKey, TransformStyle,
|
||||
};
|
||||
use webrender_traits::display_list::{HitTestInfo, ScrollTree};
|
||||
use webrender_traits::{
|
||||
CanvasToCompositorMsg, CompositorHitTestResult, FontToCompositorMsg, ImageUpdate,
|
||||
NetToCompositorMsg, ScriptToCompositorMsg, SerializedImageUpdate, UntrustedNodeAddress,
|
||||
};
|
||||
|
||||
use crate::gl::RenderTargetInfo;
|
||||
use crate::touch::{TouchAction, TouchHandler};
|
||||
|
@ -695,9 +696,9 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
/// instance in the parent process.
|
||||
fn handle_webrender_message(&mut self, msg: ForwardedToCompositorMsg) {
|
||||
match msg {
|
||||
ForwardedToCompositorMsg::Layout(
|
||||
script_traits::ScriptToCompositorMsg::SendInitialTransaction(pipeline),
|
||||
) => {
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::SendInitialTransaction(
|
||||
pipeline,
|
||||
)) => {
|
||||
let mut txn = Transaction::new();
|
||||
txn.set_display_list(WebRenderEpoch(0), (pipeline, Default::default()));
|
||||
self.generate_frame(&mut txn, RenderReasons::SCENE);
|
||||
|
@ -705,13 +706,11 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(
|
||||
script_traits::ScriptToCompositorMsg::SendScrollNode(
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::SendScrollNode(
|
||||
pipeline_id,
|
||||
point,
|
||||
external_scroll_id,
|
||||
),
|
||||
) => {
|
||||
)) => {
|
||||
let pipeline_id = pipeline_id.into();
|
||||
let pipeline_details = match self.pipeline_details.get_mut(&pipeline_id) {
|
||||
Some(details) => details,
|
||||
|
@ -743,13 +742,11 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(
|
||||
script_traits::ScriptToCompositorMsg::SendDisplayList {
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::SendDisplayList {
|
||||
display_list_info,
|
||||
display_list_descriptor,
|
||||
display_list_receiver,
|
||||
},
|
||||
) => {
|
||||
}) => {
|
||||
// This must match the order from the sender, currently in `shared/script/lib.rs`.
|
||||
let items_data = match display_list_receiver.recv() {
|
||||
Ok(display_list_data) => display_list_data,
|
||||
|
@ -799,7 +796,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.send_transaction(self.webrender_document, transaction);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(script_traits::ScriptToCompositorMsg::HitTest(
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::HitTest(
|
||||
pipeline,
|
||||
point,
|
||||
flags,
|
||||
|
@ -821,31 +818,23 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
let _ = sender.send(result);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(
|
||||
script_traits::ScriptToCompositorMsg::GenerateImageKey(sender),
|
||||
) |
|
||||
ForwardedToCompositorMsg::Net(net_traits::NetToCompositorMsg::GenerateImageKey(
|
||||
sender,
|
||||
)) => {
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::GenerateImageKey(sender)) |
|
||||
ForwardedToCompositorMsg::Net(NetToCompositorMsg::GenerateImageKey(sender)) => {
|
||||
let _ = sender.send(self.webrender_api.generate_image_key());
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Layout(
|
||||
script_traits::ScriptToCompositorMsg::UpdateImages(updates),
|
||||
) => {
|
||||
ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::UpdateImages(updates)) => {
|
||||
let mut txn = Transaction::new();
|
||||
for update in updates {
|
||||
match update {
|
||||
script_traits::SerializedImageUpdate::AddImage(key, desc, data) => {
|
||||
SerializedImageUpdate::AddImage(key, desc, data) => {
|
||||
match data.to_image_data() {
|
||||
Ok(data) => txn.add_image(key, desc, data, None),
|
||||
Err(e) => warn!("error when sending image data: {:?}", e),
|
||||
}
|
||||
},
|
||||
script_traits::SerializedImageUpdate::DeleteImage(key) => {
|
||||
txn.delete_image(key)
|
||||
},
|
||||
script_traits::SerializedImageUpdate::UpdateImage(key, desc, data) => {
|
||||
SerializedImageUpdate::DeleteImage(key) => txn.delete_image(key),
|
||||
SerializedImageUpdate::UpdateImage(key, desc, data) => {
|
||||
match data.to_image_data() {
|
||||
Ok(data) => txn.update_image(key, desc, data, &DirtyRect::All),
|
||||
Err(e) => warn!("error when sending image data: {:?}", e),
|
||||
|
@ -857,11 +846,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.send_transaction(self.webrender_document, txn);
|
||||
},
|
||||
|
||||
ForwardedToCompositorMsg::Net(net_traits::NetToCompositorMsg::AddImage(
|
||||
key,
|
||||
desc,
|
||||
data,
|
||||
)) => {
|
||||
ForwardedToCompositorMsg::Net(NetToCompositorMsg::AddImage(key, desc, data)) => {
|
||||
let mut txn = Transaction::new();
|
||||
txn.add_image(key, desc, data, None);
|
||||
self.webrender_api
|
||||
|
@ -929,13 +914,13 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
let mut txn = Transaction::new();
|
||||
for update in updates {
|
||||
match update {
|
||||
ImageUpdate::Add(key, descriptor, data) => {
|
||||
ImageUpdate::AddImage(key, descriptor, data) => {
|
||||
txn.add_image(key, descriptor, data, None)
|
||||
},
|
||||
ImageUpdate::Update(key, descriptor, data) => {
|
||||
ImageUpdate::UpdateImage(key, descriptor, data) => {
|
||||
txn.update_image(key, descriptor, data, &DirtyRect::All)
|
||||
},
|
||||
ImageUpdate::Delete(key) => txn.delete_image(key),
|
||||
ImageUpdate::DeleteImage(key) => txn.delete_image(key),
|
||||
}
|
||||
}
|
||||
self.webrender_api
|
||||
|
@ -1469,7 +1454,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
event_type,
|
||||
button,
|
||||
result.point_in_viewport.to_untyped(),
|
||||
Some(result.node),
|
||||
Some(result.node.into()),
|
||||
Some(result.point_relative_to_item),
|
||||
button as u16,
|
||||
);
|
||||
|
@ -1549,7 +1534,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
None => return,
|
||||
};
|
||||
|
||||
let event = MouseMoveEvent(result.point_in_viewport, Some(result.node), 0);
|
||||
let event = MouseMoveEvent(result.point_in_viewport, Some(result.node.into()), 0);
|
||||
let msg = ConstellationMsg::ForwardEvent(result.pipeline_id, event);
|
||||
if let Err(e) = self.constellation_chan.send(msg) {
|
||||
warn!("Sending event to constellation failed ({:?}).", e);
|
||||
|
@ -1568,7 +1553,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
event_type,
|
||||
identifier,
|
||||
result.point_in_viewport,
|
||||
Some(result.node),
|
||||
Some(result.node.into()),
|
||||
);
|
||||
let msg = ConstellationMsg::ForwardEvent(result.pipeline_id, event);
|
||||
if let Err(e) = self.constellation_chan.send(msg) {
|
||||
|
@ -1579,7 +1564,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
|
||||
pub fn send_wheel_event(&mut self, delta: WheelDelta, point: DevicePoint) {
|
||||
if let Some(result) = self.hit_test_at_point(point) {
|
||||
let event = WheelEvent(delta, result.point_in_viewport, Some(result.node));
|
||||
let event = WheelEvent(delta, result.point_in_viewport, Some(result.node.into()));
|
||||
let msg = ConstellationMsg::ForwardEvent(result.pipeline_id, event);
|
||||
if let Err(e) = self.constellation_chan.send(msg) {
|
||||
warn!("Sending event to constellation failed ({:?}).", e);
|
||||
|
|
|
@ -155,7 +155,7 @@ use style_traits::CSSPixel;
|
|||
use webgpu::{self, WebGPU, WebGPURequest};
|
||||
use webrender::{RenderApi, RenderApiSender};
|
||||
use webrender_api::DocumentId;
|
||||
use webrender_traits::WebrenderExternalImageRegistry;
|
||||
use webrender_traits::{WebRenderNetApi, WebRenderScriptApi, WebrenderExternalImageRegistry};
|
||||
|
||||
use crate::browsingcontext::{
|
||||
AllBrowsingContextsIterator, BrowsingContext, FullyActiveBrowsingContextsIterator,
|
||||
|
@ -392,11 +392,11 @@ pub struct Constellation<STF, SWF> {
|
|||
|
||||
/// A channel for content processes to send messages that will
|
||||
/// be relayed to the WebRender thread.
|
||||
webrender_api_ipc_sender: script_traits::WebrenderIpcSender,
|
||||
webrender_api_ipc_sender: WebRenderScriptApi,
|
||||
|
||||
/// A channel for content process image caches to send messages
|
||||
/// that will be relayed to the WebRender thread.
|
||||
webrender_image_api_sender: net_traits::WebrenderIpcSender,
|
||||
webrender_image_api_sender: WebRenderNetApi,
|
||||
|
||||
/// A map of message-port Id to info.
|
||||
message_ports: HashMap<MessagePortId, MessagePortInfo>,
|
||||
|
@ -785,12 +785,8 @@ where
|
|||
scheduler_receiver,
|
||||
document_states: HashMap::new(),
|
||||
webrender_document: state.webrender_document,
|
||||
webrender_api_ipc_sender: script_traits::WebrenderIpcSender::new(
|
||||
webrender_ipc_sender,
|
||||
),
|
||||
webrender_image_api_sender: net_traits::WebrenderIpcSender::new(
|
||||
webrender_image_ipc_sender,
|
||||
),
|
||||
webrender_api_ipc_sender: WebRenderScriptApi::new(webrender_ipc_sender),
|
||||
webrender_image_api_sender: WebRenderNetApi::new(webrender_image_ipc_sender),
|
||||
webrender_wgpu,
|
||||
shutting_down: false,
|
||||
handled_warnings: VecDeque::new(),
|
||||
|
|
|
@ -185,10 +185,10 @@ pub struct InitialPipelineState {
|
|||
pub prev_throttled: bool,
|
||||
|
||||
/// Webrender api.
|
||||
pub webrender_image_api_sender: net_traits::WebrenderIpcSender,
|
||||
pub webrender_image_api_sender: webrender_traits::WebRenderNetApi,
|
||||
|
||||
/// Webrender api.
|
||||
pub webrender_api_sender: script_traits::WebrenderIpcSender,
|
||||
pub webrender_api_sender: webrender_traits::WebRenderScriptApi,
|
||||
|
||||
/// The ID of the document processed by this script thread.
|
||||
pub webrender_document: DocumentId,
|
||||
|
@ -502,8 +502,8 @@ pub struct UnprivilegedPipelineContent {
|
|||
opts: Opts,
|
||||
prefs: HashMap<String, PrefValue>,
|
||||
pipeline_namespace_id: PipelineNamespaceId,
|
||||
webrender_api_sender: script_traits::WebrenderIpcSender,
|
||||
webrender_image_api_sender: net_traits::WebrenderIpcSender,
|
||||
webrender_api_sender: webrender_traits::WebRenderScriptApi,
|
||||
webrender_image_api_sender: webrender_traits::WebRenderNetApi,
|
||||
webrender_document: DocumentId,
|
||||
webgl_chan: Option<WebGLPipeline>,
|
||||
webxr_registry: webxr_api::Registry,
|
||||
|
|
|
@ -30,6 +30,7 @@ log = { workspace = true }
|
|||
malloc_size_of = { workspace = true }
|
||||
malloc_size_of_derive = { workspace = true }
|
||||
net_traits = { workspace = true }
|
||||
pixels = { path = "../pixels" }
|
||||
parking_lot = { workspace = true }
|
||||
profile_traits = { workspace = true }
|
||||
range = { path = "../range" }
|
||||
|
@ -50,4 +51,5 @@ style_traits = { workspace = true }
|
|||
unicode-bidi = { workspace = true, features = ["with_serde"] }
|
||||
unicode-script = { workspace = true }
|
||||
webrender_api = { workspace = true }
|
||||
webrender_traits = { workspace = true }
|
||||
xi-unicode = { workspace = true }
|
||||
|
|
|
@ -27,7 +27,6 @@ use log::{debug, warn};
|
|||
use net_traits::image_cache::UsePlaceholder;
|
||||
use range::Range;
|
||||
use script_layout_interface::{combine_id_with_fragment_type, FragmentType};
|
||||
use script_traits::compositor::ScrollSensitivity;
|
||||
use servo_config::opts;
|
||||
use servo_geometry::{self, MaxRect};
|
||||
use style::color::AbsoluteColor;
|
||||
|
@ -52,6 +51,7 @@ use webrender_api::{
|
|||
ExternalScrollId, FilterOp, GlyphInstance, ImageRendering, LineStyle, NinePatchBorder,
|
||||
NinePatchBorderSource, NormalBorder, PropertyBinding, StickyOffsetBounds,
|
||||
};
|
||||
use webrender_traits::display_list::ScrollSensitivity;
|
||||
|
||||
use super::StackingContextId;
|
||||
use crate::block::BlockFlow;
|
||||
|
|
|
@ -20,8 +20,7 @@ use base::id::PipelineId;
|
|||
use base::print_tree::PrintTree;
|
||||
use embedder_traits::Cursor;
|
||||
use euclid::{SideOffsets2D, Vector2D};
|
||||
use net_traits::image::base::Image;
|
||||
use script_traits::compositor::{ScrollSensitivity, ScrollTreeNodeId};
|
||||
use pixels::Image;
|
||||
use serde::Serialize;
|
||||
use servo_geometry::MaxRect;
|
||||
use style::computed_values::_servo_top_layer::T as InTopLayer;
|
||||
|
@ -33,6 +32,7 @@ use webrender_api::{
|
|||
FilterOp, GlyphInstance, GradientStop, ImageKey, MixBlendMode, PrimitiveFlags, Shadow,
|
||||
SpatialId, StickyOffsetBounds, TransformStyle,
|
||||
};
|
||||
use webrender_traits::display_list::{ScrollSensitivity, ScrollTreeNodeId};
|
||||
|
||||
use super::StackingContextId;
|
||||
|
||||
|
|
|
@ -10,15 +10,15 @@
|
|||
use base::id::PipelineId;
|
||||
use base::WebRenderEpochToU16;
|
||||
use log::trace;
|
||||
use script_traits::compositor::{
|
||||
CompositorDisplayListInfo, ScrollSensitivity, ScrollTreeNodeId, ScrollableNodeInfo,
|
||||
};
|
||||
use webrender_api::units::{LayoutPoint, LayoutSize, LayoutVector2D};
|
||||
use webrender_api::{
|
||||
self, ClipChainId, ClipId, CommonItemProperties, DisplayItem as WrDisplayItem,
|
||||
DisplayListBuilder, Epoch, HasScrollLinkedEffect, PrimitiveFlags, PropertyBinding, RasterSpace,
|
||||
ReferenceFrameKind, SpaceAndClipInfo, SpatialId, SpatialTreeItemKey,
|
||||
};
|
||||
use webrender_traits::display_list::{
|
||||
CompositorDisplayListInfo, ScrollSensitivity, ScrollTreeNodeId, ScrollableNodeInfo,
|
||||
};
|
||||
|
||||
use crate::display_list::items::{
|
||||
BaseDisplayItem, ClipScrollNode, ClipScrollNodeType, ClipType, DisplayItem, DisplayList,
|
||||
|
|
|
@ -20,8 +20,8 @@ use gfx::text::text_run::{TextRun, TextRunSlice};
|
|||
use html5ever::{local_name, namespace_url, ns};
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use log::debug;
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder};
|
||||
use pixels::{Image, ImageMetadata};
|
||||
use range::*;
|
||||
use script_layout_interface::wrapper_traits::{
|
||||
PseudoElementType, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
||||
|
|
|
@ -30,6 +30,7 @@ ipc-channel = { workspace = true }
|
|||
log = { workspace = true }
|
||||
net_traits = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
pixels = { path = "../pixels" }
|
||||
range = { path = "../range" }
|
||||
rayon = { workspace = true }
|
||||
script_layout_interface = { workspace = true }
|
||||
|
@ -47,6 +48,7 @@ unicode-segmentation = { workspace = true }
|
|||
url = { workspace = true }
|
||||
data-url = { workspace = true }
|
||||
webrender_api = { workspace = true }
|
||||
webrender_traits = { workspace = true }
|
||||
xi-unicode = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -12,7 +12,6 @@ use euclid::{Point2D, SideOffsets2D, Size2D};
|
|||
use fnv::FnvHashMap;
|
||||
use gfx::text::glyph::GlyphStore;
|
||||
use net_traits::image_cache::UsePlaceholder;
|
||||
use script_traits::compositor::{CompositorDisplayListInfo, ScrollSensitivity, ScrollTreeNodeId};
|
||||
use servo_geometry::MaxRect;
|
||||
use style::color::{AbsoluteColor, ColorSpace};
|
||||
use style::computed_values::text_decoration_style::T as ComputedTextDecorationStyle;
|
||||
|
@ -24,6 +23,9 @@ use style::values::specified::text::TextDecorationLine;
|
|||
use style::values::specified::ui::CursorKind;
|
||||
use style_traits::CSSPixel;
|
||||
use webrender_api::{self as wr, units, BoxShadowClipMode, ClipChainId};
|
||||
use webrender_traits::display_list::{
|
||||
CompositorDisplayListInfo, ScrollSensitivity, ScrollTreeNodeId,
|
||||
};
|
||||
use wr::units::LayoutVector2D;
|
||||
|
||||
use crate::context::LayoutContext;
|
||||
|
|
|
@ -9,7 +9,6 @@ use base::print_tree::PrintTree;
|
|||
use euclid::default::Rect;
|
||||
use euclid::SideOffsets2D;
|
||||
use log::warn;
|
||||
use script_traits::compositor::{ScrollSensitivity, ScrollTreeNodeId, ScrollableNodeInfo};
|
||||
use servo_arc::Arc as ServoArc;
|
||||
use servo_config::opts::DebugOptions;
|
||||
use style::computed_values::float::T as ComputedFloat;
|
||||
|
@ -24,6 +23,7 @@ use style::values::specified::box_::DisplayOutside;
|
|||
use style::Zero;
|
||||
use webrender_api as wr;
|
||||
use webrender_api::units::{LayoutPoint, LayoutRect, LayoutTransform, LayoutVector2D};
|
||||
use webrender_traits::display_list::{ScrollSensitivity, ScrollTreeNodeId, ScrollableNodeInfo};
|
||||
use wr::units::{LayoutPixel, LayoutSize};
|
||||
use wr::{ClipChainId, SpatialTreeItemKey, StickyOffsetBounds};
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::sync::{Arc, Mutex};
|
|||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
||||
use base::id::{BrowsingContextId, PipelineId};
|
||||
use html5ever::{local_name, namespace_url, ns};
|
||||
use net_traits::image::base::Image as NetImage;
|
||||
use pixels::Image;
|
||||
use script_layout_interface::wrapper_traits::{
|
||||
LayoutDataTrait, LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
||||
};
|
||||
|
@ -96,7 +96,7 @@ impl Drop for BoxSlot<'_> {
|
|||
pub(crate) trait NodeExt<'dom>: 'dom + LayoutNode<'dom> {
|
||||
/// Returns the image if it’s loaded, and its size in image pixels
|
||||
/// adjusted for `image_density`.
|
||||
fn as_image(self) -> Option<(Option<Arc<NetImage>>, PhysicalSize<f64>)>;
|
||||
fn as_image(self) -> Option<(Option<Arc<Image>>, PhysicalSize<f64>)>;
|
||||
fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)>;
|
||||
fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)>;
|
||||
fn as_video(self) -> Option<(webrender_api::ImageKey, PhysicalSize<f64>)>;
|
||||
|
@ -117,7 +117,7 @@ impl<'dom, LayoutNodeType> NodeExt<'dom> for LayoutNodeType
|
|||
where
|
||||
LayoutNodeType: 'dom + LayoutNode<'dom>,
|
||||
{
|
||||
fn as_image(self) -> Option<(Option<Arc<NetImage>>, PhysicalSize<f64>)> {
|
||||
fn as_image(self) -> Option<(Option<Arc<Image>>, PhysicalSize<f64>)> {
|
||||
let node = self.to_threadsafe();
|
||||
let (resource, metadata) = node.image_data()?;
|
||||
let (width, height) = resource
|
||||
|
|
|
@ -7,13 +7,13 @@ use script_layout_interface::wrapper_traits::{
|
|||
LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
||||
};
|
||||
use script_layout_interface::{LayoutElementType, LayoutNodeType};
|
||||
use script_traits::compositor::ScrollSensitivity;
|
||||
use serde::Serialize;
|
||||
use servo_arc::Arc;
|
||||
use style::dom::OpaqueNode;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::{Length, Overflow};
|
||||
use style_traits::CSSPixel;
|
||||
use webrender_traits::display_list::ScrollSensitivity;
|
||||
|
||||
use crate::cell::ArcRefCell;
|
||||
use crate::context::LayoutContext;
|
||||
|
|
|
@ -6,12 +6,12 @@ use app_units::Au;
|
|||
use base::print_tree::PrintTree;
|
||||
use euclid::default::{Point2D, Rect, Size2D};
|
||||
use fxhash::FxHashSet;
|
||||
use script_traits::compositor::ScrollSensitivity;
|
||||
use serde::Serialize;
|
||||
use style::animation::AnimationSetKey;
|
||||
use style::dom::OpaqueNode;
|
||||
use style::values::computed::Length;
|
||||
use webrender_api::units;
|
||||
use webrender_traits::display_list::ScrollSensitivity;
|
||||
|
||||
use super::{ContainingBlockManager, Fragment, Tag};
|
||||
use crate::cell::ArcRefCell;
|
||||
|
|
|
@ -10,8 +10,8 @@ use base::id::{BrowsingContextId, PipelineId};
|
|||
use canvas_traits::canvas::{CanvasId, CanvasMsg, FromLayoutMsg};
|
||||
use data_url::DataUrl;
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use net_traits::image::base::Image;
|
||||
use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder};
|
||||
use pixels::Image;
|
||||
use serde::Serialize;
|
||||
use servo_arc::Arc as ServoArc;
|
||||
use style::properties::ComputedValues;
|
||||
|
|
|
@ -45,3 +45,4 @@ style_traits = { workspace = true }
|
|||
time = { workspace = true }
|
||||
url = { workspace = true }
|
||||
webrender_api = { workspace = true }
|
||||
webrender_traits = { workspace = true }
|
||||
|
|
|
@ -69,7 +69,7 @@ use script_layout_interface::{
|
|||
use script_traits::{
|
||||
ConstellationControlMsg, DrawAPaintImageResult, IFrameSizeMsg, LayoutControlMsg,
|
||||
LayoutMsg as ConstellationMsg, PaintWorkletError, Painter, ScrollState, UntrustedNodeAddress,
|
||||
WebrenderIpcSender, WindowSizeData, WindowSizeType,
|
||||
WindowSizeData, WindowSizeType,
|
||||
};
|
||||
use servo_arc::Arc as ServoArc;
|
||||
use servo_atoms::Atom;
|
||||
|
@ -102,6 +102,7 @@ use style::traversal_flags::TraversalFlags;
|
|||
use style_traits::{CSSPixel, DevicePixel, SpeculativePainter};
|
||||
use url::Url;
|
||||
use webrender_api::{units, ColorF, HitTestFlags};
|
||||
use webrender_traits::WebRenderScriptApi;
|
||||
|
||||
/// Information needed by layout.
|
||||
pub struct LayoutThread {
|
||||
|
@ -176,7 +177,7 @@ pub struct LayoutThread {
|
|||
registered_painters: RegisteredPaintersImpl,
|
||||
|
||||
/// Webrender interface.
|
||||
webrender_api: WebrenderIpcSender,
|
||||
webrender_api: WebRenderScriptApi,
|
||||
|
||||
/// Paint time metrics.
|
||||
paint_time_metrics: PaintTimeMetrics,
|
||||
|
@ -365,7 +366,7 @@ impl Layout for LayoutThread {
|
|||
.webrender_api
|
||||
.hit_test(Some(self.id.into()), client_point, flags);
|
||||
|
||||
results.iter().map(|result| result.node).collect()
|
||||
results.iter().map(|result| result.node.into()).collect()
|
||||
}
|
||||
|
||||
fn query_offset_parent(&self, node: OpaqueNode) -> OffsetParentResponse {
|
||||
|
@ -567,7 +568,7 @@ impl LayoutThread {
|
|||
image_cache: Arc<dyn ImageCache>,
|
||||
font_cache_thread: FontCacheThread,
|
||||
time_profiler_chan: profile_time::ProfilerChan,
|
||||
webrender_api: WebrenderIpcSender,
|
||||
webrender_api: WebRenderScriptApi,
|
||||
paint_time_metrics: PaintTimeMetrics,
|
||||
window_size: WindowSizeData,
|
||||
) -> LayoutThread {
|
||||
|
|
|
@ -41,3 +41,4 @@ style = { workspace = true }
|
|||
style_traits = { workspace = true }
|
||||
url = { workspace = true }
|
||||
webrender_api = { workspace = true }
|
||||
webrender_traits = { workspace = true }
|
||||
|
|
|
@ -55,7 +55,7 @@ use script_layout_interface::{
|
|||
use script_traits::{
|
||||
ConstellationControlMsg, DrawAPaintImageResult, IFrameSizeMsg, LayoutControlMsg,
|
||||
LayoutMsg as ConstellationMsg, PaintWorkletError, Painter, ScrollState, UntrustedNodeAddress,
|
||||
WebrenderIpcSender, WindowSizeData, WindowSizeType,
|
||||
WindowSizeData, WindowSizeType,
|
||||
};
|
||||
use servo_arc::Arc as ServoArc;
|
||||
use servo_atoms::Atom;
|
||||
|
@ -89,6 +89,7 @@ use style_traits::{CSSPixel, DevicePixel, SpeculativePainter};
|
|||
use url::Url;
|
||||
use webrender_api::units::LayoutPixel;
|
||||
use webrender_api::{units, ExternalScrollId, HitTestFlags};
|
||||
use webrender_traits::WebRenderScriptApi;
|
||||
|
||||
/// Information needed by layout.
|
||||
pub struct LayoutThread {
|
||||
|
@ -158,7 +159,7 @@ pub struct LayoutThread {
|
|||
registered_painters: RegisteredPaintersImpl,
|
||||
|
||||
/// Webrender interface.
|
||||
webrender_api: WebrenderIpcSender,
|
||||
webrender_api: WebRenderScriptApi,
|
||||
|
||||
/// Paint time metrics.
|
||||
paint_time_metrics: PaintTimeMetrics,
|
||||
|
@ -328,7 +329,7 @@ impl Layout for LayoutThread {
|
|||
.webrender_api
|
||||
.hit_test(Some(self.id.into()), client_point, flags);
|
||||
|
||||
results.iter().map(|result| result.node).collect()
|
||||
results.iter().map(|result| result.node.into()).collect()
|
||||
}
|
||||
|
||||
fn query_offset_parent(&self, node: OpaqueNode) -> OffsetParentResponse {
|
||||
|
@ -484,7 +485,7 @@ impl LayoutThread {
|
|||
image_cache: Arc<dyn ImageCache>,
|
||||
font_cache_thread: FontCacheThread,
|
||||
time_profiler_chan: profile_time::ProfilerChan,
|
||||
webrender_api_sender: WebrenderIpcSender,
|
||||
webrender_api_sender: WebRenderScriptApi,
|
||||
paint_time_metrics: PaintTimeMetrics,
|
||||
window_size: WindowSizeData,
|
||||
) -> LayoutThread {
|
||||
|
|
|
@ -65,6 +65,7 @@ tungstenite = { workspace = true }
|
|||
url = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
webrender_api = { workspace = true }
|
||||
webrender_traits = { workspace = true }
|
||||
webpki-roots = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -12,19 +12,17 @@ use embedder_traits::resources::{self, Resource};
|
|||
use imsz::imsz_from_reader;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use log::{debug, warn};
|
||||
use net_traits::image::base::{load_from_memory, Image, ImageMetadata};
|
||||
use net_traits::image_cache::{
|
||||
CorsStatus, ImageCache, ImageCacheResult, ImageOrMetadataAvailable, ImageResponder,
|
||||
ImageResponse, PendingImageId, PendingImageResponse, UsePlaceholder,
|
||||
ImageCache, ImageCacheResult, ImageOrMetadataAvailable, ImageResponder, ImageResponse,
|
||||
PendingImageId, PendingImageResponse, UsePlaceholder,
|
||||
};
|
||||
use net_traits::request::CorsSettings;
|
||||
use net_traits::{
|
||||
FetchMetadata, FetchResponseMsg, FilteredMetadata, NetworkError, WebrenderIpcSender,
|
||||
};
|
||||
use pixels::PixelFormat;
|
||||
use net_traits::{FetchMetadata, FetchResponseMsg, FilteredMetadata, NetworkError};
|
||||
use pixels::{load_from_memory, CorsStatus, Image, ImageMetadata, PixelFormat};
|
||||
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||
use webrender_api::units::DeviceIntSize;
|
||||
use webrender_api::{ImageData, ImageDescriptor, ImageDescriptorFlags, ImageFormat};
|
||||
use webrender_traits::WebRenderNetApi;
|
||||
|
||||
use crate::resource_thread::CoreResourceThreadPool;
|
||||
|
||||
|
@ -47,13 +45,13 @@ fn decode_bytes_sync(key: LoadKey, bytes: &[u8], cors: CorsStatus) -> DecoderMsg
|
|||
DecoderMsg { key, image }
|
||||
}
|
||||
|
||||
fn get_placeholder_image(webrender_api: &WebrenderIpcSender, data: &[u8]) -> Arc<Image> {
|
||||
fn get_placeholder_image(webrender_api: &WebRenderNetApi, data: &[u8]) -> Arc<Image> {
|
||||
let mut image = load_from_memory(data, CorsStatus::Unsafe).unwrap();
|
||||
set_webrender_image_key(webrender_api, &mut image);
|
||||
Arc::new(image)
|
||||
}
|
||||
|
||||
fn set_webrender_image_key(webrender_api: &WebrenderIpcSender, image: &mut Image) {
|
||||
fn set_webrender_image_key(webrender_api: &WebRenderNetApi, image: &mut Image) {
|
||||
if image.id.is_some() {
|
||||
return;
|
||||
}
|
||||
|
@ -331,7 +329,7 @@ struct ImageCacheStore {
|
|||
placeholder_url: ServoUrl,
|
||||
|
||||
// Webrender API instance.
|
||||
webrender_api: WebrenderIpcSender,
|
||||
webrender_api: WebRenderNetApi,
|
||||
}
|
||||
|
||||
impl ImageCacheStore {
|
||||
|
@ -418,7 +416,7 @@ pub struct ImageCacheImpl {
|
|||
}
|
||||
|
||||
impl ImageCache for ImageCacheImpl {
|
||||
fn new(webrender_api: WebrenderIpcSender) -> ImageCacheImpl {
|
||||
fn new(webrender_api: WebRenderNetApi) -> ImageCacheImpl {
|
||||
debug!("New image cache");
|
||||
|
||||
let rippy_data = resources::read_bytes(Resource::RippyPNG);
|
||||
|
|
|
@ -12,6 +12,10 @@ path = "lib.rs"
|
|||
|
||||
[dependencies]
|
||||
euclid = { workspace = true }
|
||||
ipc-channel = { workspace = true }
|
||||
image = { workspace = true }
|
||||
malloc_size_of = { workspace = true }
|
||||
malloc_size_of_derive = { workspace = true }
|
||||
log = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
webrender_api = { workspace = true }
|
||||
|
|
|
@ -3,10 +3,15 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
|
||||
use euclid::default::{Point2D, Rect, Size2D};
|
||||
use image::ImageFormat;
|
||||
use ipc_channel::ipc::IpcSharedMemory;
|
||||
use log::debug;
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use webrender_api::ImageKey;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum PixelFormat {
|
||||
|
@ -98,3 +103,148 @@ pub fn clip(
|
|||
.intersection(&Rect::from_size(surface))
|
||||
.filter(|rect| !rect.is_empty())
|
||||
}
|
||||
|
||||
/// 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,
|
||||
}
|
||||
|
||||
#[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();
|
||||
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"
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,6 +116,7 @@ uuid = { workspace = true, features = ["serde"] }
|
|||
webdriver = { workspace = true }
|
||||
webgpu = { path = "../webgpu" }
|
||||
webrender_api = { workspace = true }
|
||||
webrender_traits = { workspace = true }
|
||||
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
|
||||
xml5ever = { workspace = true }
|
||||
|
||||
|
|
|
@ -20,10 +20,9 @@ use ipc_channel::router::ROUTER;
|
|||
use js::jsapi::JSAutoRealm;
|
||||
use js::rust::HandleObject;
|
||||
use mime::{self, Mime};
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
use net_traits::image_cache::{
|
||||
CorsStatus, ImageCache, ImageCacheResult, ImageOrMetadataAvailable, ImageResponse,
|
||||
PendingImageId, PendingImageResponse, UsePlaceholder,
|
||||
ImageCache, ImageCacheResult, ImageOrMetadataAvailable, ImageResponse, PendingImageId,
|
||||
PendingImageResponse, UsePlaceholder,
|
||||
};
|
||||
use net_traits::request::{CorsSettings, Destination, Initiator, Referrer, RequestBuilder};
|
||||
use net_traits::{
|
||||
|
@ -31,6 +30,7 @@ use net_traits::{
|
|||
ResourceFetchTiming, ResourceTimingType,
|
||||
};
|
||||
use num_traits::ToPrimitive;
|
||||
use pixels::{CorsStatus, Image, ImageMetadata};
|
||||
use servo_url::origin::{ImmutableOrigin, MutableOrigin};
|
||||
use servo_url::ServoUrl;
|
||||
use style::attr::{
|
||||
|
|
|
@ -20,14 +20,13 @@ use ipc_channel::ipc;
|
|||
use ipc_channel::router::ROUTER;
|
||||
use js::jsapi::JSAutoRealm;
|
||||
use media::{glplayer_channel, GLPlayerMsg, GLPlayerMsgForward, WindowGLContext};
|
||||
use net_traits::image::base::Image;
|
||||
use net_traits::request::Destination;
|
||||
use net_traits::{
|
||||
CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, Metadata, NetworkError,
|
||||
ResourceFetchTiming, ResourceTimingType,
|
||||
};
|
||||
use pixels::Image;
|
||||
use script_layout_interface::HTMLMediaData;
|
||||
use script_traits::{ImageUpdate, WebrenderIpcSender};
|
||||
use servo_config::pref;
|
||||
use servo_media::player::audio::AudioRenderer;
|
||||
use servo_media::player::video::{VideoFrame, VideoFrameRenderer};
|
||||
|
@ -38,6 +37,7 @@ use webrender_api::{
|
|||
ExternalImageData, ExternalImageId, ExternalImageType, ImageBufferKind, ImageData,
|
||||
ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey,
|
||||
};
|
||||
use webrender_traits::{ImageUpdate, WebRenderScriptApi};
|
||||
|
||||
use crate::document_loader::{LoadBlocker, LoadType};
|
||||
use crate::dom::attr::Attr;
|
||||
|
@ -154,7 +154,7 @@ impl FrameHolder {
|
|||
|
||||
pub struct MediaFrameRenderer {
|
||||
player_id: Option<u64>,
|
||||
api: WebrenderIpcSender,
|
||||
api: WebRenderScriptApi,
|
||||
current_frame: Option<(ImageKey, i32, i32)>,
|
||||
old_frame: Option<ImageKey>,
|
||||
very_old_frame: Option<ImageKey>,
|
||||
|
@ -163,7 +163,7 @@ pub struct MediaFrameRenderer {
|
|||
}
|
||||
|
||||
impl MediaFrameRenderer {
|
||||
fn new(render_api_sender: WebrenderIpcSender) -> Self {
|
||||
fn new(render_api_sender: WebRenderScriptApi) -> Self {
|
||||
Self {
|
||||
player_id: None,
|
||||
api: render_api_sender,
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::default::Default;
|
|||
use dom_struct::dom_struct;
|
||||
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
|
||||
use js::rust::HandleObject;
|
||||
use net_traits::image::base::Image;
|
||||
use pixels::Image;
|
||||
use servo_arc::Arc;
|
||||
|
||||
use crate::dom::attr::Attr;
|
||||
|
|
|
@ -23,7 +23,7 @@ use js::jsapi::JSObject;
|
|||
use js::rust::HandleObject;
|
||||
use libc::{self, c_void, uintptr_t};
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
use pixels::{Image, ImageMetadata};
|
||||
use script_layout_interface::{
|
||||
GenericLayoutData, HTMLCanvasData, HTMLMediaData, LayoutElementType, LayoutNodeType, QueryMsg,
|
||||
SVGSVGData, StyleData, TrustedNodeAddress,
|
||||
|
|
|
@ -56,7 +56,7 @@ use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
|
|||
use script_traits::{
|
||||
ConstellationControlMsg, DocumentState, HistoryEntryReplacement, LoadData, ScriptMsg,
|
||||
ScriptToConstellationChan, ScrollState, StructuredSerializedData, TimerEventId,
|
||||
TimerSchedulerMsg, WebrenderIpcSender, WindowSizeData, WindowSizeType,
|
||||
TimerSchedulerMsg, WindowSizeData, WindowSizeType,
|
||||
};
|
||||
use selectors::attr::CaseSensitivity;
|
||||
use servo_arc::Arc as ServoArc;
|
||||
|
@ -76,6 +76,7 @@ use style_traits::{CSSPixel, DevicePixel, ParsingMode};
|
|||
use url::Position;
|
||||
use webrender_api::units::{DeviceIntPoint, DeviceIntSize, LayoutPixel};
|
||||
use webrender_api::{DocumentId, ExternalScrollId};
|
||||
use webrender_traits::WebRenderScriptApi;
|
||||
|
||||
use super::bindings::trace::HashMapTracedValues;
|
||||
use crate::dom::bindings::cell::{DomRefCell, Ref};
|
||||
|
@ -318,7 +319,7 @@ pub struct Window {
|
|||
/// Webrender API Sender
|
||||
#[ignore_malloc_size_of = "Wraps an IpcSender"]
|
||||
#[no_trace]
|
||||
webrender_api_sender: WebrenderIpcSender,
|
||||
webrender_api_sender: WebRenderScriptApi,
|
||||
|
||||
/// Indicate whether a SetDocumentStatus message has been sent after a reflow is complete.
|
||||
/// It is used to avoid sending idle message more than once, which is unneccessary.
|
||||
|
@ -521,7 +522,7 @@ impl Window {
|
|||
self.add_pending_reflow();
|
||||
}
|
||||
|
||||
pub fn get_webrender_api_sender(&self) -> WebrenderIpcSender {
|
||||
pub fn get_webrender_api_sender(&self) -> WebRenderScriptApi {
|
||||
self.webrender_api_sender.clone()
|
||||
}
|
||||
|
||||
|
@ -2537,7 +2538,7 @@ impl Window {
|
|||
webxr_registry: webxr_api::Registry,
|
||||
microtask_queue: Rc<MicrotaskQueue>,
|
||||
webrender_document: DocumentId,
|
||||
webrender_api_sender: WebrenderIpcSender,
|
||||
webrender_api_sender: WebRenderScriptApi,
|
||||
relayout_event: bool,
|
||||
prepare_for_screenshot: bool,
|
||||
unminify_js: bool,
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::sync::Arc as StdArc;
|
|||
use base::id::{BrowsingContextId, PipelineId};
|
||||
use gfx_traits::ByteIndex;
|
||||
use html5ever::{local_name, namespace_url, ns};
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
use pixels::{Image, ImageMetadata};
|
||||
use range::Range;
|
||||
use script_layout_interface::wrapper_traits::{
|
||||
LayoutDataTrait, LayoutNode, PseudoElementType, ThreadSafeLayoutNode,
|
||||
|
|
|
@ -83,7 +83,7 @@ use script_traits::{
|
|||
LayoutMsg, LoadData, LoadOrigin, MediaSessionActionType, MouseButton, MouseEventType,
|
||||
NewLayoutInfo, Painter, ProgressiveWebMetricType, ScriptMsg, ScriptToConstellationChan,
|
||||
StructuredSerializedData, TimerSchedulerMsg, TouchEventType, TouchId, UntrustedNodeAddress,
|
||||
UpdatePipelineIdReason, WebrenderIpcSender, WheelDelta, WindowSizeData, WindowSizeType,
|
||||
UpdatePipelineIdReason, WheelDelta, WindowSizeData, WindowSizeType,
|
||||
};
|
||||
use servo_atoms::Atom;
|
||||
use servo_config::opts;
|
||||
|
@ -95,6 +95,7 @@ use url::Position;
|
|||
use webgpu::WebGPUMsg;
|
||||
use webrender_api::units::LayoutPixel;
|
||||
use webrender_api::DocumentId;
|
||||
use webrender_traits::WebRenderScriptApi;
|
||||
|
||||
use crate::document_loader::DocumentLoader;
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
|
@ -674,7 +675,7 @@ pub struct ScriptThread {
|
|||
|
||||
/// Webrender API sender.
|
||||
#[no_trace]
|
||||
webrender_api_sender: WebrenderIpcSender,
|
||||
webrender_api_sender: WebRenderScriptApi,
|
||||
|
||||
/// Periodically print out on which events script threads spend their processing time.
|
||||
profile_script_events: bool,
|
||||
|
|
|
@ -36,8 +36,7 @@ use compositing::webview::UnknownWebView;
|
|||
use compositing::windowing::{EmbedderEvent, EmbedderMethods, WindowMethods};
|
||||
use compositing::{CompositeTarget, IOCompositor, InitialCompositorState, ShutdownState};
|
||||
use compositing_traits::{
|
||||
CanvasToCompositorMsg, CompositorMsg, CompositorProxy, CompositorReceiver, ConstellationMsg,
|
||||
FontToCompositorMsg, ForwardedToCompositorMsg,
|
||||
CompositorMsg, CompositorProxy, CompositorReceiver, ConstellationMsg, ForwardedToCompositorMsg,
|
||||
};
|
||||
#[cfg(all(
|
||||
not(target_os = "windows"),
|
||||
|
@ -96,8 +95,8 @@ use webrender_api::{
|
|||
NativeFontHandle,
|
||||
};
|
||||
use webrender_traits::{
|
||||
WebRenderFontApi, WebrenderExternalImageHandlers, WebrenderExternalImageRegistry,
|
||||
WebrenderImageHandlerType,
|
||||
CanvasToCompositorMsg, FontToCompositorMsg, ImageUpdate, WebRenderFontApi,
|
||||
WebrenderExternalImageHandlers, WebrenderExternalImageRegistry, WebrenderImageHandlerType,
|
||||
};
|
||||
pub use {
|
||||
background_hang_monitor, base, bluetooth, bluetooth_traits, canvas, canvas_traits, compositing,
|
||||
|
@ -1100,7 +1099,7 @@ impl canvas_paint_thread::WebrenderApi for CanvasWebrenderApi {
|
|||
)));
|
||||
receiver.recv().ok()
|
||||
}
|
||||
fn update_images(&self, updates: Vec<canvas_paint_thread::ImageUpdate>) {
|
||||
fn update_images(&self, updates: Vec<ImageUpdate>) {
|
||||
self.0
|
||||
.send(CompositorMsg::Forwarded(ForwardedToCompositorMsg::Canvas(
|
||||
CanvasToCompositorMsg::UpdateImages(updates),
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -162,6 +162,7 @@ class MachCommands(CommandBase):
|
|||
"constellation",
|
||||
"style_config",
|
||||
"compositing",
|
||||
"pixels",
|
||||
]
|
||||
if not packages:
|
||||
packages = set(os.listdir(path.join(self.context.topdir, "tests", "unit"))) - set(['.DS_Store'])
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue