1use std::{
7 cell::UnsafeCell,
8 ops::{Index, IndexMut},
9 sync::atomic::{AtomicU32, AtomicU64, Ordering},
10 u32,
11};
12
13use secgate::util::Handle;
14use twizzler::{
15 error::TwzError,
16 object::{MapFlags, ObjID, Object, ObjectBuilder, TypedObject},
17 ptr::{InvPtr, RefSlice, RefSliceMut},
18 BaseType, Invariant,
19};
20use twizzler_abi::syscall::{
21 sys_thread_sync, ThreadSync, ThreadSyncFlags, ThreadSyncOp, ThreadSyncReference,
22 ThreadSyncSleep, ThreadSyncWake,
23};
24
25#[derive(Clone)]
26pub struct BufferObject {
28 obj: Object<DisplayBufferBase>,
29}
30
31impl From<Object<DisplayBufferBase>> for BufferObject {
32 fn from(obj: Object<DisplayBufferBase>) -> Self {
33 Self { obj }
34 }
35}
36
37const DBF_PHASE: u64 = 0x1;
38const DBF_COMP_DONE: u64 = 0x2;
39
40const MAX_W: u64 = 8192;
41const MAX_H: u64 = 8192;
42const MAX_BUFFER_SIZE: u64 = MAX_W * MAX_H * 4;
43
44#[derive(Invariant, BaseType)]
45pub struct DisplayBufferBase {
46 pub flags: AtomicU64,
47 pub buffers: [DisplayBuffer; 2],
48}
49
50#[derive(Invariant, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
51pub struct Rect {
52 pub x: u32,
53 pub y: u32,
54 pub w: u32,
55 pub h: u32,
56}
57
58impl From<WindowConfig> for Rect {
59 fn from(value: WindowConfig) -> Self {
60 Self {
61 x: value.x,
62 y: value.y,
63 w: value.w,
64 h: value.h,
65 }
66 }
67}
68
69impl Rect {
70 pub const fn new(x: u32, y: u32, w: u32, h: u32) -> Self {
71 Self { x, y, w, h }
72 }
73
74 pub const fn full() -> Self {
75 Self {
76 x: 0,
77 y: 0,
78 w: u32::MAX,
79 h: u32::MAX,
80 }
81 }
82
83 pub fn is_covered_by_any(&self, rects: &[Rect]) -> bool {
84 for rect in rects {
85 if rect.x <= self.x
86 && rect.y <= self.y
87 && rect.x + rect.w >= self.x + self.w
88 && rect.y + rect.h >= self.y + self.h
89 {
90 return true;
91 }
92 }
93 false
94 }
95
96 pub fn extent_of(rects: &[Rect]) -> Self {
97 let x = rects.iter().min_by_key(|r| r.x).map(|r| r.x).unwrap_or(0);
98 let y = rects.iter().min_by_key(|r| r.y).map(|r| r.y).unwrap_or(0);
99 Rect {
100 x,
101 y,
102 w: rects
103 .iter()
104 .max_by_key(|r| r.x + r.w)
105 .map(|r| r.x + r.w)
106 .unwrap_or(0)
107 - x,
108 h: rects
109 .iter()
110 .max_by_key(|r| r.y + r.h)
111 .map(|r| r.y + r.h)
112 .unwrap_or(0)
113 - y,
114 }
115 }
116}
117
118const NUM_DAMAGE: usize = 8;
119const FULL_DAMAGE: u64 = 0xFFFFFFFFFFFFFFFF;
120
121#[derive(Invariant)]
122pub struct DisplayBuffer {
123 pub comp_width: AtomicU32,
124 pub comp_height: AtomicU32,
125 pub width: AtomicU32,
126 pub height: AtomicU32,
127 pub byte_len: u64,
128 pub ptr: InvPtr<u32>,
129 pub damage: UnsafeCell<[Rect; NUM_DAMAGE]>,
130 pub damage_count: AtomicU64,
131}
132
133pub struct Buffer<'a> {
134 buffer: &'a [u32],
135 db: &'a DisplayBuffer,
136}
137
138impl<'a> AsRef<[u32]> for Buffer<'a> {
139 fn as_ref(&self) -> &[u32] {
140 self.buffer
141 }
142}
143
144impl<'a> Index<usize> for Buffer<'a> {
145 type Output = u32;
146
147 fn index(&self, index: usize) -> &Self::Output {
148 &self.buffer[index]
149 }
150}
151
152impl<'a> Buffer<'a> {
153 fn new(s: &mut RefSlice<'a, u32>, db: &'a DisplayBuffer) -> Self {
154 Self {
155 buffer: s.as_slice(),
156 db,
157 }
158 }
159
160 pub fn damage_rects(&self) -> &[Rect] {
161 unsafe { self.db.damage() }
162 }
163
164 pub fn len(&self) -> usize {
165 self.buffer.len()
166 }
167
168 pub fn as_slice(&self) -> &[u32] {
169 self.buffer
170 }
171}
172
173pub struct BufferMut<'a> {
174 buffer: &'a mut [u32],
175 db: &'a DisplayBuffer,
176}
177
178impl<'a> AsRef<[u32]> for BufferMut<'a> {
179 fn as_ref(&self) -> &[u32] {
180 self.buffer
181 }
182}
183
184impl<'a> AsMut<[u32]> for BufferMut<'a> {
185 fn as_mut(&mut self) -> &mut [u32] {
186 self.buffer
187 }
188}
189
190impl<'a> Index<usize> for BufferMut<'a> {
191 type Output = u32;
192
193 fn index(&self, index: usize) -> &Self::Output {
194 &self.buffer[index]
195 }
196}
197
198impl<'a> IndexMut<usize> for BufferMut<'a> {
199 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
200 &mut self.buffer[index]
201 }
202}
203
204impl<'a> BufferMut<'a> {
205 fn new(s: &mut RefSliceMut<'a, u32>, db: &'a DisplayBuffer) -> Self {
206 Self {
207 buffer: s.as_slice_mut(),
208 db,
209 }
210 }
211
212 pub fn damage_rects(&self) -> &[Rect] {
213 unsafe { self.db.damage() }
214 }
215
216 pub fn damage(&self, dmg: Rect) {
217 unsafe { self.db.append_damage(dmg) };
218 }
219
220 pub fn len(&self) -> usize {
221 self.buffer.len()
222 }
223
224 pub fn as_slice(&self) -> &[u32] {
225 self.buffer
226 }
227
228 pub fn as_slice_mut(&mut self) -> &mut [u32] {
229 self.buffer
230 }
231}
232
233impl DisplayBuffer {
234 unsafe fn buffer_mut(&self) -> RefSliceMut<'_, u32> {
235 let ptr = self.ptr.resolve().as_mut();
236 let slice = RefSliceMut::from_ref(ptr, self.byte_len as usize);
237 slice
238 }
239
240 unsafe fn buffer(&self) -> RefSlice<'_, u32> {
241 let ptr = self.ptr.resolve();
242 let slice = RefSlice::from_ref(ptr, self.byte_len as usize);
243 slice
244 }
245
246 unsafe fn append_damage(&self, dmg: Rect) {
247 let current_count = self.damage_count.load(Ordering::SeqCst);
248 if current_count == FULL_DAMAGE {
249 return;
250 }
251 let damage = self.damage.get().as_mut().unwrap_unchecked();
252 if current_count as usize == NUM_DAMAGE {
253 damage[0] = Rect::extent_of(&damage.as_slice()[..(current_count as usize)]);
254 self.damage_count.store(1, Ordering::Release);
255 return;
256 }
257
258 if dmg.is_covered_by_any(&damage[..(current_count as usize)]) {
259 return;
260 }
261
262 damage[current_count as usize] = dmg;
263 self.damage_count.fetch_add(1, Ordering::Release);
264 }
265
266 unsafe fn reset_damage(&self) {
267 self.damage_count.store(0, Ordering::SeqCst);
268 }
269
270 unsafe fn damage(&self) -> &[Rect] {
271 const FD: [Rect; 1] = [Rect::full()];
272 let count = self.damage_count.load(Ordering::Acquire);
273 if count == FULL_DAMAGE {
274 return &FD;
275 }
276 &self.damage.get().as_ref().unwrap_unchecked()[..count as usize]
277 }
278}
279
280impl BufferObject {
281 pub fn id(&self) -> ObjID {
282 self.obj.id()
283 }
284
285 pub fn create_new(w: u32, h: u32) -> Result<Self, TwzError> {
286 let builder = ObjectBuilder::default();
287 let obj = builder.build_inplace(|mut obj| {
288 let buf1 = obj.static_alloc(0).unwrap();
289 let buf2 = obj.static_alloc(0).unwrap();
290
291 let base = DisplayBufferBase {
292 flags: AtomicU64::new(0),
293 buffers: [
294 DisplayBuffer {
295 comp_width: AtomicU32::new(w),
296 comp_height: AtomicU32::new(h),
297 width: AtomicU32::new(w),
298 height: AtomicU32::new(h),
299 byte_len: MAX_BUFFER_SIZE,
300 ptr: InvPtr::from_raw_parts(0, buf1.offset()),
301 damage_count: AtomicU64::new(0),
302 damage: UnsafeCell::new([Rect::full(); NUM_DAMAGE]),
303 },
304 DisplayBuffer {
305 comp_width: AtomicU32::new(w),
306 comp_height: AtomicU32::new(h),
307 width: AtomicU32::new(w),
308 height: AtomicU32::new(h),
309 byte_len: MAX_BUFFER_SIZE,
310 ptr: InvPtr::from_raw_parts(0, buf2.offset()),
311 damage_count: AtomicU64::new(0),
312 damage: UnsafeCell::new([Rect::full(); NUM_DAMAGE]),
313 },
314 ],
315 };
316 obj.write(base)
317 })?;
318
319 Ok(BufferObject { obj })
320 }
321
322 pub fn has_data_for_read(&self) -> bool {
324 self.obj.base().flags.load(Ordering::SeqCst) & DBF_COMP_DONE == 0
325 }
326
327 pub fn read_buffer<R>(&self, mut f: impl FnMut(Buffer, u32, u32) -> R) -> R {
329 let base = self.obj.base();
330 let flags = base.flags.load(Ordering::SeqCst);
331
332 let buffer = if flags & DBF_PHASE != 0 {
333 &base.buffers[0]
334 } else {
335 &base.buffers[1]
336 };
337 let cw = buffer.width.load(Ordering::SeqCst);
338 let ch = buffer.height.load(Ordering::SeqCst);
339 let buf = unsafe { buffer.buffer() };
340 let mut buf = buf.slice(0..((cw * ch) as usize));
341 let r = f(Buffer::new(&mut buf, buffer), cw, ch);
342 r
343 }
344
345 pub fn read_done(&self, new_w: u32, new_h: u32) {
348 let base = self.obj.base();
349 let flags = base.flags.load(Ordering::SeqCst);
350 let buffer = if flags & DBF_PHASE != 0 {
351 &base.buffers[0]
352 } else {
353 &base.buffers[1]
354 };
355 buffer.comp_height.store(new_h, Ordering::Release);
356 buffer.comp_width.store(new_w, Ordering::Release);
357 unsafe { buffer.reset_damage() };
358 base.flags.fetch_or(DBF_COMP_DONE, Ordering::SeqCst);
359 let _ = sys_thread_sync(
360 &mut [ThreadSync::new_wake(ThreadSyncWake::new(
361 ThreadSyncReference::Virtual(&base.flags),
362 usize::MAX,
363 ))],
364 None,
365 );
366 }
367
368 pub fn update_buffer<R>(&self, mut f: impl FnMut(BufferMut, u32, u32) -> R) -> R {
370 let base = self.obj.base();
371 let flags = base.flags.load(Ordering::SeqCst);
372
373 let buffer = if flags & DBF_PHASE != 0 {
374 &base.buffers[1]
375 } else {
376 &base.buffers[0]
377 };
378 let cw = buffer.comp_width.load(Ordering::SeqCst);
379 let ch = buffer.comp_height.load(Ordering::SeqCst);
380
381 let buf = unsafe { buffer.buffer_mut() };
382 let mut buf = buf.slice(0..((cw * ch) as usize));
383 let r = f(BufferMut::new(&mut buf, buffer), cw, ch);
384 buffer.height.store(ch, Ordering::Release);
385 buffer.width.store(cw, Ordering::Release);
386 r
387 }
388
389 pub fn flip(&self) {
391 let base = self.obj.base();
392 let mut flags = base.flags.load(Ordering::SeqCst);
393
394 while flags & DBF_COMP_DONE == 0 {
395 let _ = sys_thread_sync(
396 &mut [ThreadSync::new_sleep(ThreadSyncSleep::new(
397 ThreadSyncReference::Virtual(&base.flags),
398 flags,
399 ThreadSyncOp::Equal,
400 ThreadSyncFlags::empty(),
401 ))],
402 None,
403 );
404 flags = base.flags.load(Ordering::SeqCst);
405 }
406
407 let (src_buffer, dst_buffer) = if flags & DBF_PHASE != 0 {
408 (&base.buffers[0], &base.buffers[1])
409 } else {
410 (&base.buffers[1], &base.buffers[0])
411 };
412
413 let w = src_buffer.width.load(Ordering::Acquire);
414 let h = src_buffer.height.load(Ordering::Acquire);
415 for dmg in unsafe { src_buffer.damage() } {
416 for y in dmg.y..(dmg.y + dmg.h.min(h - dmg.y)) {
417 let start = (y * w + dmg.x) as usize;
418 let len = dmg.w.min(w - dmg.x) as usize;
419 let src = &unsafe { src_buffer.buffer().as_slice() }[start..(start + len)];
420 let dst =
421 &mut unsafe { dst_buffer.buffer_mut().as_slice_mut() }[start..(start + len)];
422 dst.copy_from_slice(src);
423 }
424 }
425
426 let new_flags = (flags ^ DBF_PHASE) & !DBF_COMP_DONE;
427 base.flags.store(new_flags, Ordering::SeqCst);
428
429 let _ = sys_thread_sync(
430 &mut [ThreadSync::new_wake(ThreadSyncWake::new(
431 ThreadSyncReference::Virtual(&base.flags),
432 usize::MAX,
433 ))],
434 None,
435 );
436 }
437}
438
439#[secgate::gatecall]
440pub fn start_display() -> Result<(), TwzError> {}
441#[secgate::gatecall]
442pub fn create_window(winfo: WindowConfig) -> Result<(ObjID, u32), TwzError> {}
443#[secgate::gatecall]
444pub fn drop_window(handle: u32) -> Result<(), TwzError> {}
445#[secgate::gatecall]
446pub fn reconfigure_window(handle: u32, wconfig: WindowConfig) -> Result<(), TwzError> {}
447#[secgate::gatecall]
448pub fn get_window_config(handle: u32) -> Result<WindowConfig, TwzError> {}
449#[secgate::gatecall]
450pub fn get_display_info() -> Result<WindowConfig, TwzError> {}
451
452#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
453#[repr(C)]
454pub struct WindowConfig {
455 pub w: u32,
456 pub h: u32,
457 pub x: u32,
458 pub y: u32,
459 pub z: u32,
460}
461#[repr(C)]
462pub struct WindowHandle {
464 key: u32,
465 pub window_buffer: BufferObject,
466}
467
468impl WindowHandle {
469 pub fn reconfigure(&self, wconfig: WindowConfig) -> Result<(), TwzError> {
471 reconfigure_window(self.key, wconfig)
472 }
473
474 pub fn get_config(&self) -> Result<WindowConfig, TwzError> {
476 get_window_config(self.key)
477 }
478}
479
480impl Drop for WindowHandle {
481 fn drop(&mut self) {
482 self.release();
483 }
484}
485
486impl Handle for WindowHandle {
487 type OpenError = TwzError;
488
489 type OpenInfo = WindowConfig;
490
491 fn open(info: Self::OpenInfo) -> Result<Self, Self::OpenError>
492 where
493 Self: Sized,
494 {
495 let (id, key) = create_window(info)?;
496 Ok(WindowHandle {
497 key,
498 window_buffer: BufferObject::from(unsafe {
499 Object::map_unchecked(id, MapFlags::READ | MapFlags::WRITE)
500 }?),
501 })
502 }
503
504 fn release(&mut self) {
505 let _ = drop_window(self.key);
506 }
507}