From aad40343bc16947428bd5c16c83e3fdf00d08dd7 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 27 Dec 2022 15:27:36 -0800 Subject: [PATCH] wayland: Block dispatching if back buffer isn't released https://github.com/rust-windowing/softbuffer/issues/41 If `set_buffer` can just be called in a loop without waiting for buffers to be released or a frame callback, but can also be called in other ways, I don't know if there's a better solution than blocking. Should fix https://github.com/rust-windowing/softbuffer/issues/48. The animation example could probably be implemented better, but this is at least better. I guess it should be documented that `set_buffer` may block? I don't know how this compares to other backends. --- src/wayland/mod.rs | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index bc90b63..356e0e7 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -1,6 +1,5 @@ use crate::{error::unwrap, SoftBufferError}; use raw_window_handle::{WaylandDisplayHandle, WaylandWindowHandle}; -use std::collections::VecDeque; use wayland_client::{ backend::{Backend, ObjectId}, globals::{registry_queue_init, GlobalListContents}, @@ -18,8 +17,7 @@ pub struct WaylandImpl { qh: QueueHandle, surface: wl_surface::WlSurface, shm: wl_shm::WlShm, - // 0-2 buffers - buffers: VecDeque, + buffers: Option<(WaylandBuffer, WaylandBuffer)>, } impl WaylandImpl { @@ -61,24 +59,22 @@ impl WaylandImpl { }) } - // Allocate or reuse a buffer of the given size fn buffer(&mut self, width: i32, height: i32) -> &WaylandBuffer { - let buffer = if let Some(mut buffer) = self.buffers.pop_front() { - if buffer.released() { - buffer.resize(width, height); - buffer - } else { - // If we have more than 1 unreleased buffer, destroy it - if self.buffers.is_empty() { - self.buffers.push_back(buffer); - } - WaylandBuffer::new(&self.shm, width, height, &self.qh) + self.buffers = Some(if let Some((front, mut back)) = self.buffers.take() { + // Swap buffers; block if back buffer not released yet + while !back.released() { + self.event_queue.blocking_dispatch(&mut State).unwrap(); } + back.resize(width, height); + (back, front) } else { - WaylandBuffer::new(&self.shm, width, height, &self.qh) - }; - self.buffers.push_back(buffer); - self.buffers.back().unwrap() + // Allocate front and back buffer + ( + WaylandBuffer::new(&self.shm, width, height, &self.qh), + WaylandBuffer::new(&self.shm, width, height, &self.qh), + ) + }); + &self.buffers.as_ref().unwrap().0 } pub(super) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {