drm: adjust RenderSurface to swapchain changes and AsDmabuf

This commit is contained in:
Victor Brekenfeld 2021-05-13 15:09:23 +02:00
parent 5cf328a1b8
commit 2200d09841
1 changed files with 43 additions and 30 deletions

View File

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