diff options
Diffstat (limited to 'components/script/dom/webxr/xrrenderstate.rs')
-rw-r--r-- | components/script/dom/webxr/xrrenderstate.rs | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/components/script/dom/webxr/xrrenderstate.rs b/components/script/dom/webxr/xrrenderstate.rs new file mode 100644 index 00000000000..cf6976404d6 --- /dev/null +++ b/components/script/dom/webxr/xrrenderstate.rs @@ -0,0 +1,155 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use std::cell::Cell; + +use dom_struct::dom_struct; +use js::rust::MutableHandleValue; +use webxr_api::SubImages; + +use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::XRRenderStateBinding::XRRenderStateMethods; +use crate::dom::bindings::num::Finite; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; +use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; +use crate::dom::bindings::utils::to_frozen_array; +use crate::dom::globalscope::GlobalScope; +use crate::dom::xrlayer::XRLayer; +use crate::dom::xrwebgllayer::XRWebGLLayer; +use crate::script_runtime::JSContext; + +#[dom_struct] +pub struct XRRenderState { + reflector_: Reflector, + depth_near: Cell<f64>, + depth_far: Cell<f64>, + inline_vertical_fov: Cell<Option<f64>>, + base_layer: MutNullableDom<XRWebGLLayer>, + layers: DomRefCell<Vec<Dom<XRLayer>>>, +} + +impl XRRenderState { + pub fn new_inherited( + depth_near: f64, + depth_far: f64, + inline_vertical_fov: Option<f64>, + layer: Option<&XRWebGLLayer>, + layers: Vec<&XRLayer>, + ) -> XRRenderState { + debug_assert!(layer.is_none() || layers.is_empty()); + XRRenderState { + reflector_: Reflector::new(), + depth_near: Cell::new(depth_near), + depth_far: Cell::new(depth_far), + inline_vertical_fov: Cell::new(inline_vertical_fov), + base_layer: MutNullableDom::new(layer), + layers: DomRefCell::new(layers.into_iter().map(Dom::from_ref).collect()), + } + } + + pub fn new( + global: &GlobalScope, + depth_near: f64, + depth_far: f64, + inline_vertical_fov: Option<f64>, + layer: Option<&XRWebGLLayer>, + layers: Vec<&XRLayer>, + ) -> DomRoot<XRRenderState> { + reflect_dom_object( + Box::new(XRRenderState::new_inherited( + depth_near, + depth_far, + inline_vertical_fov, + layer, + layers, + )), + global, + ) + } + + pub fn clone_object(&self) -> DomRoot<Self> { + XRRenderState::new( + &self.global(), + self.depth_near.get(), + self.depth_far.get(), + self.inline_vertical_fov.get(), + self.base_layer.get().as_deref(), + self.layers.borrow().iter().map(|x| &**x).collect(), + ) + } + + pub fn set_depth_near(&self, depth: f64) { + self.depth_near.set(depth) + } + pub fn set_depth_far(&self, depth: f64) { + self.depth_far.set(depth) + } + pub fn set_inline_vertical_fov(&self, fov: f64) { + debug_assert!(self.inline_vertical_fov.get().is_some()); + self.inline_vertical_fov.set(Some(fov)) + } + pub fn set_base_layer(&self, layer: Option<&XRWebGLLayer>) { + self.base_layer.set(layer) + } + pub fn set_layers(&self, layers: Vec<&XRLayer>) { + *self.layers.borrow_mut() = layers.into_iter().map(Dom::from_ref).collect(); + } + pub fn with_layers<F, R>(&self, f: F) -> R + where + F: FnOnce(&[Dom<XRLayer>]) -> R, + { + let layers = self.layers.borrow(); + f(&layers) + } + pub fn has_sub_images(&self, sub_images: &[SubImages]) -> bool { + if let Some(base_layer) = self.base_layer.get() { + match sub_images.len() { + // For inline sessions, there may be a base layer, but it won't have a framebuffer + 0 => base_layer.layer_id().is_none(), + // For immersive sessions, the base layer will have a framebuffer, + // so we make sure the layer id's match up + 1 => base_layer.layer_id() == Some(sub_images[0].layer_id), + _ => false, + } + } else { + // The layers API is only for immersive sessions + let layers = self.layers.borrow(); + sub_images.len() == layers.len() && + sub_images + .iter() + .zip(layers.iter()) + .all(|(sub_image, layer)| Some(sub_image.layer_id) == layer.layer_id()) + } + } +} + +impl XRRenderStateMethods<crate::DomTypeHolder> for XRRenderState { + /// <https://immersive-web.github.io/webxr/#dom-xrrenderstate-depthnear> + fn DepthNear(&self) -> Finite<f64> { + Finite::wrap(self.depth_near.get()) + } + + /// <https://immersive-web.github.io/webxr/#dom-xrrenderstate-depthfar> + fn DepthFar(&self) -> Finite<f64> { + Finite::wrap(self.depth_far.get()) + } + + /// <https://immersive-web.github.io/webxr/#dom-xrrenderstate-inlineverticalfieldofview> + fn GetInlineVerticalFieldOfView(&self) -> Option<Finite<f64>> { + self.inline_vertical_fov.get().map(Finite::wrap) + } + + /// <https://immersive-web.github.io/webxr/#dom-xrrenderstate-baselayer> + fn GetBaseLayer(&self) -> Option<DomRoot<XRWebGLLayer>> { + self.base_layer.get() + } + + /// <https://immersive-web.github.io/layers/#dom-xrrenderstate-layers> + fn Layers(&self, cx: JSContext, retval: MutableHandleValue) { + // TODO: cache this array? + let layers = self.layers.borrow(); + let layers: Vec<&XRLayer> = layers.iter().map(|x| &**x).collect(); + to_frozen_array(&layers[..], cx, retval) + } +} |