1use 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
24pub(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)] 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 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}