compositing/
webrender_external_images.rs1use std::rc::Rc;
6
7use canvas_traits::webgl::{WebGLContextId, WebGLThreads};
8use compositing_traits::rendering_context::RenderingContext;
9use compositing_traits::{ExternalImageSource, WebRenderExternalImageApi};
10use euclid::default::Size2D;
11use log::debug;
12use rustc_hash::FxHashMap;
13use surfman::chains::{SwapChainAPI, SwapChains, SwapChainsAPI};
14use surfman::{Device, SurfaceTexture};
15use webgl::webgl_thread::WebGLContextBusyMap;
16
17pub struct WebGLExternalImages {
19 webgl_threads: WebGLThreads,
20 rendering_context: Rc<dyn RenderingContext>,
21 swap_chains: SwapChains<WebGLContextId, Device>,
22 busy_webgl_context_map: WebGLContextBusyMap,
23 locked_front_buffers: FxHashMap<WebGLContextId, SurfaceTexture>,
24}
25
26impl WebGLExternalImages {
27 pub fn new(
28 webgl_threads: WebGLThreads,
29 rendering_context: Rc<dyn RenderingContext>,
30 swap_chains: SwapChains<WebGLContextId, Device>,
31 busy_webgl_context_map: WebGLContextBusyMap,
32 ) -> Self {
33 Self {
34 webgl_threads,
35 rendering_context,
36 swap_chains,
37 busy_webgl_context_map,
38 locked_front_buffers: FxHashMap::default(),
39 }
40 }
41
42 fn lock_swap_chain(&mut self, id: WebGLContextId) -> Option<(u32, Size2D<i32>)> {
43 debug!("... locking chain {:?}", id);
44
45 {
46 let mut busy_webgl_context_map = self.busy_webgl_context_map.write();
47 *busy_webgl_context_map.entry(id).or_default() += 1;
48 }
49
50 let front_buffer = self.swap_chains.get(id)?.take_surface()?;
51 let (surface_texture, gl_texture, size) =
52 self.rendering_context.create_texture(front_buffer)?;
53 self.locked_front_buffers.insert(id, surface_texture);
54
55 Some((gl_texture, size))
56 }
57
58 fn unlock_swap_chain(&mut self, id: WebGLContextId) -> Option<()> {
59 debug!("... unlocked chain {:?}", id);
60 let locked_front_buffer = self.locked_front_buffers.remove(&id)?;
61 let locked_front_buffer = self
62 .rendering_context
63 .destroy_texture(locked_front_buffer)?;
64
65 self.swap_chains
66 .get(id)
67 .expect("Should always have a SwapChain for a busy WebGLContext")
68 .recycle_surface(locked_front_buffer);
69
70 {
71 let mut busy_webgl_context_map = self.busy_webgl_context_map.write();
72 *busy_webgl_context_map.entry(id).or_insert(1) -= 1;
73 }
74
75 let _ = self.webgl_threads.finished_rendering_to_context(id);
76
77 Some(())
78 }
79}
80
81impl WebRenderExternalImageApi for WebGLExternalImages {
82 fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, Size2D<i32>) {
83 let (texture_id, size) = self.lock_swap_chain(WebGLContextId(id)).unwrap_or_default();
84 (ExternalImageSource::NativeTexture(texture_id), size)
85 }
86
87 fn unlock(&mut self, id: u64) {
88 self.unlock_swap_chain(WebGLContextId(id));
89 }
90}