script/dom/webgl/extensions/
wrapper.rs1use std::ptr::NonNull;
6
7use js::context::JSContext;
8use js::jsapi::JSObject;
9use malloc_size_of::MallocSizeOf;
10use script_bindings::reflector::DomObject;
11
12use super::{WebGLExtension, WebGLExtensionSpec, WebGLExtensions};
13use crate::dom::bindings::root::MutNullableDom;
14use crate::dom::bindings::trace::JSTraceable;
15use crate::dom::webgl::webglrenderingcontext::WebGLRenderingContext;
16
17pub(crate) trait WebGLExtensionWrapper: JSTraceable + MallocSizeOf {
20 fn instance_or_init(
21 &self,
22 cx: &mut JSContext,
23 ctx: &WebGLRenderingContext,
24 ext: &WebGLExtensions,
25 ) -> NonNull<JSObject>;
26 fn spec(&self) -> WebGLExtensionSpec;
27 fn is_supported(&self, _: &WebGLExtensions) -> bool;
28 fn is_enabled(&self) -> bool;
29 fn enable(&self, ext: &WebGLExtensions);
30 fn name(&self) -> &'static str;
31}
32
33#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
34#[derive(JSTraceable, MallocSizeOf)]
35pub(crate) struct TypedWebGLExtensionWrapper<T: WebGLExtension> {
36 extension: MutNullableDom<T::Extension>,
37}
38
39impl<T: WebGLExtension> TypedWebGLExtensionWrapper<T> {
42 pub(crate) fn new() -> TypedWebGLExtensionWrapper<T> {
43 TypedWebGLExtensionWrapper {
44 extension: MutNullableDom::new(None),
45 }
46 }
47}
48
49impl<T> WebGLExtensionWrapper for TypedWebGLExtensionWrapper<T>
50where
51 T: WebGLExtension + JSTraceable + MallocSizeOf + 'static,
52{
53 #[expect(unsafe_code)]
54 fn instance_or_init(
55 &self,
56 cx: &mut JSContext,
57 ctx: &WebGLRenderingContext,
58 ext: &WebGLExtensions,
59 ) -> NonNull<JSObject> {
60 let mut enabled = true;
61 let extension = self.extension.or_init(|| {
62 enabled = false;
63 T::new(cx, ctx)
64 });
65 if !enabled {
66 self.enable(ext);
67 }
68 unsafe { NonNull::new_unchecked(extension.reflector().get_jsobject().get()) }
69 }
70
71 fn spec(&self) -> WebGLExtensionSpec {
72 T::spec()
73 }
74
75 fn is_supported(&self, ext: &WebGLExtensions) -> bool {
76 self.is_enabled() || T::is_supported(ext)
77 }
78
79 fn is_enabled(&self) -> bool {
80 self.extension.get().is_some()
81 }
82
83 fn enable(&self, ext: &WebGLExtensions) {
84 T::enable(ext);
85 }
86
87 fn name(&self) -> &'static str {
88 T::name()
89 }
90}