gbm: fix calling lock_front_buffer without eglSwapBuffers

This commit is contained in:
Victor Brekenfeld 2018-11-22 18:22:39 +01:00
parent 8824e49b82
commit e7575d08b8
4 changed files with 37 additions and 37 deletions

View File

@ -91,7 +91,12 @@ unsafe impl<D: RawDevice + 'static> NativeSurface for GbmSurface<D> {
where where
F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>, F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
{ {
if self.0.crtc.commit_pending() { if self.0.crtc.commit_pending() || {
let fb = self.0.front_buffer.take();
let res = fb.is_none();
self.0.front_buffer.set(fb);
res
} {
self.recreate(flip).map_err(|_| SwapBuffersError::ContextLost) self.recreate(flip).map_err(|_| SwapBuffersError::ContextLost)
} else { } else {
self.page_flip(flip) self.page_flip(flip)

View File

@ -1,6 +1,6 @@
use super::{Device, DeviceHandler, RawDevice, ResourceHandles, ResourceInfo, Surface}; use super::{Device, DeviceHandler, RawDevice, ResourceHandles, ResourceInfo, Surface};
use drm::control::{connector, crtc, framebuffer, Device as ControlDevice, Mode}; use drm::control::{connector, crtc, Device as ControlDevice, Mode};
use gbm::{self, BufferObjectFlags, Format as GbmFormat}; use gbm::{self, BufferObjectFlags, Format as GbmFormat};
use nix::libc::dev_t; use nix::libc::dev_t;
@ -127,6 +127,9 @@ impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D> {
) -> Result<GbmSurface<D>> { ) -> Result<GbmSurface<D>> {
info!(self.logger, "Initializing GbmSurface"); info!(self.logger, "Initializing GbmSurface");
let drm_surface = Device::create_surface(&mut **self.dev.borrow_mut(), crtc, mode, connectors)
.chain_err(|| ErrorKind::UnderlyingBackendError)?;
let (w, h) = mode.size(); let (w, h) = mode.size();
let surface = self let surface = self
.dev .dev
@ -138,19 +141,6 @@ impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D> {
BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING, BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
).chain_err(|| ErrorKind::SurfaceCreationFailed)?; ).chain_err(|| ErrorKind::SurfaceCreationFailed)?;
// init the first screen
// (must be done before calling page_flip for the first time)
let mut front_bo = surface
.lock_front_buffer()
.chain_err(|| ErrorKind::FrontBufferLockFailed)?;
debug!(self.logger, "FrontBuffer color format: {:?}", front_bo.format());
// we need a framebuffer for the front buffer
let fb = framebuffer::create(&*self.dev.borrow(), &*front_bo)
.chain_err(|| ErrorKind::UnderlyingBackendError)?;
front_bo.set_userdata(fb).unwrap();
let cursor = Cell::new(( let cursor = Cell::new((
self.dev self.dev
.borrow() .borrow()
@ -166,11 +156,10 @@ impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D> {
let backend = Rc::new(GbmSurfaceInternal { let backend = Rc::new(GbmSurfaceInternal {
dev: self.dev.clone(), dev: self.dev.clone(),
surface: RefCell::new(surface), surface: RefCell::new(surface),
crtc: Device::create_surface(&mut **self.dev.borrow_mut(), crtc, mode, connectors) crtc: drm_surface,
.chain_err(|| ErrorKind::UnderlyingBackendError)?,
cursor, cursor,
current_frame_buffer: Cell::new(fb), current_frame_buffer: Cell::new(None),
front_buffer: Cell::new(front_bo), front_buffer: Cell::new(None),
next_buffer: Cell::new(None), next_buffer: Cell::new(None),
logger: self.logger.new(o!("crtc" => format!("{:?}", crtc))), logger: self.logger.new(o!("crtc" => format!("{:?}", crtc))),
}); });

View File

@ -44,11 +44,12 @@ impl<S: SessionObserver + 'static, D: RawDevice + ControlDevice + AsSessionObser
if let Some(backends) = self.backends.upgrade() { if let Some(backends) = self.backends.upgrade() {
for (crtc, backend) in backends.borrow().iter() { for (crtc, backend) in backends.borrow().iter() {
if let Some(backend) = backend.upgrade() { if let Some(backend) = backend.upgrade() {
// restart rendering loop // restart rendering loop, if it was previously running
if let Err(err) = &backend if let Some(Err(err)) = backend.current_frame_buffer.get().map(|fb|
backend
.crtc .crtc
.page_flip(backend.current_frame_buffer.get().handle()) .page_flip(fb.handle())
{ ) {
warn!(self.logger, "Failed to restart rendering loop. Error: {}", err); warn!(self.logger, "Failed to restart rendering loop. Error: {}", err);
} }
// reset cursor // reset cursor

View File

@ -19,8 +19,8 @@ pub(super) struct GbmSurfaceInternal<D: RawDevice + 'static> {
pub(super) surface: RefCell<gbm::Surface<framebuffer::Info>>, pub(super) surface: RefCell<gbm::Surface<framebuffer::Info>>,
pub(super) crtc: <D as Device>::Surface, pub(super) crtc: <D as Device>::Surface,
pub(super) cursor: Cell<(BufferObject<()>, (u32, u32))>, pub(super) cursor: Cell<(BufferObject<()>, (u32, u32))>,
pub(super) current_frame_buffer: Cell<framebuffer::Info>, pub(super) current_frame_buffer: Cell<Option<framebuffer::Info>>,
pub(super) front_buffer: Cell<SurfaceBufferHandle<framebuffer::Info>>, pub(super) front_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>,
pub(super) next_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>, pub(super) next_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>,
pub(super) logger: ::slog::Logger, pub(super) logger: ::slog::Logger,
} }
@ -31,7 +31,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
// this is called from the PageFlipHandler // this is called from the PageFlipHandler
if let Some(next_buffer) = self.next_buffer.replace(None) { if let Some(next_buffer) = self.next_buffer.replace(None) {
trace!(self.logger, "Releasing old front buffer"); trace!(self.logger, "Releasing old front buffer");
self.front_buffer.set(next_buffer); self.front_buffer.set(Some(next_buffer));
// drop and release the old buffer // drop and release the old buffer
} }
} }
@ -83,7 +83,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
trace!(self.logger, "Queueing Page flip"); trace!(self.logger, "Queueing Page flip");
self.crtc.page_flip(fb.handle())?; self.crtc.page_flip(fb.handle())?;
self.current_frame_buffer.set(fb); self.current_frame_buffer.set(Some(fb));
Ok(()) Ok(())
} }
@ -96,7 +96,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
// Recreate the surface and the related resources to match the new // Recreate the surface and the related resources to match the new
// resolution. // resolution.
debug!(self.logger, "Reinitializing surface for new mode: {}:{}", w, h); debug!(self.logger, "(Re-)Initializing surface for mode: {}:{}", w, h);
let surface = self let surface = self
.dev .dev
.borrow_mut() .borrow_mut()
@ -107,8 +107,6 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING, BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
).chain_err(|| ErrorKind::SurfaceCreationFailed)?; ).chain_err(|| ErrorKind::SurfaceCreationFailed)?;
flip()?;
// Clean up next_buffer // Clean up next_buffer
{ {
if let Some(mut old_bo) = self.next_buffer.take() { if let Some(mut old_bo) = self.next_buffer.take() {
@ -123,9 +121,11 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
} }
} }
flip()?;
// Cleanup front_buffer and init the first screen on the new front_buffer // Cleanup front_buffer and init the first screen on the new front_buffer
// (must be done before calling page_flip for the first time) // (must be done before calling page_flip for the first time)
let mut old_front_bo = self.front_buffer.replace({ let old_front_bo = self.front_buffer.replace({
let mut front_bo = surface let mut front_bo = surface
.lock_front_buffer() .lock_front_buffer()
.chain_err(|| ErrorKind::FrontBufferLockFailed)?; .chain_err(|| ErrorKind::FrontBufferLockFailed)?;
@ -140,10 +140,11 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
.commit(fb.handle()) .commit(fb.handle())
.chain_err(|| ErrorKind::UnderlyingBackendError)?; .chain_err(|| ErrorKind::UnderlyingBackendError)?;
self.current_frame_buffer.set(Some(fb));
front_bo.set_userdata(fb).unwrap(); front_bo.set_userdata(fb).unwrap();
front_bo Some(front_bo)
}); });
if let Ok(Some(fb)) = old_front_bo.take_userdata() { if let Some(Ok(Some(fb))) = old_front_bo.map(|mut bo| bo.take_userdata()) {
if let Err(err) = framebuffer::destroy(&self.crtc, fb.handle()) { if let Err(err) = framebuffer::destroy(&self.crtc, fb.handle()) {
warn!( warn!(
self.logger, self.logger,
@ -283,8 +284,6 @@ impl<D: RawDevice + 'static> Drop for GbmSurfaceInternal<D> {
if let Ok(Some(fb)) = { if let Ok(Some(fb)) = {
if let Some(mut next) = self.next_buffer.take() { if let Some(mut next) = self.next_buffer.take() {
next.take_userdata() next.take_userdata()
} else if let Ok(mut next) = self.surface.borrow().lock_front_buffer() {
next.take_userdata()
} else { } else {
Ok(None) Ok(None)
} }
@ -293,7 +292,13 @@ impl<D: RawDevice + 'static> Drop for GbmSurfaceInternal<D> {
let _ = framebuffer::destroy(&self.crtc, fb.handle()); let _ = framebuffer::destroy(&self.crtc, fb.handle());
} }
if let Ok(Some(fb)) = self.front_buffer.get_mut().take_userdata() { if let Ok(Some(fb)) = {
if let Some(mut next) = self.front_buffer.take() {
next.take_userdata()
} else {
Ok(None)
}
} {
// ignore failure at this point // ignore failure at this point
let _ = framebuffer::destroy(&self.crtc, fb.handle()); let _ = framebuffer::destroy(&self.crtc, fb.handle());
} }