x11: emit errors when presentation fails

This commit is contained in:
i509VCB 2021-12-17 19:14:14 -06:00
parent d6051a873f
commit ed105528de
No known key found for this signature in database
GPG Key ID: EE47F5EFC5EE8CDC
4 changed files with 54 additions and 93 deletions

View File

@ -73,6 +73,7 @@
- EGLBufferReader now checks if buffers are alive before using them.
- LibSeat no longer panics on seat disable event.
- X11 backend will report an error when trying to present a dmabuf fails.
### Anvil

View File

@ -29,54 +29,23 @@
use std::sync::atomic::Ordering;
use super::{Window, X11Error};
use super::{PresentError, Window, X11Error};
use drm_fourcc::DrmFourcc;
use nix::fcntl;
use x11rb::connection::Connection;
use x11rb::protocol::dri3::ConnectionExt as _;
use x11rb::protocol::present::{self, ConnectionExt};
use x11rb::protocol::xproto::PixmapWrapper;
use x11rb::rust_connection::{ConnectionError, ReplyOrIdError};
use x11rb::utils::RawFdContainer;
use x11rb::{
connection::Connection,
protocol::{
dri3::ConnectionExt as _,
present::{self, ConnectionExt},
xproto::PixmapWrapper,
},
utils::RawFdContainer,
};
use crate::backend::allocator::dmabuf::Dmabuf;
use crate::backend::allocator::Buffer;
use crate::backend::allocator::{dmabuf::Dmabuf, Buffer};
// Shm can be easily supported in the future using, xcb_shm_create_pixmap.
#[derive(Debug, thiserror::Error)]
pub enum CreatePixmapError {
#[error("An x11 protocol error occured")]
Protocol(X11Error),
#[error("The Dmabuf had too many planes")]
TooManyPlanes,
#[error("Duplicating the file descriptors for the dmabuf handles failed")]
DupFailed(String),
#[error("Buffer had incorrect format, expected: {0}")]
IncorrectFormat(DrmFourcc),
}
impl From<X11Error> for CreatePixmapError {
fn from(e: X11Error) -> Self {
CreatePixmapError::Protocol(e)
}
}
impl From<ReplyOrIdError> for CreatePixmapError {
fn from(e: ReplyOrIdError) -> Self {
X11Error::from(e).into()
}
}
impl From<ConnectionError> for CreatePixmapError {
fn from(e: ConnectionError) -> Self {
X11Error::from(e).into()
}
}
pub trait PixmapWrapperExt<'c, C>
where
C: Connection,
@ -88,7 +57,7 @@ where
connection: &'c C,
window: &Window,
dmabuf: &Dmabuf,
) -> Result<PixmapWrapper<'c, C>, CreatePixmapError>;
) -> Result<PixmapWrapper<'c, C>, X11Error>;
/// Presents the pixmap to the window.
///
@ -108,9 +77,9 @@ where
connection: &'c C,
window: &Window,
dmabuf: &Dmabuf,
) -> Result<PixmapWrapper<'c, C>, CreatePixmapError> {
) -> Result<PixmapWrapper<'c, C>, X11Error> {
if dmabuf.format().code != window.format() {
return Err(CreatePixmapError::IncorrectFormat(window.format()));
return Err(PresentError::IncorrectFormat(window.format()).into());
}
let mut fds = Vec::new();
@ -121,7 +90,7 @@ where
handle,
fcntl::FcntlArg::F_DUPFD_CLOEXEC(3), // Set to 3 so the fd cannot become stdin, stdout or stderr
)
.map_err(|e| CreatePixmapError::DupFailed(e.to_string()))?;
.map_err(|e| PresentError::DupFailed(e.to_string()))?;
fds.push(RawFdContainer::new(fd))
}
@ -129,7 +98,7 @@ where
// We need dri3 >= 1.2 in order to use the enhanced dri3_pixmap_from_buffers function.
let xid = if window.0.extensions.dri3 >= Some((1, 2)) {
if dmabuf.num_planes() > 4 {
return Err(CreatePixmapError::TooManyPlanes);
return Err(PresentError::TooManyPlanes.into());
}
let xid = connection.generate_id()?;
@ -165,7 +134,7 @@ where
} else {
// Old codepath can only create a pixmap using one plane from a dmabuf.
if dmabuf.num_planes() != 1 {
return Err(CreatePixmapError::TooManyPlanes);
return Err(PresentError::TooManyPlanes.into());
}
let xid = connection.generate_id()?;

View File

@ -6,24 +6,26 @@ use x11rb::rust_connection::{ConnectError, ConnectionError, ReplyError, ReplyOrI
use crate::backend::{allocator::gbm::GbmConvertError, drm::CreateDrmNodeError};
use super::PresentError;
/// An error emitted by the X11 backend during setup.
#[derive(Debug, thiserror::Error)]
pub enum X11Error {
/// Connecting to the X server failed.
#[error("Connecting to the X server failed")]
ConnectionFailed(ConnectError),
ConnectionFailed(#[from] ConnectError),
/// A required X11 extension was not present or has the right version.
#[error("{0}")]
MissingExtension(MissingExtensionError),
MissingExtension(#[from] MissingExtensionError),
/// Some protocol error occurred during setup.
#[error("Some protocol error occurred during setup")]
Protocol(ReplyOrIdError),
Protocol(#[from] ReplyOrIdError),
/// Creating the window failed.
#[error("Creating the window failed")]
CreateWindow(CreateWindowError),
CreateWindow(#[from] CreateWindowError),
/// An X11 surface already exists for this window.
#[error("An X11 surface already exists for this window")]
@ -42,13 +44,11 @@ pub enum X11Error {
/// Failed to allocate buffers needed to present to the window.
#[error("Failed to allocate buffers needed to present to the window")]
Allocation(AllocateBuffersError),
}
Allocation(#[from] AllocateBuffersError),
impl From<ConnectError> for X11Error {
fn from(err: ConnectError) -> Self {
Self::ConnectionFailed(err)
}
/// Error while presenting to a window.
#[error(transparent)]
Present(#[from] PresentError),
}
impl From<ReplyError> for X11Error {
@ -63,12 +63,6 @@ impl From<ConnectionError> for X11Error {
}
}
impl From<ReplyOrIdError> for X11Error {
fn from(err: ReplyOrIdError) -> Self {
Self::Protocol(err)
}
}
/// An error that occurs when a required X11 extension is not present.
#[derive(Debug, thiserror::Error)]
pub enum MissingExtensionError {
@ -99,12 +93,6 @@ pub enum MissingExtensionError {
},
}
impl From<MissingExtensionError> for X11Error {
fn from(err: MissingExtensionError) -> Self {
Self::MissingExtension(err)
}
}
/// An error which may occur when creating an X11 window.
#[derive(Debug, thiserror::Error)]
pub enum CreateWindowError {
@ -117,12 +105,6 @@ pub enum CreateWindowError {
NoVisual,
}
impl From<CreateWindowError> for X11Error {
fn from(err: CreateWindowError) -> Self {
Self::CreateWindow(err)
}
}
/// An error which may occur when allocating buffers for presentation to the window.
#[derive(Debug, thiserror::Error)]
pub enum AllocateBuffersError {
@ -165,9 +147,3 @@ impl From<CreateDrmNodeError> for AllocateBuffersError {
}
}
}
impl From<AllocateBuffersError> for X11Error {
fn from(err: AllocateBuffersError) -> Self {
Self::Allocation(err)
}
}

View File

@ -19,6 +19,24 @@ use crate::{
utils::{Logical, Size},
};
use super::X11Error;
/// An error that may occur when presenting.
#[derive(Debug, thiserror::Error)]
pub enum PresentError {
/// The dmabuf being presented has too many planes.
#[error("The Dmabuf had too many planes")]
TooManyPlanes,
/// Duplicating the dmabuf handles failed.
#[error("Duplicating the file descriptors for the dmabuf handles failed")]
DupFailed(String),
/// The format dmabuf presented does not match the format of the window.
#[error("Buffer had incorrect format, expected: {0}")]
IncorrectFormat(DrmFourcc),
}
/// An X11 surface which uses GBM to allocate and present buffers.
#[derive(Debug)]
pub struct X11Surface {
@ -67,7 +85,7 @@ impl X11Surface {
/// or [`reset_buffers`](Self::reset_buffer) is used to reset the buffers.
pub fn buffer(&mut self) -> Result<(Dmabuf, u8), AllocateBuffersError> {
if let Some(new_size) = self.resize.try_iter().last() {
self.resize(new_size)?;
self.resize(new_size);
}
if self.buffer.is_none() {
@ -92,7 +110,7 @@ impl X11Surface {
}
/// Consume and submit the buffer to the window.
pub fn submit(&mut self) -> Result<(), AllocateBuffersError> {
pub fn submit(&mut self) -> Result<(), X11Error> {
if let Some(connection) = self.connection.upgrade() {
// Get a new buffer
let mut next = self
@ -107,15 +125,14 @@ impl X11Surface {
}
let window = self.window().ok_or(AllocateBuffersError::WindowDestroyed)?;
if let Ok(pixmap) = PixmapWrapper::with_dmabuf(
let pixmap = PixmapWrapper::with_dmabuf(
&*connection,
window.as_ref(),
next.userdata().get::<Dmabuf>().unwrap(),
) {
)?;
// Now present the current buffer
let _ = pixmap.present(&*connection, window.as_ref());
}
let _ = pixmap.present(&*connection, window.as_ref())?;
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.
@ -130,13 +147,11 @@ impl X11Surface {
self.buffer = None;
}
fn resize(&mut self, size: Size<u16, Logical>) -> Result<(), AllocateBuffersError> {
fn resize(&mut self, size: Size<u16, Logical>) {
self.swapchain.resize(size.w as u32, size.h as u32);
self.buffer = None;
self.width = size.w;
self.height = size.h;
Ok(())
}
}