mirror of
https://github.com/YaLTeR/niri.git
synced 2025-10-05 16:12:47 +02:00
tty: Add support for disabling DRM devices
This commit is contained in:
committed by
Ivan Molodetskikh
parent
b7f1e382a2
commit
5c91e3191d
@@ -18,6 +18,8 @@ debug {
|
||||
disable-direct-scanout
|
||||
restrict-primary-scanout-to-matching-format
|
||||
render-drm-device "/dev/dri/renderD129"
|
||||
ignore-drm-device "/dev/dri/renderD128"
|
||||
ignore-drm-device "/dev/dri/renderD130"
|
||||
force-pipewire-invalid-modifier
|
||||
dbus-interfaces-in-non-session-instances
|
||||
wait-for-frame-completion-before-queueing
|
||||
@@ -115,6 +117,20 @@ debug {
|
||||
}
|
||||
```
|
||||
|
||||
### `ignore-drm-device`
|
||||
|
||||
<sup>Since: next release</sup>
|
||||
|
||||
List DRM devices that niri will ignore.
|
||||
Useful for GPU passthrough when you don't want niri to open a certain device.
|
||||
|
||||
```kdl
|
||||
debug {
|
||||
ignore-drm-device "/dev/dri/renderD128"
|
||||
ignore-drm-device "/dev/dri/renderD130"
|
||||
}
|
||||
```
|
||||
|
||||
### `force-pipewire-invalid-modifier`
|
||||
|
||||
<sup>Since: 25.01</sup>
|
||||
|
@@ -13,6 +13,7 @@ pub struct Debug {
|
||||
pub keep_max_bpc_unchanged: bool,
|
||||
pub restrict_primary_scanout_to_matching_format: bool,
|
||||
pub render_drm_device: Option<PathBuf>,
|
||||
pub ignored_drm_devices: Vec<PathBuf>,
|
||||
pub force_pipewire_invalid_modifier: bool,
|
||||
pub emulate_zero_presentation_time: bool,
|
||||
pub disable_resize_throttling: bool,
|
||||
@@ -45,6 +46,8 @@ pub struct DebugPart {
|
||||
pub restrict_primary_scanout_to_matching_format: Option<Flag>,
|
||||
#[knuffel(child, unwrap(argument))]
|
||||
pub render_drm_device: Option<PathBuf>,
|
||||
#[knuffel(children(name = "ignore-drm-device"), unwrap(argument))]
|
||||
pub ignored_drm_devices: Vec<PathBuf>,
|
||||
#[knuffel(child)]
|
||||
pub force_pipewire_invalid_modifier: Option<Flag>,
|
||||
#[knuffel(child)]
|
||||
@@ -91,6 +94,9 @@ impl MergeWith<DebugPart> for Debug {
|
||||
);
|
||||
|
||||
merge_clone_opt!((self, part), preview_render, render_drm_device);
|
||||
|
||||
self.ignored_drm_devices
|
||||
.extend(part.ignored_drm_devices.iter().cloned());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -831,6 +831,8 @@ mod tests {
|
||||
|
||||
debug {
|
||||
render-drm-device "/dev/dri/renderD129"
|
||||
ignore-drm-device "/dev/dri/renderD128"
|
||||
ignore-drm-device "/dev/dri/renderD130"
|
||||
}
|
||||
|
||||
workspace "workspace-1" {
|
||||
@@ -2008,6 +2010,10 @@ mod tests {
|
||||
render_drm_device: Some(
|
||||
"/dev/dri/renderD129",
|
||||
),
|
||||
ignored_drm_devices: [
|
||||
"/dev/dri/renderD128",
|
||||
"/dev/dri/renderD130",
|
||||
],
|
||||
force_pipewire_invalid_modifier: false,
|
||||
emulate_zero_presentation_time: false,
|
||||
disable_resize_throttling: false,
|
||||
|
@@ -83,6 +83,8 @@ pub struct Tty {
|
||||
primary_node: DrmNode,
|
||||
// DRM render node corresponding to the primary GPU.
|
||||
primary_render_node: DrmNode,
|
||||
// Ignored DRM nodes.
|
||||
ignored_nodes: HashSet<DrmNode>,
|
||||
// Devices indexed by DRM node (not necessarily the render node).
|
||||
devices: HashMap<DrmNode, OutputDevice>,
|
||||
// The dma-buf global corresponds to the output device (the primary GPU). It is only `Some()`
|
||||
@@ -328,6 +330,11 @@ impl Tty {
|
||||
}
|
||||
info!("using as the render node: {node_path}");
|
||||
|
||||
let mut ignored_nodes = ignored_nodes_from_config(&config.borrow());
|
||||
if ignored_nodes.remove(&primary_node) || ignored_nodes.remove(&primary_render_node) {
|
||||
warn!("ignoring the primary node or render node is not allowed");
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
config,
|
||||
session,
|
||||
@@ -336,6 +343,7 @@ impl Tty {
|
||||
gpu_manager,
|
||||
primary_node,
|
||||
primary_render_node,
|
||||
ignored_nodes,
|
||||
devices: HashMap::new(),
|
||||
dmabuf_global: None,
|
||||
update_output_config_on_resume: false,
|
||||
@@ -504,6 +512,11 @@ impl Tty {
|
||||
|
||||
let node = DrmNode::from_dev_id(device_id)?;
|
||||
|
||||
if self.ignored_nodes.contains(&node) {
|
||||
debug!("node is ignored, skipping");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let open_flags = OFlags::RDWR | OFlags::CLOEXEC | OFlags::NOCTTY | OFlags::NONBLOCK;
|
||||
let fd = self.session.open(path, open_flags)?;
|
||||
let device_fd = DrmDeviceFd::new(DeviceFd::from(fd));
|
||||
@@ -1822,6 +1835,48 @@ impl Tty {
|
||||
}
|
||||
self.update_output_config_on_resume = false;
|
||||
|
||||
// Update ignored nodes.
|
||||
let mut ignored_nodes = ignored_nodes_from_config(&self.config.borrow());
|
||||
if ignored_nodes.remove(&self.primary_node)
|
||||
|| ignored_nodes.remove(&self.primary_render_node)
|
||||
{
|
||||
warn!("ignoring the primary node or render node is not allowed");
|
||||
}
|
||||
if ignored_nodes != self.ignored_nodes {
|
||||
self.ignored_nodes = ignored_nodes;
|
||||
|
||||
let mut device_list = self
|
||||
.udev_dispatcher
|
||||
.as_source_ref()
|
||||
.device_list()
|
||||
.map(|(device_id, path)| (device_id, path.to_owned()))
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
let removed_devices = self
|
||||
.devices
|
||||
.keys()
|
||||
.filter(|node| {
|
||||
self.ignored_nodes.contains(node) || !device_list.contains_key(&node.dev_id())
|
||||
})
|
||||
.copied()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for node in removed_devices {
|
||||
device_list.remove(&node.dev_id());
|
||||
self.device_removed(node.dev_id(), niri);
|
||||
}
|
||||
|
||||
for node in self.devices.keys() {
|
||||
device_list.remove(&node.dev_id());
|
||||
}
|
||||
|
||||
for (device_id, path) in device_list {
|
||||
if let Err(err) = self.device_added(device_id, &path, niri) {
|
||||
warn!("error adding device {path:?}: {err:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out if we should disable laptop panels.
|
||||
let mut disable_laptop_panels = false;
|
||||
if niri.is_lid_closed {
|
||||
@@ -2181,10 +2236,7 @@ impl GammaProps {
|
||||
}
|
||||
}
|
||||
|
||||
fn primary_node_from_config(config: &Config) -> Option<(DrmNode, DrmNode)> {
|
||||
let path = config.debug.render_drm_device.as_ref()?;
|
||||
debug!("attempting to use render node from config: {path:?}");
|
||||
|
||||
fn primary_node_from_render_node(path: &Path) -> Option<(DrmNode, DrmNode)> {
|
||||
match DrmNode::from_path(path) {
|
||||
Ok(node) => {
|
||||
if node.ty() == NodeType::Render {
|
||||
@@ -2215,9 +2267,30 @@ fn primary_node_from_config(config: &Config) -> Option<(DrmNode, DrmNode)> {
|
||||
warn!("error opening {path:?} as DRM node: {err:?}");
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn primary_node_from_config(config: &Config) -> Option<(DrmNode, DrmNode)> {
|
||||
let path = config.debug.render_drm_device.as_ref()?;
|
||||
debug!("attempting to use render node from config: {path:?}");
|
||||
|
||||
primary_node_from_render_node(path)
|
||||
}
|
||||
|
||||
fn ignored_nodes_from_config(config: &Config) -> HashSet<DrmNode> {
|
||||
let mut disabled_nodes = HashSet::new();
|
||||
|
||||
for path in &config.debug.ignored_drm_devices {
|
||||
if let Some((primary_node, render_node)) = primary_node_from_render_node(path) {
|
||||
disabled_nodes.insert(primary_node);
|
||||
disabled_nodes.insert(render_node);
|
||||
}
|
||||
}
|
||||
|
||||
disabled_nodes
|
||||
}
|
||||
|
||||
fn surface_dmabuf_feedback(
|
||||
compositor: &GbmDrmCompositor,
|
||||
primary_formats: FormatSet,
|
||||
|
@@ -1504,6 +1504,10 @@ impl State {
|
||||
output_config_changed = true;
|
||||
}
|
||||
|
||||
if config.debug.ignored_drm_devices != old_config.debug.ignored_drm_devices {
|
||||
output_config_changed = true;
|
||||
}
|
||||
|
||||
// FIXME: move backdrop rendering into layout::Monitor, then this will become unnecessary.
|
||||
if config.overview.backdrop_color != old_config.overview.backdrop_color {
|
||||
output_config_changed = true;
|
||||
|
Reference in New Issue
Block a user