1use 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
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 #[allow(clippy::unnecessary_to_owned)] 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 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}