canvas: Do not update ImageKey during canvas layout (#35719)

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
Samson 2025-03-12 16:36:52 +01:00 committed by GitHub
parent f31043602a
commit 6f6840d63c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 90 additions and 126 deletions

View file

@ -21,7 +21,7 @@ use servo_arc::Arc as ServoArc;
use style::color::AbsoluteColor; use style::color::AbsoluteColor;
use style::properties::style_structs::Font as FontStyleStruct; use style::properties::style_structs::Font as FontStyleStruct;
use unicode_script::Script; use unicode_script::Script;
use webrender_api::units::{DeviceIntSize, RectExt as RectExt_}; use webrender_api::units::RectExt as RectExt_;
use webrender_api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey}; use webrender_api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey};
use webrender_traits::{CrossProcessCompositorApi, ImageUpdate, SerializableImageData}; use webrender_traits::{CrossProcessCompositorApi, ImageUpdate, SerializableImageData};
@ -465,6 +465,10 @@ impl<'a> CanvasData<'a> {
} }
} }
pub fn image_key(&self) -> ImageKey {
self.image_key
}
pub fn draw_image( pub fn draw_image(
&mut self, &mut self,
image_data: &[u8], image_data: &[u8],
@ -1249,7 +1253,7 @@ impl<'a> CanvasData<'a> {
.create_drawtarget(Size2D::new(size.width, size.height)); .create_drawtarget(Size2D::new(size.width, size.height));
self.state = self.backend.recreate_paint_state(&self.state); self.state = self.backend.recreate_paint_state(&self.state);
self.saved_states.clear(); self.saved_states.clear();
self.update_wr_image(size.cast().cast_unit()); self.update_image_rendering();
} }
pub fn send_pixels(&mut self, chan: IpcSender<IpcSharedMemory>) { pub fn send_pixels(&mut self, chan: IpcSender<IpcSharedMemory>) {
@ -1260,20 +1264,10 @@ impl<'a> CanvasData<'a> {
}); });
} }
pub fn send_data(&mut self, chan: IpcSender<CanvasImageData>) { /// Update image in WebRender
let size = self.drawtarget.get_size(); pub fn update_image_rendering(&mut self) {
self.update_wr_image(size.cast_unit());
let data = CanvasImageData {
image_key: self.image_key,
};
chan.send(data).unwrap();
}
fn update_wr_image(&mut self, size: DeviceIntSize) {
let descriptor = ImageDescriptor { let descriptor = ImageDescriptor {
size, size: self.drawtarget.get_size().cast_unit(),
stride: None, stride: None,
format: ImageFormat::BGRA8, format: ImageFormat::BGRA8,
offset: 0, offset: 0,

View file

@ -16,6 +16,7 @@ use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use log::warn; use log::warn;
use net_traits::ResourceThreads; use net_traits::ResourceThreads;
use webrender_api::ImageKey;
use webrender_traits::CrossProcessCompositorApi; use webrender_traits::CrossProcessCompositorApi;
use crate::canvas_data::*; use crate::canvas_data::*;
@ -79,8 +80,9 @@ impl<'a> CanvasPaintThread<'a> {
}, },
}, },
Ok(CanvasMsg::FromLayout(message, canvas_id)) => match message { Ok(CanvasMsg::FromLayout(message, canvas_id)) => match message {
FromLayoutMsg::SendData(chan) => { FromLayoutMsg::UpdateImage(sender) => {
canvas_paint_thread.canvas(canvas_id).send_data(chan); canvas_paint_thread.canvas(canvas_id).update_image_rendering();
sender.send(()).unwrap();
}, },
}, },
Err(e) => { Err(e) => {
@ -90,9 +92,9 @@ impl<'a> CanvasPaintThread<'a> {
} }
recv(create_receiver) -> msg => { recv(create_receiver) -> msg => {
match msg { match msg {
Ok(ConstellationCanvasMsg::Create { id_sender: creator, size }) => { Ok(ConstellationCanvasMsg::Create { sender: creator, size }) => {
let canvas_id = canvas_paint_thread.create_canvas(size); let canvas_data = canvas_paint_thread.create_canvas(size);
creator.send(canvas_id).unwrap(); creator.send(canvas_data).unwrap();
}, },
Ok(ConstellationCanvasMsg::Exit) => break, Ok(ConstellationCanvasMsg::Exit) => break,
Err(e) => { Err(e) => {
@ -109,15 +111,16 @@ impl<'a> CanvasPaintThread<'a> {
(create_sender, ipc_sender) (create_sender, ipc_sender)
} }
pub fn create_canvas(&mut self, size: Size2D<u64>) -> CanvasId { pub fn create_canvas(&mut self, size: Size2D<u64>) -> (CanvasId, ImageKey) {
let canvas_id = self.next_canvas_id; let canvas_id = self.next_canvas_id;
self.next_canvas_id.0 += 1; self.next_canvas_id.0 += 1;
let canvas_data = let canvas_data =
CanvasData::new(size, self.compositor_api.clone(), self.font_context.clone()); CanvasData::new(size, self.compositor_api.clone(), self.font_context.clone());
let image_key = canvas_data.image_key();
self.canvases.insert(canvas_id, canvas_data); self.canvases.insert(canvas_id, canvas_data);
canvas_id (canvas_id, image_key)
} }
fn process_canvas_2d_message(&mut self, message: Canvas2dMsg, canvas_id: CanvasId) { fn process_canvas_2d_message(&mut self, message: Canvas2dMsg, canvas_id: CanvasId) {

View file

@ -159,7 +159,7 @@ use webgpu::{self, WebGPU, WebGPURequest, WebGPUResponse};
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
use webrender::RenderApi; use webrender::RenderApi;
use webrender::RenderApiSender; use webrender::RenderApiSender;
use webrender_api::DocumentId; use webrender_api::{DocumentId, ImageKey};
use webrender_traits::{CompositorHitTestResult, WebrenderExternalImageRegistry}; use webrender_traits::{CompositorHitTestResult, WebrenderExternalImageRegistry};
use crate::browsingcontext::{ use crate::browsingcontext::{
@ -4362,21 +4362,22 @@ where
fn handle_create_canvas_paint_thread_msg( fn handle_create_canvas_paint_thread_msg(
&mut self, &mut self,
size: UntypedSize2D<u64>, size: UntypedSize2D<u64>,
response_sender: IpcSender<(IpcSender<CanvasMsg>, CanvasId)>, response_sender: IpcSender<(IpcSender<CanvasMsg>, CanvasId, ImageKey)>,
) { ) {
let (canvas_id_sender, canvas_id_receiver) = unbounded(); let (canvas_data_sender, canvas_data_receiver) = unbounded();
if let Err(e) = self.canvas_sender.send(ConstellationCanvasMsg::Create { if let Err(e) = self.canvas_sender.send(ConstellationCanvasMsg::Create {
id_sender: canvas_id_sender, sender: canvas_data_sender,
size, size,
}) { }) {
return warn!("Create canvas paint thread failed ({})", e); return warn!("Create canvas paint thread failed ({})", e);
} }
let canvas_id = match canvas_id_receiver.recv() { let (canvas_id, image_key) = match canvas_data_receiver.recv() {
Ok(canvas_id) => canvas_id, Ok(canvas_data) => canvas_data,
Err(e) => return warn!("Create canvas paint thread id response failed ({})", e), Err(e) => return warn!("Create canvas paint thread id response failed ({})", e),
}; };
if let Err(e) = response_sender.send((self.canvas_ipc_sender.clone(), canvas_id)) { if let Err(e) = response_sender.send((self.canvas_ipc_sender.clone(), canvas_id, image_key))
{
warn!("Create canvas paint thread response failed ({})", e); warn!("Create canvas paint thread response failed ({})", e);
} }
} }

View file

@ -21,7 +21,6 @@ use euclid::default::{Point2D, Rect, SideOffsets2D as UntypedSideOffsets2D, Size
use euclid::{Scale, SideOffsets2D, rect}; use euclid::{Scale, SideOffsets2D, rect};
use fnv::FnvHashMap; use fnv::FnvHashMap;
use fonts::ByteIndex; use fonts::ByteIndex;
use ipc_channel::ipc;
use log::{debug, warn}; use log::{debug, warn};
use net_traits::image_cache::UsePlaceholder; use net_traits::image_cache::UsePlaceholder;
use range::Range; use range::Range;
@ -1770,16 +1769,17 @@ impl Fragment {
let image_key = match canvas_fragment_info.source { let image_key = match canvas_fragment_info.source {
CanvasFragmentSource::WebGL(image_key) => image_key, CanvasFragmentSource::WebGL(image_key) => image_key,
CanvasFragmentSource::WebGPU(image_key) => image_key, CanvasFragmentSource::WebGPU(image_key) => image_key,
CanvasFragmentSource::Image(ref ipc_renderer) => { CanvasFragmentSource::Image((image_key, canvas_id, ref ipc_renderer)) => {
let ipc_renderer = ipc_renderer.lock().unwrap(); let ipc_renderer = ipc_renderer.lock().unwrap();
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc_channel::ipc::channel().unwrap();
ipc_renderer ipc_renderer
.send(CanvasMsg::FromLayout( .send(CanvasMsg::FromLayout(
FromLayoutMsg::SendData(sender), FromLayoutMsg::UpdateImage(sender),
canvas_fragment_info.canvas_id, canvas_id,
)) ))
.unwrap(); .unwrap();
receiver.recv().unwrap().image_key receiver.recv().unwrap();
image_key
}, },
CanvasFragmentSource::Empty => return, CanvasFragmentSource::Empty => return,
}; };

View file

@ -338,7 +338,7 @@ impl InlineAbsoluteFragmentInfo {
#[derive(Clone)] #[derive(Clone)]
pub enum CanvasFragmentSource { pub enum CanvasFragmentSource {
WebGL(ImageKey), WebGL(ImageKey),
Image(Arc<Mutex<IpcSender<CanvasMsg>>>), Image((ImageKey, CanvasId, Arc<Mutex<IpcSender<CanvasMsg>>>)),
WebGPU(ImageKey), WebGPU(ImageKey),
/// Transparent black /// Transparent black
Empty, Empty,
@ -349,15 +349,18 @@ pub struct CanvasFragmentInfo {
pub source: CanvasFragmentSource, pub source: CanvasFragmentSource,
pub dom_width: Au, pub dom_width: Au,
pub dom_height: Au, pub dom_height: Au,
pub canvas_id: CanvasId,
} }
impl CanvasFragmentInfo { impl CanvasFragmentInfo {
pub fn new(data: HTMLCanvasData) -> CanvasFragmentInfo { pub fn new(data: HTMLCanvasData) -> CanvasFragmentInfo {
let source = match data.source { let source = match data.source {
HTMLCanvasDataSource::WebGL(texture_id) => CanvasFragmentSource::WebGL(texture_id), HTMLCanvasDataSource::WebGL(texture_id) => CanvasFragmentSource::WebGL(texture_id),
HTMLCanvasDataSource::Image(ipc_sender) => { HTMLCanvasDataSource::Image((image_key, canvas_id, ipc_sender)) => {
CanvasFragmentSource::Image(Arc::new(Mutex::new(ipc_sender))) CanvasFragmentSource::Image((
image_key,
canvas_id,
Arc::new(Mutex::new(ipc_sender)),
))
}, },
HTMLCanvasDataSource::WebGPU(image_key) => CanvasFragmentSource::WebGPU(image_key), HTMLCanvasDataSource::WebGPU(image_key) => CanvasFragmentSource::WebGPU(image_key),
HTMLCanvasDataSource::Empty => CanvasFragmentSource::Empty, HTMLCanvasDataSource::Empty => CanvasFragmentSource::Empty,
@ -367,7 +370,6 @@ impl CanvasFragmentInfo {
source, source,
dom_width: Au::from_px(data.width as i32), dom_width: Au::from_px(data.width as i32),
dom_height: Au::from_px(data.height as i32), dom_height: Au::from_px(data.height as i32),
canvas_id: data.canvas_id,
} }
} }
} }

View file

@ -155,17 +155,14 @@ where
let canvas_data = node.canvas_data()?; let canvas_data = node.canvas_data()?;
let source = match canvas_data.source { let source = match canvas_data.source {
HTMLCanvasDataSource::WebGL(texture_id) => CanvasSource::WebGL(texture_id), HTMLCanvasDataSource::WebGL(texture_id) => CanvasSource::WebGL(texture_id),
HTMLCanvasDataSource::Image(ipc_sender) => { HTMLCanvasDataSource::Image((image_key, canvas_id, ipc_sender)) => {
CanvasSource::Image(Arc::new(Mutex::new(ipc_sender))) CanvasSource::Image((image_key, canvas_id, Arc::new(Mutex::new(ipc_sender))))
}, },
HTMLCanvasDataSource::WebGPU(image_key) => CanvasSource::WebGPU(image_key), HTMLCanvasDataSource::WebGPU(image_key) => CanvasSource::WebGPU(image_key),
HTMLCanvasDataSource::Empty => CanvasSource::Empty, HTMLCanvasDataSource::Empty => CanvasSource::Empty,
}; };
Some(( Some((
CanvasInfo { CanvasInfo { source },
source,
canvas_id: canvas_data.canvas_id,
},
PhysicalSize::new(canvas_data.width.into(), canvas_data.height.into()), PhysicalSize::new(canvas_data.width.into(), canvas_data.height.into()),
)) ))
} }

View file

@ -98,7 +98,7 @@ impl NaturalSizes {
pub(crate) enum CanvasSource { pub(crate) enum CanvasSource {
WebGL(ImageKey), WebGL(ImageKey),
Image(Arc<Mutex<IpcSender<CanvasMsg>>>), Image((ImageKey, CanvasId, Arc<Mutex<IpcSender<CanvasMsg>>>)),
WebGPU(ImageKey), WebGPU(ImageKey),
/// transparent black /// transparent black
Empty, Empty,
@ -122,7 +122,6 @@ impl fmt::Debug for CanvasSource {
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct CanvasInfo { pub(crate) struct CanvasInfo {
pub source: CanvasSource, pub source: CanvasSource,
pub canvas_id: CanvasId,
} }
#[derive(Debug)] #[derive(Debug)]
@ -382,16 +381,17 @@ impl ReplacedContents {
let image_key = match canvas_info.source { let image_key = match canvas_info.source {
CanvasSource::WebGL(image_key) => image_key, CanvasSource::WebGL(image_key) => image_key,
CanvasSource::WebGPU(image_key) => image_key, CanvasSource::WebGPU(image_key) => image_key,
CanvasSource::Image(ref ipc_renderer) => { CanvasSource::Image((image_key, canvas_id, ref ipc_renderer)) => {
let ipc_renderer = ipc_renderer.lock().unwrap(); let ipc_renderer = ipc_renderer.lock().unwrap();
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
ipc_renderer ipc_renderer
.send(CanvasMsg::FromLayout( .send(CanvasMsg::FromLayout(
FromLayoutMsg::SendData(sender), FromLayoutMsg::UpdateImage(sender),
canvas_info.canvas_id, canvas_id,
)) ))
.unwrap(); .unwrap();
receiver.recv().unwrap().image_key receiver.recv().unwrap();
image_key
}, },
CanvasSource::Empty => return vec![], CanvasSource::Empty => return vec![],
}; };

View file

@ -4,7 +4,6 @@
//! Common interfaces for Canvas Contexts //! Common interfaces for Canvas Contexts
use canvas_traits::canvas::CanvasId;
use euclid::default::Size2D; use euclid::default::Size2D;
use ipc_channel::ipc::IpcSharedMemory; use ipc_channel::ipc::IpcSharedMemory;
use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource}; use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource};
@ -20,7 +19,6 @@ pub(crate) trait LayoutCanvasRenderingContextHelpers {
pub(crate) trait LayoutHTMLCanvasElementHelpers { pub(crate) trait LayoutHTMLCanvasElementHelpers {
fn data(self) -> HTMLCanvasData; fn data(self) -> HTMLCanvasData;
fn get_canvas_id_for_layout(self) -> CanvasId;
} }
pub(crate) trait CanvasContext { pub(crate) trait CanvasContext {

View file

@ -34,6 +34,7 @@ use style::values::specified::color::Color;
use style_traits::values::ToCss; use style_traits::values::ToCss;
use style_traits::{CssWriter, ParsingMode}; use style_traits::{CssWriter, ParsingMode};
use url::Url; use url::Url;
use webrender_api::ImageKey;
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{ use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{
@ -145,6 +146,8 @@ pub(crate) struct CanvasState {
ipc_renderer: IpcSender<CanvasMsg>, ipc_renderer: IpcSender<CanvasMsg>,
#[no_trace] #[no_trace]
canvas_id: CanvasId, canvas_id: CanvasId,
#[no_trace]
image_key: ImageKey,
state: DomRefCell<CanvasContextState>, state: DomRefCell<CanvasContextState>,
origin_clean: Cell<bool>, origin_clean: Cell<bool>,
#[ignore_malloc_size_of = "Arc"] #[ignore_malloc_size_of = "Arc"]
@ -172,7 +175,7 @@ impl CanvasState {
script_to_constellation_chan script_to_constellation_chan
.send(ScriptMsg::CreateCanvasPaintThread(size, sender)) .send(ScriptMsg::CreateCanvasPaintThread(size, sender))
.unwrap(); .unwrap();
let (ipc_renderer, canvas_id) = receiver.recv().unwrap(); let (ipc_renderer, canvas_id, image_key) = receiver.recv().unwrap();
debug!("Done."); debug!("Done.");
// Worklets always receive a unique origin. This messes with fetching // Worklets always receive a unique origin. This messes with fetching
// cached images in the case of paint worklets, since the image cache // cached images in the case of paint worklets, since the image cache
@ -191,6 +194,7 @@ impl CanvasState {
base_url: global.api_base_url(), base_url: global.api_base_url(),
missing_image_urls: DomRefCell::new(Vec::new()), missing_image_urls: DomRefCell::new(Vec::new()),
saved_states: DomRefCell::new(Vec::new()), saved_states: DomRefCell::new(Vec::new()),
image_key,
origin, origin,
} }
} }
@ -199,6 +203,10 @@ impl CanvasState {
&self.ipc_renderer &self.ipc_renderer
} }
pub(crate) fn image_key(&self) -> ImageKey {
self.image_key
}
pub(crate) fn get_missing_image_urls(&self) -> &DomRefCell<Vec<ServoUrl>> { pub(crate) fn get_missing_image_urls(&self) -> &DomRefCell<Vec<ServoUrl>> {
&self.missing_image_urls &self.missing_image_urls
} }

View file

@ -2,16 +2,15 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use canvas_traits::canvas::{ use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg, FromScriptMsg};
Canvas2dMsg, CanvasId, CanvasImageData, CanvasMsg, FromLayoutMsg, FromScriptMsg,
};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::default::{Point2D, Rect, Size2D}; use euclid::default::{Point2D, Rect, Size2D};
use ipc_channel::ipc::{IpcSender, IpcSharedMemory}; use ipc_channel::ipc::IpcSharedMemory;
use profile_traits::ipc; use profile_traits::ipc;
use script_layout_interface::HTMLCanvasDataSource;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use crate::canvas_context::CanvasContext; use crate::canvas_context::{CanvasContext, LayoutCanvasRenderingContextHelpers};
use crate::canvas_state::CanvasState; use crate::canvas_state::CanvasState;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{ use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{
CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin, CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin,
@ -112,28 +111,16 @@ impl CanvasRenderingContext2D {
); );
self.canvas_state.get_rect(self.canvas.size(), rect) self.canvas_state.get_rect(self.canvas.size(), rect)
} }
pub(crate) fn send_data(&self, sender: IpcSender<CanvasImageData>) {
let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender), self.get_canvas_id());
let _ = self.canvas_state.get_ipc_renderer().send(msg);
}
} }
pub(crate) trait LayoutCanvasRenderingContext2DHelpers { impl LayoutCanvasRenderingContextHelpers for LayoutDom<'_, CanvasRenderingContext2D> {
fn get_ipc_renderer(self) -> IpcSender<CanvasMsg>; fn canvas_data_source(self) -> HTMLCanvasDataSource {
fn get_canvas_id(self) -> CanvasId; let canvas_state = &self.unsafe_get().canvas_state;
} HTMLCanvasDataSource::Image((
canvas_state.image_key(),
impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<'_, CanvasRenderingContext2D> { canvas_state.get_canvas_id(),
fn get_ipc_renderer(self) -> IpcSender<CanvasMsg> { canvas_state.get_ipc_renderer().clone(),
(self.unsafe_get()).canvas_state.get_ipc_renderer().clone() ))
}
fn get_canvas_id(self) -> CanvasId {
// FIXME(nox): This relies on the fact that CanvasState::get_canvas_id
// does nothing fancy but it would be easier to trust a
// LayoutDom<_>-like type that would wrap the &CanvasState.
self.unsafe_get().canvas_state.get_canvas_id()
} }
} }

View file

@ -6,7 +6,6 @@ use std::cell::{Cell, RefCell};
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
use canvas_traits::canvas::CanvasId;
use canvas_traits::webgl::{GLContextAttributes, WebGLVersion}; use canvas_traits::webgl::{GLContextAttributes, WebGLVersion};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::default::Size2D; use euclid::default::Size2D;
@ -48,9 +47,7 @@ use crate::dom::bindings::reflector::{DomGlobal, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, ToLayout}; use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, ToLayout};
use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::blob::Blob; use crate::dom::blob::Blob;
use crate::dom::canvasrenderingcontext2d::{ use crate::dom::canvasrenderingcontext2d::CanvasRenderingContext2D;
CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers,
};
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::element::{AttributeMutation, Element, LayoutElementHelpers}; use crate::dom::element::{AttributeMutation, Element, LayoutElementHelpers};
#[cfg(not(feature = "webgpu"))] #[cfg(not(feature = "webgpu"))]
@ -208,9 +205,7 @@ impl LayoutHTMLCanvasElementHelpers for LayoutDom<'_, HTMLCanvasElement> {
fn data(self) -> HTMLCanvasData { fn data(self) -> HTMLCanvasData {
let source = unsafe { let source = unsafe {
match self.unsafe_get().context.borrow_for_layout().as_ref() { match self.unsafe_get().context.borrow_for_layout().as_ref() {
Some(CanvasContext::Context2d(context)) => { Some(CanvasContext::Context2d(context)) => context.to_layout().canvas_data_source(),
HTMLCanvasDataSource::Image(context.to_layout().get_ipc_renderer())
},
Some(CanvasContext::WebGL(context)) => context.to_layout().canvas_data_source(), Some(CanvasContext::WebGL(context)) => context.to_layout().canvas_data_source(),
Some(CanvasContext::WebGL2(context)) => context.to_layout().canvas_data_source(), Some(CanvasContext::WebGL2(context)) => context.to_layout().canvas_data_source(),
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
@ -229,20 +224,6 @@ impl LayoutHTMLCanvasElementHelpers for LayoutDom<'_, HTMLCanvasElement> {
source, source,
width: width_attr.map_or(DEFAULT_WIDTH, |val| val.as_uint()), width: width_attr.map_or(DEFAULT_WIDTH, |val| val.as_uint()),
height: height_attr.map_or(DEFAULT_HEIGHT, |val| val.as_uint()), height: height_attr.map_or(DEFAULT_HEIGHT, |val| val.as_uint()),
canvas_id: self.get_canvas_id_for_layout(),
}
}
#[allow(unsafe_code)]
fn get_canvas_id_for_layout(self) -> CanvasId {
let canvas = self.unsafe_get();
unsafe {
if let &Some(CanvasContext::Context2d(ref context)) = canvas.context.borrow_for_layout()
{
context.to_layout().get_canvas_id()
} else {
CanvasId(0)
}
} }
} }
} }

View file

@ -4,13 +4,14 @@
use std::cell::Cell; use std::cell::Cell;
use canvas_traits::canvas::{CanvasId, CanvasImageData, CanvasMsg, FromLayoutMsg}; use canvas_traits::canvas::{CanvasId, CanvasMsg, FromLayoutMsg};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::{Scale, Size2D}; use euclid::{Scale, Size2D};
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc;
use script_bindings::reflector::Reflector; use script_bindings::reflector::Reflector;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use style_traits::CSSPixel; use style_traits::CSSPixel;
use webrender_api::ImageKey;
use webrender_api::units::DevicePixel; use webrender_api::units::DevicePixel;
use super::bindings::reflector::DomGlobal as _; use super::bindings::reflector::DomGlobal as _;
@ -64,9 +65,13 @@ impl PaintRenderingContext2D {
self.canvas_state.get_canvas_id() self.canvas_state.get_canvas_id()
} }
pub(crate) fn send_data(&self, sender: IpcSender<CanvasImageData>) { /// Send update to canvas paint thread and returns [`ImageKey`]
let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender), self.get_canvas_id()); pub(crate) fn image_key(&self) -> ImageKey {
let (sender, receiver) = ipc::channel().unwrap();
let msg = CanvasMsg::FromLayout(FromLayoutMsg::UpdateImage(sender), self.get_canvas_id());
let _ = self.canvas_state.get_ipc_renderer().send(msg); let _ = self.canvas_state.get_ipc_renderer().send(msg);
receiver.recv().unwrap();
self.canvas_state.image_key()
} }
pub(crate) fn take_missing_image_urls(&self) -> Vec<ServoUrl> { pub(crate) fn take_missing_image_urls(&self) -> Vec<ServoUrl> {

View file

@ -23,7 +23,6 @@ use js::rust::wrappers::{Call, Construct1};
use js::rust::{HandleValue, Runtime}; use js::rust::{HandleValue, Runtime};
use net_traits::image_cache::ImageCache; use net_traits::image_cache::ImageCache;
use pixels::PixelFormat; use pixels::PixelFormat;
use profile_traits::ipc;
use script_traits::{DrawAPaintImageResult, PaintWorkletError, Painter}; use script_traits::{DrawAPaintImageResult, PaintWorkletError, Painter};
use servo_config::pref; use servo_config::pref;
use servo_url::ServoUrl; use servo_url::ServoUrl;
@ -40,7 +39,7 @@ use crate::dom::bindings::codegen::Bindings::VoidFunctionBinding::VoidFunction;
use crate::dom::bindings::conversions::{get_property, get_property_jsval}; use crate::dom::bindings::conversions::{get_property, get_property_jsval};
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{DomGlobal, DomObject}; use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::cssstylevalue::CSSStyleValue; use crate::dom::cssstylevalue::CSSStyleValue;
@ -354,19 +353,13 @@ impl PaintWorkletGlobalScope {
return self.invalid_image(size_in_dpx, missing_image_urls); return self.invalid_image(size_in_dpx, missing_image_urls);
} }
let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()) let image_key = rendering_context.image_key();
.expect("IPC channel creation.");
rendering_context.send_data(sender);
let image_key = match receiver.recv() {
Ok(data) => Some(data.image_key),
_ => None,
};
DrawAPaintImageResult { DrawAPaintImageResult {
width: size_in_dpx.width, width: size_in_dpx.width,
height: size_in_dpx.height, height: size_in_dpx.height,
format: PixelFormat::BGRA8, format: PixelFormat::BGRA8,
image_key, image_key: Some(image_key),
missing_image_urls, missing_image_urls,
} }
} }

View file

@ -12,7 +12,6 @@ use serde::{Deserialize, Serialize};
use serde_bytes::ByteBuf; use serde_bytes::ByteBuf;
use style::color::AbsoluteColor; use style::color::AbsoluteColor;
use style::properties::style_structs::Font as FontStyleStruct; use style::properties::style_structs::Font as FontStyleStruct;
use webrender_api::ImageKey;
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
pub enum FillRule { pub enum FillRule {
@ -32,11 +31,6 @@ pub enum CanvasMsg {
Close(CanvasId), Close(CanvasId),
} }
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CanvasImageData {
pub image_key: ImageKey,
}
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub enum Canvas2dMsg { pub enum Canvas2dMsg {
Arc(Point2D<f32>, f32, f32, f32, bool), Arc(Point2D<f32>, f32, f32, f32, bool),
@ -84,7 +78,7 @@ pub enum Canvas2dMsg {
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
pub enum FromLayoutMsg { pub enum FromLayoutMsg {
SendData(IpcSender<CanvasImageData>), UpdateImage(IpcSender<()>),
} }
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]

View file

@ -8,6 +8,7 @@
use crossbeam_channel::Sender; use crossbeam_channel::Sender;
use euclid::default::Size2D; use euclid::default::Size2D;
use webrender_api::ImageKey;
use crate::canvas::CanvasId; use crate::canvas::CanvasId;
@ -17,7 +18,7 @@ pub mod webgl;
pub enum ConstellationCanvasMsg { pub enum ConstellationCanvasMsg {
Create { Create {
id_sender: Sender<CanvasId>, sender: Sender<(CanvasId, ImageKey)>,
size: Size2D<u64>, size: Size2D<u64>,
}, },
Exit, Exit,

View file

@ -25,6 +25,7 @@ use servo_url::{ImmutableOrigin, ServoUrl};
use style_traits::CSSPixel; use style_traits::CSSPixel;
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
use webgpu::{WebGPU, WebGPUResponse, wgc}; use webgpu::{WebGPU, WebGPUResponse, wgc};
use webrender_api::ImageKey;
use crate::mem::MemoryReportResult; use crate::mem::MemoryReportResult;
use crate::{ use crate::{
@ -144,7 +145,7 @@ pub enum ScriptMsg {
/// 2D canvases may use the GPU and we don't want to give untrusted content access to the GPU.) /// 2D canvases may use the GPU and we don't want to give untrusted content access to the GPU.)
CreateCanvasPaintThread( CreateCanvasPaintThread(
UntypedSize2D<u64>, UntypedSize2D<u64>,
IpcSender<(IpcSender<CanvasMsg>, CanvasId)>, IpcSender<(IpcSender<CanvasMsg>, CanvasId, ImageKey)>,
), ),
/// Notifies the constellation that this frame has received focus. /// Notifies the constellation that this frame has received focus.
Focus, Focus,

View file

@ -120,7 +120,7 @@ pub enum LayoutElementType {
pub enum HTMLCanvasDataSource { pub enum HTMLCanvasDataSource {
WebGL(ImageKey), WebGL(ImageKey),
Image(IpcSender<CanvasMsg>), Image((ImageKey, CanvasId, IpcSender<CanvasMsg>)),
WebGPU(ImageKey), WebGPU(ImageKey),
/// transparent black /// transparent black
Empty, Empty,
@ -130,7 +130,6 @@ pub struct HTMLCanvasData {
pub source: HTMLCanvasDataSource, pub source: HTMLCanvasDataSource,
pub width: u32, pub width: u32,
pub height: u32, pub height: u32,
pub canvas_id: CanvasId,
} }
pub struct SVGSVGData { pub struct SVGSVGData {