webgl/
webxr.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::num::NonZeroU32;
6use std::rc::Rc;
7
8use canvas_traits::webgl::{
9    GenericSender, WebGLMsg, WebXRCommand, WebXRLayerManagerId, webgl_channel,
10};
11use rustc_hash::FxHashMap;
12use surfman::{Context, Device};
13use webxr::SurfmanGL as WebXRSurfman;
14use webxr_api::{
15    ContextId as WebXRContextId, Error as WebXRError, GLContexts as WebXRContexts,
16    GLTypes as WebXRTypes, LayerGrandManager as WebXRLayerGrandManager,
17    LayerGrandManagerAPI as WebXRLayerGrandManagerAPI, LayerId as WebXRLayerId,
18    LayerInit as WebXRLayerInit, LayerManager as WebXRLayerManager,
19    LayerManagerAPI as WebXRLayerManagerAPI, LayerManagerFactory as WebXRLayerManagerFactory,
20    SubImages as WebXRSubImages,
21};
22
23use crate::webgl_thread::WebGLThread;
24
25/// Bridge between WebGL and WebXR
26pub(crate) struct WebXRBridge {
27    factory_receiver: crossbeam_channel::Receiver<WebXRLayerManagerFactory<WebXRSurfman>>,
28    managers: FxHashMap<WebXRLayerManagerId, Box<dyn WebXRLayerManagerAPI<WebXRSurfman>>>,
29    next_manager_id: NonZeroU32,
30}
31
32impl WebXRBridge {
33    pub(crate) fn new(init: WebXRBridgeInit) -> WebXRBridge {
34        let WebXRBridgeInit {
35            factory_receiver, ..
36        } = init;
37        let managers = FxHashMap::default();
38        let next_manager_id = NonZeroU32::MIN;
39        WebXRBridge {
40            factory_receiver,
41            managers,
42            next_manager_id,
43        }
44    }
45}
46
47impl WebXRBridge {
48    pub(crate) fn create_layer_manager(
49        &mut self,
50        contexts: &mut dyn WebXRContexts<WebXRSurfman>,
51    ) -> Result<WebXRLayerManagerId, WebXRError> {
52        let factory = self
53            .factory_receiver
54            .recv()
55            .map_err(|_| WebXRError::CommunicationError)?;
56        let manager = factory.build(contexts)?;
57        let manager_id = WebXRLayerManagerId::new(self.next_manager_id);
58        self.next_manager_id = self
59            .next_manager_id
60            .checked_add(1)
61            .expect("next_manager_id should not overflow");
62        self.managers.insert(manager_id, manager);
63        Ok(manager_id)
64    }
65
66    pub(crate) fn destroy_layer_manager(&mut self, manager_id: WebXRLayerManagerId) {
67        self.managers.remove(&manager_id);
68    }
69
70    pub(crate) fn create_layer(
71        &mut self,
72        manager_id: WebXRLayerManagerId,
73        contexts: &mut dyn WebXRContexts<WebXRSurfman>,
74        context_id: WebXRContextId,
75        layer_init: WebXRLayerInit,
76    ) -> Result<WebXRLayerId, WebXRError> {
77        let manager = self
78            .managers
79            .get_mut(&manager_id)
80            .ok_or(WebXRError::NoMatchingDevice)?;
81        manager.create_layer(contexts, context_id, layer_init)
82    }
83
84    pub(crate) fn destroy_layer(
85        &mut self,
86        manager_id: WebXRLayerManagerId,
87        contexts: &mut dyn WebXRContexts<WebXRSurfman>,
88        context_id: WebXRContextId,
89        layer_id: WebXRLayerId,
90    ) {
91        if let Some(manager) = self.managers.get_mut(&manager_id) {
92            manager.destroy_layer(contexts, context_id, layer_id);
93        }
94    }
95
96    pub(crate) fn destroy_all_layers(
97        &mut self,
98        contexts: &mut dyn WebXRContexts<WebXRSurfman>,
99        context_id: WebXRContextId,
100    ) {
101        for manager in self.managers.values_mut() {
102            for (other_id, layer_id) in manager.layers().to_vec() {
103                if other_id == context_id {
104                    manager.destroy_layer(contexts, context_id, layer_id);
105                }
106            }
107        }
108    }
109
110    pub(crate) fn begin_frame(
111        &mut self,
112        manager_id: WebXRLayerManagerId,
113        contexts: &mut dyn WebXRContexts<WebXRSurfman>,
114        layers: &[(WebXRContextId, WebXRLayerId)],
115    ) -> Result<Vec<WebXRSubImages>, WebXRError> {
116        let manager = self
117            .managers
118            .get_mut(&manager_id)
119            .ok_or(WebXRError::NoMatchingDevice)?;
120        manager.begin_frame(contexts, layers)
121    }
122
123    pub(crate) fn end_frame(
124        &mut self,
125        manager_id: WebXRLayerManagerId,
126        contexts: &mut dyn WebXRContexts<WebXRSurfman>,
127        layers: &[(WebXRContextId, WebXRLayerId)],
128    ) -> Result<(), WebXRError> {
129        let manager = self
130            .managers
131            .get_mut(&manager_id)
132            .ok_or(WebXRError::NoMatchingDevice)?;
133        manager.end_frame(contexts, layers)
134    }
135}
136
137pub(crate) struct WebXRBridgeInit {
138    sender: GenericSender<WebGLMsg>,
139    factory_receiver: crossbeam_channel::Receiver<WebXRLayerManagerFactory<WebXRSurfman>>,
140    factory_sender: crossbeam_channel::Sender<WebXRLayerManagerFactory<WebXRSurfman>>,
141}
142
143impl WebXRBridgeInit {
144    pub(crate) fn new(sender: GenericSender<WebGLMsg>) -> WebXRBridgeInit {
145        let (factory_sender, factory_receiver) = crossbeam_channel::unbounded();
146        WebXRBridgeInit {
147            sender,
148            factory_sender,
149            factory_receiver,
150        }
151    }
152
153    pub(crate) fn layer_grand_manager(&self) -> WebXRLayerGrandManager<WebXRSurfman> {
154        WebXRLayerGrandManager::new(WebXRBridgeGrandManager {
155            sender: self.sender.clone(),
156            factory_sender: self.factory_sender.clone(),
157        })
158    }
159}
160
161struct WebXRBridgeGrandManager {
162    sender: GenericSender<WebGLMsg>,
163    // WebXR layer manager factories use generic trait objects under the
164    // hood, which aren't deserializable (even using typetag)
165    // so we can't send them over the regular webgl channel.
166    // Fortunately, the webgl thread runs in the same process as
167    // the webxr threads, so we can use a crossbeam channel to send
168    // factories.
169    factory_sender: crossbeam_channel::Sender<WebXRLayerManagerFactory<WebXRSurfman>>,
170}
171
172impl WebXRLayerGrandManagerAPI<WebXRSurfman> for WebXRBridgeGrandManager {
173    fn create_layer_manager(
174        &self,
175        factory: WebXRLayerManagerFactory<WebXRSurfman>,
176    ) -> Result<WebXRLayerManager, WebXRError> {
177        let (sender, receiver) = webgl_channel().ok_or(WebXRError::CommunicationError)?;
178        let _ = self.factory_sender.send(factory);
179        let _ = self
180            .sender
181            .send(WebGLMsg::WebXRCommand(WebXRCommand::CreateLayerManager(
182                sender,
183            )));
184        let sender = self.sender.clone();
185        let manager_id = receiver
186            .recv()
187            .map_err(|_| WebXRError::CommunicationError)??;
188        let layers = Vec::new();
189        Ok(WebXRLayerManager::new(WebXRBridgeManager {
190            manager_id,
191            sender,
192            layers,
193        }))
194    }
195
196    fn clone_layer_grand_manager(&self) -> WebXRLayerGrandManager<WebXRSurfman> {
197        WebXRLayerGrandManager::new(WebXRBridgeGrandManager {
198            sender: self.sender.clone(),
199            factory_sender: self.factory_sender.clone(),
200        })
201    }
202}
203
204struct WebXRBridgeManager {
205    sender: GenericSender<WebGLMsg>,
206    manager_id: WebXRLayerManagerId,
207    layers: Vec<(WebXRContextId, WebXRLayerId)>,
208}
209
210impl<GL: WebXRTypes> WebXRLayerManagerAPI<GL> for WebXRBridgeManager {
211    fn create_layer(
212        &mut self,
213        _: &mut dyn WebXRContexts<GL>,
214        context_id: WebXRContextId,
215        init: WebXRLayerInit,
216    ) -> Result<WebXRLayerId, WebXRError> {
217        let (sender, receiver) = webgl_channel().ok_or(WebXRError::CommunicationError)?;
218        let _ = self
219            .sender
220            .send(WebGLMsg::WebXRCommand(WebXRCommand::CreateLayer(
221                self.manager_id,
222                context_id,
223                init,
224                sender,
225            )));
226        let layer_id = receiver
227            .recv()
228            .map_err(|_| WebXRError::CommunicationError)??;
229        self.layers.push((context_id, layer_id));
230        Ok(layer_id)
231    }
232
233    fn destroy_layer(
234        &mut self,
235        _: &mut dyn WebXRContexts<GL>,
236        context_id: WebXRContextId,
237        layer_id: WebXRLayerId,
238    ) {
239        self.layers.retain(|&ids| ids != (context_id, layer_id));
240        let _ = self
241            .sender
242            .send(WebGLMsg::WebXRCommand(WebXRCommand::DestroyLayer(
243                self.manager_id,
244                context_id,
245                layer_id,
246            )));
247    }
248
249    fn layers(&self) -> &[(WebXRContextId, WebXRLayerId)] {
250        &self.layers[..]
251    }
252
253    fn begin_frame(
254        &mut self,
255        _: &mut dyn WebXRContexts<GL>,
256        layers: &[(WebXRContextId, WebXRLayerId)],
257    ) -> Result<Vec<WebXRSubImages>, WebXRError> {
258        let (sender, receiver) = webgl_channel().ok_or(WebXRError::CommunicationError)?;
259        let _ = self
260            .sender
261            .send(WebGLMsg::WebXRCommand(WebXRCommand::BeginFrame(
262                self.manager_id,
263                layers.to_vec(),
264                sender,
265            )));
266        receiver
267            .recv()
268            .map_err(|_| WebXRError::CommunicationError)?
269    }
270
271    fn end_frame(
272        &mut self,
273        _: &mut dyn WebXRContexts<GL>,
274        layers: &[(WebXRContextId, WebXRLayerId)],
275    ) -> Result<(), WebXRError> {
276        let (sender, receiver) = webgl_channel().ok_or(WebXRError::CommunicationError)?;
277        let _ = self
278            .sender
279            .send(WebGLMsg::WebXRCommand(WebXRCommand::EndFrame(
280                self.manager_id,
281                layers.to_vec(),
282                sender,
283            )));
284        receiver
285            .recv()
286            .map_err(|_| WebXRError::CommunicationError)?
287    }
288}
289
290impl Drop for WebXRBridgeManager {
291    fn drop(&mut self) {
292        let _ = self
293            .sender
294            .send(WebGLMsg::WebXRCommand(WebXRCommand::DestroyLayerManager(
295                self.manager_id,
296            )));
297    }
298}
299
300impl WebXRContexts<WebXRSurfman> for WebGLThread {
301    fn device(&self, context_id: WebXRContextId) -> Option<Rc<Device>> {
302        self.maybe_device_for_context(context_id.into())
303    }
304
305    fn context(&mut self, context_id: WebXRContextId) -> Option<&mut Context> {
306        let data = self.make_current_if_needed_mut(context_id.into())?;
307        Some(&mut data.ctx)
308    }
309
310    fn bindings(&mut self, context_id: WebXRContextId) -> Option<&glow::Context> {
311        let data = self.make_current_if_needed(context_id.into())?;
312        Some(&data.gl)
313    }
314}