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