diff --git a/components/script/dom/canvas/2d/canvasrenderingcontext2d.rs b/components/script/dom/canvas/2d/canvasrenderingcontext2d.rs index ee63ffd1a94..fc13f82426c 100644 --- a/components/script/dom/canvas/2d/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvas/2d/canvasrenderingcontext2d.rs @@ -13,19 +13,23 @@ use servo_url::ServoUrl; use webrender_api::ImageKey; use super::canvas_state::CanvasState; -use crate::canvas_context::{CanvasContext, CanvasHelpers, LayoutCanvasRenderingContextHelpers}; +use crate::canvas_context::{ + CanvasContext, CanvasHelpers, HTMLCanvasElementOrOffscreenCanvas, + LayoutCanvasRenderingContextHelpers, +}; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{ CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin, CanvasRenderingContext2DMethods, CanvasTextAlign, CanvasTextBaseline, }; use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit; use crate::dom::bindings::codegen::UnionTypes::{ - HTMLCanvasElementOrOffscreenCanvas, StringOrCanvasGradientOrCanvasPattern, + HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas, + StringOrCanvasGradientOrCanvasPattern, }; use crate::dom::bindings::error::{ErrorResult, Fallible}; use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; -use crate::dom::bindings::root::{DomRoot, LayoutDom}; +use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom}; use crate::dom::bindings::str::DOMString; use crate::dom::canvasgradient::CanvasGradient; use crate::dom::canvaspattern::CanvasPattern; @@ -62,19 +66,18 @@ impl CanvasRenderingContext2D { }) } - #[cfg_attr(crown, allow(crown::unrooted_must_root))] pub(crate) fn new( global: &GlobalScope, canvas: &HTMLCanvasElement, size: Size2D, can_gc: CanGc, ) -> Option> { - let boxed = Box::new(CanvasRenderingContext2D::new_inherited( + CanvasRenderingContext2D::new_inherited( global, - HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(canvas)), + HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(Dom::from_ref(canvas)), size, - )?); - Some(reflect_dom_object(boxed, global, can_gc)) + ) + .map(|context| reflect_dom_object(Box::new(context), global, can_gc)) } // https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state @@ -119,8 +122,8 @@ impl CanvasContext for CanvasRenderingContext2D { self.canvas_state.get_canvas_id() } - fn canvas(&self) -> Option { - Some(self.canvas.clone()) + fn canvas(&self) -> Option { + Some(RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas)) } fn update_rendering(&self, canvas_epoch: Epoch) -> bool { @@ -178,7 +181,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingCo // https://html.spec.whatwg.org/multipage/#dom-context-2d-canvas fn Canvas(&self) -> DomRoot { match &self.canvas { - HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => canvas.clone(), + HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => canvas.as_rooted(), _ => panic!("Should not be called from offscreen canvas"), } } diff --git a/components/script/dom/canvas/2d/offscreencanvasrenderingcontext2d.rs b/components/script/dom/canvas/2d/offscreencanvasrenderingcontext2d.rs index cbad02f8499..c0fe793fc8f 100644 --- a/components/script/dom/canvas/2d/offscreencanvasrenderingcontext2d.rs +++ b/components/script/dom/canvas/2d/offscreencanvasrenderingcontext2d.rs @@ -2,27 +2,30 @@ * 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 crate::dom::bindings::codegen::GenericBindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2D_Binding::CanvasRenderingContext2DMethods; -use crate::canvas_context::CanvasContext; -use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; use canvas_traits::canvas::Canvas2dMsg; use dom_struct::dom_struct; +use euclid::default::Size2D; use pixels::Snapshot; +use crate::canvas_context::{CanvasContext, HTMLCanvasElementOrOffscreenCanvas}; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{ CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin, - CanvasTextAlign, CanvasTextBaseline, + CanvasRenderingContext2DMethods, CanvasTextAlign, CanvasTextBaseline, }; use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrix2DInit; use crate::dom::bindings::codegen::Bindings::OffscreenCanvasRenderingContext2DBinding::OffscreenCanvasRenderingContext2DMethods; -use crate::dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern; +use crate::dom::bindings::codegen::UnionTypes::{ + HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas, + StringOrCanvasGradientOrCanvasPattern, +}; use crate::dom::bindings::error::{ErrorResult, Fallible}; use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::reflect_dom_object; -use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::DOMString; use crate::dom::canvasgradient::CanvasGradient; use crate::dom::canvaspattern::CanvasPattern; +use crate::dom::canvasrenderingcontext2d::CanvasRenderingContext2D; use crate::dom::dommatrix::DOMMatrix; use crate::dom::globalscope::GlobalScope; use crate::dom::imagedata::ImageData; @@ -31,8 +34,6 @@ use crate::dom::path2d::Path2D; use crate::dom::textmetrics::TextMetrics; use crate::script_runtime::CanGc; -use super::canvasrenderingcontext2d::CanvasRenderingContext2D; - #[dom_struct] pub(crate) struct OffscreenCanvasRenderingContext2D { context: CanvasRenderingContext2D, @@ -42,28 +43,26 @@ impl OffscreenCanvasRenderingContext2D { #[cfg_attr(crown, allow(crown::unrooted_must_root))] fn new_inherited( global: &GlobalScope, - canvas: &OffscreenCanvas, + canvas: HTMLCanvasElementOrOffscreenCanvas, + size: Size2D, ) -> Option { - let size = canvas.get_size().cast(); Some(OffscreenCanvasRenderingContext2D { - context: CanvasRenderingContext2D::new_inherited( - global, - HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(DomRoot::from_ref(canvas)), - size, - )?, + context: CanvasRenderingContext2D::new_inherited(global, canvas, size)?, }) } - #[cfg_attr(crown, allow(crown::unrooted_must_root))] pub(crate) fn new( global: &GlobalScope, canvas: &OffscreenCanvas, + size: Size2D, can_gc: CanGc, ) -> Option> { - let boxed = Box::new(OffscreenCanvasRenderingContext2D::new_inherited( - global, canvas, - )?); - Some(reflect_dom_object(boxed, global, can_gc)) + OffscreenCanvasRenderingContext2D::new_inherited( + global, + HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(Dom::from_ref(canvas)), + size, + ) + .map(|context| reflect_dom_object(Box::new(context), global, can_gc)) } pub(crate) fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) { @@ -78,7 +77,7 @@ impl CanvasContext for OffscreenCanvasRenderingContext2D { self.context.context_id() } - fn canvas(&self) -> Option { + fn canvas(&self) -> Option { self.context.canvas() } @@ -109,7 +108,7 @@ impl OffscreenCanvasRenderingContext2DMethods // https://html.spec.whatwg.org/multipage/offscreencontext2d-canvas fn Canvas(&self) -> DomRoot { match self.context.canvas() { - Some(HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas, + Some(RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas)) => canvas, _ => panic!("Should not be called from onscreen canvas"), } } diff --git a/components/script/dom/canvas/canvas_context.rs b/components/script/dom/canvas/canvas_context.rs index dd452d5488d..594da353a7c 100644 --- a/components/script/dom/canvas/canvas_context.rs +++ b/components/script/dom/canvas/canvas_context.rs @@ -6,19 +6,17 @@ use base::Epoch; use euclid::default::Size2D; -use layout_api::HTMLCanvasData; use pixels::Snapshot; use script_bindings::root::{Dom, DomRoot}; use webrender_api::ImageKey; -use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; +use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas; use crate::dom::bindings::inheritance::Castable; -use crate::dom::html::htmlcanvaselement::HTMLCanvasElement; use crate::dom::node::{Node, NodeDamage}; #[cfg(feature = "webgpu")] use crate::dom::types::GPUCanvasContext; use crate::dom::types::{ - CanvasRenderingContext2D, ImageBitmapRenderingContext, OffscreenCanvas, + CanvasRenderingContext2D, HTMLCanvasElement, ImageBitmapRenderingContext, OffscreenCanvas, OffscreenCanvasRenderingContext2D, WebGL2RenderingContext, WebGLRenderingContext, }; @@ -27,8 +25,45 @@ pub(crate) trait LayoutCanvasRenderingContextHelpers { fn canvas_data_source(self) -> Option; } -pub(crate) trait LayoutHTMLCanvasElementHelpers { - fn data(self) -> HTMLCanvasData; +/// Non rooted variant of [`crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas`] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +#[derive(Clone, JSTraceable, MallocSizeOf)] +pub(crate) enum HTMLCanvasElementOrOffscreenCanvas { + HTMLCanvasElement(Dom), + OffscreenCanvas(Dom), +} + +impl From<&RootedHTMLCanvasElementOrOffscreenCanvas> for HTMLCanvasElementOrOffscreenCanvas { + /// Returns a traced version suitable for use as member of other DOM objects. + #[cfg_attr(crown, allow(crown::unrooted_must_root))] + fn from( + value: &RootedHTMLCanvasElementOrOffscreenCanvas, + ) -> HTMLCanvasElementOrOffscreenCanvas { + match value { + RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => { + HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas.as_traced()) + }, + RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => { + HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas.as_traced()) + }, + } + } +} + +impl From<&HTMLCanvasElementOrOffscreenCanvas> for RootedHTMLCanvasElementOrOffscreenCanvas { + /// Returns a rooted version suitable for use on the stack. + fn from( + value: &HTMLCanvasElementOrOffscreenCanvas, + ) -> RootedHTMLCanvasElementOrOffscreenCanvas { + match value { + HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => { + RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas.as_rooted()) + }, + HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => { + RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas.as_rooted()) + }, + } + } } pub(crate) trait CanvasContext { @@ -36,7 +71,7 @@ pub(crate) trait CanvasContext { fn context_id(&self) -> Self::ID; - fn canvas(&self) -> Option; + fn canvas(&self) -> Option; fn resize(&self); @@ -61,7 +96,8 @@ pub(crate) trait CanvasContext { } fn mark_as_dirty(&self) { - if let Some(HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas)) = &self.canvas() + if let Some(RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas)) = + self.canvas() { canvas.upcast::().dirty(NodeDamage::Other); } @@ -82,12 +118,12 @@ pub(crate) trait CanvasContext { }; match canvas { - HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(ref canvas) => { + RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => { canvas.upcast::().is_connected() }, // FIXME(34628): Offscreen canvases should be considered offscreen if a placeholder is set. // - HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(_) => false, + RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(_) => false, } } } @@ -109,12 +145,36 @@ impl CanvasHelpers for HTMLCanvasElementOrOffscreenCanvas { fn canvas(&self) -> Option> { match self { - HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => Some(canvas.clone()), + HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => { + Some(canvas.as_rooted()) + }, HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas.placeholder(), } } } +impl CanvasHelpers for RootedHTMLCanvasElementOrOffscreenCanvas { + fn size(&self) -> Size2D { + match self { + RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => { + canvas.get_size().cast() + }, + RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas.get_size(), + } + } + + fn canvas(&self) -> Option> { + match self { + RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => { + Some(canvas.clone()) + }, + RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => { + canvas.placeholder() + }, + } + } +} + /// Non rooted variant of [`crate::dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::RenderingContext`] #[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] #[derive(Clone, JSTraceable, MallocSizeOf)] @@ -133,7 +193,7 @@ impl CanvasContext for RenderingContext { fn context_id(&self) -> Self::ID {} - fn canvas(&self) -> Option { + fn canvas(&self) -> Option { match self { RenderingContext::Placeholder(offscreen_canvas) => offscreen_canvas.context()?.canvas(), RenderingContext::Context2d(context) => context.canvas(), @@ -297,7 +357,7 @@ impl CanvasContext for OffscreenRenderingContext { fn context_id(&self) -> Self::ID {} - fn canvas(&self) -> Option { + fn canvas(&self) -> Option { match self { OffscreenRenderingContext::Context2d(context) => context.canvas(), OffscreenRenderingContext::BitmapRenderer(context) => context.canvas(), diff --git a/components/script/dom/canvas/imagebitmaprenderingcontext.rs b/components/script/dom/canvas/imagebitmaprenderingcontext.rs index 47c3e2ebe02..b37d6533882 100644 --- a/components/script/dom/canvas/imagebitmaprenderingcontext.rs +++ b/components/script/dom/canvas/imagebitmaprenderingcontext.rs @@ -9,11 +9,14 @@ use euclid::default::Size2D; use pixels::Snapshot; use webrender_api::ImageKey; -use crate::canvas_context::{CanvasContext, CanvasHelpers, LayoutCanvasRenderingContextHelpers}; +use crate::canvas_context::{ + CanvasContext, CanvasHelpers, HTMLCanvasElementOrOffscreenCanvas, + LayoutCanvasRenderingContextHelpers, +}; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::ImageBitmapBinding::ImageBitmapMethods; use crate::dom::bindings::codegen::Bindings::ImageBitmapRenderingContextBinding::ImageBitmapRenderingContextMethods; -use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; +use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas; use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::reflector::{Reflector, reflect_dom_object}; use crate::dom::bindings::root::{DomRoot, LayoutDom}; @@ -37,6 +40,7 @@ pub(crate) struct ImageBitmapRenderingContext { impl ImageBitmapRenderingContext { /// + #[cfg_attr(crown, allow(crown::unrooted_must_root))] fn new_inherited(canvas: HTMLCanvasElementOrOffscreenCanvas) -> ImageBitmapRenderingContext { ImageBitmapRenderingContext { reflector_: Reflector::new(), @@ -48,11 +52,13 @@ impl ImageBitmapRenderingContext { pub(crate) fn new( global: &GlobalScope, - canvas: HTMLCanvasElementOrOffscreenCanvas, + canvas: &RootedHTMLCanvasElementOrOffscreenCanvas, can_gc: CanGc, ) -> DomRoot { reflect_dom_object( - Box::new(ImageBitmapRenderingContext::new_inherited(canvas)), + Box::new(ImageBitmapRenderingContext::new_inherited( + HTMLCanvasElementOrOffscreenCanvas::from(canvas), + )), global, can_gc, ) @@ -99,8 +105,8 @@ impl CanvasContext for ImageBitmapRenderingContext { fn context_id(&self) -> Self::ID {} - fn canvas(&self) -> Option { - Some(self.canvas.clone()) + fn canvas(&self) -> Option { + Some(RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas)) } /// @@ -158,8 +164,8 @@ impl CanvasContext for ImageBitmapRenderingContext { impl ImageBitmapRenderingContextMethods for ImageBitmapRenderingContext { /// - fn Canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas { - self.canvas.clone() + fn Canvas(&self) -> RootedHTMLCanvasElementOrOffscreenCanvas { + RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas) } /// diff --git a/components/script/dom/canvas/offscreencanvas.rs b/components/script/dom/canvas/offscreencanvas.rs index ced6a4cf76f..f95f173ebbe 100644 --- a/components/script/dom/canvas/offscreencanvas.rs +++ b/components/script/dom/canvas/offscreencanvas.rs @@ -20,7 +20,7 @@ use crate::dom::bindings::codegen::Bindings::OffscreenCanvasBinding::{ ImageEncodeOptions, OffscreenCanvasMethods, OffscreenRenderingContext as RootedOffscreenRenderingContext, }; -use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; +use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas; use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object_with_proto}; @@ -135,7 +135,8 @@ impl OffscreenCanvas { _ => None, }; } - let context = OffscreenCanvasRenderingContext2D::new(&self.global(), self, can_gc)?; + let context = + OffscreenCanvasRenderingContext2D::new(&self.global(), self, self.get_size(), can_gc)?; *self.context.borrow_mut() = Some(OffscreenRenderingContext::Context2d(Dom::from_ref( &*context, ))); @@ -159,11 +160,10 @@ impl OffscreenCanvas { // Step 1. Let context be the result of running the // ImageBitmapRenderingContext creation algorithm given this and // options. - let context = ImageBitmapRenderingContext::new( - &self.global(), - HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(DomRoot::from_ref(self)), - can_gc, - ); + let canvas = + RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(DomRoot::from_ref(self)); + + let context = ImageBitmapRenderingContext::new(&self.global(), &canvas, can_gc); // Step 2. Set this's context mode to bitmaprenderer. *self.context.borrow_mut() = Some(OffscreenRenderingContext::BitmapRenderer( diff --git a/components/script/dom/gpucanvascontext.rs b/components/script/dom/gpucanvascontext.rs index 312b7e119fa..42e19d71e80 100644 --- a/components/script/dom/gpucanvascontext.rs +++ b/components/script/dom/gpucanvascontext.rs @@ -2,15 +2,14 @@ * 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 base::Epoch; use dom_struct::dom_struct; use webrender_api::ImageKey; +use crate::canvas_context::LayoutCanvasRenderingContextHelpers; use crate::dom::bindings::codegen::Bindings::GPUCanvasContextBinding::GPUCanvasContextMethods; -use crate::dom::bindings::codegen::UnionTypes; +use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas; use crate::dom::bindings::reflector::Reflector; use crate::dom::bindings::root::LayoutDom; -use crate::dom::html::htmlcanvaselement::LayoutCanvasRenderingContextHelpers; #[dom_struct] pub(crate) struct GPUCanvasContext { @@ -26,7 +25,7 @@ impl GPUCanvasContext { impl GPUCanvasContextMethods for GPUCanvasContext { /// - fn Canvas(&self) -> UnionTypes::HTMLCanvasElementOrOffscreenCanvas { + fn Canvas(&self) -> RootedHTMLCanvasElementOrOffscreenCanvas { unimplemented!() } } diff --git a/components/script/dom/html/htmlcanvaselement.rs b/components/script/dom/html/htmlcanvaselement.rs index 52f1fc7c81c..a0e5456aa67 100644 --- a/components/script/dom/html/htmlcanvaselement.rs +++ b/components/script/dom/html/htmlcanvaselement.rs @@ -24,7 +24,7 @@ use servo_media::streams::MediaStreamType; use servo_media::streams::registry::MediaStreamId; use style::attr::AttrValue; -pub(crate) use crate::canvas_context::*; +use crate::canvas_context::{CanvasContext, LayoutCanvasRenderingContextHelpers, RenderingContext}; use crate::conversions::Convert; use crate::dom::attr::Attr; use crate::dom::bindings::callback::ExceptionHandling; @@ -34,7 +34,7 @@ use crate::dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::{ }; use crate::dom::bindings::codegen::Bindings::MediaStreamBinding::MediaStreamMethods; use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; -use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; +use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas; use crate::dom::bindings::conversions::ConversionResult; use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::inheritance::Castable; @@ -156,6 +156,10 @@ impl HTMLCanvasElement { } } +pub(crate) trait LayoutHTMLCanvasElementHelpers { + fn data(self) -> HTMLCanvasData; +} + impl LayoutHTMLCanvasElementHelpers for LayoutDom<'_, HTMLCanvasElement> { #[allow(unsafe_code)] fn data(self) -> HTMLCanvasData { @@ -227,11 +231,10 @@ impl HTMLCanvasElement { // Step 1. Let context be the result of running the // ImageBitmapRenderingContext creation algorithm given this and // options. - let context = ImageBitmapRenderingContext::new( - &self.owner_global(), - HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self)), - can_gc, - ); + let canvas = + RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self)); + + let context = ImageBitmapRenderingContext::new(&self.owner_global(), &canvas, can_gc); // Step 2. Set this's context mode to bitmaprenderer. *self.context_mode.borrow_mut() = @@ -254,9 +257,10 @@ impl HTMLCanvasElement { }; } let window = self.owner_window(); + let canvas = + RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self)); let size = self.get_size(); let attrs = Self::get_gl_attributes(cx, options)?; - let canvas = HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self)); let context = WebGLRenderingContext::new( &window, &canvas, @@ -286,9 +290,10 @@ impl HTMLCanvasElement { }; } let window = self.owner_window(); + let canvas = + RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self)); let size = self.get_size(); let attrs = Self::get_gl_attributes(cx, options)?; - let canvas = HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self)); let context = WebGL2RenderingContext::new(&window, &canvas, size, attrs, can_gc)?; *self.context_mode.borrow_mut() = Some(RenderingContext::WebGL2(Dom::from_ref(&*context))); Some(context) diff --git a/components/script/dom/webgl/webgl2renderingcontext.rs b/components/script/dom/webgl/webgl2renderingcontext.rs index 7117cf526cf..0b523d7950d 100644 --- a/components/script/dom/webgl/webgl2renderingcontext.rs +++ b/components/script/dom/webgl/webgl2renderingcontext.rs @@ -29,7 +29,7 @@ use url::Host; use webrender_api::ImageKey; use super::validations::types::TexImageTarget; -use crate::canvas_context::CanvasContext; +use crate::canvas_context::{CanvasContext, LayoutCanvasRenderingContextHelpers}; use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::{ WebGL2RenderingContextConstants as constants, WebGL2RenderingContextMethods, }; @@ -38,15 +38,14 @@ use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{ }; use crate::dom::bindings::codegen::UnionTypes::{ ArrayBufferViewOrArrayBuffer, Float32ArrayOrUnrestrictedFloatSequence, - HTMLCanvasElementOrOffscreenCanvas, Int32ArrayOrLongSequence, - Uint32ArrayOrUnsignedLongSequence, + HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas, + Int32ArrayOrLongSequence, Uint32ArrayOrUnsignedLongSequence, }; use crate::dom::bindings::error::{ErrorResult, Fallible}; use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom, ToLayout}; use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; -use crate::dom::html::htmlcanvaselement::LayoutCanvasRenderingContextHelpers; #[cfg(feature = "webxr")] use crate::dom::promise::Promise; use crate::dom::webgl::validations::WebGLValidator; @@ -133,7 +132,7 @@ struct ReadPixelsSizes { impl WebGL2RenderingContext { fn new_inherited( window: &Window, - canvas: &HTMLCanvasElementOrOffscreenCanvas, + canvas: &RootedHTMLCanvasElementOrOffscreenCanvas, size: Size2D, attrs: GLContextAttributes, can_gc: CanGc, @@ -179,10 +178,9 @@ impl WebGL2RenderingContext { }) } - #[cfg_attr(crown, allow(crown::unrooted_must_root))] pub(crate) fn new( window: &Window, - canvas: &HTMLCanvasElementOrOffscreenCanvas, + canvas: &RootedHTMLCanvasElementOrOffscreenCanvas, size: Size2D, attrs: GLContextAttributes, can_gc: CanGc, @@ -973,8 +971,8 @@ impl CanvasContext for WebGL2RenderingContext { self.base.context_id() } - fn canvas(&self) -> Option { - self.base.canvas().clone() + fn canvas(&self) -> Option { + self.base.canvas() } fn resize(&self) { @@ -1000,7 +998,7 @@ impl CanvasContext for WebGL2RenderingContext { impl WebGL2RenderingContextMethods for WebGL2RenderingContext { /// - fn Canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas { + fn Canvas(&self) -> RootedHTMLCanvasElementOrOffscreenCanvas { self.base.Canvas() } diff --git a/components/script/dom/webgl/webglrenderingcontext.rs b/components/script/dom/webgl/webglrenderingcontext.rs index 6664639fb3d..4e96bd7c2d6 100644 --- a/components/script/dom/webgl/webglrenderingcontext.rs +++ b/components/script/dom/webgl/webglrenderingcontext.rs @@ -35,7 +35,9 @@ use serde::{Deserialize, Serialize}; use servo_config::pref; use webrender_api::ImageKey; -use crate::canvas_context::CanvasContext; +use crate::canvas_context::{ + CanvasContext, HTMLCanvasElementOrOffscreenCanvas, LayoutCanvasRenderingContextHelpers, +}; use crate::dom::bindings::cell::{DomRefCell, Ref, RefMut}; use crate::dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysConstants; use crate::dom::bindings::codegen::Bindings::EXTBlendMinmaxBinding::EXTBlendMinmaxConstants; @@ -47,7 +49,8 @@ use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{ }; use crate::dom::bindings::codegen::UnionTypes::{ ArrayBufferViewOrArrayBuffer, Float32ArrayOrUnrestrictedFloatSequence, - HTMLCanvasElementOrOffscreenCanvas, Int32ArrayOrLongSequence, + HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas, + Int32ArrayOrLongSequence, }; use crate::dom::bindings::conversions::DerivedFrom; use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; @@ -56,7 +59,6 @@ use crate::dom::bindings::reflector::{DomGlobal, DomObject, Reflector, reflect_d use crate::dom::bindings::root::{DomOnceCell, DomRoot, LayoutDom, MutNullableDom}; use crate::dom::bindings::str::DOMString; use crate::dom::event::{Event, EventBubbles, EventCancelable}; -use crate::dom::html::htmlcanvaselement::LayoutCanvasRenderingContextHelpers; use crate::dom::node::{Node, NodeDamage, NodeTraits}; #[cfg(feature = "webxr")] use crate::dom::promise::Promise; @@ -216,9 +218,10 @@ pub(crate) struct WebGLRenderingContext { } impl WebGLRenderingContext { + #[cfg_attr(crown, allow(crown::unrooted_must_root))] pub(crate) fn new_inherited( window: &Window, - canvas: &HTMLCanvasElementOrOffscreenCanvas, + canvas: HTMLCanvasElementOrOffscreenCanvas, webgl_version: WebGLVersion, size: Size2D, attrs: GLContextAttributes, @@ -248,7 +251,7 @@ impl WebGLRenderingContext { webgl_version, glsl_version: ctx_data.glsl_version, limits: ctx_data.limits, - canvas: canvas.clone(), + canvas, last_error: Cell::new(None), texture_packing_alignment: Cell::new(4), texture_unpacking_settings: Cell::new(TextureUnpacking::CONVERT_COLORSPACE), @@ -285,13 +288,19 @@ impl WebGLRenderingContext { #[cfg_attr(crown, allow(crown::unrooted_must_root))] pub(crate) fn new( window: &Window, - canvas: &HTMLCanvasElementOrOffscreenCanvas, + canvas: &RootedHTMLCanvasElementOrOffscreenCanvas, webgl_version: WebGLVersion, size: Size2D, attrs: GLContextAttributes, can_gc: CanGc, ) -> Option> { - match WebGLRenderingContext::new_inherited(window, canvas, webgl_version, size, attrs) { + match WebGLRenderingContext::new_inherited( + window, + HTMLCanvasElementOrOffscreenCanvas::from(canvas), + webgl_version, + size, + attrs, + ) { Ok(ctx) => Some(reflect_dom_object(Box::new(ctx), window, can_gc)), Err(msg) => { error!("Couldn't create WebGLRenderingContext: {}", msg); @@ -304,10 +313,10 @@ impl WebGLRenderingContext { can_gc, ); match canvas { - HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => { + RootedHTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => { event.upcast::().fire(canvas.upcast(), can_gc); }, - HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => { + RootedHTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => { event.upcast::().fire(canvas.upcast(), can_gc); }, } @@ -1930,8 +1939,8 @@ impl CanvasContext for WebGLRenderingContext { self.webgl_sender.context_id() } - fn canvas(&self) -> Option { - Some(self.canvas.clone()) + fn canvas(&self) -> Option { + Some(RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas)) } fn resize(&self) { @@ -2075,8 +2084,8 @@ impl Drop for WebGLRenderingContext { impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1 - fn Canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas { - self.canvas.clone() + fn Canvas(&self) -> RootedHTMLCanvasElementOrOffscreenCanvas { + RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11 diff --git a/components/script/dom/webgpu/gpucanvascontext.rs b/components/script/dom/webgpu/gpucanvascontext.rs index d3769695af0..a00b2ec56c1 100644 --- a/components/script/dom/webgpu/gpucanvascontext.rs +++ b/components/script/dom/webgpu/gpucanvascontext.rs @@ -20,7 +20,10 @@ use wgpu_core::id; use super::gpuconvert::convert_texture_descriptor; use super::gputexture::GPUTexture; -use crate::canvas_context::{CanvasContext, CanvasHelpers}; +use crate::canvas_context::{ + CanvasContext, CanvasHelpers, HTMLCanvasElementOrOffscreenCanvas, + LayoutCanvasRenderingContextHelpers, +}; use crate::conversions::Convert; use crate::dom::bindings::codegen::Bindings::GPUCanvasContextBinding::GPUCanvasContextMethods; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUTexture_Binding::GPUTextureMethods; @@ -29,15 +32,15 @@ use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ GPUObjectDescriptorBase, GPUTextureDescriptor, GPUTextureDimension, GPUTextureFormat, GPUTextureUsageConstants, }; -use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; +use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas as RootedHTMLCanvasElementOrOffscreenCanvas; use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; -use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom}; +use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom}; use crate::dom::bindings::str::USVString; use crate::dom::bindings::weakref::WeakRef; use crate::dom::document::WebGPUContextsMap; use crate::dom::globalscope::GlobalScope; -use crate::dom::html::htmlcanvaselement::{HTMLCanvasElement, LayoutCanvasRenderingContextHelpers}; +use crate::dom::html::htmlcanvaselement::HTMLCanvasElement; use crate::dom::node::NodeTraits; use crate::script_runtime::CanGc; @@ -91,6 +94,7 @@ pub(crate) struct GPUCanvasContext { } impl GPUCanvasContext { + #[cfg_attr(crown, allow(crown::unrooted_must_root))] fn new_inherited( global: &GlobalScope, canvas: HTMLCanvasElementOrOffscreenCanvas, @@ -139,7 +143,7 @@ impl GPUCanvasContext { let this = reflect_dom_object( Box::new(GPUCanvasContext::new_inherited( global, - HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(canvas)), + HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(Dom::from_ref(canvas)), channel, document.webgpu_contexts(), )), @@ -328,8 +332,8 @@ impl CanvasContext for GPUCanvasContext { }) } - fn canvas(&self) -> Option { - Some(self.canvas.clone()) + fn canvas(&self) -> Option { + Some(RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas)) } } @@ -341,8 +345,8 @@ impl LayoutCanvasRenderingContextHelpers for LayoutDom<'_, GPUCanvasContext> { impl GPUCanvasContextMethods for GPUCanvasContext { /// - fn Canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas { - self.canvas.clone() + fn Canvas(&self) -> RootedHTMLCanvasElementOrOffscreenCanvas { + RootedHTMLCanvasElementOrOffscreenCanvas::from(&self.canvas) } /// diff --git a/components/script/dom/webxr/xrwebgllayer.rs b/components/script/dom/webxr/xrwebgllayer.rs index 32a745f42b7..087aad6e7f4 100644 --- a/components/script/dom/webxr/xrwebgllayer.rs +++ b/components/script/dom/webxr/xrwebgllayer.rs @@ -10,14 +10,13 @@ use euclid::{Rect, Size2D}; use js::rust::HandleObject; use webxr_api::{ContextId as WebXRContextId, LayerId, LayerInit, Viewport}; -use crate::canvas_context::CanvasContext as _; +use crate::canvas_context::CanvasContext; use crate::conversions::Convert; use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants; use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods; use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::{ XRWebGLLayerInit, XRWebGLLayerMethods, XRWebGLRenderingContext, }; -use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; @@ -125,14 +124,7 @@ impl XRWebGLLayer { size.1.try_into().unwrap_or(0), ) } else { - let size = match self.context().Canvas() { - HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => canvas.get_size(), - HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => { - let size = canvas.get_size(); - Size2D::new(size.width, size.height) - }, - }; - Size2D::from_untyped(size) + Size2D::from_untyped(self.context().size()) } }