1use crate::{
2 error::{InitError, SwResultExt},
3 util, Rect, SoftBufferError,
4};
5use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle};
6use std::{
7 cell::RefCell,
8 num::{NonZeroI32, NonZeroU32},
9 rc::Rc,
10};
11use wayland_client::{
12 backend::{Backend, ObjectId},
13 globals::{registry_queue_init, GlobalListContents},
14 protocol::{wl_registry, wl_shm, wl_surface},
15 Connection, Dispatch, EventQueue, Proxy, QueueHandle,
16};
17
18mod buffer;
19use buffer::WaylandBuffer;
20
21struct State;
22
23pub struct WaylandDisplayImpl<D: ?Sized> {
24 conn: Option<Connection>,
25 event_queue: RefCell<EventQueue<State>>,
26 qh: QueueHandle<State>,
27 shm: wl_shm::WlShm,
28
29 _display: D,
34}
35
36impl<D: HasDisplayHandle + ?Sized> WaylandDisplayImpl<D> {
37 pub(crate) fn new(display: D) -> Result<Self, InitError<D>>
38 where
39 D: Sized,
40 {
41 let raw = display.display_handle()?.as_raw();
42 let wayland_handle = match raw {
43 RawDisplayHandle::Wayland(w) => w.display,
44 _ => return Err(InitError::Unsupported(display)),
45 };
46
47 let backend = unsafe { Backend::from_foreign_display(wayland_handle.as_ptr().cast()) };
48 let conn = Connection::from_backend(backend);
49 let (globals, event_queue) =
50 registry_queue_init(&conn).swbuf_err("Failed to make round trip to server")?;
51 let qh = event_queue.handle();
52 let shm: wl_shm::WlShm = globals
53 .bind(&qh, 1..=1, ())
54 .swbuf_err("Failed to instantiate Wayland Shm")?;
55 Ok(Self {
56 conn: Some(conn),
57 event_queue: RefCell::new(event_queue),
58 qh,
59 shm,
60 _display: display,
61 })
62 }
63
64 fn conn(&self) -> &Connection {
65 self.conn.as_ref().unwrap()
66 }
67}
68
69impl<D: ?Sized> Drop for WaylandDisplayImpl<D> {
70 fn drop(&mut self) {
71 self.conn = None;
73 }
74}
75
76pub struct WaylandImpl<D: ?Sized, W: ?Sized> {
77 display: Rc<WaylandDisplayImpl<D>>,
78 surface: Option<wl_surface::WlSurface>,
79 buffers: Option<(WaylandBuffer, WaylandBuffer)>,
80 size: Option<(NonZeroI32, NonZeroI32)>,
81
82 window_handle: W,
87}
88
89impl<D: HasDisplayHandle + ?Sized, W: HasWindowHandle> WaylandImpl<D, W> {
90 pub(crate) fn new(window: W, display: Rc<WaylandDisplayImpl<D>>) -> Result<Self, InitError<W>> {
91 let raw = window.window_handle()?.as_raw();
93 let wayland_handle = match raw {
94 RawWindowHandle::Wayland(w) => w.surface,
95 _ => return Err(InitError::Unsupported(window)),
96 };
97
98 let surface_id = unsafe {
99 ObjectId::from_ptr(
100 wl_surface::WlSurface::interface(),
101 wayland_handle.as_ptr().cast(),
102 )
103 }
104 .swbuf_err("Failed to create proxy for surface ID.")?;
105 let surface = wl_surface::WlSurface::from_id(display.conn(), surface_id)
106 .swbuf_err("Failed to create proxy for surface ID.")?;
107 Ok(Self {
108 display,
109 surface: Some(surface),
110 buffers: Default::default(),
111 size: None,
112 window_handle: window,
113 })
114 }
115
116 #[inline]
118 pub fn window(&self) -> &W {
119 &self.window_handle
120 }
121
122 pub fn resize(&mut self, width: NonZeroU32, height: NonZeroU32) -> Result<(), SoftBufferError> {
123 self.size = Some(
124 (|| {
125 let width = NonZeroI32::try_from(width).ok()?;
126 let height = NonZeroI32::try_from(height).ok()?;
127 Some((width, height))
128 })()
129 .ok_or(SoftBufferError::SizeOutOfRange { width, height })?,
130 );
131 Ok(())
132 }
133
134 pub fn buffer_mut(&mut self) -> Result<BufferImpl<'_, D, W>, SoftBufferError> {
135 let (width, height) = self
136 .size
137 .expect("Must set size of surface before calling `buffer_mut()`");
138
139 if let Some((_front, back)) = &mut self.buffers {
140 if !back.released() {
142 let mut event_queue = self.display.event_queue.borrow_mut();
143 while !back.released() {
144 event_queue.blocking_dispatch(&mut State).map_err(|err| {
145 SoftBufferError::PlatformError(
146 Some("Wayland dispatch failure".to_string()),
147 Some(Box::new(err)),
148 )
149 })?;
150 }
151 }
152
153 back.resize(width.get(), height.get());
155 } else {
156 self.buffers = Some((
158 WaylandBuffer::new(
159 &self.display.shm,
160 width.get(),
161 height.get(),
162 &self.display.qh,
163 ),
164 WaylandBuffer::new(
165 &self.display.shm,
166 width.get(),
167 height.get(),
168 &self.display.qh,
169 ),
170 ));
171 };
172
173 let age = self.buffers.as_mut().unwrap().1.age;
174 Ok(BufferImpl {
175 stack: util::BorrowStack::new(self, |buffer| {
176 Ok(unsafe { buffer.buffers.as_mut().unwrap().1.mapped_mut() })
177 })?,
178 age,
179 })
180 }
181
182 pub fn fetch(&mut self) -> Result<Vec<u32>, SoftBufferError> {
184 Err(SoftBufferError::Unimplemented)
185 }
186
187 fn present_with_damage(&mut self, damage: &[Rect]) -> Result<(), SoftBufferError> {
188 let _ = self
189 .display
190 .event_queue
191 .borrow_mut()
192 .dispatch_pending(&mut State);
193
194 if let Some((front, back)) = &mut self.buffers {
195 std::mem::swap(front, back);
197
198 front.age = 1;
199 if back.age != 0 {
200 back.age += 1;
201 }
202
203 front.attach(self.surface.as_ref().unwrap());
204
205 if self.surface().version() < 4 {
209 self.surface().damage(0, 0, i32::MAX, i32::MAX);
210 } else {
211 for rect in damage {
212 let (x, y, width, height) = (|| {
214 Some((
215 i32::try_from(rect.x).ok()?,
216 i32::try_from(rect.y).ok()?,
217 i32::try_from(rect.width.get()).ok()?,
218 i32::try_from(rect.height.get()).ok()?,
219 ))
220 })()
221 .ok_or(SoftBufferError::DamageOutOfRange { rect: *rect })?;
222 self.surface().damage_buffer(x, y, width, height);
223 }
224 }
225
226 self.surface().commit();
227 }
228
229 let _ = self.display.event_queue.borrow_mut().flush();
230
231 Ok(())
232 }
233
234 fn surface(&self) -> &wl_surface::WlSurface {
235 self.surface.as_ref().unwrap()
236 }
237}
238
239impl<D: ?Sized, W: ?Sized> Drop for WaylandImpl<D, W> {
240 fn drop(&mut self) {
241 self.surface = None;
243 }
244}
245
246pub struct BufferImpl<'a, D: ?Sized, W> {
247 stack: util::BorrowStack<'a, WaylandImpl<D, W>, [u32]>,
248 age: u8,
249}
250
251impl<'a, D: HasDisplayHandle + ?Sized, W: HasWindowHandle> BufferImpl<'a, D, W> {
252 #[inline]
253 pub fn pixels(&self) -> &[u32] {
254 self.stack.member()
255 }
256
257 #[inline]
258 pub fn pixels_mut(&mut self) -> &mut [u32] {
259 self.stack.member_mut()
260 }
261
262 pub fn age(&self) -> u8 {
263 self.age
264 }
265
266 pub fn present_with_damage(self, damage: &[Rect]) -> Result<(), SoftBufferError> {
267 self.stack.into_container().present_with_damage(damage)
268 }
269
270 pub fn present(self) -> Result<(), SoftBufferError> {
271 let imp = self.stack.into_container();
272 let (width, height) = imp
273 .size
274 .expect("Must set size of surface before calling `present()`");
275 imp.present_with_damage(&[Rect {
276 x: 0,
277 y: 0,
278 width: width.try_into().unwrap(),
280 height: height.try_into().unwrap(),
281 }])
282 }
283}
284
285impl Dispatch<wl_registry::WlRegistry, GlobalListContents> for State {
286 fn event(
287 _: &mut State,
288 _: &wl_registry::WlRegistry,
289 _: wl_registry::Event,
290 _: &GlobalListContents,
291 _: &Connection,
292 _: &QueueHandle<State>,
293 ) {
294 }
296}
297
298impl Dispatch<wl_shm::WlShm, ()> for State {
299 fn event(
300 _: &mut State,
301 _: &wl_shm::WlShm,
302 _: wl_shm::Event,
303 _: &(),
304 _: &Connection,
305 _: &QueueHandle<State>,
306 ) {
307 }
308}