1use 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
25pub(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 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}