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
|
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)
|
||||||
|
|
|
@ -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))),
|
||||||
});
|
});
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue