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