diff --git a/anvil/src/udev.rs b/anvil/src/udev.rs index 3b4d3ef..d61c392 100644 --- a/anvil/src/udev.rs +++ b/anvil/src/udev.rs @@ -264,7 +264,7 @@ pub fn run_udev(log: Logger) { event_loop.handle().remove(udev_event_source); } -pub type RenderSurface = GbmBufferedSurface; +pub type RenderSurface = GbmBufferedSurface>>, SessionFd>; struct SurfaceData { surface: RenderSurface, @@ -279,7 +279,7 @@ struct BackendData { #[cfg(feature = "debug")] fps_texture: Gles2Texture, renderer: Rc>, - gbm: GbmDevice, + gbm: Rc>>, registration_token: RegistrationToken, event_dispatcher: Dispatcher<'static, DrmDevice, AnvilState>, dev_id: u64, @@ -287,7 +287,7 @@ struct BackendData { fn scan_connectors( device: &mut DrmDevice, - gbm: &GbmDevice, + gbm: &Rc>>, renderer: &mut Gles2Renderer, output_map: &mut crate::output_map::OutputMap, signaler: &Signaler, @@ -483,6 +483,7 @@ impl AnvilState { } } + let gbm = Rc::new(RefCell::new(gbm)); let backends = Rc::new(RefCell::new(scan_connectors( &mut device, &gbm, diff --git a/src/backend/drm/surface/gbm.rs b/src/backend/drm/surface/gbm.rs index 7fc16c5..9ec9414 100644 --- a/src/backend/drm/surface/gbm.rs +++ b/src/backend/drm/surface/gbm.rs @@ -4,12 +4,12 @@ use std::sync::Arc; use drm::buffer::PlanarBuffer; use drm::control::{connector, crtc, framebuffer, plane, Device, Mode}; -use gbm::{BufferObject, Device as GbmDevice}; +use gbm::BufferObject; use crate::backend::allocator::{ dmabuf::{AsDmabuf, Dmabuf}, gbm::GbmConvertError, - Format, Fourcc, Modifier, Slot, Swapchain, + Allocator, Format, Fourcc, Modifier, Slot, Swapchain, }; use crate::backend::drm::{device::DevPath, surface::DrmSurfaceInternal, DrmError, DrmSurface}; use crate::backend::SwapBuffersError; @@ -18,17 +18,19 @@ use slog::{debug, error, o, trace, warn}; /// Simplified abstraction of a swapchain for gbm-buffers displayed on a [`DrmSurface`]. #[derive(Debug)] -pub struct GbmBufferedSurface { +pub struct GbmBufferedSurface> + 'static, D: AsRawFd + 'static> { current_fb: Slot>, pending_fb: Option>>, queued_fb: Option>>, next_fb: Option>>, - swapchain: Swapchain, BufferObject<()>>, + swapchain: Swapchain>, drm: Arc>, } -impl GbmBufferedSurface +impl GbmBufferedSurface where + A: Allocator>, + A::Error: std::error::Error + Send + Sync, D: AsRawFd + 'static, { /// Create a new `GbmBufferedSurface` from a given compatible combination @@ -40,10 +42,10 @@ where #[allow(clippy::type_complexity)] pub fn new( drm: DrmSurface, - allocator: GbmDevice, + allocator: A, mut renderer_formats: HashSet, log: L, - ) -> Result, Error> + ) -> Result, Error> where L: Into>, { @@ -121,7 +123,7 @@ where let mode = drm.pending_mode(); - let mut swapchain: Swapchain, BufferObject<()>> = Swapchain::new( + let mut swapchain: Swapchain> = Swapchain::new( allocator, mode.size().0 as u32, mode.size().1 as u32, @@ -130,7 +132,7 @@ where ); // Test format - let buffer = swapchain.acquire()?.unwrap(); + let buffer = swapchain.acquire().map_err(Error::GbmError)?.unwrap(); let format = Format { code, modifier: buffer.modifier().unwrap(), // no guarantee @@ -171,9 +173,13 @@ where /// /// *Note*: This function can be called multiple times and /// will return the same buffer until it is queued (see [`GbmBufferedSurface::queue_buffer`]). - pub fn next_buffer(&mut self) -> Result<(Dmabuf, u8), Error> { + pub fn next_buffer(&mut self) -> Result<(Dmabuf, u8), Error> { if self.next_fb.is_none() { - let slot = self.swapchain.acquire()?.ok_or(Error::NoFreeSlotsError)?; + let slot = self + .swapchain + .acquire() + .map_err(Error::GbmError)? + .ok_or(Error::NoFreeSlotsError)?; let maybe_buffer = slot.userdata().get::().cloned(); if maybe_buffer.is_none() { @@ -197,7 +203,7 @@ where /// *Note*: This function needs to be followed up with [`GbmBufferedSurface::frame_submitted`] /// when a vblank event is received, that denotes successful scanout of the buffer. /// Otherwise the underlying swapchain will eventually run out of buffers. - pub fn queue_buffer(&mut self) -> Result<(), Error> { + pub fn queue_buffer(&mut self) -> Result<(), Error> { self.queued_fb = self.next_fb.take(); if self.pending_fb.is_none() && self.queued_fb.is_some() { self.submit()?; @@ -210,7 +216,7 @@ where /// *Note*: Needs to be called, after the vblank event of the matching [`DrmDevice`](super::super::DrmDevice) /// was received after calling [`GbmBufferedSurface::queue_buffer`] on this surface. /// Otherwise the underlying swapchain will run out of buffers eventually. - pub fn frame_submitted(&mut self) -> Result<(), Error> { + pub fn frame_submitted(&mut self) -> Result<(), Error> { if let Some(mut pending) = self.pending_fb.take() { std::mem::swap(&mut pending, &mut self.current_fb); if self.queued_fb.is_some() { @@ -221,7 +227,7 @@ where Ok(()) } - fn submit(&mut self) -> Result<(), Error> { + fn submit(&mut self) -> Result<(), Error> { // yes it does not look like it, but both of these lines should be safe in all cases. let slot = self.queued_fb.take().unwrap(); let fb = slot.userdata().get::>().unwrap().fb; @@ -276,13 +282,13 @@ where /// (e.g. no suitable [`encoder`](drm::control::encoder) may be found) /// or is not compatible with the currently pending /// [`Mode`](drm::control::Mode). - pub fn add_connector(&self, connector: connector::Handle) -> Result<(), Error> { + pub fn add_connector(&self, connector: connector::Handle) -> Result<(), Error> { self.drm.add_connector(connector).map_err(Error::DrmError) } /// Tries to mark a [`connector`](drm::control::connector) /// for removal on the next commit. - pub fn remove_connector(&self, connector: connector::Handle) -> Result<(), Error> { + pub fn remove_connector(&self, connector: connector::Handle) -> Result<(), Error> { self.drm.remove_connector(connector).map_err(Error::DrmError) } @@ -292,7 +298,7 @@ where /// (e.g. no suitable [`encoder`](drm::control::encoder) may be found) /// or is not compatible with the currently pending /// [`Mode`](drm::control::Mode). - pub fn set_connectors(&self, connectors: &[connector::Handle]) -> Result<(), Error> { + pub fn set_connectors(&self, connectors: &[connector::Handle]) -> Result<(), Error> { self.drm.set_connectors(connectors).map_err(Error::DrmError) } @@ -314,7 +320,7 @@ where /// Fails if the mode is not compatible with the underlying /// [`crtc`](drm::control::crtc) or any of the /// pending [`connector`](drm::control::connector)s. - pub fn use_mode(&mut self, mode: Mode) -> Result<(), Error> { + pub fn use_mode(&mut self, mode: Mode) -> Result<(), Error> { self.drm.use_mode(mode).map_err(Error::DrmError)?; let (w, h) = mode.size(); self.swapchain.resize(w as _, h as _); @@ -334,9 +340,10 @@ impl Drop for FbHandle { } } -fn attach_framebuffer(drm: &Arc>, bo: &BufferObject<()>) -> Result, Error> +fn attach_framebuffer(drm: &Arc>, bo: &BufferObject<()>) -> Result, Error> where - A: AsRawFd + 'static, + E: std::error::Error + Send + Sync, + D: AsRawFd + 'static, { let modifier = match bo.modifier().unwrap() { Modifier::Invalid => None, @@ -385,7 +392,7 @@ where /// Errors thrown by a [`GbmBufferedSurface`] #[derive(Debug, thiserror::Error)] -pub enum Error { +pub enum Error { /// No supported pixel format for the given plane could be determined #[error("No supported plane buffer format found")] NoSupportedPlaneFormat, @@ -406,14 +413,14 @@ pub enum Error { DrmError(#[from] DrmError), /// Error importing the rendered buffer to libgbm for scan-out #[error("The underlying gbm device encounted an error: {0}")] - GbmError(#[from] std::io::Error), + GbmError(#[source] E), /// Error exporting as Dmabuf #[error("The allocated buffer could not be exported as a dmabuf: {0}")] AsDmabufError(#[from] GbmConvertError), } -impl From for SwapBuffersError { - fn from(err: Error) -> SwapBuffersError { +impl From> for SwapBuffersError { + fn from(err: Error) -> SwapBuffersError { match err { x @ Error::NoSupportedPlaneFormat | x @ Error::NoSupportedRendererFormat