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 http://mozilla.org/MPL/2.0/. */
4 
5 use dom::bindings::reflector::DomObject;
6 use dom::bindings::root::{DomRoot, MutNullableDom};
7 use dom::bindings::trace::JSTraceable;
8 use dom::webglrenderingcontext::WebGLRenderingContext;
9 use js::jsapi::JSObject;
10 use malloc_size_of::MallocSizeOf;
11 use std::any::Any;
12 use std::ptr::NonNull;
13 use super::{WebGLExtension, WebGLExtensions, WebGLExtensionSpec};
14 
15 /// Trait used internally by WebGLExtensions to store and
16 /// handle the different WebGL extensions in a common list.
17 pub trait WebGLExtensionWrapper: JSTraceable + MallocSizeOf {
instance_or_init(&self, ctx: &WebGLRenderingContext, ext: &WebGLExtensions) -> NonNull<JSObject>18     fn instance_or_init(&self,
19                         ctx: &WebGLRenderingContext,
20                         ext: &WebGLExtensions)
21                         -> NonNull<JSObject>;
spec(&self) -> WebGLExtensionSpec22     fn spec(&self) -> WebGLExtensionSpec;
is_supported(&self, &WebGLExtensions) -> bool23     fn is_supported(&self, &WebGLExtensions) -> bool;
is_enabled(&self) -> bool24     fn is_enabled(&self) -> bool;
enable(&self, ext: &WebGLExtensions)25     fn enable(&self, ext: &WebGLExtensions);
name(&self) -> &'static str26     fn name(&self) -> &'static str;
as_any(&self) -> &Any27     fn as_any(&self) -> &Any;
28 }
29 
30 #[must_root]
31 #[derive(JSTraceable, MallocSizeOf)]
32 pub struct TypedWebGLExtensionWrapper<T: WebGLExtension> {
33     extension: MutNullableDom<T::Extension>
34 }
35 
36 /// Typed WebGL Extension implementation.
37 /// Exposes the exact MutNullableDom<DOMObject> type defined by the extension.
38 impl<T: WebGLExtension> TypedWebGLExtensionWrapper<T> {
new() -> TypedWebGLExtensionWrapper<T>39     pub fn new() -> TypedWebGLExtensionWrapper<T> {
40         TypedWebGLExtensionWrapper {
41             extension: MutNullableDom::new(None)
42         }
43     }
44 }
45 
46 impl<T> WebGLExtensionWrapper for TypedWebGLExtensionWrapper<T>
47                               where T: WebGLExtension + JSTraceable + MallocSizeOf + 'static {
48     #[allow(unsafe_code)]
instance_or_init(&self, ctx: &WebGLRenderingContext, ext: &WebGLExtensions) -> NonNull<JSObject>49     fn instance_or_init(&self,
50                         ctx: &WebGLRenderingContext,
51                         ext: &WebGLExtensions)
52                         -> NonNull<JSObject> {
53         let mut enabled = true;
54         let extension = self.extension.or_init(|| {
55             enabled = false;
56             T::new(ctx)
57         });
58         if !enabled {
59             self.enable(ext);
60         }
61         unsafe {
62             NonNull::new_unchecked(extension.reflector().get_jsobject().get())
63         }
64     }
65 
spec(&self) -> WebGLExtensionSpec66     fn spec(&self) -> WebGLExtensionSpec {
67          T::spec()
68     }
69 
is_supported(&self, ext: &WebGLExtensions) -> bool70     fn is_supported(&self, ext: &WebGLExtensions) -> bool {
71         self.is_enabled() || T::is_supported(ext)
72     }
73 
is_enabled(&self) -> bool74     fn is_enabled(&self) -> bool {
75         self.extension.get().is_some()
76     }
77 
enable(&self, ext: &WebGLExtensions)78     fn enable(&self, ext: &WebGLExtensions) {
79         T::enable(ext);
80     }
81 
name(&self) -> &'static str82     fn name(&self) -> &'static str {
83         T::name()
84     }
85 
as_any<'a>(&'a self) -> &'a Any86     fn as_any<'a>(&'a self) -> &'a Any {
87         self
88     }
89 }
90 
91 impl<T> TypedWebGLExtensionWrapper<T>
92     where T: WebGLExtension + JSTraceable + MallocSizeOf + 'static
93 {
dom_object(&self) -> Option<DomRoot<T::Extension>>94     pub fn dom_object(&self) -> Option<DomRoot<T::Extension>> {
95         self.extension.get()
96     }
97 }
98