aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorMichael Yang <admin@my4ng.dev>2025-08-24 00:53:54 +1000
committerIvan Molodetskikh <yalterz@gmail.com>2025-08-24 16:06:06 +0300
commit969f382e3e52f2a6c9d5f398d19f36dc32df0dd5 (patch)
tree398d28275e9e1edbb23d9a9dfb2dd06f1e793a25 /src/backend
parent2865ec3e47fa0b170f82f4beeefa56a5ea49d133 (diff)
downloadniri-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.rs143
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> {