From c6c87bdaa16eb5abe777009c9a69900468fa3102 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Sun, 13 Nov 2022 13:23:15 +0100 Subject: [PATCH] backend: add DevicesEnumerated event --- jay-config/src/_private/client.rs | 11 +++++++++++ jay-config/src/_private/ipc.rs | 1 + jay-config/src/lib.rs | 8 ++++++++ src/backend.rs | 1 + src/backends/metal.rs | 3 +++ src/backends/metal/monitor.rs | 29 +++++++++++++++++++++++++---- src/backends/x.rs | 4 ++++ src/config.rs | 4 ++++ src/it/test_config.rs | 1 + src/state.rs | 6 ++++++ src/tasks/backend.rs | 1 + 11 files changed, 65 insertions(+), 4 deletions(-) diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index 21190d19..0f092d91 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -42,6 +42,7 @@ pub(crate) struct Client { on_new_input_device: RefCell>>, on_connector_connected: RefCell>>, on_graphics_initialized: Cell>>, + on_devices_enumerated: Cell>>, on_new_connector: RefCell>>, on_new_drm_device: RefCell>>, on_del_drm_device: RefCell>>, @@ -129,6 +130,7 @@ pub unsafe extern "C" fn init( on_new_input_device: Default::default(), on_connector_connected: Default::default(), on_graphics_initialized: Default::default(), + on_devices_enumerated: Default::default(), on_new_connector: Default::default(), on_new_drm_device: Default::default(), on_del_drm_device: Default::default(), @@ -550,6 +552,10 @@ impl Client { self.on_graphics_initialized.set(Some(Box::new(f))); } + pub fn on_devices_enumerated(&self, f: F) { + self.on_devices_enumerated.set(Some(Box::new(f))); + } + pub fn set_seat(&self, device: InputDevice, seat: Seat) { self.send(&ClientMessage::SetSeat { device, seat }) } @@ -734,6 +740,11 @@ impl Client { handler(); } } + ServerMessage::DevicesEnumerated => { + if let Some(handler) = self.on_devices_enumerated.take() { + handler(); + } + } } } diff --git a/jay-config/src/_private/ipc.rs b/jay-config/src/_private/ipc.rs index 60f66396..23c52a59 100644 --- a/jay-config/src/_private/ipc.rs +++ b/jay-config/src/_private/ipc.rs @@ -55,6 +55,7 @@ pub enum ServerMessage { device: DrmDevice, }, Idle, + DevicesEnumerated, } #[derive(Encode, BorrowDecode, Debug)] diff --git a/jay-config/src/lib.rs b/jay-config/src/lib.rs index 9a79920d..83fb35ee 100644 --- a/jay-config/src/lib.rs +++ b/jay-config/src/lib.rs @@ -139,3 +139,11 @@ impl Display for PciId { pub fn on_idle(f: F) { get!().on_idle(f) } + +/// Sets the callback to be called when all devices have been enumerated. +/// +/// This callback is only invoked once during the lifetime of the compositor. This is a +/// good place to select the DRM device used for rendering. +pub fn on_devices_enumerated(f: F) { + get!().on_devices_enumerated(f) +} diff --git a/src/backend.rs b/src/backend.rs index dab3c2de..57b78438 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -142,6 +142,7 @@ pub enum BackendEvent { NewDrmDevice(Rc), NewConnector(Rc), NewInputDevice(Rc), + DevicesEnumerated, } #[derive(Debug, Copy, Clone, Eq, PartialEq)] diff --git a/src/backends/metal.rs b/src/backends/metal.rs index 6bc130c7..6b0d666c 100644 --- a/src/backends/metal.rs +++ b/src/backends/metal.rs @@ -31,6 +31,7 @@ use { clonecell::{CloneCell, UnsafeCellCloneSafe}, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, + numcell::NumCell, oserror::OsError, smallmap::SmallMap, syncqueue::SyncQueue, @@ -226,6 +227,7 @@ pub async fn create(state: &Rc) -> Result, MetalError> { input_devices: Default::default(), drm_devices: Default::default(), pending_drm_devices: Default::default(), + num_pending_devices: Default::default(), }); let udev = Rc::new(Udev::new()?); let monitor = Rc::new(udev.create_monitor()?); @@ -309,6 +311,7 @@ struct DeviceHolder { input_devices: RefCell>>>, drm_devices: CopyHashMap>, pending_drm_devices: CopyHashMap, + num_pending_devices: NumCell, } impl LibInputAdapter for DeviceHolder { diff --git a/src/backends/metal/monitor.rs b/src/backends/metal/monitor.rs index 305bda02..603f73c8 100644 --- a/src/backends/metal/monitor.rs +++ b/src/backends/metal/monitor.rs @@ -5,11 +5,13 @@ use { video::{MetalDrmDeviceData, PendingDrmDevice}, MetalBackend, MetalDevice, MetalError, MetalInputDevice, }, - dbus::TRUE, + dbus::{DbusError, TRUE}, udev::UdevDevice, utils::{bitflags::BitflagsExt, errorfmt::ErrorFmt, nonblock::set_nonblock}, video::drm::DrmMaster, - wire_dbus::org::freedesktop::login1::session::{PauseDevice, ResumeDevice}, + wire_dbus::org::freedesktop::login1::session::{ + PauseDevice, ResumeDevice, TakeDeviceReply, + }, }, bstr::ByteSlice, std::{cell::Cell, rc::Rc}, @@ -199,7 +201,7 @@ impl MetalBackend { }; self.device_holder.pending_drm_devices.set(devnum, dev); let slf = self.clone(); - self.session.get_device(devnum, move |res| { + self.get_device(devnum, move |res| { let dev = match slf.device_holder.pending_drm_devices.remove(&devnum) { Some(d) if d.id == id => d, _ => return, @@ -303,7 +305,7 @@ impl MetalBackend { self.device_holder .devices .set(devnum, MetalDevice::Input(dev)); - self.session.get_device(devnum, move |res| { + self.get_device(devnum, move |res| { let id = &slf.device_holder.devices; let mut slots = slf.device_holder.input_devices.borrow_mut(); let dev = 'dev: { @@ -345,4 +347,23 @@ impl MetalBackend { }); None } + + fn get_device(self: &Rc, dev: c::dev_t, f: F) + where + F: FnOnce(Result<&TakeDeviceReply, DbusError>) + 'static, + { + self.device_holder.num_pending_devices.fetch_add(1); + let slf = self.clone(); + self.session.get_device(dev, move |res| { + let rem = slf.device_holder.num_pending_devices.fetch_sub(1); + f(res); + if rem == 1 { + slf.state + .backend_events + .push(BackendEvent::DevicesEnumerated); + // Set to 1 to ensure this branch is never taken again. + slf.device_holder.num_pending_devices.set(1); + } + }) + } } diff --git a/src/backends/x.rs b/src/backends/x.rs index 0de49b0c..bd8aeb4f 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -299,6 +299,10 @@ impl XBackend { self.active_output(output).await; } + self.state + .backend_events + .push(BackendEvent::DevicesEnumerated); + pending().await } diff --git a/src/config.rs b/src/config.rs index 00f9cb46..04277eeb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -122,6 +122,10 @@ impl ConfigProxy { self.send(&ServerMessage::GraphicsInitialized); } + pub fn devices_enumerated(&self) { + self.send(&ServerMessage::DevicesEnumerated); + } + pub fn clear(&self) { self.send(&ServerMessage::Clear); } diff --git a/src/it/test_config.rs b/src/it/test_config.rs index b662e033..9bb1c8b6 100644 --- a/src/it/test_config.rs +++ b/src/it/test_config.rs @@ -105,6 +105,7 @@ unsafe extern "C" fn handle_msg(data: *const u8, msg: *const u8, size: usize) { ServerMessage::NewDrmDev { .. } => {} ServerMessage::DelDrmDev { .. } => {} ServerMessage::Idle => {} + ServerMessage::DevicesEnumerated => {} } } diff --git a/src/state.rs b/src/state.rs index dcf899d2..604021f1 100644 --- a/src/state.rs +++ b/src/state.rs @@ -268,6 +268,12 @@ impl State { self.reload_cursors(); } + pub fn devices_enumerated(&self) { + if let Some(config) = self.config.get() { + config.devices_enumerated() + } + } + pub fn set_render_ctx(&self, ctx: Option<&Rc>) { self.render_ctx.set(ctx.cloned()); self.render_ctx_version.fetch_add(1); diff --git a/src/tasks/backend.rs b/src/tasks/backend.rs index 291a1af4..e34710ed 100644 --- a/src/tasks/backend.rs +++ b/src/tasks/backend.rs @@ -25,6 +25,7 @@ impl BackendEventHandler { BackendEvent::NewConnector(connector) => connector::handle(&self.state, &connector), BackendEvent::NewInputDevice(s) => input_device::handle(&self.state, s), BackendEvent::NewDrmDevice(d) => drmdev::handle(&self.state, d), + BackendEvent::DevicesEnumerated => self.state.devices_enumerated(), } } }