diff --git a/Cargo.lock b/Cargo.lock index 29aea613..2df71027 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -429,6 +429,7 @@ dependencies = [ "once_cell", "pango", "pangocairo", + "parking_lot", "pin-project", "rand", "renderdoc", @@ -477,6 +478,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "lock_api" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.14" @@ -621,6 +631,29 @@ dependencies = [ "system-deps", ] +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "pin-project" version = "1.0.10" @@ -747,6 +780,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "redox_syscall" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" version = "1.5.4" @@ -812,6 +854,12 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "serde" version = "1.0.136" @@ -999,6 +1047,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" + [[package]] name = "wio" version = "0.2.2" diff --git a/Cargo.toml b/Cargo.toml index ffab7a52..232aa9d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ i4config = { path = "i4config" } default-config = { path = "default-config" } x11rb = { version = "0.9.0", features = ["composite", "cursor"] } pin-project = "1.0.10" +parking_lot = "0.12.0" [build-dependencies] repc = "0.1.1" diff --git a/src/backends/metal/monitor.rs b/src/backends/metal/monitor.rs index 9ce8d92e..a3bdc518 100644 --- a/src/backends/metal/monitor.rs +++ b/src/backends/metal/monitor.rs @@ -85,20 +85,22 @@ impl MetalBackend { fn handle_drm_device_resume(self: &Rc, dev: &Rc, _fd: Rc) { log::info!("Device resumed: {}", dev.dev.devnode.to_bytes().as_bstr()); - let start = Instant::now(); if let Err(e) = self.resume_drm_device(dev) { log::error!("Could not resume drm device: {}", ErrorFmt(e)); } - log::info!("resume took {:?}", start.elapsed()); } fn handle_input_device_resume(self: &Rc, dev: &Rc, fd: Rc) { + let start = Instant::now(); log::info!("Device resumed: {}", dev.devnode.to_bytes().as_bstr()); - dev.fd.set(Some(fd)); + if let Some(old) = dev.fd.set(Some(fd)) { + self.state.fdcloser.close(old); + } let inputdev = match self.libinput.open(dev.devnode.as_c_str()) { Ok(d) => d, Err(_) => return, }; + log::info!("took {:?}", start.elapsed()); inputdev.device().set_slot(dev.slot); dev.inputdev.set(Some(inputdev)); } diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index cefaa7a7..95ba702c 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -20,7 +20,6 @@ use std::cell::Cell; use std::ffi::CString; use std::fmt::{Debug, Formatter}; use std::rc::Rc; -use std::time::Instant; use uapi::c; pub struct PendingDrmDevice { @@ -69,8 +68,6 @@ pub struct MetalConnector { pub id: DrmConnector, pub master: Rc, - pub active: Cell, - pub output_id: OutputId, pub crtcs: AHashMap>, @@ -226,7 +223,6 @@ fn create_connector( Ok(MetalConnector { id: connector, master: dev.master.clone(), - active: Cell::new(false), output_id: state.output_ids.next(), crtcs, mode: CloneCell::new(info.modes.first().cloned().map(|m| Rc::new(m))), @@ -593,56 +589,8 @@ impl MetalBackend { self.present(&connector); } - fn reuse_primary_planes(&self, dev: &MetalDrmDevice) -> AHashSet { - let mut crtc_primary_planes = AHashMap::new(); - for connector in dev.connectors.values() { - connector.active.set(false); - connector.primary_plane.set(None); - if let Some(crtc) = connector.crtc.get() { - crtc_primary_planes.insert(crtc.id, vec![]); - } - } + fn reset_planes(&self, dev: &MetalDrmDevice, changes: &mut Change) { for plane in dev.dev.planes.values() { - if plane.ty == PlaneType::Primary { - if let Some(ncp) = crtc_primary_planes.get_mut(&plane.crtc_id.value.get()) { - ncp.push(plane.clone()); - } - } - } - let mut reuse_possible = true; - for planes in crtc_primary_planes.values() { - if planes.len() > 1 { - reuse_possible = false; - break; - } - if let Some(plane) = planes.first() { - if !plane.formats.contains_key(&XRGB8888.drm) { - reuse_possible = false; - break; - } - } - } - let mut preserve = AHashSet::new(); - if !reuse_possible { - log::warn!("Not reusing primary planes"); - return preserve; - } - for connector in dev.connectors.values() { - if let Some(planes) = crtc_primary_planes.get(&connector.crtc_id.value.get()) { - if let Some(plane) = planes.first() { - connector.primary_plane.set(Some(plane.clone())); - preserve.insert(plane.id); - } - } - } - preserve - } - - fn reset_planes(&self, dev: &MetalDrmDevice, changes: &mut Change, preserve: &AHashSet) { - for plane in dev.dev.planes.values() { - if preserve.contains(&plane.id) { - continue; - } plane.crtc_id.value.set(DrmCrtc::NONE); changes.change_object(plane.id, |c| { c.change(plane.crtc_id.id, 0); @@ -686,33 +634,15 @@ impl MetalBackend { } } } - let preserve = self.reuse_primary_planes(dev); - self.reset_planes(dev, &mut changes, &preserve); - { - let mut connector: Vec<_> = dev.connectors.values().collect(); - connector.sort_by_key(|k| { - if k.primary_plane.get().is_some() { - 0 - } else { - 1 - } - }); - for connector in connector { - if let Err(e) = self.assign_connector_plane(dev, connector, &mut changes) { - log::error!("Could not assign a plane: {}", ErrorFmt(e)); - } - } - } + self.reset_planes(dev, &mut changes); for connector in dev.connectors.values() { - if !connector.active.get() { - connector.primary_plane.set(None); + if let Err(e) = self.assign_connector_plane(dev, connector, &mut changes) { + log::error!("Could not assign a plane: {}", ErrorFmt(e)); } } - let mut start = Instant::now(); if let Err(e) = changes.commit(flags, 0) { return Err(MetalError::Modeset(e)); } - log::info!("commit 2: {:?}", start.elapsed()); Ok(()) } @@ -892,34 +822,32 @@ impl MetalBackend { return Ok(()); } }; - let mut primary_plane = connector.primary_plane.get(); - if primary_plane.is_none() { + let primary_plane = 'primary_plane: { for plane in crtc.possible_planes.values() { if plane.ty == PlaneType::Primary && plane.crtc_id.value.get().is_none() && plane.formats.contains_key(&XRGB8888.drm) { - primary_plane = Some(plane.clone()); - break; + break 'primary_plane plane.clone(); } } - } - let primary_plane = match primary_plane { - Some(p) => p, - _ => return Err(MetalError::NoPrimaryPlaneForConnector), - }; - let format = ModifiedFormat { - format: XRGB8888, - modifier: INVALID_MODIFIER, + return Err(MetalError::NoPrimaryPlaneForConnector); }; + connector.buffers.set(None); let buffers = match connector.buffers.get() { Some(b) => b, - None => Rc::new(self.create_scanout_buffers( - dev, - &format, - mode.hdisplay as _, - mode.vdisplay as _, - )?), + None => { + let format = ModifiedFormat { + format: XRGB8888, + modifier: INVALID_MODIFIER, + }; + Rc::new(self.create_scanout_buffers( + dev, + &format, + mode.hdisplay as _, + mode.vdisplay as _, + )?) + }, }; changes.change_object(primary_plane.id, |c| { c.change(primary_plane.fb_id, buffers[0].drm.id().0 as _); @@ -944,7 +872,6 @@ impl MetalBackend { primary_plane.src_h.value.set((mode.vdisplay as u32) << 16); connector.buffers.set(Some(buffers)); connector.primary_plane.set(Some(primary_plane.clone())); - connector.active.set(true); Ok(()) } diff --git a/src/main.rs b/src/main.rs index e8d0c1ee..c6f891ea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,6 +55,7 @@ use std::ops::Deref; use std::rc::Rc; use thiserror::Error; use wheel::Wheel; +use crate::utils::fdcloser::FdCloser; #[macro_use] mod macros; @@ -101,6 +102,7 @@ mod xwayland; fn main() { env_logger::builder() + .format_timestamp_millis() .filter_level(LevelFilter::Info) .filter_level(LevelFilter::Debug) // .filter_level(LevelFilter::Trace) @@ -178,6 +180,7 @@ fn main_() -> Result<(), MainError> { pending_float_layout: Default::default(), pending_float_titles: Default::default(), dbus: Dbus::new(&engine, &run_toplevel), + fdcloser: FdCloser::new(), }); forker.install(&state); let config = config::ConfigProxy::default(&state); diff --git a/src/state.rs b/src/state.rs index f831b789..f993baa6 100644 --- a/src/state.rs +++ b/src/state.rs @@ -28,6 +28,8 @@ use crate::{ErrorFmt, Wheel, XkbContext}; use ahash::AHashMap; use std::cell::{Cell, RefCell}; use std::rc::Rc; +use std::sync::Arc; +use crate::utils::fdcloser::FdCloser; pub struct State { pub xkb_ctx: XkbContext, @@ -61,6 +63,7 @@ pub struct State { pub pending_float_layout: AsyncQueue>, pub pending_float_titles: AsyncQueue>, pub dbus: Dbus, + pub fdcloser: Arc, } pub struct InputDeviceData { diff --git a/src/utils/fdcloser.rs b/src/utils/fdcloser.rs new file mode 100644 index 00000000..e113ec41 --- /dev/null +++ b/src/utils/fdcloser.rs @@ -0,0 +1,47 @@ +use std::mem; +use std::rc::Rc; +use std::sync::Arc; +use parking_lot::{Condvar, Mutex}; +use uapi::OwnedFd; + +pub struct FdCloser { + fds: Mutex>, + cv: Condvar, +} + +impl FdCloser { + pub fn new() -> Arc { + let slf = Arc::new(Self { + fds: Mutex::new(Vec::new()), + cv: Condvar::new(), + }); + let slf2 = slf.clone(); + std::thread::spawn(move || { + let mut fds = vec![]; + let mut lock = slf2.fds.lock(); + loop { + mem::swap(&mut *lock, &mut fds); + if fds.len() > 0 { + drop(lock); + fds.clear(); + lock = slf2.fds.lock(); + } else { + slf2.cv.wait(&mut lock); + } + } + }); + slf + } + + pub fn close(&self, fd: Rc) { + match Rc::try_unwrap(fd) { + Ok(fd) => { + self.fds.lock().push(fd); + self.cv.notify_all(); + }, + Err(_e) => { + log::warn!("Could not close file descriptor in separate thread. There are still references."); + } + } + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 4f30b22a..1be9f5c9 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -22,3 +22,4 @@ pub mod tri; pub mod vasprintf; pub mod vec_ext; pub mod vecstorage; +pub mod fdcloser;