x11: fixup buffer age

The current code always acquires the buffer it just submitted,
which results in always rendering to a buffer with age "1", although
its contents are older, because the currently held buffer is already
submitted, just not to the swapchain. When it finally is submitted
its age is again set to 1, the other gets its correct age (but too late)
and the circle is repeated again. So lets fix that.
This commit is contained in:
Victor Brekenfeld 2021-11-28 01:14:17 +01:00
parent 485aa2a9c7
commit bd305dc7ee
2 changed files with 23 additions and 19 deletions

View File

@ -306,7 +306,9 @@ pub fn run_x11(log: Logger) {
} }
// Submit the buffer // Submit the buffer
backend_data.surface.submit(); if let Err(err) = backend_data.surface.submit() {
error!(log, "Error submitting buffer for display: {}", err);
}
} }
Err(err) => { Err(err) => {

View File

@ -349,8 +349,7 @@ pub struct X11Surface {
format: DrmFourcc, format: DrmFourcc,
width: u16, width: u16,
height: u16, height: u16,
current: Option<Slot<BufferObject<()>>>, buffer: Option<Slot<BufferObject<()>>>,
next: Option<Slot<BufferObject<()>>>,
} }
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
@ -467,8 +466,7 @@ impl X11Surface {
format, format,
width: size.w, width: size.w,
height: size.h, height: size.h,
current: None, buffer: None,
next: None,
resize: recv, resize: recv,
}) })
} }
@ -493,8 +491,8 @@ impl X11Surface {
self.resize(new_size)?; self.resize(new_size)?;
} }
if self.next.is_none() { if self.buffer.is_none() {
self.next = Some( self.buffer = Some(
self.swapchain self.swapchain
.acquire() .acquire()
.map_err(Into::<AllocateBuffersError>::into)? .map_err(Into::<AllocateBuffersError>::into)?
@ -502,7 +500,7 @@ impl X11Surface {
); );
} }
let slot = self.next.as_ref().unwrap(); let slot = self.buffer.as_ref().unwrap();
let age = slot.age(); let age = slot.age();
match slot.userdata().get::<Dmabuf>() { match slot.userdata().get::<Dmabuf>() {
Some(dmabuf) => Ok((dmabuf.clone(), age)), Some(dmabuf) => Ok((dmabuf.clone(), age)),
@ -515,41 +513,45 @@ impl X11Surface {
} }
/// Consume and submit the buffer to the window. /// Consume and submit the buffer to the window.
pub fn submit(&mut self) { pub fn submit(&mut self) -> Result<(), AllocateBuffersError> {
if let Some(connection) = self.connection.upgrade() { if let Some(connection) = self.connection.upgrade() {
// Get a new buffer
let mut next = self
.swapchain
.acquire()
.map_err(Into::<AllocateBuffersError>::into)?
.ok_or(AllocateBuffersError::NoFreeSlots)?;
// Swap the buffers // Swap the buffers
if let Some(mut next) = self.next.take() { if let Some(current) = self.buffer.as_mut() {
if let Some(current) = self.current.as_mut() {
mem::swap(&mut next, current); mem::swap(&mut next, current);
self.swapchain.submitted(next);
} else {
self.current = Some(next);
}
} }
if let Ok(pixmap) = PixmapWrapper::with_dmabuf( if let Ok(pixmap) = PixmapWrapper::with_dmabuf(
&*connection, &*connection,
&self.window, &self.window,
self.current.as_ref().unwrap().userdata().get::<Dmabuf>().unwrap(), next.userdata().get::<Dmabuf>().unwrap(),
) { ) {
// Now present the current buffer // Now present the current buffer
let _ = pixmap.present(&*connection, &self.window); let _ = pixmap.present(&*connection, &self.window);
} }
self.swapchain.submitted(next);
// Flush the connection after presenting to the window to ensure we don't run out of buffer space in the X11 connection. // Flush the connection after presenting to the window to ensure we don't run out of buffer space in the X11 connection.
let _ = connection.flush(); let _ = connection.flush();
} }
Ok(())
} }
/// Resets the internal buffers, e.g. to reset age values /// Resets the internal buffers, e.g. to reset age values
pub fn reset_buffers(&mut self) { pub fn reset_buffers(&mut self) {
self.swapchain.reset_buffers(); self.swapchain.reset_buffers();
self.next = None; self.buffer = None;
} }
fn resize(&mut self, size: Size<u16, Logical>) -> Result<(), AllocateBuffersError> { fn resize(&mut self, size: Size<u16, Logical>) -> Result<(), AllocateBuffersError> {
self.swapchain.resize(size.w as u32, size.h as u32); self.swapchain.resize(size.w as u32, size.h as u32);
self.next = None; self.buffer = None;
self.width = size.w; self.width = size.w;
self.height = size.h; self.height = size.h;