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