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