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
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)
} else {
self.page_flip(flip)

View File

@ -1,6 +1,6 @@
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 nix::libc::dev_t;
@ -127,6 +127,9 @@ impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D> {
) -> Result<GbmSurface<D>> {
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 surface = self
.dev
@ -138,19 +141,6 @@ impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D> {
BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
).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((
self.dev
.borrow()
@ -166,11 +156,10 @@ impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D> {
let backend = Rc::new(GbmSurfaceInternal {
dev: self.dev.clone(),
surface: RefCell::new(surface),
crtc: Device::create_surface(&mut **self.dev.borrow_mut(), crtc, mode, connectors)
.chain_err(|| ErrorKind::UnderlyingBackendError)?,
crtc: drm_surface,
cursor,
current_frame_buffer: Cell::new(fb),
front_buffer: Cell::new(front_bo),
current_frame_buffer: Cell::new(None),
front_buffer: Cell::new(None),
next_buffer: Cell::new(None),
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() {
for (crtc, backend) in backends.borrow().iter() {
if let Some(backend) = backend.upgrade() {
// restart rendering loop
if let Err(err) = &backend
.crtc
.page_flip(backend.current_frame_buffer.get().handle())
{
// restart rendering loop, if it was previously running
if let Some(Err(err)) = backend.current_frame_buffer.get().map(|fb|
backend
.crtc
.page_flip(fb.handle())
) {
warn!(self.logger, "Failed to restart rendering loop. Error: {}", err);
}
// 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) crtc: <D as Device>::Surface,
pub(super) cursor: Cell<(BufferObject<()>, (u32, u32))>,
pub(super) current_frame_buffer: Cell<framebuffer::Info>,
pub(super) front_buffer: Cell<SurfaceBufferHandle<framebuffer::Info>>,
pub(super) current_frame_buffer: Cell<Option<framebuffer::Info>>,
pub(super) front_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>,
pub(super) next_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>,
pub(super) logger: ::slog::Logger,
}
@ -31,7 +31,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
// this is called from the PageFlipHandler
if let Some(next_buffer) = self.next_buffer.replace(None) {
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
}
}
@ -83,7 +83,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
trace!(self.logger, "Queueing Page flip");
self.crtc.page_flip(fb.handle())?;
self.current_frame_buffer.set(fb);
self.current_frame_buffer.set(Some(fb));
Ok(())
}
@ -96,7 +96,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
// Recreate the surface and the related resources to match the new
// resolution.
debug!(self.logger, "Reinitializing surface for new mode: {}:{}", w, h);
debug!(self.logger, "(Re-)Initializing surface for mode: {}:{}", w, h);
let surface = self
.dev
.borrow_mut()
@ -107,8 +107,6 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
).chain_err(|| ErrorKind::SurfaceCreationFailed)?;
flip()?;
// Clean up next_buffer
{
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
// (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
.lock_front_buffer()
.chain_err(|| ErrorKind::FrontBufferLockFailed)?;
@ -140,10 +140,11 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
.commit(fb.handle())
.chain_err(|| ErrorKind::UnderlyingBackendError)?;
self.current_frame_buffer.set(Some(fb));
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()) {
warn!(
self.logger,
@ -283,8 +284,6 @@ impl<D: RawDevice + 'static> Drop for GbmSurfaceInternal<D> {
if let Ok(Some(fb)) = {
if let Some(mut next) = self.next_buffer.take() {
next.take_userdata()
} else if let Ok(mut next) = self.surface.borrow().lock_front_buffer() {
next.take_userdata()
} else {
Ok(None)
}
@ -293,7 +292,13 @@ impl<D: RawDevice + 'static> Drop for GbmSurfaceInternal<D> {
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
let _ = framebuffer::destroy(&self.crtc, fb.handle());
}