webxr_api/
layer.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::fmt::Debug;
6use std::num::NonZeroU32;
7use std::sync::atomic::{AtomicUsize, Ordering};
8
9use euclid::{Rect, Size2D};
10
11use crate::{Error, Viewport, Viewports};
12
13#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
14#[cfg_attr(feature = "ipc", derive(Deserialize, Serialize))]
15pub struct ContextId(pub u64);
16
17#[cfg(feature = "ipc")]
18use serde::{Deserialize, Serialize};
19
20pub trait GLTypes {
21    type Device;
22    type Context;
23    type Bindings;
24}
25
26pub trait GLContexts<GL: GLTypes> {
27    fn device(&self, context_id: ContextId) -> Option<GL::Device>;
28    fn bindings(&mut self, context_id: ContextId) -> Option<&GL::Bindings>;
29    fn context(&mut self, context_id: ContextId) -> Option<&mut GL::Context>;
30}
31
32impl GLTypes for () {
33    type Bindings = ();
34    type Device = ();
35    type Context = ();
36}
37
38impl GLContexts<()> for () {
39    fn device(&self, _: ContextId) -> Option<()> {
40        Some(())
41    }
42
43    fn context(&mut self, _: ContextId) -> Option<&mut ()> {
44        Some(self)
45    }
46
47    fn bindings(&mut self, _: ContextId) -> Option<&()> {
48        Some(self)
49    }
50}
51
52pub trait LayerGrandManagerAPI<GL: GLTypes> {
53    fn create_layer_manager(&self, factory: LayerManagerFactory<GL>)
54    -> Result<LayerManager, Error>;
55
56    fn clone_layer_grand_manager(&self) -> LayerGrandManager<GL>;
57}
58
59pub struct LayerGrandManager<GL>(Box<dyn Send + LayerGrandManagerAPI<GL>>);
60
61impl<GL: GLTypes> Clone for LayerGrandManager<GL> {
62    fn clone(&self) -> Self {
63        self.0.clone_layer_grand_manager()
64    }
65}
66
67impl<GL> Debug for LayerGrandManager<GL> {
68    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
69        "LayerGrandManager(...)".fmt(fmt)
70    }
71}
72
73impl<GL: GLTypes> LayerGrandManager<GL> {
74    pub fn new<GM>(grand_manager: GM) -> LayerGrandManager<GL>
75    where
76        GM: 'static + Send + LayerGrandManagerAPI<GL>,
77    {
78        LayerGrandManager(Box::new(grand_manager))
79    }
80
81    pub fn create_layer_manager<F, M>(&self, factory: F) -> Result<LayerManager, Error>
82    where
83        F: 'static + Send + FnOnce(&mut dyn GLContexts<GL>) -> Result<M, Error>,
84        M: 'static + LayerManagerAPI<GL>,
85    {
86        self.0
87            .create_layer_manager(LayerManagerFactory::new(factory))
88    }
89}
90
91pub trait LayerManagerAPI<GL: GLTypes> {
92    fn create_layer(
93        &mut self,
94        contexts: &mut dyn GLContexts<GL>,
95        context_id: ContextId,
96        init: LayerInit,
97    ) -> Result<LayerId, Error>;
98
99    fn destroy_layer(
100        &mut self,
101        contexts: &mut dyn GLContexts<GL>,
102        context_id: ContextId,
103        layer_id: LayerId,
104    );
105
106    fn layers(&self) -> &[(ContextId, LayerId)];
107
108    fn begin_frame(
109        &mut self,
110        contexts: &mut dyn GLContexts<GL>,
111        layers: &[(ContextId, LayerId)],
112    ) -> Result<Vec<SubImages>, Error>;
113
114    fn end_frame(
115        &mut self,
116        contexts: &mut dyn GLContexts<GL>,
117        layers: &[(ContextId, LayerId)],
118    ) -> Result<(), Error>;
119}
120
121pub struct LayerManager(Box<dyn Send + LayerManagerAPI<()>>);
122
123impl Debug for LayerManager {
124    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
125        "LayerManager(...)".fmt(fmt)
126    }
127}
128
129impl LayerManager {
130    pub fn create_layer(
131        &mut self,
132        context_id: ContextId,
133        init: LayerInit,
134    ) -> Result<LayerId, Error> {
135        self.0.create_layer(&mut (), context_id, init)
136    }
137
138    pub fn destroy_layer(&mut self, context_id: ContextId, layer_id: LayerId) {
139        self.0.destroy_layer(&mut (), context_id, layer_id);
140    }
141
142    pub fn begin_frame(
143        &mut self,
144        layers: &[(ContextId, LayerId)],
145    ) -> Result<Vec<SubImages>, Error> {
146        self.0.begin_frame(&mut (), layers)
147    }
148
149    pub fn end_frame(&mut self, layers: &[(ContextId, LayerId)]) -> Result<(), Error> {
150        self.0.end_frame(&mut (), layers)
151    }
152}
153
154impl LayerManager {
155    pub fn new<M>(manager: M) -> LayerManager
156    where
157        M: 'static + Send + LayerManagerAPI<()>,
158    {
159        LayerManager(Box::new(manager))
160    }
161}
162
163impl Drop for LayerManager {
164    fn drop(&mut self) {
165        log::debug!("Dropping LayerManager");
166        let layers: Vec<_> = self.0.layers().to_vec();
167        for (context_id, layer_id) in layers.into_iter() {
168            self.destroy_layer(context_id, layer_id);
169        }
170    }
171}
172
173#[allow(clippy::type_complexity)]
174pub struct LayerManagerFactory<GL: GLTypes>(
175    Box<dyn Send + FnOnce(&mut dyn GLContexts<GL>) -> Result<Box<dyn LayerManagerAPI<GL>>, Error>>,
176);
177
178impl<GL: GLTypes> Debug for LayerManagerFactory<GL> {
179    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
180        "LayerManagerFactory(...)".fmt(fmt)
181    }
182}
183
184impl<GL: GLTypes> LayerManagerFactory<GL> {
185    pub fn new<F, M>(factory: F) -> LayerManagerFactory<GL>
186    where
187        F: 'static + Send + FnOnce(&mut dyn GLContexts<GL>) -> Result<M, Error>,
188        M: 'static + LayerManagerAPI<GL>,
189    {
190        LayerManagerFactory(Box::new(move |contexts| Ok(Box::new(factory(contexts)?))))
191    }
192
193    pub fn build(
194        self,
195        contexts: &mut dyn GLContexts<GL>,
196    ) -> Result<Box<dyn LayerManagerAPI<GL>>, Error> {
197        (self.0)(contexts)
198    }
199}
200
201#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
202#[cfg_attr(feature = "ipc", derive(Deserialize, Serialize))]
203pub struct LayerId(usize);
204
205static NEXT_LAYER_ID: AtomicUsize = AtomicUsize::new(0);
206
207impl Default for LayerId {
208    fn default() -> Self {
209        LayerId(NEXT_LAYER_ID.fetch_add(1, Ordering::SeqCst))
210    }
211}
212
213#[derive(Clone, Copy, Debug)]
214#[cfg_attr(feature = "ipc", derive(Deserialize, Serialize))]
215pub enum LayerInit {
216    /// <https://www.w3.org/TR/webxr/#dictdef-xrwebgllayerinit>
217    WebGLLayer {
218        antialias: bool,
219        depth: bool,
220        stencil: bool,
221        alpha: bool,
222        ignore_depth_values: bool,
223        framebuffer_scale_factor: f32,
224    },
225    /// <https://immersive-web.github.io/layers/#xrprojectionlayerinittype>
226    ProjectionLayer {
227        depth: bool,
228        stencil: bool,
229        alpha: bool,
230        scale_factor: f32,
231    },
232    // TODO: other layer types
233}
234
235impl LayerInit {
236    pub fn texture_size(&self, viewports: &Viewports) -> Size2D<i32, Viewport> {
237        match self {
238            LayerInit::WebGLLayer {
239                framebuffer_scale_factor: scale,
240                ..
241            } |
242            LayerInit::ProjectionLayer {
243                scale_factor: scale,
244                ..
245            } => {
246                let native_size = viewports
247                    .viewports
248                    .iter()
249                    .fold(Rect::zero(), |acc, view| acc.union(view))
250                    .size;
251                (native_size.to_f32() * *scale).to_i32()
252            },
253        }
254    }
255}
256
257/// <https://immersive-web.github.io/layers/#enumdef-xrlayerlayout>
258#[derive(Clone, Copy, Debug)]
259#[cfg_attr(feature = "ipc", derive(Deserialize, Serialize))]
260pub enum LayerLayout {
261    // TODO: Default
262    // Allocates one texture
263    Mono,
264    // Allocates one texture, which is split in half vertically, giving two subimages
265    StereoLeftRight,
266    // Allocates one texture, which is split in half horizonally, giving two subimages
267    StereoTopBottom,
268}
269
270#[derive(Clone, Debug)]
271#[cfg_attr(feature = "ipc", derive(Deserialize, Serialize))]
272pub struct SubImages {
273    pub layer_id: LayerId,
274    pub sub_image: Option<SubImage>,
275    pub view_sub_images: Vec<SubImage>,
276}
277
278/// <https://immersive-web.github.io/layers/#xrsubimagetype>
279#[derive(Clone, Debug)]
280#[cfg_attr(feature = "ipc", derive(Deserialize, Serialize))]
281pub struct SubImage {
282    pub color_texture: Option<NonZeroU32>,
283    pub depth_stencil_texture: Option<NonZeroU32>,
284    pub texture_array_index: Option<u32>,
285    pub viewport: Rect<i32, Viewport>,
286}