gbm: fix calling lock_front_buffer without eglSwapBuffers
This commit is contained in:
parent
8824e49b82
commit
e7575d08b8
|
@ -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)
|
||||
|
|
|
@ -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))),
|
||||
});
|
||||
|
|
|
@ -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
|
||||
// restart rendering loop, if it was previously running
|
||||
if let Some(Err(err)) = backend.current_frame_buffer.get().map(|fb|
|
||||
backend
|
||||
.crtc
|
||||
.page_flip(backend.current_frame_buffer.get().handle())
|
||||
{
|
||||
.page_flip(fb.handle())
|
||||
) {
|
||||
warn!(self.logger, "Failed to restart rendering loop. Error: {}", err);
|
||||
}
|
||||
// reset cursor
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue