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
333pub 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}