Skip to main content

script/dom/webxr/
xrrenderstate.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::cell::Cell;
6
7use dom_struct::dom_struct;
8use js::rust::MutableHandleValue;
9use script_bindings::cell::DomRefCell;
10use script_bindings::reflector::{Reflector, reflect_dom_object};
11use webxr_api::SubImages;
12
13use crate::dom::bindings::codegen::Bindings::XRRenderStateBinding::XRRenderStateMethods;
14use crate::dom::bindings::num::Finite;
15use crate::dom::bindings::reflector::DomGlobal;
16use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
17use crate::dom::bindings::utils::to_frozen_array;
18use crate::dom::window::Window;
19use crate::dom::xrlayer::XRLayer;
20use crate::dom::xrwebgllayer::XRWebGLLayer;
21use crate::script_runtime::{CanGc, JSContext};
22
23#[dom_struct]
24pub(crate) struct XRRenderState {
25    reflector_: Reflector,
26    depth_near: Cell<f64>,
27    depth_far: Cell<f64>,
28    inline_vertical_fov: Cell<Option<f64>>,
29    base_layer: MutNullableDom<XRWebGLLayer>,
30    layers: DomRefCell<Vec<Dom<XRLayer>>>,
31}
32
33impl XRRenderState {
34    pub(crate) fn new_inherited(
35        depth_near: f64,
36        depth_far: f64,
37        inline_vertical_fov: Option<f64>,
38        layer: Option<&XRWebGLLayer>,
39        layers: Vec<&XRLayer>,
40    ) -> XRRenderState {
41        debug_assert!(layer.is_none() || layers.is_empty());
42        XRRenderState {
43            reflector_: Reflector::new(),
44            depth_near: Cell::new(depth_near),
45            depth_far: Cell::new(depth_far),
46            inline_vertical_fov: Cell::new(inline_vertical_fov),
47            base_layer: MutNullableDom::new(layer),
48            layers: DomRefCell::new(layers.into_iter().map(Dom::from_ref).collect()),
49        }
50    }
51
52    pub(crate) fn new(
53        window: &Window,
54        depth_near: f64,
55        depth_far: f64,
56        inline_vertical_fov: Option<f64>,
57        layer: Option<&XRWebGLLayer>,
58        layers: Vec<&XRLayer>,
59        can_gc: CanGc,
60    ) -> DomRoot<XRRenderState> {
61        reflect_dom_object(
62            Box::new(XRRenderState::new_inherited(
63                depth_near,
64                depth_far,
65                inline_vertical_fov,
66                layer,
67                layers,
68            )),
69            window,
70            can_gc,
71        )
72    }
73
74    pub(crate) fn clone_object(&self) -> DomRoot<Self> {
75        XRRenderState::new(
76            self.global().as_window(),
77            self.depth_near.get(),
78            self.depth_far.get(),
79            self.inline_vertical_fov.get(),
80            self.base_layer.get().as_deref(),
81            self.layers.borrow().iter().map(|x| &**x).collect(),
82            CanGc::deprecated_note(),
83        )
84    }
85
86    pub(crate) fn set_depth_near(&self, depth: f64) {
87        self.depth_near.set(depth)
88    }
89    pub(crate) fn set_depth_far(&self, depth: f64) {
90        self.depth_far.set(depth)
91    }
92    pub(crate) fn set_inline_vertical_fov(&self, fov: f64) {
93        debug_assert!(self.inline_vertical_fov.get().is_some());
94        self.inline_vertical_fov.set(Some(fov))
95    }
96    pub(crate) fn set_base_layer(&self, layer: Option<&XRWebGLLayer>) {
97        self.base_layer.set(layer)
98    }
99    pub(crate) fn set_layers(&self, layers: Vec<&XRLayer>) {
100        *self.layers.borrow_mut() = layers.into_iter().map(Dom::from_ref).collect();
101    }
102    pub(crate) fn with_layers<F, R>(&self, f: F) -> R
103    where
104        F: FnOnce(&[Dom<XRLayer>]) -> R,
105    {
106        let layers = self.layers.borrow();
107        f(&layers)
108    }
109    pub(crate) fn has_sub_images(&self, sub_images: &[SubImages]) -> bool {
110        if let Some(base_layer) = self.base_layer.get() {
111            match sub_images.len() {
112                // For inline sessions, there may be a base layer, but it won't have a framebuffer
113                0 => base_layer.layer_id().is_none(),
114                // For immersive sessions, the base layer will have a framebuffer,
115                // so we make sure the layer id's match up
116                1 => base_layer.layer_id() == Some(sub_images[0].layer_id),
117                _ => false,
118            }
119        } else {
120            // The layers API is only for immersive sessions
121            let layers = self.layers.borrow();
122            sub_images.len() == layers.len() &&
123                sub_images
124                    .iter()
125                    .zip(layers.iter())
126                    .all(|(sub_image, layer)| Some(sub_image.layer_id) == layer.layer_id())
127        }
128    }
129}
130
131impl XRRenderStateMethods<crate::DomTypeHolder> for XRRenderState {
132    /// <https://immersive-web.github.io/webxr/#dom-xrrenderstate-depthnear>
133    fn DepthNear(&self) -> Finite<f64> {
134        Finite::wrap(self.depth_near.get())
135    }
136
137    /// <https://immersive-web.github.io/webxr/#dom-xrrenderstate-depthfar>
138    fn DepthFar(&self) -> Finite<f64> {
139        Finite::wrap(self.depth_far.get())
140    }
141
142    /// <https://immersive-web.github.io/webxr/#dom-xrrenderstate-inlineverticalfieldofview>
143    fn GetInlineVerticalFieldOfView(&self) -> Option<Finite<f64>> {
144        self.inline_vertical_fov.get().map(Finite::wrap)
145    }
146
147    /// <https://immersive-web.github.io/webxr/#dom-xrrenderstate-baselayer>
148    fn GetBaseLayer(&self) -> Option<DomRoot<XRWebGLLayer>> {
149        self.base_layer.get()
150    }
151
152    /// <https://immersive-web.github.io/layers/#dom-xrrenderstate-layers>
153    fn Layers(&self, cx: JSContext, can_gc: CanGc, retval: MutableHandleValue) {
154        // TODO: cache this array?
155        let layers = self.layers.borrow();
156        let layers: Vec<&XRLayer> = layers.iter().map(|x| &**x).collect();
157        to_frozen_array(&layers[..], cx, retval, can_gc)
158    }
159}