diff options
| author | Michael Yang <admin@my4ng.dev> | 2025-08-24 00:53:54 +1000 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-08-24 16:06:06 +0300 |
| commit | 969f382e3e52f2a6c9d5f398d19f36dc32df0dd5 (patch) | |
| tree | 398d28275e9e1edbb23d9a9dfb2dd06f1e793a25 /src/backend | |
| parent | 2865ec3e47fa0b170f82f4beeefa56a5ea49d133 (diff) | |
| download | niri-969f382e3e52f2a6c9d5f398d19f36dc32df0dd5.tar.gz niri-969f382e3e52f2a6c9d5f398d19f36dc32df0dd5.tar.bz2 niri-969f382e3e52f2a6c9d5f398d19f36dc32df0dd5.zip | |
feat: reset HDR connector properties
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/tty.rs | 143 |
1 files changed, 112 insertions, 31 deletions
diff --git a/src/backend/tty.rs b/src/backend/tty.rs index 045f48fc..f6324edf 100644 --- a/src/backend/tty.rs +++ b/src/backend/tty.rs @@ -250,6 +250,12 @@ struct GammaProps { previous_blob: Option<NonZeroU64>, } +struct ConnectorProperties<'a> { + device: &'a DrmDevice, + connector: connector::Handle, + properties: Vec<(property::Info, property::RawValue)>, +} + impl Tty { pub fn new( config: Rc<RefCell<Config>>, @@ -857,14 +863,23 @@ impl Tty { } debug!("picking mode: {mode:?}"); - if !niri.config.borrow().debug.keep_max_bpc_unchanged { - // We only use 8888 RGB formats, so set max bpc to 8 to allow more types of links to - // run. - match set_max_bpc(&device.drm, connector.handle(), 8) { - Ok(bpc) => debug!("set max bpc to {bpc}"), - Err(err) => debug!("error setting max bpc: {err:?}"), + if let Ok(props) = ConnectorProperties::try_new(&device.drm, connector.handle()) { + match reset_hdr(&props) { + Ok(()) => debug!("reset HDR properties"), + Err(err) => debug!("error resetting HDR properties: {err:?}"), } - } + + if !niri.config.borrow().debug.keep_max_bpc_unchanged { + // We only use 8888 RGB formats, so set max bpc to 8 to allow more types of links to + // run. + match set_max_bpc(&props, 8) { + Ok(bpc) => debug!("set max bpc to {bpc}"), + Err(err) => debug!("error setting max bpc: {err:?}"), + } + } + } else { + warn!("failed to get connector properties"); + }; let mut gamma_props = GammaProps::new(&device.drm, crtc) .map_err(|err| debug!("error getting gamma properties: {err:?}")) @@ -1825,6 +1840,20 @@ impl Tty { continue; } + if let Ok(props) = ConnectorProperties::try_new(&device.drm, surface.connector) { + match reset_hdr(&props) { + Ok(()) => { + debug!("output {:?}: reset HDR properties", surface.name.connector) + } + Err(err) => debug!( + "output {:?} HDR: error resetting HDR properties: {err:?}", + surface.name.connector + ), + } + } else { + warn!("failed to get connector properties"); + }; + // Check if we need to change the mode. let Some(connector) = device.drm_scanner.connectors().get(&surface.connector) else { @@ -2452,39 +2481,91 @@ fn get_edid_info( libdisplay_info::info::Info::parse_edid(&data).context("error parsing EDID") } -fn set_max_bpc(device: &DrmDevice, connector: connector::Handle, bpc: u64) -> anyhow::Result<u64> { - let props = device - .get_properties(connector) - .context("error getting properties")?; - for (prop, value) in props { - let info = device - .get_property(prop) - .context("error getting property")?; - if info.name().to_str() != Ok("max bpc") { - continue; - } +impl<'a> ConnectorProperties<'a> { + fn try_new(device: &'a DrmDevice, connector: connector::Handle) -> anyhow::Result<Self> { + let prop_vals = device + .get_properties(connector) + .context("error getting properties")?; - let property::ValueType::UnsignedRange(min, max) = info.value_type() else { - bail!("wrong property type") - }; + let mut properties = Vec::new(); - let bpc = bpc.clamp(min, max); + for (prop, value) in prop_vals { + let info = device + .get_property(prop) + .context("error getting property")?; - let property::Value::UnsignedRange(value) = info.value_type().convert_value(value) else { - bail!("wrong property type") - }; - if value == bpc { - return Ok(bpc); + properties.push((info, value)); } - device - .set_property(connector, prop, property::Value::UnsignedRange(bpc).into()) + Ok(Self { + device, + connector, + properties, + }) + } + + fn find(&self, name: &std::ffi::CStr) -> anyhow::Result<&(property::Info, property::RawValue)> { + for prop in &self.properties { + if prop.0.name() == name { + return Ok(prop); + } + } + + Err(anyhow!("couldn't find property: {name:?}")) + } +} + +const DRM_MODE_COLORIMETRY_DEFAULT: u64 = 0; + +fn reset_hdr(props: &ConnectorProperties) -> anyhow::Result<()> { + let (info, value) = props.find(c"HDR_OUTPUT_METADATA")?; + let property::ValueType::Blob = info.value_type() else { + bail!("wrong property type") + }; + + if *value != 0 { + props + .device + .set_property(props.connector, info.handle(), 0) .context("error setting property")?; + } - return Ok(bpc); + let (info, value) = props.find(c"Colorspace")?; + let property::ValueType::Enum(_) = info.value_type() else { + bail!("wrong property type") + }; + if *value != DRM_MODE_COLORIMETRY_DEFAULT { + props + .device + .set_property(props.connector, info.handle(), DRM_MODE_COLORIMETRY_DEFAULT) + .context("error setting property")?; } - Err(anyhow!("couldn't find max bpc property")) + Ok(()) +} + +fn set_max_bpc(props: &ConnectorProperties, bpc: u64) -> anyhow::Result<u64> { + let (info, value) = props.find(c"max bpc")?; + let property::ValueType::UnsignedRange(min, max) = info.value_type() else { + bail!("wrong property type") + }; + + let bpc = bpc.clamp(min, max); + let property::Value::UnsignedRange(value) = info.value_type().convert_value(*value) else { + bail!("wrong property type") + }; + + if value != bpc { + props + .device + .set_property( + props.connector, + info.handle(), + property::Value::UnsignedRange(bpc).into(), + ) + .context("error setting property")?; + } + Ok(bpc) } fn is_vrr_capable(device: &DrmDevice, connector: connector::Handle) -> Option<bool> { |
