aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Wallace <yungwallace@live.com>2024-02-11 13:15:03 -0500
committerIvan Molodetskikh <yalterz@gmail.com>2024-02-12 09:48:54 +0400
commit385454378bfde6f69246d5f11362c8d25a30d1eb (patch)
treec99cc6f0a49126bcadc32c84eb90035db11c6b41
parent18f06a7acd79feb16dc667b68a1ffd0d59e234c8 (diff)
downloadniri-385454378bfde6f69246d5f11362c8d25a30d1eb.tar.gz
niri-385454378bfde6f69246d5f11362c8d25a30d1eb.tar.bz2
niri-385454378bfde6f69246d5f11362c8d25a30d1eb.zip
Implement DRM leasing
Closes #178
-rw-r--r--src/backend/tty.rs87
-rw-r--r--src/handlers/mod.rs56
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);