From bd83bc5b2dcc06759f1eed499cea8c58623a05c8 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 2 Dec 2017 17:07:52 +0100 Subject: [PATCH] Restore drm state correctly --- Cargo.toml | 3 +++ src/backend/drm/backend.rs | 4 ++++ src/backend/drm/mod.rs | 38 +++++++++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8f7332b..8d079e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,3 +47,6 @@ backend_session_udev = ["libudev", "backend_session"] backend_session_logind = ["backend_session", "dbus", "systemd"] backend_udev = ["libudev", "backend_drm", "backend_session_udev"] renderer_glium = ["glium"] + +[patch.crates-io] +drm = { git = "https://github.com/Drakulix/drm-rs.git", branch = "feature/current_encoder" } diff --git a/src/backend/drm/backend.rs b/src/backend/drm/backend.rs index 9343003..4ff7533 100644 --- a/src/backend/drm/backend.rs +++ b/src/backend/drm/backend.rs @@ -385,6 +385,7 @@ impl Drop for DrmBackend { fn drop(&mut self) { // Drop framebuffers attached to the userdata of the gbm surface buffers. // (They don't implement drop, as they need the device) + let crtc = self.crtc; self.graphics.rent_all_mut(|graphics| { if let Some(fb) = graphics.gbm.surface.rent(|egl| { if let Some(mut next) = egl.buffers.next_buffer.take() { @@ -406,6 +407,9 @@ impl Drop for DrmBackend { // ignore failure at this point let _ = framebuffer::destroy(&*graphics.context.devices.drm, fb.handle()); } + + // ignore failure at this point + let _ = crtc::clear_cursor(&*graphics.context.devices.drm, crtc); }) } } diff --git a/src/backend/drm/mod.rs b/src/backend/drm/mod.rs index bca5375..aa63895 100644 --- a/src/backend/drm/mod.rs +++ b/src/backend/drm/mod.rs @@ -262,6 +262,7 @@ use self::devices::{Context, Devices}; pub struct DrmDevice + 'static> { context: Rc, backends: HashMap>, + old_state: HashMap)>, active: bool, logger: ::slog::Logger, } @@ -361,6 +362,31 @@ impl + Borrow + 'static> DrmDevice { // we want to mode-set, so we better be the master drm.set_master().chain_err(|| ErrorKind::DrmMasterFailed)?; + let mut old_state = HashMap::new(); + let res_handles = drm.resource_handles() + .chain_err(|| { + ErrorKind::DrmDev(format!("Loading drm resources on {:?}", drm)) + })?; + for &con in res_handles.connectors() { + let con_info = connector::Info::load_from_device(&drm, con) + .chain_err(|| { + ErrorKind::DrmDev(format!("Loading connector info on {:?}", drm)) + })?; + if let Some(enc) = con_info.current_encoder() { + let enc_info = encoder::Info::load_from_device(&drm, enc) + .chain_err(|| { + ErrorKind::DrmDev(format!("Loading encoder info on {:?}", drm)) + })?; + if let Some(crtc) = enc_info.current_crtc() { + let info = crtc::Info::load_from_device(&drm, crtc) + .chain_err(|| { + ErrorKind::DrmDev(format!("Loading crtc info on {:?}", drm)) + })?; + old_state.entry(crtc).or_insert((info, Vec::new())).1.push(con); + } + } + } + // Open the gbm device from the drm device and create a context based on that Ok(DrmDevice { context: Rc::new(Context::try_new( @@ -384,6 +410,7 @@ impl + Borrow + 'static> DrmDevice { }, )?), backends: HashMap::new(), + old_state, active: true, logger: log, }) @@ -415,7 +442,7 @@ impl + Borrow + 'static> DrmDevice { for connector in &connectors { let con_info = connector::Info::load_from_device(self.context.head().head(), *connector) .chain_err(|| { - ErrorKind::DrmDev(format!("{:?}", self.context.head().head())) + ErrorKind::DrmDev(format!("Loading connector info on {:?}", self.context.head().head())) })?; // check the mode @@ -429,14 +456,14 @@ impl + Borrow + 'static> DrmDevice { .iter() .map(|encoder| { encoder::Info::load_from_device(self.context.head().head(), *encoder).chain_err(|| { - ErrorKind::DrmDev(format!("{:?}", self.context.head().head())) + ErrorKind::DrmDev(format!("Loading encoder info on {:?}", self.context.head().head())) }) }) .collect::>>()?; // and if any encoder supports the selected crtc let resource_handles = self.resource_handles().chain_err(|| { - ErrorKind::DrmDev(format!("{:?}", self.context.head().head())) + ErrorKind::DrmDev(format!("Loading drm resources on {:?}", self.context.head().head())) })?; if !encoders .iter() @@ -507,6 +534,11 @@ impl + 'static> Drop for DrmDevice { if Rc::strong_count(&self.context) > 1 { panic!("Pending DrmBackends. Please free all backends before the DrmDevice gets destroyed"); } + for (handle, (info, connectors)) in self.old_state.drain() { + if let Err(err) = crtc::set(self.context.head().head(), handle, info.fb(), &connectors, info.position(), info.mode()) { + error!(self.logger, "Failed to reset crtc ({:?}). Error: {}", handle, err); + } + } if let Err(err) = self.drop_master() { error!(self.logger, "Failed to drop drm master state. Error: {}", err); }