x11: store dmabufs in buffer object userdata

This commit is contained in:
i509VCB 2021-11-04 16:56:45 -05:00 committed by Victor Brekenfeld
parent 42b646a152
commit 53d43905ac
3 changed files with 51 additions and 41 deletions

View File

@ -63,8 +63,7 @@ pub fn run_x11(log: Logger) {
// Create the gbm device for buffer allocation and the X11 surface which presents to the window. // Create the gbm device for buffer allocation and the X11 surface which presents to the window.
let device = gbm::Device::new(drm_node).expect("Failed to create gbm device"); let device = gbm::Device::new(drm_node).expect("Failed to create gbm device");
let format = backend.format(); let format = backend.format();
let surface = let surface = X11Surface::new(&mut backend, device, format).expect("Failed to create X11 surface");
X11Surface::new(&mut backend, device, format).expect("Failed to create X11 surface");
// Initialize EGL using the GBM device setup earlier. // Initialize EGL using the GBM device setup earlier.
let egl = EGLDisplay::new(&surface, log.clone()).expect("Failed to create EGLDisplay"); let egl = EGLDisplay::new(&surface, log.clone()).expect("Failed to create EGLDisplay");
@ -213,7 +212,7 @@ pub fn run_x11(log: Logger) {
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
let fps_texture = &backend_data.fps_texture; let fps_texture = &backend_data.fps_texture;
if let Err(err) = renderer.bind(present.buffer()) { if let Err(err) = renderer.bind(present.buffer().expect("gbm device was destroyed")) {
error!(log, "Error while binding buffer: {}", err); error!(log, "Error while binding buffer: {}", err);
} }

View File

@ -1,5 +1,6 @@
use std::io; use std::io;
use gbm::DeviceDestroyedError;
use nix::errno::Errno; use nix::errno::Errno;
use x11rb::rust_connection::{ConnectError, ConnectionError, ReplyError, ReplyOrIdError}; use x11rb::rust_connection::{ConnectError, ConnectionError, ReplyError, ReplyOrIdError};
@ -120,7 +121,11 @@ impl From<CreateWindowError> for X11Error {
pub enum AllocateBuffersError { pub enum AllocateBuffersError {
/// Failed to open the DRM device to allocate buffers. /// Failed to open the DRM device to allocate buffers.
#[error("Failed to open the DRM device to allocate buffers.")] #[error("Failed to open the DRM device to allocate buffers.")]
OpenDevice(io::Error), OpenDevice(#[from] io::Error),
/// The gbm device was destroyed
#[error("The gbm device was destroyed.")]
DeviceDestroyed(#[from] DeviceDestroyedError),
/// The device used to allocate buffers is not the correct drm node type. /// The device used to allocate buffers is not the correct drm node type.
#[error("The device used to allocate buffers is not the correct drm node type.")] #[error("The device used to allocate buffers is not the correct drm node type.")]
@ -128,7 +133,7 @@ pub enum AllocateBuffersError {
/// Exporting a dmabuf failed. /// Exporting a dmabuf failed.
#[error("Exporting a dmabuf failed.")] #[error("Exporting a dmabuf failed.")]
ExportDmabuf(GbmConvertError), ExportDmabuf(#[from] GbmConvertError),
} }
impl From<Errno> for AllocateBuffersError { impl From<Errno> for AllocateBuffersError {
@ -137,18 +142,6 @@ impl From<Errno> for AllocateBuffersError {
} }
} }
impl From<io::Error> for AllocateBuffersError {
fn from(err: io::Error) -> Self {
Self::OpenDevice(err)
}
}
impl From<GbmConvertError> for AllocateBuffersError {
fn from(err: GbmConvertError) -> Self {
Self::ExportDmabuf(err)
}
}
impl From<CreateDrmNodeError> for AllocateBuffersError { impl From<CreateDrmNodeError> for AllocateBuffersError {
fn from(err: CreateDrmNodeError) -> Self { fn from(err: CreateDrmNodeError) -> Self {
match err { match err {

View File

@ -83,7 +83,7 @@ use crate::{
}; };
use calloop::{EventSource, Poll, PostAction, Readiness, Token, TokenFactory}; use calloop::{EventSource, Poll, PostAction, Readiness, Token, TokenFactory};
use drm_fourcc::DrmFourcc; use drm_fourcc::DrmFourcc;
use gbm::BufferObjectFlags; use gbm::{BufferObject, BufferObjectFlags};
use nix::{ use nix::{
fcntl::{self, OFlag}, fcntl::{self, OFlag},
sys::stat::Mode, sys::stat::Mode,
@ -344,8 +344,8 @@ pub struct X11Surface {
format: DrmFourcc, format: DrmFourcc,
width: u16, width: u16,
height: u16, height: u16,
current: Dmabuf, current: BufferObject<Dmabuf>,
next: Dmabuf, next: BufferObject<Dmabuf>,
} }
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
@ -447,16 +447,17 @@ impl X11Surface {
} }
let size = backend.window().size(); let size = backend.window().size();
let current = device let mut current = device
.create_buffer_object::<()>(size.w as u32, size.h as u32, format, BufferObjectFlags::empty()) .create_buffer_object(size.w as u32, size.h as u32, format, BufferObjectFlags::empty())
.map_err(Into::<AllocateBuffersError>::into)? .map_err(Into::<AllocateBuffersError>::into)?;
.export() current
.set_userdata(current.export().map_err(Into::<AllocateBuffersError>::into)?)
.map_err(Into::<AllocateBuffersError>::into)?; .map_err(Into::<AllocateBuffersError>::into)?;
let next = device let mut next = device
.create_buffer_object::<()>(size.w as u32, size.h as u32, format, BufferObjectFlags::empty()) .create_buffer_object(size.w as u32, size.h as u32, format, BufferObjectFlags::empty())
.map_err(Into::<AllocateBuffersError>::into)? .map_err(Into::<AllocateBuffersError>::into)?;
.export() next.set_userdata(next.export().map_err(Into::<AllocateBuffersError>::into)?)
.map_err(Into::<AllocateBuffersError>::into)?; .map_err(Into::<AllocateBuffersError>::into)?;
let (sender, recv) = mpsc::channel(); let (sender, recv) = mpsc::channel();
@ -498,25 +499,30 @@ impl X11Surface {
} }
fn resize(&mut self, size: Size<u16, Logical>) -> Result<(), AllocateBuffersError> { fn resize(&mut self, size: Size<u16, Logical>) -> Result<(), AllocateBuffersError> {
let current = self let mut current = self
.device .device
.create_buffer_object::<()>( .create_buffer_object(
size.w as u32, size.w as u32,
size.h as u32, size.h as u32,
self.format, self.format,
BufferObjectFlags::empty(), BufferObjectFlags::empty(),
)? )
.export()?; .map_err(Into::<AllocateBuffersError>::into)?;
current
.set_userdata(current.export().map_err(Into::<AllocateBuffersError>::into)?)
.map_err(Into::<AllocateBuffersError>::into)?;
let next = self let mut next = self
.device .device
.create_buffer_object::<()>( .create_buffer_object(
size.w as u32, size.w as u32,
size.h as u32, size.h as u32,
self.format, self.format,
BufferObjectFlags::empty(), BufferObjectFlags::empty(),
)? )
.export()?; .map_err(Into::<AllocateBuffersError>::into)?;
next.set_userdata(next.export().map_err(Into::<AllocateBuffersError>::into)?)
.map_err(Into::<AllocateBuffersError>::into)?;
self.width = size.w; self.width = size.w;
self.height = size.h; self.height = size.h;
@ -556,8 +562,13 @@ impl Present<'_> {
/// Returns the next buffer that will be presented to the Window. /// Returns the next buffer that will be presented to the Window.
/// ///
/// You may bind this buffer to a renderer to render. /// You may bind this buffer to a renderer to render.
pub fn buffer(&self) -> Dmabuf { pub fn buffer(&self) -> Result<Dmabuf, AllocateBuffersError> {
self.surface.next.clone() Ok(self
.surface
.next
.userdata()
.map(|dmabuf| dmabuf.cloned())
.map(Option::unwrap)?)
} }
} }
@ -569,10 +580,17 @@ impl Drop for Present<'_> {
// Swap the buffers // Swap the buffers
mem::swap(&mut surface.next, &mut surface.current); mem::swap(&mut surface.next, &mut surface.current);
if let Ok(pixmap) = PixmapWrapper::with_dmabuf(&*connection, &surface.window, &surface.current) { match surface.current.userdata().map(Option::unwrap) {
Ok(dmabuf) => {
if let Ok(pixmap) = PixmapWrapper::with_dmabuf(&*connection, &surface.window, &dmabuf) {
// Now present the current buffer // Now present the current buffer
let _ = pixmap.present(&*connection, &surface.window); let _ = pixmap.present(&*connection, &surface.window);
} }
}
Err(_err) => {
todo!("Log error")
}
}
// 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();