mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
feat: reset HDR connector properties
This commit is contained in:
committed by
Ivan Molodetskikh
parent
2865ec3e47
commit
969f382e3e
+117
-36
@@ -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 mut properties = Vec::new();
|
||||
|
||||
for (prop, value) in prop_vals {
|
||||
let info = device
|
||||
.get_property(prop)
|
||||
.context("error getting property")?;
|
||||
|
||||
properties.push((info, value));
|
||||
}
|
||||
|
||||
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 {
|
||||
return Ok(bpc);
|
||||
}
|
||||
|
||||
device
|
||||
.set_property(connector, prop, property::Value::UnsignedRange(bpc).into())
|
||||
.context("error setting property")?;
|
||||
|
||||
return Ok(bpc);
|
||||
Ok(Self {
|
||||
device,
|
||||
connector,
|
||||
properties,
|
||||
})
|
||||
}
|
||||
|
||||
Err(anyhow!("couldn't find max bpc property"))
|
||||
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")?;
|
||||
}
|
||||
|
||||
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")?;
|
||||
}
|
||||
|
||||
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> {
|
||||
|
||||
Reference in New Issue
Block a user