Restore drm state correctly

This commit is contained in:
Drakulix 2017-12-02 17:07:52 +01:00
parent 33286df0d6
commit bd83bc5b2d
3 changed files with 42 additions and 3 deletions

View File

@ -47,3 +47,6 @@ backend_session_udev = ["libudev", "backend_session"]
backend_session_logind = ["backend_session", "dbus", "systemd"] backend_session_logind = ["backend_session", "dbus", "systemd"]
backend_udev = ["libudev", "backend_drm", "backend_session_udev"] backend_udev = ["libudev", "backend_drm", "backend_session_udev"]
renderer_glium = ["glium"] renderer_glium = ["glium"]
[patch.crates-io]
drm = { git = "https://github.com/Drakulix/drm-rs.git", branch = "feature/current_encoder" }

View File

@ -385,6 +385,7 @@ impl Drop for DrmBackend {
fn drop(&mut self) { fn drop(&mut self) {
// Drop framebuffers attached to the userdata of the gbm surface buffers. // Drop framebuffers attached to the userdata of the gbm surface buffers.
// (They don't implement drop, as they need the device) // (They don't implement drop, as they need the device)
let crtc = self.crtc;
self.graphics.rent_all_mut(|graphics| { self.graphics.rent_all_mut(|graphics| {
if let Some(fb) = graphics.gbm.surface.rent(|egl| { if let Some(fb) = graphics.gbm.surface.rent(|egl| {
if let Some(mut next) = egl.buffers.next_buffer.take() { if let Some(mut next) = egl.buffers.next_buffer.take() {
@ -406,6 +407,9 @@ impl Drop for DrmBackend {
// ignore failure at this point // ignore failure at this point
let _ = framebuffer::destroy(&*graphics.context.devices.drm, fb.handle()); let _ = framebuffer::destroy(&*graphics.context.devices.drm, fb.handle());
} }
// ignore failure at this point
let _ = crtc::clear_cursor(&*graphics.context.devices.drm, crtc);
}) })
} }
} }

View File

@ -262,6 +262,7 @@ use self::devices::{Context, Devices};
pub struct DrmDevice<B: Borrow<DrmBackend> + 'static> { pub struct DrmDevice<B: Borrow<DrmBackend> + 'static> {
context: Rc<Context>, context: Rc<Context>,
backends: HashMap<crtc::Handle, StateToken<B>>, backends: HashMap<crtc::Handle, StateToken<B>>,
old_state: HashMap<crtc::Handle, (crtc::Info, Vec<connector::Handle>)>,
active: bool, active: bool,
logger: ::slog::Logger, 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 // we want to mode-set, so we better be the master
drm.set_master().chain_err(|| ErrorKind::DrmMasterFailed)?; 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 // Open the gbm device from the drm device and create a context based on that
Ok(DrmDevice { Ok(DrmDevice {
context: Rc::new(Context::try_new( context: Rc::new(Context::try_new(
@ -384,6 +410,7 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
}, },
)?), )?),
backends: HashMap::new(), backends: HashMap::new(),
old_state,
active: true, active: true,
logger: log, logger: log,
}) })
@ -415,7 +442,7 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
for connector in &connectors { for connector in &connectors {
let con_info = connector::Info::load_from_device(self.context.head().head(), *connector) let con_info = connector::Info::load_from_device(self.context.head().head(), *connector)
.chain_err(|| { .chain_err(|| {
ErrorKind::DrmDev(format!("{:?}", self.context.head().head())) ErrorKind::DrmDev(format!("Loading connector info on {:?}", self.context.head().head()))
})?; })?;
// check the mode // check the mode
@ -429,14 +456,14 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
.iter() .iter()
.map(|encoder| { .map(|encoder| {
encoder::Info::load_from_device(self.context.head().head(), *encoder).chain_err(|| { 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>>>()?; .collect::<Result<Vec<encoder::Info>>>()?;
// and if any encoder supports the selected crtc // and if any encoder supports the selected crtc
let resource_handles = self.resource_handles().chain_err(|| { 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 if !encoders
.iter() .iter()
@ -507,6 +534,11 @@ impl<B: Borrow<DrmBackend> + 'static> Drop for DrmDevice<B> {
if Rc::strong_count(&self.context) > 1 { if Rc::strong_count(&self.context) > 1 {
panic!("Pending DrmBackends. Please free all backends before the DrmDevice gets destroyed"); 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() { if let Err(err) = self.drop_master() {
error!(self.logger, "Failed to drop drm master state. Error: {}", err); error!(self.logger, "Failed to drop drm master state. Error: {}", err);
} }