diff --git a/src/backend/drm/render.rs b/src/backend/drm/render.rs index 1c3e3cd..bcddb09 100644 --- a/src/backend/drm/render.rs +++ b/src/backend/drm/render.rs @@ -1,5 +1,4 @@ use std::collections::HashSet; -use std::convert::TryInto; use std::os::unix::io::AsRawFd; use std::sync::Arc; @@ -11,8 +10,10 @@ use gbm::{BufferObject, BufferObjectFlags, Device as GbmDevice}; use wayland_server::protocol::{wl_buffer, wl_shm}; use super::{device::DevPath, surface::DrmSurfaceInternal, DrmError, DrmSurface}; -use crate::backend::allocator::{ - dmabuf::Dmabuf, Allocator, Buffer, Format, Fourcc, Modifier, Slot, Swapchain, SwapchainError, +use crate::backend::{ + allocator::{ + dmabuf::{AsDmabuf, Dmabuf}, Allocator, Buffer, Format, Fourcc, Modifier, Slot, Swapchain, + }, }; use crate::backend::egl::EGLBuffer; use crate::backend::renderer::{Bind, Renderer, Texture, Transform}; @@ -29,12 +30,12 @@ pub struct DrmRenderSurface< D: AsRawFd + 'static, A: Allocator, R: Bind, - B: Buffer + TryInto, + B: Buffer, > { _format: Format, - buffers: Buffers, - current_buffer: Option>>>, - swapchain: Swapchain>, Dmabuf>, + buffers: Buffers, + current_buffer: Option<(Slot>)>, Dmabuf)>, + swapchain: Swapchain>)>, renderer: R, drm: Arc>, } @@ -43,7 +44,7 @@ impl DrmRenderSurface where D: AsRawFd + 'static, A: Allocator, - B: Buffer + TryInto, + B: Buffer + AsDmabuf, R: Bind + Renderer, E1: std::error::Error + 'static, E2: std::error::Error + 'static, @@ -160,12 +161,12 @@ where let mut swapchain = Swapchain::new(allocator, mode.size().0 as u32, mode.size().1 as u32, format); // Test format - let buffer = swapchain.acquire()?.unwrap(); + let buffer = swapchain.acquire().map_err(Error::SwapchainError)?.unwrap(); + let dmabuf = buffer.export().map_err(Error::AsDmabufError)?; { - let dmabuf: Dmabuf = (*buffer).clone(); match renderer - .bind(dmabuf) + .bind(dmabuf.clone()) .map_err(Error::::RenderError) .and_then(|_| { renderer @@ -190,9 +191,9 @@ where } } - let bo = import_dmabuf(&drm, &gbm, &*buffer)?; + let bo = import_dmabuf(&drm, &gbm, &dmabuf)?; let fb = bo.userdata().unwrap().unwrap().fb; - buffer.set_userdata(bo); + buffer.set_userdata((dmabuf, bo)); match drm.test_buffer(fb, &mode, true) { Ok(_) => { @@ -329,7 +330,7 @@ impl Renderer for DrmRenderSurface where D: AsRawFd + 'static, A: Allocator, - B: Buffer + TryInto, + B: Buffer + AsDmabuf, R: Bind + Renderer, T: Texture, E1: std::error::Error + 'static, @@ -371,9 +372,13 @@ where return Ok(()); } - let slot = self.swapchain.acquire()?.ok_or(Error::NoFreeSlotsError)?; - self.renderer.bind((*slot).clone()).map_err(Error::RenderError)?; - self.current_buffer = Some(slot); + let slot = self.swapchain.acquire().map_err(Error::SwapchainError)?.ok_or(Error::NoFreeSlotsError)?; + let dmabuf = match &*slot.userdata() { + Some((buf, _)) => buf.clone(), + None => (*slot).export().map_err(Error::AsDmabufError)?, + }; + self.renderer.bind(dmabuf.clone()).map_err(Error::RenderError)?; + self.current_buffer = Some((slot, dmabuf)); self.renderer .begin(width, height, Transform::Flipped180 /* TODO: add Add implementation to add and correct _transform here */) .map_err(Error::RenderError) @@ -401,9 +406,10 @@ where let result = self.renderer.finish(); if result.is_ok() { + let (slot, dmabuf) = self.current_buffer.take().unwrap(); match self .buffers - .queue::(self.current_buffer.take().unwrap()) + .queue::(slot, dmabuf) { Ok(()) => {} Err(Error::DrmError(drm)) => return Err(drm.into()), @@ -426,23 +432,24 @@ impl Drop for FbHandle { } } -struct Buffers { +struct Buffers { gbm: GbmDevice, drm: Arc>, - _current_fb: Slot>>, - pending_fb: Option>>>, - queued_fb: Option>>>, + _current_fb: Slot>)>, + pending_fb: Option>)>>, + queued_fb: Option>)>>, } -impl Buffers +impl Buffers where + B: Buffer + AsDmabuf, D: AsRawFd + 'static, { pub fn new( drm: Arc>, gbm: GbmDevice, - slot: Slot>>, - ) -> Buffers { + slot: Slot>)>, + ) -> Buffers { Buffers { drm, gbm, @@ -454,16 +461,18 @@ where pub fn queue( &mut self, - slot: Slot>>, + slot: Slot>)>, + dmabuf: Dmabuf, ) -> Result<(), Error> where + B: AsDmabuf, E1: std::error::Error + 'static, E2: std::error::Error + 'static, E3: std::error::Error + 'static, { if slot.userdata().is_none() { - let bo = import_dmabuf(&self.drm, &self.gbm, &*slot)?; - slot.set_userdata(bo); + let bo = import_dmabuf(&self.drm, &self.gbm, &dmabuf)?; + slot.set_userdata((dmabuf, bo)); } self.queued_fb = Some(slot); @@ -499,7 +508,7 @@ where { // 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().as_ref().unwrap().userdata().unwrap().unwrap().fb; + let fb = slot.userdata().as_ref().unwrap().1.userdata().unwrap().unwrap().fb; let flip = if self.drm.commit_pending() { self.drm.commit(fb, true) @@ -604,7 +613,10 @@ where GbmError(#[from] std::io::Error), /// Error allocating or converting newly created buffers #[error("The swapchain encounted an error: {0}")] - SwapchainError(#[from] SwapchainError), + SwapchainError(#[source] E1), + /// Error exporting as Dmabuf + #[error("The allocated buffer could not be exported as a dmabuf: {0}")] + AsDmabufError(#[source] E2), /// Error during rendering #[error("The renderer encounted an error: {0}")] RenderError(#[source] E3), @@ -626,6 +638,7 @@ impl< Error::DrmError(err) => err.into(), Error::GbmError(err) => SwapBuffersError::ContextLost(Box::new(err)), Error::SwapchainError(err) => SwapBuffersError::ContextLost(Box::new(err)), + Error::AsDmabufError(err) => SwapBuffersError::ContextLost(Box::new(err)), Error::RenderError(err) => err.into(), } }