[#26488] Refactors WebGLFramebuffer deletion (#37589)

Testing: No tests added
Fixes: Partially #26488

Signed-off-by: Domenico Rizzo <domenico.rizzo@gmail.com>
This commit is contained in:
Domenico Rizzo 2025-06-21 20:27:39 +02:00 committed by GitHub
parent f370606fa8
commit 5579b11cf6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -13,6 +13,7 @@ use canvas_traits::webgl::{
}; };
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::Size2D; use euclid::Size2D;
use script_bindings::weakref::WeakRef;
#[cfg(feature = "webxr")] #[cfg(feature = "webxr")]
use webxr_api::Viewport; use webxr_api::Viewport;
@ -91,15 +92,66 @@ pub(crate) enum WebGLFramebufferAttachmentRoot {
Texture(DomRoot<WebGLTexture>), Texture(DomRoot<WebGLTexture>),
} }
#[derive(JSTraceable, MallocSizeOf)]
struct DroppableWebGLFramebuffer {
#[no_trace]
id: WebGLFramebufferId,
is_deleted: Cell<bool>,
context: WeakRef<WebGLRenderingContext>,
}
impl DroppableWebGLFramebuffer {
fn new(
id: WebGLFramebufferId,
is_deleted: Cell<bool>,
context: WeakRef<WebGLRenderingContext>,
) -> Self {
Self {
id,
is_deleted,
context,
}
}
}
impl DroppableWebGLFramebuffer {
pub(crate) fn id(&self) -> WebGLFramebufferId {
self.id
}
pub(crate) fn is_deleted(&self) -> bool {
self.is_deleted.get()
}
pub(crate) fn set_deleted(&self, deleted: bool) {
self.is_deleted.set(deleted);
}
pub(crate) fn delete(&self, operation_fallibility: Operation) {
if !self.is_deleted() {
self.set_deleted(true);
if let Some(context) = self.context.root() {
let cmd = WebGLCommand::DeleteFramebuffer(self.id());
match operation_fallibility {
Operation::Fallible => context.send_command_ignored(cmd),
Operation::Infallible => context.send_command(cmd),
}
}
}
}
}
impl Drop for DroppableWebGLFramebuffer {
fn drop(&mut self) {
self.delete(Operation::Fallible);
}
}
#[dom_struct] #[dom_struct]
pub(crate) struct WebGLFramebuffer { pub(crate) struct WebGLFramebuffer {
webgl_object: WebGLObject, webgl_object: WebGLObject,
#[no_trace] #[no_trace]
webgl_version: WebGLVersion, webgl_version: WebGLVersion,
#[no_trace]
id: WebGLFramebufferId,
target: Cell<Option<u32>>, target: Cell<Option<u32>>,
is_deleted: Cell<bool>,
size: Cell<Option<(i32, i32)>>, size: Cell<Option<(i32, i32)>>,
status: Cell<u32>, status: Cell<u32>,
// The attachment points for textures and renderbuffers on this // The attachment points for textures and renderbuffers on this
@ -115,6 +167,7 @@ pub(crate) struct WebGLFramebuffer {
// https://github.com/immersive-web/webxr/issues/856 // https://github.com/immersive-web/webxr/issues/856
#[cfg(feature = "webxr")] #[cfg(feature = "webxr")]
xr_session: MutNullableDom<XRSession>, xr_session: MutNullableDom<XRSession>,
droppable: DroppableWebGLFramebuffer,
} }
impl WebGLFramebuffer { impl WebGLFramebuffer {
@ -122,9 +175,7 @@ impl WebGLFramebuffer {
Self { Self {
webgl_object: WebGLObject::new_inherited(context), webgl_object: WebGLObject::new_inherited(context),
webgl_version: context.webgl_version(), webgl_version: context.webgl_version(),
id,
target: Cell::new(None), target: Cell::new(None),
is_deleted: Cell::new(false),
size: Cell::new(None), size: Cell::new(None),
status: Cell::new(constants::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT), status: Cell::new(constants::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT),
colors: vec![DomRefCell::new(None); context.limits().max_color_attachments as usize], colors: vec![DomRefCell::new(None); context.limits().max_color_attachments as usize],
@ -136,6 +187,7 @@ impl WebGLFramebuffer {
is_initialized: Cell::new(false), is_initialized: Cell::new(false),
#[cfg(feature = "webxr")] #[cfg(feature = "webxr")]
xr_session: Default::default(), xr_session: Default::default(),
droppable: DroppableWebGLFramebuffer::new(id, Cell::new(false), WeakRef::new(context)),
} }
} }
@ -181,7 +233,7 @@ impl WebGLFramebuffer {
impl WebGLFramebuffer { impl WebGLFramebuffer {
pub(crate) fn id(&self) -> WebGLFramebufferId { pub(crate) fn id(&self) -> WebGLFramebufferId {
self.id self.droppable.id()
} }
#[cfg(feature = "webxr")] #[cfg(feature = "webxr")]
@ -215,27 +267,19 @@ impl WebGLFramebuffer {
.context() .context()
.send_command(WebGLCommand::BindFramebuffer( .send_command(WebGLCommand::BindFramebuffer(
target, target,
WebGLFramebufferBindingRequest::Explicit(self.id), WebGLFramebufferBindingRequest::Explicit(self.id()),
)); ));
} }
pub(crate) fn delete(&self, operation_fallibility: Operation) { pub(crate) fn delete(&self, operation_fallibility: Operation) {
if !self.is_deleted.get() { self.droppable.delete(operation_fallibility);
self.is_deleted.set(true);
let context = self.upcast::<WebGLObject>().context();
let cmd = WebGLCommand::DeleteFramebuffer(self.id);
match operation_fallibility {
Operation::Fallible => context.send_command_ignored(cmd),
Operation::Infallible => context.send_command(cmd),
}
}
} }
pub(crate) fn is_deleted(&self) -> bool { pub(crate) fn is_deleted(&self) -> bool {
// TODO: if a framebuffer has an attachment which is invalid due to // TODO: if a framebuffer has an attachment which is invalid due to
// being outside a webxr rAF, should this make the framebuffer invalid? // being outside a webxr rAF, should this make the framebuffer invalid?
// https://github.com/immersive-web/layers/issues/196 // https://github.com/immersive-web/layers/issues/196
self.is_deleted.get() self.droppable.is_deleted()
} }
pub(crate) fn size(&self) -> Option<(i32, i32)> { pub(crate) fn size(&self) -> Option<(i32, i32)> {
@ -1030,12 +1074,6 @@ impl WebGLFramebuffer {
} }
} }
impl Drop for WebGLFramebuffer {
fn drop(&mut self) {
self.delete(Operation::Fallible);
}
}
static INTERESTING_ATTACHMENT_POINTS: &[u32] = &[ static INTERESTING_ATTACHMENT_POINTS: &[u32] = &[
constants::DEPTH_ATTACHMENT, constants::DEPTH_ATTACHMENT,
constants::STENCIL_ATTACHMENT, constants::STENCIL_ATTACHMENT,