From a30eb5c49c99108e11ab73ea491f292fd6173e03 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 23 Dec 2024 16:18:45 -0800 Subject: [PATCH] WIP mirroring size/scale comparison To determine if `mirroring_state` is needed, we want to compare the untransformed dimensions of the source output to the target outputs mode. The fact the mode comparision previously compared refresh rate (since it compared the whole `Mode`) seems unintended. We should also re-create the `MirroringState` when the source output dimensions changes. Not sure the exact best API here... --- src/backend/kms/surface/mod.rs | 76 ++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/src/backend/kms/surface/mod.rs b/src/backend/kms/surface/mod.rs index 834217be..dbb20803 100644 --- a/src/backend/kms/surface/mod.rs +++ b/src/backend/kms/surface/mod.rs @@ -147,26 +147,52 @@ pub struct SurfaceThreadState { egui: EguiState, } +#[derive(Debug, PartialEq)] +struct MirroringOutputConfig { + size: Size, + fractional_scale: f64, +} + +impl MirroringOutputConfig { + fn for_output_untransformed(output: &Output) -> Self { + Self { + // Apply inverse of output transform to mode size to get correct size + // for an untransformed render. + size: output.current_transform().invert().transform_size( + output + .current_mode() + .map(|mode| mode.size) + .unwrap_or_default(), + ), + fractional_scale: output.current_scale().fractional_scale(), + } + } + + fn for_output(output: &Output) -> Self { + Self { + size: output + .current_mode() + .map(|mode| mode.size) + .unwrap_or_default(), + fractional_scale: output.current_scale().fractional_scale(), + } + } +} + #[derive(Debug)] struct MirroringState { texture: TextureRenderBuffer, damage_tracker: OutputDamageTracker, + output_config: MirroringOutputConfig, } impl MirroringState { fn new_with_renderer( renderer: &mut GlMultiRenderer, format: Fourcc, - output: &Output, + output_config: MirroringOutputConfig, ) -> Result { - // Apply inverse of output transform to mode size to get correct size - // for an untransformed render. - let size = output.current_transform().invert().transform_size( - output - .current_mode() - .map(|mode| mode.size) - .unwrap_or_default(), - ); + let size = output_config.size; let buffer_size = size.to_logical(1).to_buffer(1, Transform::Normal); let opaque_regions = vec![Rectangle::from_loc_and_size((0, 0), buffer_size)]; @@ -180,15 +206,13 @@ impl MirroringState { ); // Don't use `from_output` to avoid applying output transform - let damage_tracker = OutputDamageTracker::new( - size, - output.current_scale().fractional_scale(), - Transform::Normal, - ); + let damage_tracker = + OutputDamageTracker::new(size, output_config.fractional_scale, Transform::Normal); Ok(MirroringState { texture: texture_buffer, damage_tracker, + output_config, }) } } @@ -1090,20 +1114,28 @@ impl SurfaceThreadState { // actual rendering let res = if let Some(mirrored_output) = self.mirroring.as_ref().filter(|mirrored_output| { - mirrored_output.current_mode().is_some_and(|mirror_mode| { - self.output - .current_mode() - .is_some_and(|mode| mode != mirror_mode) - }) || mirrored_output.current_scale().fractional_scale() - != self.output.current_scale().fractional_scale() + MirroringOutputConfig::for_output_untransformed(mirrored_output) + != MirroringOutputConfig::for_output(&self.output) }) { + let mirrored_output_config = + MirroringOutputConfig::for_output_untransformed(mirrored_output); let mirroring_state = match self.mirroring_textures.entry(self.target_node) { - hash_map::Entry::Occupied(occupied) => occupied.into_mut(), + hash_map::Entry::Occupied(occupied) => { + let mirroring_state = occupied.into_mut(); + if mirroring_state.output_config != mirrored_output_config { + *mirroring_state = MirroringState::new_with_renderer( + &mut renderer, + compositor.format(), + mirrored_output_config, + )? + } + mirroring_state + } hash_map::Entry::Vacant(vacant) => { vacant.insert(MirroringState::new_with_renderer( &mut renderer, compositor.format(), - mirrored_output, + mirrored_output_config, )?) } };