diff options
| author | Shawn Wallace <yungwallace@live.com> | 2024-02-11 13:15:03 -0500 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-02-12 09:48:54 +0400 |
| commit | 385454378bfde6f69246d5f11362c8d25a30d1eb (patch) | |
| tree | c99cc6f0a49126bcadc32c84eb90035db11c6b41 | |
| parent | 18f06a7acd79feb16dc667b68a1ffd0d59e234c8 (diff) | |
| download | niri-385454378bfde6f69246d5f11362c8d25a30d1eb.tar.gz niri-385454378bfde6f69246d5f11362c8d25a30d1eb.tar.bz2 niri-385454378bfde6f69246d5f11362c8d25a30d1eb.zip | |
Implement DRM leasing
Closes #178
| -rw-r--r-- | src/backend/tty.rs | 87 | ||||
| -rw-r--r-- | src/handlers/mod.rs | 56 |
2 files changed, 137 insertions, 6 deletions
diff --git a/src/backend/tty.rs b/src/backend/tty.rs index ed6b832b..9caaf440 100644 --- a/src/backend/tty.rs +++ b/src/backend/tty.rs @@ -41,6 +41,9 @@ use smithay::reexports::wayland_protocols; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; use smithay::utils::DeviceFd; use smithay::wayland::dmabuf::{DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal}; +use smithay::wayland::drm_lease::{ + DrmLease, DrmLeaseBuilder, DrmLeaseRequest, DrmLeaseState, LeaseRejected, +}; use smithay_drm_extras::drm_scanner::{DrmScanEvent, DrmScanner}; use smithay_drm_extras::edid::EdidInfo; use wayland_protocols::wp::linux_dmabuf::zv1::server::zwp_linux_dmabuf_feedback_v1::TrancheFlags; @@ -105,7 +108,7 @@ type GbmDrmCompositor = DrmCompositor< DrmDeviceFd, >; -struct OutputDevice { +pub struct OutputDevice { token: RegistrationToken, render_node: DrmNode, drm_scanner: DrmScanner, @@ -114,6 +117,42 @@ struct OutputDevice { // See https://github.com/Smithay/smithay/issues/1102. drm: DrmDevice, gbm: GbmDevice<DrmDeviceFd>, + + pub drm_lease_state: DrmLeaseState, + non_desktop_connectors: HashSet<(connector::Handle, crtc::Handle)>, + active_leases: Vec<DrmLease>, +} + +impl OutputDevice { + pub fn lease_request( + &self, + request: DrmLeaseRequest, + ) -> Result<DrmLeaseBuilder, LeaseRejected> { + let mut builder = DrmLeaseBuilder::new(&self.drm); + for connector in request.connectors { + let (_, crtc) = self + .non_desktop_connectors + .iter() + .find(|(conn, _)| connector == *conn) + .ok_or_else(|| { + warn!("Attempted to lease connector that is not non-desktop"); + LeaseRejected::default() + })?; + builder.add_connector(connector); + builder.add_crtc(*crtc); + let planes = self.drm.planes(crtc).map_err(LeaseRejected::with_cause)?; + builder.add_plane(planes.primary.handle); + } + Ok(builder) + } + + pub fn new_lease(&mut self, lease: DrmLease) { + self.active_leases.push(lease); + } + + pub fn remove_lease(&mut self, lease_id: u32) { + self.active_leases.retain(|l| l.id() != lease_id); + } } #[derive(Debug, Clone, Copy)] @@ -376,6 +415,8 @@ impl Tty { debug!("device added: {device_id} {path:?}"); let node = DrmNode::from_dev_id(device_id)?; + let drm_lease_state = DrmLeaseState::new::<State>(&niri.display_handle, &node) + .context("Couldn't create DrmLeaseState")?; let open_flags = OFlags::RDWR | OFlags::CLOEXEC | OFlags::NOCTTY | OFlags::NONBLOCK; let fd = self.session.open(path, open_flags)?; @@ -465,6 +506,9 @@ impl Tty { gbm, drm_scanner: DrmScanner::new(), surfaces: HashMap::new(), + drm_lease_state, + active_leases: Vec::new(), + non_desktop_connectors: HashSet::new(), }; assert!(self.devices.insert(node, device).is_none()); @@ -586,6 +630,41 @@ impl Tty { ); debug!("connecting connector: {output_name}"); + let device = self.devices.get_mut(&node).context("missing device")?; + + let non_desktop = device + .drm + .get_properties(connector.handle()) + .ok() + .and_then(|props| { + let (info, value) = props + .into_iter() + .filter_map(|(handle, value)| { + let info = device.drm.get_property(handle).ok()?; + Some((info, value)) + }) + .find(|(info, _)| info.name().to_str() == Ok("non-desktop"))?; + + info.value_type().convert_value(value).as_boolean() + }) + .unwrap_or(false); + + if non_desktop { + debug!("output is non desktop"); + let description = EdidInfo::for_connector(&device.drm, connector.handle()) + .map(|info| info.model) + .unwrap_or_else(|| "Unknown".into()); + device.drm_lease_state.add_connector::<State>( + connector.handle(), + output_name, + description, + ); + device + .non_desktop_connectors + .insert((connector.handle(), crtc)); + return Ok(()); + } + let config = self .config .borrow() @@ -600,8 +679,6 @@ impl Tty { return Ok(()); } - let device = self.devices.get_mut(&node).context("missing device")?; - for m in connector.modes() { trace!("{m:?}"); } @@ -1373,6 +1450,10 @@ impl Tty { self.refresh_ipc_outputs(); } + + pub fn get_device_from_node(&mut self, node: DrmNode) -> Option<&mut OutputDevice> { + self.devices.get_mut(&node) + } } fn primary_node_from_config(config: &Config) -> Option<(DrmNode, DrmNode)> { diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index f11ff4d6..eb5a986f 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -9,6 +9,7 @@ use std::sync::Arc; use std::thread; use smithay::backend::allocator::dmabuf::Dmabuf; +use smithay::backend::drm::DrmNode; use smithay::desktop::{PopupKind, PopupManager}; use smithay::input::pointer::{CursorIcon, CursorImageStatus, PointerHandle}; use smithay::input::{keyboard, Seat, SeatHandler, SeatState}; @@ -22,6 +23,9 @@ use smithay::reexports::wayland_server::Resource; use smithay::utils::{Logical, Rectangle, Size}; use smithay::wayland::compositor::{send_surface_state, with_states}; use smithay::wayland::dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier}; +use smithay::wayland::drm_lease::{ + DrmLease, DrmLeaseBuilder, DrmLeaseHandler, DrmLeaseRequest, DrmLeaseState, LeaseRejected, +}; use smithay::wayland::idle_inhibit::IdleInhibitHandler; use smithay::wayland::idle_notify::{IdleNotifierHandler, IdleNotifierState}; use smithay::wayland::input_method::{InputMethodHandler, PopupSurface}; @@ -44,9 +48,9 @@ use smithay::wayland::session_lock::{ }; use smithay::{ delegate_cursor_shape, delegate_data_control, delegate_data_device, delegate_dmabuf, - delegate_idle_inhibit, delegate_idle_notify, delegate_input_method_manager, delegate_output, - delegate_pointer_constraints, delegate_pointer_gestures, delegate_presentation, - delegate_primary_selection, delegate_relative_pointer, delegate_seat, + delegate_drm_lease, delegate_idle_inhibit, delegate_idle_notify, delegate_input_method_manager, + delegate_output, delegate_pointer_constraints, delegate_pointer_gestures, + delegate_presentation, delegate_primary_selection, delegate_relative_pointer, delegate_seat, delegate_security_context, delegate_session_lock, delegate_tablet_manager, delegate_text_input_manager, delegate_virtual_keyboard_manager, }; @@ -374,3 +378,49 @@ impl ForeignToplevelHandler for State { } } delegate_foreign_toplevel!(State); + +impl DrmLeaseHandler for State { + fn drm_lease_state(&mut self, node: DrmNode) -> &mut DrmLeaseState { + &mut self + .backend + .tty() + .get_device_from_node(node) + .unwrap() + .drm_lease_state + } + + fn lease_request( + &mut self, + node: DrmNode, + request: DrmLeaseRequest, + ) -> Result<DrmLeaseBuilder, LeaseRejected> { + debug!( + "Received lease request for {} connectors", + request.connectors.len() + ); + self.backend + .tty() + .get_device_from_node(node) + .unwrap() + .lease_request(request) + } + + fn new_active_lease(&mut self, node: DrmNode, lease: DrmLease) { + debug!("Lease success"); + self.backend + .tty() + .get_device_from_node(node) + .unwrap() + .new_lease(lease); + } + + fn lease_destroyed(&mut self, node: DrmNode, lease_id: u32) { + debug!("Destroyed lease"); + self.backend + .tty() + .get_device_from_node(node) + .unwrap() + .remove_lease(lease_id); + } +} +delegate_drm_lease!(State); |
