webgl/webgl_mode/
inprocess.rs1use std::rc::Rc;
6use std::sync::{Arc, Mutex};
7
8use canvas_traits::webgl::{GlType, WebGLContextId, WebGLMsg, WebGLThreads, webgl_channel};
9use compositing_traits::rendering_context::RenderingContext;
10use compositing_traits::{
11 CrossProcessCompositorApi, ExternalImageSource, WebRenderExternalImageApi,
12 WebRenderExternalImageRegistry,
13};
14use euclid::default::Size2D;
15use log::debug;
16use rustc_hash::FxHashMap;
17use surfman::chains::{SwapChainAPI, SwapChains, SwapChainsAPI};
18use surfman::{Device, SurfaceTexture};
19#[cfg(feature = "webxr")]
20use webxr::SurfmanGL as WebXRSurfman;
21#[cfg(feature = "webxr")]
22use webxr_api::LayerGrandManager as WebXRLayerGrandManager;
23
24use crate::webgl_thread::{WebGLThread, WebGLThreadInit};
25
26pub struct WebGLComm {
27 pub webgl_threads: WebGLThreads,
28 pub image_handler: Box<dyn WebRenderExternalImageApi>,
29 #[cfg(feature = "webxr")]
30 pub webxr_layer_grand_manager: WebXRLayerGrandManager<WebXRSurfman>,
31}
32
33impl WebGLComm {
34 pub fn new(
36 rendering_context: Rc<dyn RenderingContext>,
37 compositor_api: CrossProcessCompositorApi,
38 external_images: Arc<Mutex<WebRenderExternalImageRegistry>>,
39 api_type: GlType,
40 ) -> WebGLComm {
41 debug!("WebGLThreads::new()");
42 let (sender, receiver) = webgl_channel::<WebGLMsg>().unwrap();
43 let webrender_swap_chains = SwapChains::new();
44 #[cfg(feature = "webxr")]
45 let webxr_init = crate::webxr::WebXRBridgeInit::new(sender.clone());
46 #[cfg(feature = "webxr")]
47 let webxr_layer_grand_manager = webxr_init.layer_grand_manager();
48 let connection = rendering_context
49 .connection()
50 .expect("Failed to get connection");
51 let adapter = connection
52 .create_adapter()
53 .expect("Failed to create adapter");
54
55 let init = WebGLThreadInit {
57 compositor_api,
58 external_images,
59 sender: sender.clone(),
60 receiver,
61 webrender_swap_chains: webrender_swap_chains.clone(),
62 connection,
63 adapter,
64 api_type,
65 #[cfg(feature = "webxr")]
66 webxr_init,
67 };
68
69 let external = WebGLExternalImages::new(rendering_context, webrender_swap_chains);
70
71 WebGLThread::run_on_own_thread(init);
72
73 WebGLComm {
74 webgl_threads: WebGLThreads(sender),
75 image_handler: Box::new(external),
76 #[cfg(feature = "webxr")]
77 webxr_layer_grand_manager,
78 }
79 }
80}
81
82struct WebGLExternalImages {
84 rendering_context: Rc<dyn RenderingContext>,
85 swap_chains: SwapChains<WebGLContextId, Device>,
86 locked_front_buffers: FxHashMap<WebGLContextId, SurfaceTexture>,
87}
88
89impl WebGLExternalImages {
90 fn new(
91 rendering_context: Rc<dyn RenderingContext>,
92 swap_chains: SwapChains<WebGLContextId, Device>,
93 ) -> Self {
94 Self {
95 rendering_context,
96 swap_chains,
97 locked_front_buffers: FxHashMap::default(),
98 }
99 }
100
101 fn lock_swap_chain(&mut self, id: WebGLContextId) -> Option<(u32, Size2D<i32>)> {
102 debug!("... locking chain {:?}", id);
103 let front_buffer = self.swap_chains.get(id)?.take_surface()?;
104
105 if let Some((surface_texture, gl_texture, size)) =
106 self.rendering_context.create_texture(front_buffer)
107 {
108 self.locked_front_buffers.insert(id, surface_texture);
109
110 Some((gl_texture, size))
111 } else {
112 None
113 }
114 }
115
116 fn unlock_swap_chain(&mut self, id: WebGLContextId) -> Option<()> {
117 debug!("... unlocked chain {:?}", id);
118 let locked_front_buffer = self.locked_front_buffers.remove(&id)?;
119 if let Some(locked_front_buffer) =
120 self.rendering_context.destroy_texture(locked_front_buffer)
121 {
122 self.swap_chains
123 .get(id)?
124 .recycle_surface(locked_front_buffer);
125 Some(())
126 } else {
127 None
128 }
129 }
130}
131
132impl WebRenderExternalImageApi for WebGLExternalImages {
133 fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, Size2D<i32>) {
134 let id = WebGLContextId(id);
135 let (texture_id, size) = self.lock_swap_chain(id).unwrap_or_default();
136 (ExternalImageSource::NativeTexture(texture_id), size)
137 }
138
139 fn unlock(&mut self, id: u64) {
140 let id = WebGLContextId(id);
141 self.unlock_swap_chain(id);
142 }
143}