Skip to main content

repose_core/
render_context.rs

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