From 6647b93e1ed9b28581f0e212b15936a7477d3e34 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Mon, 14 Jul 2025 11:03:34 +0200 Subject: [PATCH] head-management: add drm-color-space-info-v1 extension --- src/compositor.rs | 2 + src/ifs/head_management.rs | 24 ++++++- .../head_management/head_management_macros.rs | 1 + src/ifs/head_management/jay_head_ext.rs | 1 + .../jay_head_ext_drm_color_space_info_v1.rs | 66 +++++++++++++++++++ src/state.rs | 4 ++ src/tasks/connector.rs | 2 + wire/jay_head_ext_drm_color_space_info_v1.txt | 11 ++++ ...ad_manager_ext_drm_color_space_info_v1.txt | 7 ++ 9 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/ifs/head_management/jay_head_ext/jay_head_ext_drm_color_space_info_v1.rs create mode 100644 wire/jay_head_ext_drm_color_space_info_v1.txt create mode 100644 wire/jay_head_manager_ext_drm_color_space_info_v1.txt diff --git a/src/compositor.rs b/src/compositor.rs index 47df6469..11f2fa86 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -657,6 +657,8 @@ fn create_dummy_output(state: &Rc) { tearing_enabled: backend_state.tearing, tearing_active: false, format: XRGB8888, + color_space: backend_state.color_space, + transfer_function: backend_state.transfer_function, }; let connector_data = Rc::new(ConnectorData { id, diff --git a/src/ifs/head_management.rs b/src/ifs/head_management.rs index 0ffba943..24370bce 100644 --- a/src/ifs/head_management.rs +++ b/src/ifs/head_management.rs @@ -1,6 +1,9 @@ use { crate::{ - backend::{ConnectorId, Mode, MonitorInfo, transaction::BackendConnectorTransactionError}, + backend::{ + BackendColorSpace, BackendTransferFunction, ConnectorId, Mode, MonitorInfo, + transaction::BackendConnectorTransactionError, + }, client::ClientId, format::Format, globals::GlobalName, @@ -84,6 +87,8 @@ pub struct HeadState { pub tearing_enabled: bool, pub tearing_active: bool, pub format: &'static Format, + pub color_space: BackendColorSpace, + pub transfer_function: BackendTransferFunction, } impl HeadState { @@ -420,4 +425,21 @@ impl HeadManagers { } } } + + pub fn handle_colors_change( + &self, + color_space: BackendColorSpace, + transfer_function: BackendTransferFunction, + ) { + let state = &mut *self.state.borrow_mut(); + state.color_space = color_space; + state.transfer_function = transfer_function; + for head in self.managers.lock().values() { + skip_in_transaction!(head); + if let Some(ext) = &head.ext.drm_color_space_info_v1 { + ext.send_state(state); + head.session.schedule_done(); + } + } + } } diff --git a/src/ifs/head_management/head_management_macros.rs b/src/ifs/head_management/head_management_macros.rs index 92371a3e..4c1cb23c 100644 --- a/src/ifs/head_management/head_management_macros.rs +++ b/src/ifs/head_management/head_management_macros.rs @@ -402,4 +402,5 @@ declare_extensions! { vrr_state_v1: VrrStateV1, tearing_state_v1: TearingStateV1, format_info_v1: FormatInfoV1, + drm_color_space_info_v1: DrmColorSpaceInfoV1, } diff --git a/src/ifs/head_management/jay_head_ext.rs b/src/ifs/head_management/jay_head_ext.rs index 422b6511..40378563 100644 --- a/src/ifs/head_management/jay_head_ext.rs +++ b/src/ifs/head_management/jay_head_ext.rs @@ -5,6 +5,7 @@ pub(super) mod jay_head_ext_compositor_space_scaler_v1; pub(super) mod jay_head_ext_compositor_space_transformer_v1; pub(super) mod jay_head_ext_connector_info_v1; pub(super) mod jay_head_ext_core_info_v1; +pub(super) mod jay_head_ext_drm_color_space_info_v1; pub(super) mod jay_head_ext_format_info_v1; pub(super) mod jay_head_ext_mode_info_v1; pub(super) mod jay_head_ext_mode_setter_v1; diff --git a/src/ifs/head_management/jay_head_ext/jay_head_ext_drm_color_space_info_v1.rs b/src/ifs/head_management/jay_head_ext/jay_head_ext_drm_color_space_info_v1.rs new file mode 100644 index 00000000..0b57ee44 --- /dev/null +++ b/src/ifs/head_management/jay_head_ext/jay_head_ext_drm_color_space_info_v1.rs @@ -0,0 +1,66 @@ +use { + crate::{ + backend::CONCAP_CONNECTOR, + ifs::head_management::{HeadCommon, HeadState}, + state::ConnectorData, + wire::{ + jay_head_ext_drm_color_space_info_v1::{ + Colorimetry, HdmiEotf, JayHeadExtDrmColorSpaceInfoV1RequestHandler, + }, + jay_head_manager_ext_drm_color_space_info_v1::JayHeadManagerExtDrmColorSpaceInfoV1RequestHandler, + }, + }, + std::rc::Rc, +}; + +impl_drm_color_space_info_v1! { + version = 1, + filter = filter, + after_announce = after_announce, + after_transaction = after_transaction, +} + +impl MgrName { + fn filter(&self, connector: &ConnectorData, _common: &Rc) -> bool { + connector.connector.caps().contains(CONCAP_CONNECTOR) + } +} + +impl HeadName { + fn after_announce(&self, shared: &HeadState) { + self.send_state(shared); + } + + fn after_transaction(&self, shared: &HeadState, tran: &HeadState) { + if (shared.color_space, shared.transfer_function) + != (tran.color_space, tran.transfer_function) + { + self.send_state(shared); + } + } + + pub(in super::super) fn send_state(&self, state: &HeadState) { + self.client.event(HdmiEotf { + self_id: self.id, + eotf: state.transfer_function.to_drm() as u32, + }); + self.client.event(Colorimetry { + self_id: self.id, + colorimetry: state.color_space.to_drm() as u32, + }); + } +} + +impl JayHeadManagerExtDrmColorSpaceInfoV1RequestHandler for MgrName { + type Error = ErrorName; + + mgr_common_req!(); +} + +impl JayHeadExtDrmColorSpaceInfoV1RequestHandler for HeadName { + type Error = ErrorName; + + head_common_req!(); +} + +error!(); diff --git a/src/state.rs b/src/state.rs index 7da56328..18e1bc3a 100644 --- a/src/state.rs +++ b/src/state.rs @@ -462,6 +462,10 @@ impl ConnectorData { if old.format != s.format { self.head_managers.handle_format_change(s.format); } + if (old.color_space, old.transfer_function) != (s.color_space, s.transfer_function) { + self.head_managers + .handle_colors_change(s.color_space, s.transfer_function); + } if let Some(output) = state.outputs.get(&self.connector.id()) && let Some(node) = &output.node { diff --git a/src/tasks/connector.rs b/src/tasks/connector.rs index eb2f4ff5..3a646f88 100644 --- a/src/tasks/connector.rs +++ b/src/tasks/connector.rs @@ -63,6 +63,8 @@ pub fn handle(state: &Rc, connector: &Rc) { tearing_enabled: backend_state.tearing, tearing_active: false, format: backend_state.format, + color_space: backend_state.color_space, + transfer_function: backend_state.transfer_function, }; let data = Rc::new(ConnectorData { id, diff --git a/wire/jay_head_ext_drm_color_space_info_v1.txt b/wire/jay_head_ext_drm_color_space_info_v1.txt new file mode 100644 index 00000000..d58ecd2d --- /dev/null +++ b/wire/jay_head_ext_drm_color_space_info_v1.txt @@ -0,0 +1,11 @@ +request destroy (destructor) { + +} + +event hdmi_eotf { + eotf: u32, +} + +event colorimetry { + colorimetry: u32, +} diff --git a/wire/jay_head_manager_ext_drm_color_space_info_v1.txt b/wire/jay_head_manager_ext_drm_color_space_info_v1.txt new file mode 100644 index 00000000..54f2b290 --- /dev/null +++ b/wire/jay_head_manager_ext_drm_color_space_info_v1.txt @@ -0,0 +1,7 @@ +request destroy (destructor) { + +} + +event head { + head: id(jay_head_ext_drm_color_space_info_v1) (new), +}