script/dom/webgl/extensions/
wrapper.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use 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
17/// Trait used internally by WebGLExtensions to store and
18/// handle the different WebGL extensions in a common list.
19pub(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
38/// Typed WebGL Extension implementation.
39/// Exposes the exact `MutNullableDom<DOMObject>` type defined by the extension.
40impl<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}