docs: Add more explanations to the gbm-drm-code

This commit is contained in:
Victor Brekenfeld 2020-06-05 21:52:01 +02:00
parent dcb3bb79a7
commit 978415987f
3 changed files with 11 additions and 1 deletions

View File

@ -30,6 +30,7 @@ impl<D: RawDevice + 'static> Backend for Gbm<D> {
type Surface = GbmSurface<D>; type Surface = GbmSurface<D>;
type Error = Error<<<D as Device>::Surface as Surface>::Error>; type Error = Error<<<D as Device>::Surface as Surface>::Error>;
// this creates an EGLDisplay for the gbm platform.
unsafe fn get_display<F>( unsafe fn get_display<F>(
display: ffi::NativeDisplayType, display: ffi::NativeDisplayType,
attribs: &[ffi::EGLint], attribs: &[ffi::EGLint],

View File

@ -134,6 +134,8 @@ impl<D: RawDevice + ControlDevice + 'static> DeviceHandler for InternalDeviceHan
if let Some(backends) = self.backends.upgrade() { if let Some(backends) = self.backends.upgrade() {
if let Some(surface) = backends.borrow().get(&crtc) { if let Some(surface) = backends.borrow().get(&crtc) {
if let Some(surface) = surface.upgrade() { if let Some(surface) = surface.upgrade() {
// here we unlock the buffer again, that was locked during rendering,
// to make sure it is always unlocked after a successful page_flip.
surface.unlock_buffer(); surface.unlock_buffer();
self.handler.vblank(crtc); self.handler.vblank(crtc);
} }

View File

@ -56,7 +56,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
.map_err(|_| Error::FrontBufferLockFailed)?; .map_err(|_| Error::FrontBufferLockFailed)?;
// create a framebuffer if the front buffer does not have one already // create a framebuffer if the front buffer does not have one already
// (they are reused by gbm) // (they are reused internally by gbm)
let maybe_fb = next_bo let maybe_fb = next_bo
.userdata() .userdata()
.map_err(|_| Error::InvalidInternalState)? .map_err(|_| Error::InvalidInternalState)?
@ -80,6 +80,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
} }
} }
// if we re-created the surface, we need to commit the new changes, as we might trigger a modeset
let result = if self.recreated.get() { let result = if self.recreated.get() {
debug!(self.logger, "Commiting new state"); debug!(self.logger, "Commiting new state");
self.crtc.commit(fb).map_err(Error::Underlying) self.crtc.commit(fb).map_err(Error::Underlying)
@ -88,6 +89,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
RawSurface::page_flip(&self.crtc, fb).map_err(Error::Underlying) RawSurface::page_flip(&self.crtc, fb).map_err(Error::Underlying)
}; };
// if it was successful, we can clear the re-created state
match result { match result {
Ok(_) => { Ok(_) => {
self.recreated.set(false); self.recreated.set(false);
@ -95,12 +97,15 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
Ok(()) Ok(())
} }
Err(err) => { Err(err) => {
// if there was an error we need to free the buffer again,
// otherwise we may never lock again.
self.unlock_buffer(); self.unlock_buffer();
Err(err) Err(err)
} }
} }
} }
// this function is called, if we e.g. need to create the surface to match a new mode.
pub fn recreate(&self) -> Result<(), Error<<<D as Device>::Surface as Surface>::Error>> { pub fn recreate(&self) -> Result<(), Error<<<D as Device>::Surface as Surface>::Error>> {
let (w, h) = self.pending_mode().size(); let (w, h) = self.pending_mode().size();
@ -129,6 +134,8 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
Ok(()) Ok(())
} }
// if the underlying drm-device is closed and re-opened framebuffers may get invalided.
// here we clear them just to be sure, they get recreated on the next page_flip.
pub fn clear_framebuffers(&self) { pub fn clear_framebuffers(&self) {
if let Some(Ok(Some(fb))) = self.next_buffer.take().map(|mut bo| bo.take_userdata()) { if let Some(Ok(Some(fb))) = self.next_buffer.take().map(|mut bo| bo.take_userdata()) {
if let Err(err) = self.crtc.destroy_framebuffer(fb) { if let Err(err) = self.crtc.destroy_framebuffer(fb) {