1mod atlas;
15mod basic;
16mod draw;
17
18use std::num::NonZeroU32;
19use std::sync::Arc;
20use std::time::Instant;
21
22pub use draw::{Draw, Shared};
23use kas::cast::Cast;
24use kas::draw::{SharedState, WindowCommon, color};
25use kas::geom::Size;
26use kas::runner::raw_window_handle::{HasDisplayHandle, HasWindowHandle};
27use kas::runner::{
28 GraphicsFeatures, GraphicsInstance, HasDisplayAndWindowHandle, RunError, WindowSurface,
29};
30
31pub struct Instance {}
33
34impl Instance {
35 #[allow(clippy::new_without_default)]
37 pub fn new() -> Self {
38 Instance {}
39 }
40}
41
42pub struct Surface {
43 size: Size,
44 surface: softbuffer::Surface<Arc<dyn HasDisplayHandle>, Arc<dyn HasWindowHandle>>,
45 draw: Draw,
46}
47
48fn color_to_u32(c: impl Into<color::Rgba8Srgb>) -> u32 {
52 u32::from_be_bytes(c.into().0) >> 8
53}
54
55impl WindowSurface for Surface {
56 type Shared = Shared;
57
58 fn size(&self) -> Size {
59 self.size
60 }
61
62 fn configure(&mut self, _: &mut Shared, size: Size) -> bool {
63 if size == self.size() {
64 return false;
65 }
66
67 self.size = size;
68 self.draw.resize(size);
69
70 let width = NonZeroU32::new(size.0.cast()).expect("zero-sized surface");
71 let height = NonZeroU32::new(size.1.cast()).expect("zero-sized surface");
72 self.surface
73 .resize(width, height)
74 .expect("surface resize failed");
75 true
76 }
77
78 fn draw_iface<'iface>(
79 &'iface mut self,
80 shared: &'iface mut SharedState<Shared>,
81 ) -> kas::draw::DrawIface<'iface, Shared> {
82 kas::draw::DrawIface::new(&mut self.draw, shared)
83 }
84
85 fn common_mut(&mut self) -> &mut WindowCommon {
86 &mut self.draw.common
87 }
88
89 fn present(&mut self, shared: &mut Shared, clear_color: color::Rgba) -> Instant {
90 let mut buffer = self
91 .surface
92 .buffer_mut()
93 .expect("failed to access surface buffer");
94 let width: usize = self.size.0.cast();
95 let height: usize = self.size.1.cast();
96 debug_assert_eq!(width * height, buffer.len());
97
98 let c = color_to_u32(clear_color);
99 buffer.fill(c);
100
101 self.draw.render(shared, &mut buffer, (width, height));
102
103 let pre_present = Instant::now();
104 buffer.present().expect("failed to present buffer");
105 pre_present
106 }
107}
108
109impl GraphicsInstance for Instance {
110 type Shared = Shared;
111
112 type Surface = Surface;
113
114 fn new_shared(&mut self, _: Option<&Surface>, _: GraphicsFeatures) -> Result<Shared, RunError> {
115 Ok(Shared::default())
116 }
117
118 fn new_surface(
119 &mut self,
120 window: std::sync::Arc<dyn HasDisplayAndWindowHandle + Send + Sync>,
121 _: bool,
122 ) -> std::result::Result<Self::Surface, RunError>
123 where
124 Self: Sized,
125 {
126 let display = window.clone() as Arc<dyn HasDisplayHandle>;
127 let window = window as Arc<dyn HasWindowHandle>;
128 let context =
129 softbuffer::Context::new(display).map_err(|err| RunError::Graphics(Box::new(err)))?;
130 let surface = softbuffer::Surface::new(&context, window)
131 .map_err(|err| RunError::Graphics(Box::new(err)))?;
132
133 Ok(Surface {
134 size: Size::ZERO,
135 surface,
136 draw: Draw::default(),
137 })
138 }
139}