script: Add CanvasContext trait (#35448)

* trait `CanvasContext`

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* fixup most stuff

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* explain and limit crown `allow(crown::unrooted_must_root)`

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

---------

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
Samson 2025-02-21 21:26:27 +01:00 committed by GitHub
parent 084006abb6
commit a6f19c0092
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 317 additions and 210 deletions

View file

@ -7,7 +7,6 @@ use std::cell::RefCell;
use arrayvec::ArrayVec;
use dom_struct::dom_struct;
use euclid::default::Size2D;
use ipc_channel::ipc::{self, IpcSharedMemory};
use script_layout_interface::HTMLCanvasDataSource;
use webgpu::swapchain::WebGPUContextId;
@ -20,6 +19,7 @@ use webrender_api::ImageKey;
use super::gpuconvert::convert_texture_descriptor;
use super::gputexture::GPUTexture;
use crate::canvas_context::CanvasContext;
use crate::conversions::Convert;
use crate::dom::bindings::codegen::Bindings::GPUCanvasContextBinding::GPUCanvasContextMethods;
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUTexture_Binding::GPUTextureMethods;
@ -30,7 +30,6 @@ use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
};
use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas;
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomGlobal, Reflector};
use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::USVString;
@ -38,20 +37,9 @@ use crate::dom::bindings::weakref::WeakRef;
use crate::dom::document::WebGPUContextsMap;
use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlcanvaselement::{HTMLCanvasElement, LayoutCanvasRenderingContextHelpers};
use crate::dom::node::{Node, NodeDamage, NodeTraits};
use crate::dom::node::NodeTraits;
use crate::script_runtime::CanGc;
impl HTMLCanvasElementOrOffscreenCanvas {
fn size(&self) -> Size2D<u64> {
match self {
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => {
canvas.get_size().cast()
},
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas.get_size(),
}
}
}
/// <https://gpuweb.github.io/gpuweb/#supported-context-formats>
fn supported_context_format(format: GPUTextureFormat) -> bool {
// TODO: GPUTextureFormat::Rgba16float
@ -260,43 +248,24 @@ impl GPUCanvasContext {
);
}
}
fn size(&self) -> Size2D<u64> {
self.canvas.size()
}
}
// public methods for canvas handling
// these methods should probably be behind trait for all canvases
impl GPUCanvasContext {
pub(crate) fn context_id(&self) -> WebGPUContextId {
impl CanvasContext for GPUCanvasContext {
type ID = WebGPUContextId;
#[cfg_attr(crown, allow(crown::unrooted_must_root))] // Crown is wrong here #35570
fn context_id(&self) -> WebGPUContextId {
self.context_id
}
pub(crate) fn mark_as_dirty(&self) {
if let HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) = &self.canvas {
canvas.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
}
}
pub(crate) fn onscreen(&self) -> bool {
match self.canvas {
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(ref canvas) => {
canvas.upcast::<Node>().is_connected()
},
// FIXME(#34628): Handle this properly
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(_) => false,
}
}
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-updating-the-rendering-of-a-webgpu-canvas>
pub(crate) fn update_rendering_of_webgpu_canvas(&self) {
fn update_rendering(&self) {
// Step 1
self.expire_current_texture();
}
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-update-the-canvas-size>
pub(crate) fn resize(&self) {
fn resize(&self) {
// Step 1
self.replace_drawing_buffer();
// Step 2
@ -309,9 +278,9 @@ impl GPUCanvasContext {
}
/// <https://gpuweb.github.io/gpuweb/#ref-for-abstract-opdef-get-a-copy-of-the-image-contents-of-a-context%E2%91%A5>
pub(crate) fn get_ipc_image(&self) -> IpcSharedMemory {
fn get_image_data_as_shared_memory(&self) -> Option<IpcSharedMemory> {
// 1. Return a copy of the image contents of context.
if self.drawing_buffer.borrow().cleared {
Some(if self.drawing_buffer.borrow().cleared {
IpcSharedMemory::from_byte(0, self.size().area() as usize * 4)
} else {
let (sender, receiver) = ipc::channel().unwrap();
@ -323,11 +292,11 @@ impl GPUCanvasContext {
})
.unwrap();
receiver.recv().unwrap()
}
})
}
pub(crate) fn get_image_data(&self) -> Vec<u8> {
self.get_ipc_image().to_vec()
fn canvas(&self) -> HTMLCanvasElementOrOffscreenCanvas {
self.canvas.clone()
}
}