Skip to main content

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 js::context::JSContext;
6use js::rust::MutableHandleObject;
7use malloc_size_of::MallocSizeOf;
8use script_bindings::reflector::DomObject;
9
10use super::{WebGLExtension, WebGLExtensionSpec, WebGLExtensions};
11use crate::dom::bindings::root::MutNullableDom;
12use crate::dom::bindings::trace::JSTraceable;
13use crate::dom::webgl::webglrenderingcontext::WebGLRenderingContext;
14
15/// Trait used internally by WebGLExtensions to store and
16/// handle the different WebGL extensions in a common list.
17pub(crate) trait WebGLExtensionWrapper: JSTraceable + MallocSizeOf {
18    fn instance_or_init(
19        &self,
20        cx: &mut JSContext,
21        ctx: &WebGLRenderingContext,
22        ext: &WebGLExtensions,
23        rval: MutableHandleObject,
24    );
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    fn instance_or_init(
53        &self,
54        cx: &mut JSContext,
55        ctx: &WebGLRenderingContext,
56        ext: &WebGLExtensions,
57        mut rval: MutableHandleObject,
58    ) {
59        let mut enabled = true;
60        let extension = self.extension.or_init(|| {
61            enabled = false;
62            T::new(cx, ctx)
63        });
64        if !enabled {
65            self.enable(ext);
66        }
67        rval.set(extension.reflector().get_jsobject().get());
68    }
69
70    fn spec(&self) -> WebGLExtensionSpec {
71        T::spec()
72    }
73
74    fn is_supported(&self, ext: &WebGLExtensions) -> bool {
75        self.is_enabled() || T::is_supported(ext)
76    }
77
78    fn is_enabled(&self) -> bool {
79        self.extension.get().is_some()
80    }
81
82    fn enable(&self, ext: &WebGLExtensions) {
83        T::enable(ext);
84    }
85
86    fn name(&self) -> &'static str {
87        T::name()
88    }
89}