Skip to main content

repose_core/
render_context.rs

1use crate::color::{ColorInfo, PixelFormat};
2use crate::{ImageHandle, request_frame};
3
4#[derive(Debug)]
5pub enum RenderCommand {
6    SetImageEncoded {
7        handle: ImageHandle,
8        bytes: Vec<u8>,
9        srgb: bool,
10    },
11    SetImageRgba8 {
12        handle: ImageHandle,
13        w: u32,
14        h: u32,
15        rgba: Vec<u8>,
16        srgb: bool,
17    },
18    SetImageNv12 {
19        handle: ImageHandle,
20        w: u32,
21        h: u32,
22        y: Vec<u8>,
23        uv: Vec<u8>,
24        color_info: ColorInfo,
25    },
26    SetImagePlanes {
27        handle: ImageHandle,
28        w: u32,
29        h: u32,
30        pixel_format: PixelFormat,
31        planes: Vec<Vec<u8>>,
32        color_info: ColorInfo,
33    },
34    RemoveImage {
35        handle: ImageHandle,
36    },
37}
38
39#[cfg(not(target_arch = "wasm32"))]
40mod imp {
41    use super::*;
42    use std::collections::{HashMap, HashSet};
43    use std::sync::atomic::{AtomicU64, Ordering};
44    use std::sync::{Arc, Mutex};
45
46    struct Queue {
47        updates: HashMap<ImageHandle, RenderCommand>,
48        removals: HashSet<ImageHandle>,
49    }
50
51    impl Queue {
52        fn new() -> Self {
53            Self {
54                updates: HashMap::new(),
55                removals: HashSet::new(),
56            }
57        }
58    }
59
60    #[derive(Clone)]
61    pub struct RenderContext {
62        next: Arc<AtomicU64>,
63        q: Arc<Mutex<Queue>>,
64    }
65
66    impl RenderContext {
67        pub fn new() -> Self {
68            Self {
69                next: Arc::new(AtomicU64::new(1)),
70                q: Arc::new(Mutex::new(Queue::new())),
71            }
72        }
73
74        pub fn alloc_image_handle(&self) -> ImageHandle {
75            self.next.fetch_add(1, Ordering::Relaxed)
76        }
77
78        pub fn set_image_encoded(&self, handle: ImageHandle, bytes: Vec<u8>, srgb: bool) {
79            let mut q = self.q.lock().unwrap();
80            q.removals.remove(&handle);
81            q.updates.insert(
82                handle,
83                RenderCommand::SetImageEncoded {
84                    handle,
85                    bytes,
86                    srgb,
87                },
88            );
89            request_frame();
90        }
91
92        pub fn set_image_rgba8(
93            &self,
94            handle: ImageHandle,
95            w: u32,
96            h: u32,
97            rgba: Vec<u8>,
98            srgb: bool,
99        ) {
100            let mut q = self.q.lock().unwrap();
101            q.removals.remove(&handle);
102            q.updates.insert(
103                handle,
104                RenderCommand::SetImageRgba8 {
105                    handle,
106                    w,
107                    h,
108                    rgba,
109                    srgb,
110                },
111            );
112            request_frame();
113        }
114
115        pub fn set_image_nv12(
116            &self,
117            handle: ImageHandle,
118            w: u32,
119            h: u32,
120            y: Vec<u8>,
121            uv: Vec<u8>,
122            color_info: ColorInfo,
123        ) {
124            self.set_image_planes(handle, w, h, PixelFormat::Nv12, vec![y, uv], color_info);
125        }
126
127        pub fn set_image_planes(
128            &self,
129            handle: ImageHandle,
130            w: u32,
131            h: u32,
132            pixel_format: PixelFormat,
133            planes: Vec<Vec<u8>>,
134            color_info: ColorInfo,
135        ) {
136            let mut q = self.q.lock().unwrap();
137            q.removals.remove(&handle);
138            q.updates.insert(
139                handle,
140                RenderCommand::SetImagePlanes {
141                    handle,
142                    w,
143                    h,
144                    pixel_format,
145                    planes,
146                    color_info,
147                },
148            );
149            request_frame();
150        }
151
152        pub fn remove_image(&self, handle: ImageHandle) {
153            let mut q = self.q.lock().unwrap();
154            q.removals.remove(&handle);
155            q.updates.remove(&handle);
156            request_frame();
157        }
158
159        pub fn drain(&self) -> Vec<RenderCommand> {
160            let mut q = self.q.lock().unwrap();
161            let mut result = Vec::with_capacity(q.removals.len() + q.updates.len());
162
163            for handle in q.removals.drain() {
164                result.push(RenderCommand::RemoveImage { handle });
165            }
166
167            for (_, cmd) in q.updates.drain() {
168                result.push(cmd);
169            }
170
171            result
172        }
173    }
174
175    impl Default for RenderContext {
176        fn default() -> Self {
177            Self::new()
178        }
179    }
180}
181
182#[cfg(target_arch = "wasm32")]
183mod imp {
184    use super::*;
185    use std::cell::RefCell;
186    use std::collections::{HashMap, HashSet};
187    use std::rc::Rc;
188
189    struct Queue {
190        updates: HashMap<ImageHandle, RenderCommand>,
191        removals: HashSet<ImageHandle>,
192    }
193
194    struct Inner {
195        next: ImageHandle,
196        q: Queue,
197    }
198
199    #[derive(Clone)]
200    pub struct RenderContext {
201        inner: Rc<RefCell<Inner>>,
202    }
203
204    impl RenderContext {
205        pub fn new() -> Self {
206            Self {
207                inner: Rc::new(RefCell::new(Inner {
208                    next: 1,
209                    q: Queue {
210                        updates: HashMap::new(),
211                        removals: HashSet::new(),
212                    },
213                })),
214            }
215        }
216
217        pub fn alloc_image_handle(&self) -> ImageHandle {
218            let mut s = self.inner.borrow_mut();
219            let id = s.next;
220            s.next += 1;
221            id
222        }
223
224        pub fn set_image_encoded(&self, handle: ImageHandle, bytes: Vec<u8>, srgb: bool) {
225            let mut s = self.inner.borrow_mut();
226            s.q.removals.remove(&handle);
227            s.q.updates.insert(
228                handle,
229                RenderCommand::SetImageEncoded {
230                    handle,
231                    bytes,
232                    srgb,
233                },
234            );
235            request_frame();
236        }
237
238        pub fn set_image_rgba8(
239            &self,
240            handle: ImageHandle,
241            w: u32,
242            h: u32,
243            rgba: Vec<u8>,
244            srgb: bool,
245        ) {
246            let mut s = self.inner.borrow_mut();
247            s.q.removals.remove(&handle);
248            s.q.updates.insert(
249                handle,
250                RenderCommand::SetImageRgba8 {
251                    handle,
252                    w,
253                    h,
254                    rgba,
255                    srgb,
256                },
257            );
258            request_frame();
259        }
260
261        pub fn set_image_nv12(
262            &self,
263            handle: ImageHandle,
264            w: u32,
265            h: u32,
266            y: Vec<u8>,
267            uv: Vec<u8>,
268            color_info: ColorInfo,
269        ) {
270            self.set_image_planes(handle, w, h, PixelFormat::Nv12, vec![y, uv], color_info);
271        }
272
273        pub fn set_image_planes(
274            &self,
275            handle: ImageHandle,
276            w: u32,
277            h: u32,
278            pixel_format: PixelFormat,
279            planes: Vec<Vec<u8>>,
280            color_info: ColorInfo,
281        ) {
282            let mut s = self.inner.borrow_mut();
283            s.q.removals.remove(&handle);
284            s.q.updates.insert(
285                handle,
286                RenderCommand::SetImagePlanes {
287                    handle,
288                    w,
289                    h,
290                    pixel_format,
291                    planes,
292                    color_info,
293                },
294            );
295            request_frame();
296        }
297
298        pub fn remove_image(&self, handle: ImageHandle) {
299            let mut s = self.inner.borrow_mut();
300            s.q.updates.remove(&handle);
301            s.q.removals.insert(handle);
302            request_frame();
303        }
304
305        pub fn drain(&self) -> Vec<RenderCommand> {
306            let mut s = self.inner.borrow_mut();
307            let mut result = Vec::with_capacity(s.q.removals.len() + s.q.updates.len());
308
309            for handle in s.q.removals.drain() {
310                result.push(RenderCommand::RemoveImage { handle });
311            }
312
313            for (_, cmd) in s.q.updates.drain() {
314                result.push(cmd);
315            }
316
317            result
318        }
319    }
320
321    impl Default for RenderContext {
322        fn default() -> Self {
323            Self::new()
324        }
325    }
326}
327
328pub use imp::RenderContext;
329
330/// RAII guard that removes the image when dropped
331pub struct ImageHandleGuard {
332    pub handle: ImageHandle,
333    rc: RenderContext,
334}
335
336impl ImageHandleGuard {
337    pub fn new(rc: &RenderContext) -> Self {
338        Self {
339            handle: rc.alloc_image_handle(),
340            rc: rc.clone(),
341        }
342    }
343}
344
345impl Drop for ImageHandleGuard {
346    fn drop(&mut self) {
347        self.rc.remove_image(self.handle);
348    }
349}
350
351impl std::ops::Deref for ImageHandleGuard {
352    type Target = ImageHandle;
353    fn deref(&self) -> &Self::Target {
354        &self.handle
355    }
356}