Fetch monitor name from EDID only once

Reduce spam when it's unavailable. Assume the name cannot change at runtime;
before if it changed, bad things would probably happen anyway.
This commit is contained in:
Ivan Molodetskikh
2025-01-04 15:37:54 +03:00
parent 4618e4851c
commit 37771259d9
+62 -51
View File
@@ -123,7 +123,7 @@ pub struct OutputDevice {
render_node: DrmNode, render_node: DrmNode,
drm_scanner: DrmScanner, drm_scanner: DrmScanner,
surfaces: HashMap<crtc::Handle, Surface>, surfaces: HashMap<crtc::Handle, Surface>,
output_ids: HashMap<crtc::Handle, OutputId>, known_crtcs: HashMap<crtc::Handle, CrtcInfo>,
// SAFETY: drop after all the objects used with them are dropped. // SAFETY: drop after all the objects used with them are dropped.
// See https://github.com/Smithay/smithay/issues/1102. // See https://github.com/Smithay/smithay/issues/1102.
drm: DrmDevice, drm: DrmDevice,
@@ -134,6 +134,13 @@ pub struct OutputDevice {
active_leases: Vec<DrmLease>, active_leases: Vec<DrmLease>,
} }
// A connected, but not necessarily enabled, crtc.
#[derive(Debug, Clone)]
pub struct CrtcInfo {
id: OutputId,
name: OutputName,
}
impl OutputDevice { impl OutputDevice {
pub fn lease_request( pub fn lease_request(
&self, &self,
@@ -173,6 +180,35 @@ impl OutputDevice {
pub fn remove_lease(&mut self, lease_id: u32) { pub fn remove_lease(&mut self, lease_id: u32) {
self.active_leases.retain(|l| l.id() != lease_id); self.active_leases.retain(|l| l.id() != lease_id);
} }
pub fn known_crtc_name(
&self,
crtc: &crtc::Handle,
conn: &connector::Info,
disable_monitor_names: bool,
) -> OutputName {
if disable_monitor_names {
let conn_name = format_connector_name(conn);
return OutputName {
connector: conn_name,
make: None,
model: None,
serial: None,
};
}
let Some(info) = self.known_crtcs.get(crtc) else {
let conn_name = format_connector_name(conn);
error!("crtc for connector {conn_name} missing from known");
return OutputName {
connector: conn_name,
make: None,
model: None,
serial: None,
};
};
info.name.clone()
}
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@@ -572,7 +608,7 @@ impl Tty {
gbm, gbm,
drm_scanner: DrmScanner::new(), drm_scanner: DrmScanner::new(),
surfaces: HashMap::new(), surfaces: HashMap::new(),
output_ids: HashMap::new(), known_crtcs: HashMap::new(),
drm_lease_state, drm_lease_state,
active_leases: Vec::new(), active_leases: Vec::new(),
non_desktop_connectors: HashSet::new(), non_desktop_connectors: HashSet::new(),
@@ -613,16 +649,16 @@ impl Tty {
crtc: Some(crtc), crtc: Some(crtc),
} => { } => {
let connector_name = format_connector_name(&connector); let connector_name = format_connector_name(&connector);
let output_name = let name = make_output_name(&device.drm, connector.handle(), connector_name);
make_output_name(&device.drm, connector.handle(), connector_name, false);
debug!( debug!(
"new connector: {} \"{}\"", "new connector: {} \"{}\"",
&output_name.connector, &name.connector,
output_name.format_make_model_serial(), name.format_make_model_serial(),
); );
// Assign an id to this crtc. // Assign an id to this crtc.
device.output_ids.insert(crtc, OutputId::next()); let id = OutputId::next();
device.known_crtcs.insert(crtc, CrtcInfo { id, name });
} }
DrmScanEvent::Disconnected { DrmScanEvent::Disconnected {
crtc: Some(crtc), .. crtc: Some(crtc), ..
@@ -643,7 +679,7 @@ impl Tty {
}; };
for crtc in removed { for crtc in removed {
if device.output_ids.remove(&crtc).is_none() { if device.known_crtcs.remove(&crtc).is_none() {
error!("output ID missing for disconnected crtc: {crtc:?}"); error!("output ID missing for disconnected crtc: {crtc:?}");
} }
} }
@@ -739,12 +775,8 @@ impl Tty {
let device = self.devices.get_mut(&node).context("missing device")?; let device = self.devices.get_mut(&node).context("missing device")?;
let output_name = make_output_name( let disable_monitor_names = self.config.borrow().debug.disable_monitor_names;
&device.drm, let output_name = device.known_crtc_name(&crtc, &connector, disable_monitor_names);
connector.handle(),
connector_name.clone(),
self.config.borrow().debug.disable_monitor_names,
);
let non_desktop = find_drm_property(&device.drm, connector.handle(), "non-desktop") let non_desktop = find_drm_property(&device.drm, connector.handle(), "non-desktop")
.and_then(|(_, info, value)| info.value_type().convert_value(value).as_boolean()) .and_then(|(_, info, value)| info.value_type().convert_value(value).as_boolean())
@@ -1543,17 +1575,13 @@ impl Tty {
let _span = tracy_client::span!("Tty::refresh_ipc_outputs"); let _span = tracy_client::span!("Tty::refresh_ipc_outputs");
let mut ipc_outputs = HashMap::new(); let mut ipc_outputs = HashMap::new();
let disable_monitor_names = self.config.borrow().debug.disable_monitor_names;
for (node, device) in &self.devices { for (node, device) in &self.devices {
for (connector, crtc) in device.drm_scanner.crtcs() { for (connector, crtc) in device.drm_scanner.crtcs() {
let connector_name = format_connector_name(connector); let connector_name = format_connector_name(connector);
let physical_size = connector.size(); let physical_size = connector.size();
let output_name = make_output_name( let output_name = device.known_crtc_name(&crtc, connector, disable_monitor_names);
&device.drm,
connector.handle(),
connector_name.clone(),
self.config.borrow().debug.disable_monitor_names,
);
let surface = device.surfaces.get(&crtc); let surface = device.surfaces.get(&crtc);
let current_crtc_mode = surface.map(|surface| surface.compositor.pending_mode()); let current_crtc_mode = surface.map(|surface| surface.compositor.pending_mode());
@@ -1609,6 +1637,12 @@ impl Tty {
}) })
.map(logical_output); .map(logical_output);
let id = device.known_crtcs.get(&crtc).map(|info| info.id);
let id = id.unwrap_or_else(|| {
error!("crtc for connector {connector_name} missing from known");
OutputId::next()
});
let ipc_output = niri_ipc::Output { let ipc_output = niri_ipc::Output {
name: connector_name, name: connector_name,
make: output_name.make.unwrap_or_else(|| "Unknown".into()), make: output_name.make.unwrap_or_else(|| "Unknown".into()),
@@ -1622,10 +1656,6 @@ impl Tty {
logical, logical,
}; };
let id = device.output_ids.get(&crtc).copied().unwrap_or_else(|| {
error!("output ID missing for crtc: {crtc:?}");
OutputId::next()
});
ipc_outputs.insert(id, ipc_output); ipc_outputs.insert(id, ipc_output);
} }
} }
@@ -1838,6 +1868,9 @@ impl Tty {
} }
} }
let config = self.config.borrow();
let disable_monitor_names = config.debug.disable_monitor_names;
for (connector, crtc) in device.drm_scanner.crtcs() { for (connector, crtc) in device.drm_scanner.crtcs() {
// Check if connected. // Check if connected.
if connector.state() != connector::State::Connected { if connector.state() != connector::State::Connected {
@@ -1853,16 +1886,9 @@ impl Tty {
continue; continue;
} }
let connector_name = format_connector_name(connector); let output_name = device.known_crtc_name(&crtc, connector, disable_monitor_names);
let output_name = make_output_name(
&device.drm, let config = config
connector.handle(),
connector_name,
self.config.borrow().debug.disable_monitor_names,
);
let config = self
.config
.borrow()
.outputs .outputs
.find(&output_name) .find(&output_name)
.cloned() .cloned()
@@ -1896,6 +1922,7 @@ impl Tty {
} }
pub fn disconnected_connector_name_by_name_match(&self, target: &str) -> Option<OutputName> { pub fn disconnected_connector_name_by_name_match(&self, target: &str) -> Option<OutputName> {
let disable_monitor_names = self.config.borrow().debug.disable_monitor_names;
for device in self.devices.values() { for device in self.devices.values() {
for (connector, crtc) in device.drm_scanner.crtcs() { for (connector, crtc) in device.drm_scanner.crtcs() {
// Check if connected. // Check if connected.
@@ -1912,13 +1939,7 @@ impl Tty {
continue; continue;
} }
let connector_name = format_connector_name(connector); let output_name = device.known_crtc_name(&crtc, connector, disable_monitor_names);
let output_name = make_output_name(
&device.drm,
connector.handle(),
connector_name,
self.config.borrow().debug.disable_monitor_names,
);
if output_name.matches(target) { if output_name.matches(target) {
return Some(output_name); return Some(output_name);
} }
@@ -2479,17 +2500,7 @@ fn make_output_name(
device: &DrmDevice, device: &DrmDevice,
connector: connector::Handle, connector: connector::Handle,
connector_name: String, connector_name: String,
disable_monitor_names: bool,
) -> OutputName { ) -> OutputName {
if disable_monitor_names {
return OutputName {
connector: connector_name,
make: None,
model: None,
serial: None,
};
}
let info = get_edid_info(device, connector) let info = get_edid_info(device, connector)
.map_err(|err| warn!("error getting EDID info for {connector_name}: {err:?}")) .map_err(|err| warn!("error getting EDID info for {connector_name}: {err:?}"))
.ok(); .ok();