From 642c6e7512f25f1fdc47dfa6a6eaec38c5faa69b Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Fri, 15 Mar 2024 11:10:54 +0400 Subject: Store gamma changes to apply on session resume --- src/backend/tty.rs | 30 ++++++++++++++++++++++++++++-- src/handlers/mod.rs | 2 +- src/protocols/gamma_control.rs | 7 +++---- 3 files changed, 32 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/backend/tty.rs b/src/backend/tty.rs index 4cc45b0c..e7b60900 100644 --- a/src/backend/tty.rs +++ b/src/backend/tty.rs @@ -169,6 +169,8 @@ struct Surface { compositor: GbmDrmCompositor, dmabuf_feedback: Option, gamma_props: Option, + /// Gamma change to apply upon session resume. + pending_gamma_change: Option>>, /// Tracy frame that goes from vblank to vblank. vblank_frame: Option, /// Frame name for the VBlank frame. @@ -394,6 +396,22 @@ impl Tty { // Refresh the connectors. self.device_changed(node.dev_id(), niri); + + // Apply pending gamma changes. + let device = self.devices.get_mut(&node).unwrap(); + for (crtc, surface) in device.surfaces.iter_mut() { + if let Some(ramp) = surface.pending_gamma_change.take() { + let ramp = ramp.as_deref(); + let res = if let Some(gamma_props) = &mut surface.gamma_props { + gamma_props.set_gamma(&device.drm, ramp) + } else { + set_gamma_for_crtc(&device.drm, *crtc, ramp) + }; + if let Err(err) = res { + warn!("error applying pending gamma change: {err:?}"); + } + } + } } // Add new devices. @@ -839,6 +857,7 @@ impl Tty { compositor, dmabuf_feedback, gamma_props, + pending_gamma_change: None, vblank_frame: None, vblank_frame_name, time_since_presentation_plot_name, @@ -1292,7 +1311,7 @@ impl Tty { } } - pub fn set_gamma(&mut self, output: &Output, ramp: Option<&[u16]>) -> anyhow::Result<()> { + pub fn set_gamma(&mut self, output: &Output, ramp: Option>) -> anyhow::Result<()> { let tty_state = output.user_data().get::().unwrap(); let crtc = tty_state.crtc; @@ -1300,8 +1319,15 @@ impl Tty { .devices .get_mut(&tty_state.node) .context("missing device")?; - let surface = device.surfaces.get_mut(&crtc).context("missing surface")?; + + // Cannot change properties while the device is inactive. + if !self.session.is_active() { + surface.pending_gamma_change = Some(ramp); + return Ok(()); + } + + let ramp = ramp.as_deref(); if let Some(gamma_props) = &mut surface.gamma_props { gamma_props.set_gamma(&device.drm, ramp) } else { diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index d027194c..e5df8b43 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -460,7 +460,7 @@ impl GammaControlHandler for State { } } - fn set_gamma(&mut self, output: &Output, ramp: Option<&[u16]>) -> Option<()> { + fn set_gamma(&mut self, output: &Output, ramp: Option>) -> Option<()> { match self.backend.tty().set_gamma(output, ramp) { Ok(()) => Some(()), Err(err) => { diff --git a/src/protocols/gamma_control.rs b/src/protocols/gamma_control.rs index 07e5a848..083710ed 100644 --- a/src/protocols/gamma_control.rs +++ b/src/protocols/gamma_control.rs @@ -28,7 +28,7 @@ pub struct GammaControlManagerGlobalData { pub trait GammaControlHandler { fn gamma_control_manager_state(&mut self) -> &mut GammaControlManagerState; fn get_gamma_size(&mut self, output: &Output) -> Option; - fn set_gamma(&mut self, output: &Output, ramp: Option<&[u16]>) -> Option<()>; + fn set_gamma(&mut self, output: &Output, ramp: Option>) -> Option<()>; } pub struct GammaControlState { @@ -162,8 +162,8 @@ where trace!("setting gamma for output {}", output.name()); // Start with a u16 slice so it's aligned correctly. - let mut buf = vec![0u16; data.gamma_size as usize * 3]; - let buf = bytemuck::cast_slice_mut(&mut buf); + let mut gamma = vec![0u16; data.gamma_size as usize * 3]; + let buf = bytemuck::cast_slice_mut(&mut gamma); let mut file = File::from(fd); { let _span = tracy_client::span!("read gamma from fd"); @@ -195,7 +195,6 @@ where } } } - let gamma = bytemuck::cast_slice(buf); if state.set_gamma(&output, Some(gamma)).is_none() { resource.failed(); -- cgit