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    WebGLMsg, WebGLSender, 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            #[allow(clippy::unnecessary_to_owned)] // Needs mutable borrow later in destroy
103            for (other_id, layer_id) in manager.layers().to_vec() {
104                if other_id == context_id {
105                    manager.destroy_layer(contexts, context_id, layer_id);
106                }
107            }
108        }
109    }
110
111    pub(crate) fn begin_frame(
112        &mut self,
113        manager_id: WebXRLayerManagerId,
114        contexts: &mut dyn WebXRContexts<WebXRSurfman>,
115        layers: &[(WebXRContextId, WebXRLayerId)],
116    ) -> Result<Vec<WebXRSubImages>, WebXRError> {
117        let manager = self
118            .managers
119            .get_mut(&manager_id)
120            .ok_or(WebXRError::NoMatchingDevice)?;
121        manager.begin_frame(contexts, layers)
122    }
123
124    pub(crate) fn end_frame(
125        &mut self,
126        manager_id: WebXRLayerManagerId,
127        contexts: &mut dyn WebXRContexts<WebXRSurfman>,
128        layers: &[(WebXRContextId, WebXRLayerId)],
129    ) -> Result<(), WebXRError> {
130        let manager = self
131            .managers
132            .get_mut(&manager_id)
133            .ok_or(WebXRError::NoMatchingDevice)?;
134        manager.end_frame(contexts, layers)
135    }
136}
137
138pub(crate) struct WebXRBridgeInit {
139    sender: WebGLSender<WebGLMsg>,
140    factory_receiver: crossbeam_channel::Receiver<WebXRLayerManagerFactory<WebXRSurfman>>,
141    factory_sender: crossbeam_channel::Sender<WebXRLayerManagerFactory<WebXRSurfman>>,
142}
143
144impl WebXRBridgeInit {
145    pub(crate) fn new(sender: WebGLSender<WebGLMsg>) -> WebXRBridgeInit {
146        let (factory_sender, factory_receiver) = crossbeam_channel::unbounded();
147        WebXRBridgeInit {
148            sender,
149            factory_sender,
150            factory_receiver,
151        }
152    }
153
154    pub(crate) fn layer_grand_manager(&self) -> WebXRLayerGrandManager<WebXRSurfman> {
155        WebXRLayerGrandManager::new(WebXRBridgeGrandManager {
156            sender: self.sender.clone(),
157            factory_sender: self.factory_sender.clone(),
158        })
159    }
160}
161
162struct WebXRBridgeGrandManager {
163    sender: WebGLSender<WebGLMsg>,
164    // WebXR layer manager factories use generic trait objects under the
165    // hood, which aren't deserializable (even using typetag)
166    // so we can't send them over the regular webgl channel.
167    // Fortunately, the webgl thread runs in the same process as
168    // the webxr threads, so we can use a crossbeam channel to send
169    // factories.
170    factory_sender: crossbeam_channel::Sender<WebXRLayerManagerFactory<WebXRSurfman>>,
171}
172
173impl WebXRLayerGrandManagerAPI<WebXRSurfman> for WebXRBridgeGrandManager {
174    fn create_layer_manager(
175        &self,
176        factory: WebXRLayerManagerFactory<WebXRSurfman>,
177    ) -> Result<WebXRLayerManager, WebXRError> {
178        let (sender, receiver) = webgl_channel().ok_or(WebXRError::CommunicationError)?;
179        let _ = self.factory_sender.send(factory);
180        let _ = self
181            .sender
182            .send(WebGLMsg::WebXRCommand(WebXRCommand::CreateLayerManager(
183                sender,
184            )));
185        let sender = self.sender.clone();
186        let manager_id = receiver
187            .recv()
188            .map_err(|_| WebXRError::CommunicationError)??;
189        let layers = Vec::new();
190        Ok(WebXRLayerManager::new(WebXRBridgeManager {
191            manager_id,
192            sender,
193            layers,
194        }))
195    }
196
197    fn clone_layer_grand_manager(&self) -> WebXRLayerGrandManager<WebXRSurfman> {
198        WebXRLayerGrandManager::new(WebXRBridgeGrandManager {
199            sender: self.sender.clone(),
200            factory_sender: self.factory_sender.clone(),
201        })
202    }
203}
204
205struct WebXRBridgeManager {
206    sender: WebGLSender<WebGLMsg>,
207    manager_id: WebXRLayerManagerId,
208    layers: Vec<(WebXRContextId, WebXRLayerId)>,
209}
210
211impl<GL: WebXRTypes> WebXRLayerManagerAPI<GL> for WebXRBridgeManager {
212    fn create_layer(
213        &mut self,
214        _: &mut dyn WebXRContexts<GL>,
215        context_id: WebXRContextId,
216        init: WebXRLayerInit,
217    ) -> Result<WebXRLayerId, WebXRError> {
218        let (sender, receiver) = webgl_channel().ok_or(WebXRError::CommunicationError)?;
219        let _ = self
220            .sender
221            .send(WebGLMsg::WebXRCommand(WebXRCommand::CreateLayer(
222                self.manager_id,
223                context_id,
224                init,
225                sender,
226            )));
227        let layer_id = receiver
228            .recv()
229            .map_err(|_| WebXRError::CommunicationError)??;
230        self.layers.push((context_id, layer_id));
231        Ok(layer_id)
232    }
233
234    fn destroy_layer(
235        &mut self,
236        _: &mut dyn WebXRContexts<GL>,
237        context_id: WebXRContextId,
238        layer_id: WebXRLayerId,
239    ) {
240        self.layers.retain(|&ids| ids != (context_id, layer_id));
241        let _ = self
242            .sender
243            .send(WebGLMsg::WebXRCommand(WebXRCommand::DestroyLayer(
244                self.manager_id,
245                context_id,
246                layer_id,
247            )));
248    }
249
250    fn layers(&self) -> &[(WebXRContextId, WebXRLayerId)] {
251        &self.layers[..]
252    }
253
254    fn begin_frame(
255        &mut self,
256        _: &mut dyn WebXRContexts<GL>,
257        layers: &[(WebXRContextId, WebXRLayerId)],
258    ) -> Result<Vec<WebXRSubImages>, WebXRError> {
259        let (sender, receiver) = webgl_channel().ok_or(WebXRError::CommunicationError)?;
260        let _ = self
261            .sender
262            .send(WebGLMsg::WebXRCommand(WebXRCommand::BeginFrame(
263                self.manager_id,
264                layers.to_vec(),
265                sender,
266            )));
267        receiver
268            .recv()
269            .map_err(|_| WebXRError::CommunicationError)?
270    }
271
272    fn end_frame(
273        &mut self,
274        _: &mut dyn WebXRContexts<GL>,
275        layers: &[(WebXRContextId, WebXRLayerId)],
276    ) -> Result<(), WebXRError> {
277        let (sender, receiver) = webgl_channel().ok_or(WebXRError::CommunicationError)?;
278        let _ = self
279            .sender
280            .send(WebGLMsg::WebXRCommand(WebXRCommand::EndFrame(
281                self.manager_id,
282                layers.to_vec(),
283                sender,
284            )));
285        receiver
286            .recv()
287            .map_err(|_| WebXRError::CommunicationError)?
288    }
289}
290
291impl Drop for WebXRBridgeManager {
292    fn drop(&mut self) {
293        let _ = self
294            .sender
295            .send(WebGLMsg::WebXRCommand(WebXRCommand::DestroyLayerManager(
296                self.manager_id,
297            )));
298    }
299}
300
301impl WebXRContexts<WebXRSurfman> for WebGLThread {
302    fn device(&self, context_id: WebXRContextId) -> Option<Rc<Device>> {
303        self.maybe_device_for_context(context_id.into())
304    }
305
306    fn context(&mut self, context_id: WebXRContextId) -> Option<&mut Context> {
307        let data = self.make_current_if_needed_mut(context_id.into())?;
308        Some(&mut data.ctx)
309    }
310
311    fn bindings(&mut self, context_id: WebXRContextId) -> Option<&glow::Context> {
312        let data = self.make_current_if_needed(context_id.into())?;
313        Some(&data.gl)
314    }
315}