Restore drm state correctly
This commit is contained in:
parent
33286df0d6
commit
bd83bc5b2d
|
@ -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" }
|
||||
|
|
|
@ -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);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -262,6 +262,7 @@ use self::devices::{Context, Devices};
|
|||
pub struct DrmDevice<B: Borrow<DrmBackend> + 'static> {
|
||||
context: Rc<Context>,
|
||||
backends: HashMap<crtc::Handle, StateToken<B>>,
|
||||
old_state: HashMap<crtc::Handle, (crtc::Info, Vec<connector::Handle>)>,
|
||||
active: bool,
|
||||
logger: ::slog::Logger,
|
||||
}
|
||||
|
@ -361,6 +362,31 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
|
|||
// 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<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
|
|||
},
|
||||
)?),
|
||||
backends: HashMap::new(),
|
||||
old_state,
|
||||
active: true,
|
||||
logger: log,
|
||||
})
|
||||
|
@ -415,7 +442,7 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
|
|||
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<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
|
|||
.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::<Result<Vec<encoder::Info>>>()?;
|
||||
|
||||
// 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<B: Borrow<DrmBackend> + 'static> Drop for DrmDevice<B> {
|
|||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue