freya_winit/drivers/
software.rs1use std::num::NonZeroU32;
2
3use freya_engine::prelude::{
4 AlphaType,
5 ColorType,
6 ImageInfo,
7 Surface as SkiaSurface,
8 wrap_pixels,
9};
10use raw_window_handle::{
11 DisplayHandle,
12 HandleError,
13 HasDisplayHandle,
14 HasWindowHandle,
15 RawDisplayHandle,
16 RawWindowHandle,
17 WindowHandle,
18};
19use winit::{
20 dpi::PhysicalSize,
21 event_loop::ActiveEventLoop,
22 window::{
23 Window,
24 WindowAttributes,
25 },
26};
27
28struct DisplayHandleWrapper(RawDisplayHandle);
29
30impl HasDisplayHandle for DisplayHandleWrapper {
31 fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
32 Ok(unsafe { DisplayHandle::borrow_raw(self.0) })
34 }
35}
36
37struct WindowHandleWrapper(RawWindowHandle);
38
39impl HasWindowHandle for WindowHandleWrapper {
40 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
41 Ok(unsafe { WindowHandle::borrow_raw(self.0) })
43 }
44}
45
46pub struct SoftwareDriver {
48 _context: softbuffer::Context<DisplayHandleWrapper>,
49 surface: softbuffer::Surface<DisplayHandleWrapper, WindowHandleWrapper>,
50}
51
52impl SoftwareDriver {
53 pub fn new(
54 event_loop: &ActiveEventLoop,
55 window_attributes: WindowAttributes,
56 ) -> Result<(Self, Window), Box<dyn std::error::Error>> {
57 let window = event_loop.create_window(window_attributes)?;
58
59 let display_handle = window.display_handle()?.as_raw();
60 let window_handle = window.window_handle()?.as_raw();
61
62 let context = softbuffer::Context::new(DisplayHandleWrapper(display_handle))
63 .map_err(|err| format!("Could not create softbuffer context: {err}"))?;
64 let mut surface = softbuffer::Surface::new(&context, WindowHandleWrapper(window_handle))
65 .map_err(|err| format!("Could not create softbuffer surface: {err}"))?;
66
67 let size = window.inner_size();
68 if let (Some(width), Some(height)) =
69 (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
70 {
71 surface
72 .resize(width, height)
73 .map_err(|err| format!("Could not size softbuffer surface: {err}"))?;
74 }
75
76 Ok((
77 Self {
78 _context: context,
79 surface,
80 },
81 window,
82 ))
83 }
84
85 pub fn present(
86 &mut self,
87 size: PhysicalSize<u32>,
88 window: &Window,
89 render: impl FnOnce(&mut SkiaSurface),
90 ) {
91 let (Some(width), Some(height)) =
92 (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
93 else {
94 return;
95 };
96
97 let mut buffer = match self.surface.buffer_mut() {
98 Ok(buffer) => buffer,
99 Err(err) => {
100 tracing::error!("Failed to acquire software buffer: {err:?}");
101 return;
102 }
103 };
104
105 let info = ImageInfo::new(
106 (width.get() as i32, height.get() as i32),
107 ColorType::BGRA8888,
108 AlphaType::Premul,
109 None,
110 );
111 let row_bytes = width.get() as usize * 4;
112 let pixels: &mut [u32] = &mut buffer;
113 let bytes: &mut [u8] = unsafe {
115 std::slice::from_raw_parts_mut(pixels.as_mut_ptr() as *mut u8, pixels.len() * 4)
116 };
117
118 match wrap_pixels(&info, bytes, Some(row_bytes), None) {
119 Some(mut wrapped_surface) => render(&mut wrapped_surface),
120 None => {
121 tracing::error!("Failed to wrap software pixels into a Skia surface");
122 return;
123 }
124 }
125
126 window.pre_present_notify();
127 if let Err(err) = buffer.present() {
128 tracing::error!("Failed to present software buffer: {err:?}");
129 }
130 }
131
132 pub fn resize(&mut self, size: PhysicalSize<u32>) {
133 let (Some(width), Some(height)) =
134 (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
135 else {
136 return;
137 };
138 if let Err(err) = self.surface.resize(width, height) {
139 tracing::error!("Failed to resize software surface: {err:?}");
140 }
141 }
142}