drm: Fix drop order
This commit is contained in:
parent
2c73651327
commit
f2466c5c50
|
@ -10,7 +10,7 @@ repository = "https://github.com/Smithay/smithay"
|
||||||
members = [ "anvil" ]
|
members = [ "anvil" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wayland-server = "0.21.4"
|
wayland-server = "0.21.6"
|
||||||
wayland-sys = "0.21.3"
|
wayland-sys = "0.21.3"
|
||||||
wayland-commons = "0.21.1"
|
wayland-commons = "0.21.1"
|
||||||
nix = "0.11"
|
nix = "0.11"
|
||||||
|
|
|
@ -385,15 +385,19 @@ impl<S: SessionNotifier, Data: 'static> UdevHandler for UdevHandlerImpl<S, Data>
|
||||||
|
|
||||||
fn device_removed(&mut self, device: dev_t) {
|
fn device_removed(&mut self, device: dev_t) {
|
||||||
// drop the backends on this side
|
// drop the backends on this side
|
||||||
if let Some((id, evt_source, _)) = self.backends.remove(&device) {
|
if let Some((id, evt_source, renderers)) = self.backends.remove(&device) {
|
||||||
|
// drop surfaces
|
||||||
|
renderers.borrow_mut().clear();
|
||||||
|
debug!(self.logger, "Surfaces dropped");
|
||||||
|
|
||||||
// don't use hardware acceleration anymore, if this was the primary gpu
|
// don't use hardware acceleration anymore, if this was the primary gpu
|
||||||
let source = evt_source.clone_inner();
|
let device = Rc::try_unwrap(evt_source.remove().unwrap()).map_err(|_| "This should not happend").unwrap().into_inner().0;
|
||||||
let evented = source.borrow();
|
if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {
|
||||||
if (*evented).0.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {
|
|
||||||
*self.active_egl_context.borrow_mut() = None;
|
*self.active_egl_context.borrow_mut() = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.notifier.unregister(id);
|
self.notifier.unregister(id);
|
||||||
|
debug!(self.logger, "Dropping device");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ pub struct EglDevice<
|
||||||
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||||
D: Device + NativeDisplay<B> + 'static,
|
D: Device + NativeDisplay<B> + 'static,
|
||||||
> where
|
> where
|
||||||
|
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
|
||||||
<D as Device>::Surface: NativeSurface,
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
dev: Rc<EGLContext<B, D>>,
|
dev: Rc<EGLContext<B, D>>,
|
||||||
|
@ -34,6 +35,7 @@ pub struct EglDevice<
|
||||||
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> AsRawFd
|
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> AsRawFd
|
||||||
for EglDevice<B, D>
|
for EglDevice<B, D>
|
||||||
where
|
where
|
||||||
|
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
|
||||||
<D as Device>::Surface: NativeSurface,
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
@ -44,6 +46,7 @@ where
|
||||||
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
|
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
|
||||||
EglDevice<B, D>
|
EglDevice<B, D>
|
||||||
where
|
where
|
||||||
|
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
|
||||||
<D as Device>::Surface: NativeSurface,
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
/// Create a new `EglGbmDrmDevice` from an open drm node
|
/// Create a new `EglGbmDrmDevice` from an open drm node
|
||||||
|
@ -93,6 +96,7 @@ struct InternalDeviceHandler<
|
||||||
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||||
D: Device + NativeDisplay<B> + 'static,
|
D: Device + NativeDisplay<B> + 'static,
|
||||||
> where
|
> where
|
||||||
|
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
|
||||||
<D as Device>::Surface: NativeSurface,
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
handler: Box<DeviceHandler<Device = EglDevice<B, D>> + 'static>,
|
handler: Box<DeviceHandler<Device = EglDevice<B, D>> + 'static>,
|
||||||
|
@ -177,9 +181,21 @@ where
|
||||||
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
|
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
|
||||||
EGLGraphicsBackend for EglDevice<B, D>
|
EGLGraphicsBackend for EglDevice<B, D>
|
||||||
where
|
where
|
||||||
|
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
|
||||||
<D as Device>::Surface: NativeSurface,
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> {
|
fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> {
|
||||||
self.dev.bind_wl_display(display)
|
self.dev.bind_wl_display(display)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
|
||||||
|
Drop for EglDevice<B, D>
|
||||||
|
where
|
||||||
|
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
|
{
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.clear_handler();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
use std::os::unix::io::RawFd;
|
use std::os::unix::io::RawFd;
|
||||||
|
use drm::control::{crtc, connector, Mode};
|
||||||
|
|
||||||
use super::EglDevice;
|
use super::EglDevice;
|
||||||
use backend::drm::Device;
|
use backend::drm::Device;
|
||||||
|
@ -16,6 +17,7 @@ impl<
|
||||||
D: Device + NativeDisplay<B> + AsSessionObserver<S> + 'static,
|
D: Device + NativeDisplay<B> + AsSessionObserver<S> + 'static,
|
||||||
> AsSessionObserver<EglDeviceObserver<S>> for EglDevice<B, D>
|
> AsSessionObserver<EglDeviceObserver<S>> for EglDevice<B, D>
|
||||||
where
|
where
|
||||||
|
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
|
||||||
<D as Device>::Surface: NativeSurface,
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
fn observer(&mut self) -> EglDeviceObserver<S> {
|
fn observer(&mut self) -> EglDeviceObserver<S> {
|
||||||
|
|
|
@ -192,3 +192,9 @@ impl<D: RawDevice + ControlDevice + 'static> AsRawFd for GbmDevice<D> {
|
||||||
self.dev.borrow().as_raw_fd()
|
self.dev.borrow().as_raw_fd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<D: RawDevice + ControlDevice + 'static> Drop for GbmDevice<D> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.clear_handler();
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,22 +26,51 @@ pub mod session;
|
||||||
pub struct LegacyDrmDevice<A: AsRawFd + 'static> {
|
pub struct LegacyDrmDevice<A: AsRawFd + 'static> {
|
||||||
dev: Rc<Dev<A>>,
|
dev: Rc<Dev<A>>,
|
||||||
dev_id: dev_t,
|
dev_id: dev_t,
|
||||||
priviledged: bool,
|
|
||||||
active: Arc<AtomicBool>,
|
active: Arc<AtomicBool>,
|
||||||
old_state: HashMap<crtc::Handle, (crtc::Info, Vec<connector::Handle>)>,
|
|
||||||
backends: Rc<RefCell<HashMap<crtc::Handle, Weak<LegacyDrmSurfaceInternal<A>>>>>,
|
backends: Rc<RefCell<HashMap<crtc::Handle, Weak<LegacyDrmSurfaceInternal<A>>>>>,
|
||||||
handler: Option<RefCell<Box<DeviceHandler<Device = LegacyDrmDevice<A>>>>>,
|
handler: Option<RefCell<Box<DeviceHandler<Device = LegacyDrmDevice<A>>>>>,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(in crate::backend::drm) struct Dev<A: AsRawFd + 'static>(A);
|
pub(in crate::backend::drm) struct Dev<A: AsRawFd + 'static> {
|
||||||
|
fd: A,
|
||||||
|
priviledged: bool,
|
||||||
|
active: Arc<AtomicBool>,
|
||||||
|
old_state: HashMap<crtc::Handle, (crtc::Info, Vec<connector::Handle>)>,
|
||||||
|
logger: ::slog::Logger,
|
||||||
|
}
|
||||||
impl<A: AsRawFd + 'static> AsRawFd for Dev<A> {
|
impl<A: AsRawFd + 'static> AsRawFd for Dev<A> {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
self.0.as_raw_fd()
|
self.fd.as_raw_fd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<A: AsRawFd + 'static> BasicDevice for Dev<A> {}
|
impl<A: AsRawFd + 'static> BasicDevice for Dev<A> {}
|
||||||
impl<A: AsRawFd + 'static> ControlDevice for Dev<A> {}
|
impl<A: AsRawFd + 'static> ControlDevice for Dev<A> {}
|
||||||
|
impl<A: AsRawFd + 'static> Drop for Dev<A> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
info!(self.logger, "Dropping device: {:?}", self.dev_path());
|
||||||
|
if self.active.load(Ordering::SeqCst) {
|
||||||
|
let old_state = self.old_state.clone();
|
||||||
|
for (handle, (info, connectors)) in old_state {
|
||||||
|
if let Err(err) = crtc::set(
|
||||||
|
&*self,
|
||||||
|
handle,
|
||||||
|
info.fb(),
|
||||||
|
&connectors,
|
||||||
|
info.position(),
|
||||||
|
info.mode(),
|
||||||
|
) {
|
||||||
|
error!(self.logger, "Failed to reset crtc ({:?}). Error: {}", handle, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.priviledged {
|
||||||
|
if let Err(err) = self.drop_master() {
|
||||||
|
error!(self.logger, "Failed to drop drm master state. Error: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<A: AsRawFd + 'static> LegacyDrmDevice<A> {
|
impl<A: AsRawFd + 'static> LegacyDrmDevice<A> {
|
||||||
/// Create a new `LegacyDrmDevice` from an open drm node
|
/// Create a new `LegacyDrmDevice` from an open drm node
|
||||||
|
@ -53,47 +82,43 @@ impl<A: AsRawFd + 'static> LegacyDrmDevice<A> {
|
||||||
L: Into<Option<::slog::Logger>>,
|
L: Into<Option<::slog::Logger>>,
|
||||||
{
|
{
|
||||||
let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_drm"));
|
let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_drm"));
|
||||||
|
info!(log, "DrmDevice initializing");
|
||||||
|
|
||||||
let dev_id = fstat(dev.as_raw_fd())
|
let dev_id = fstat(dev.as_raw_fd())
|
||||||
.chain_err(|| ErrorKind::UnableToGetDeviceId)?
|
.chain_err(|| ErrorKind::UnableToGetDeviceId)?
|
||||||
.st_rdev;
|
.st_rdev;
|
||||||
|
|
||||||
let mut drm = LegacyDrmDevice {
|
let active = Arc::new(AtomicBool::new(true));
|
||||||
// Open the drm device and create a context based on that
|
let mut dev = Dev {
|
||||||
dev: Rc::new(Dev(dev)),
|
fd: dev,
|
||||||
dev_id,
|
|
||||||
priviledged: true,
|
priviledged: true,
|
||||||
active: Arc::new(AtomicBool::new(true)),
|
|
||||||
old_state: HashMap::new(),
|
old_state: HashMap::new(),
|
||||||
backends: Rc::new(RefCell::new(HashMap::new())),
|
active: active.clone(),
|
||||||
handler: None,
|
|
||||||
logger: log.clone(),
|
logger: log.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
info!(log, "DrmDevice initializing");
|
|
||||||
|
|
||||||
// we want to modeset, so we better be the master, if we run via a tty session
|
// we want to modeset, so we better be the master, if we run via a tty session
|
||||||
if drm.set_master().is_err() {
|
if dev.set_master().is_err() {
|
||||||
warn!(log, "Unable to become drm master, assuming unpriviledged mode");
|
warn!(log, "Unable to become drm master, assuming unpriviledged mode");
|
||||||
drm.priviledged = false;
|
dev.priviledged = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
let res_handles = ControlDevice::resource_handles(&drm).chain_err(|| {
|
let res_handles = ControlDevice::resource_handles(&dev).chain_err(|| {
|
||||||
ErrorKind::DrmDev(format!("Error loading drm resources on {:?}", drm.dev_path()))
|
ErrorKind::DrmDev(format!("Error loading drm resources on {:?}", dev.dev_path()))
|
||||||
})?;
|
})?;
|
||||||
for &con in res_handles.connectors() {
|
for &con in res_handles.connectors() {
|
||||||
let con_info = connector::Info::load_from_device(&drm, con).chain_err(|| {
|
let con_info = connector::Info::load_from_device(&dev, con).chain_err(|| {
|
||||||
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", drm.dev_path()))
|
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", dev.dev_path()))
|
||||||
})?;
|
})?;
|
||||||
if let Some(enc) = con_info.current_encoder() {
|
if let Some(enc) = con_info.current_encoder() {
|
||||||
let enc_info = encoder::Info::load_from_device(&drm, enc).chain_err(|| {
|
let enc_info = encoder::Info::load_from_device(&dev, enc).chain_err(|| {
|
||||||
ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", drm.dev_path()))
|
ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", dev.dev_path()))
|
||||||
})?;
|
})?;
|
||||||
if let Some(crtc) = enc_info.current_crtc() {
|
if let Some(crtc) = enc_info.current_crtc() {
|
||||||
let info = crtc::Info::load_from_device(&drm, crtc).chain_err(|| {
|
let info = crtc::Info::load_from_device(&dev, crtc).chain_err(|| {
|
||||||
ErrorKind::DrmDev(format!("Error loading crtc info on {:?}", drm.dev_path()))
|
ErrorKind::DrmDev(format!("Error loading crtc info on {:?}", dev.dev_path()))
|
||||||
})?;
|
})?;
|
||||||
drm.old_state
|
dev.old_state
|
||||||
.entry(crtc)
|
.entry(crtc)
|
||||||
.or_insert((info, Vec::new()))
|
.or_insert((info, Vec::new()))
|
||||||
.1
|
.1
|
||||||
|
@ -102,13 +127,21 @@ impl<A: AsRawFd + 'static> LegacyDrmDevice<A> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(drm)
|
Ok(LegacyDrmDevice {
|
||||||
|
// Open the drm device and create a context based on that
|
||||||
|
dev: Rc::new(dev),
|
||||||
|
dev_id,
|
||||||
|
active,
|
||||||
|
backends: Rc::new(RefCell::new(HashMap::new())),
|
||||||
|
handler: None,
|
||||||
|
logger: log.clone(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: AsRawFd + 'static> AsRawFd for LegacyDrmDevice<A> {
|
impl<A: AsRawFd + 'static> AsRawFd for LegacyDrmDevice<A> {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
self.dev.0.as_raw_fd()
|
self.dev.as_raw_fd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,28 +280,6 @@ impl<A: AsRawFd + 'static> RawDevice for LegacyDrmDevice<A> {
|
||||||
|
|
||||||
impl<A: AsRawFd + 'static> Drop for LegacyDrmDevice<A> {
|
impl<A: AsRawFd + 'static> Drop for LegacyDrmDevice<A> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.backends.borrow_mut().clear();
|
self.clear_handler();
|
||||||
if Rc::strong_count(&self.dev) > 1 {
|
|
||||||
panic!("Pending DrmBackends. You need to free all backends before the DrmDevice gets destroyed");
|
|
||||||
}
|
|
||||||
if self.active.load(Ordering::SeqCst) {
|
|
||||||
for (handle, (info, connectors)) in self.old_state.drain() {
|
|
||||||
if let Err(err) = crtc::set(
|
|
||||||
&*self.dev,
|
|
||||||
handle,
|
|
||||||
info.fb(),
|
|
||||||
&connectors,
|
|
||||||
info.position(),
|
|
||||||
info.mode(),
|
|
||||||
) {
|
|
||||||
error!(self.logger, "Failed to reset crtc ({:?}). Error: {}", handle, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if self.priviledged {
|
|
||||||
if let Err(err) = self.drop_master() {
|
|
||||||
error!(self.logger, "Failed to drop drm master state. Error: {}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ pub struct LegacyDrmDeviceObserver<A: AsRawFd + 'static> {
|
||||||
dev_id: dev_t,
|
dev_id: dev_t,
|
||||||
priviledged: bool,
|
priviledged: bool,
|
||||||
active: Arc<AtomicBool>,
|
active: Arc<AtomicBool>,
|
||||||
old_state: HashMap<crtc::Handle, (crtc::Info, Vec<connector::Handle>)>,
|
|
||||||
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<LegacyDrmSurfaceInternal<A>>>>>,
|
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<LegacyDrmSurfaceInternal<A>>>>>,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
@ -28,9 +27,8 @@ impl<A: AsRawFd + 'static> AsSessionObserver<LegacyDrmDeviceObserver<A>> for Leg
|
||||||
LegacyDrmDeviceObserver {
|
LegacyDrmDeviceObserver {
|
||||||
dev: Rc::downgrade(&self.dev),
|
dev: Rc::downgrade(&self.dev),
|
||||||
dev_id: self.dev_id,
|
dev_id: self.dev_id,
|
||||||
old_state: self.old_state.clone(),
|
|
||||||
active: self.active.clone(),
|
active: self.active.clone(),
|
||||||
priviledged: self.priviledged,
|
priviledged: self.dev.priviledged,
|
||||||
backends: Rc::downgrade(&self.backends),
|
backends: Rc::downgrade(&self.backends),
|
||||||
logger: self.logger.clone(),
|
logger: self.logger.clone(),
|
||||||
}
|
}
|
||||||
|
@ -50,18 +48,6 @@ impl<A: AsRawFd + 'static> SessionObserver for LegacyDrmDeviceObserver<A> {
|
||||||
let _ = crtc::clear_cursor(&*device, surface.crtc);
|
let _ = crtc::clear_cursor(&*device, surface.crtc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (handle, &(ref info, ref connectors)) in &self.old_state {
|
|
||||||
if let Err(err) = crtc::set(
|
|
||||||
&*device,
|
|
||||||
*handle,
|
|
||||||
info.fb(),
|
|
||||||
connectors,
|
|
||||||
info.position(),
|
|
||||||
info.mode(),
|
|
||||||
) {
|
|
||||||
error!(self.logger, "Failed to reset crtc ({:?}). Error: {}", handle, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.active.store(false, Ordering::SeqCst);
|
self.active.store(false, Ordering::SeqCst);
|
||||||
if self.priviledged {
|
if self.priviledged {
|
||||||
|
|
Loading…
Reference in New Issue