From 471dc714aa31243f68686fb35c2b5e44bd9be33b Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Fri, 23 Aug 2024 11:02:34 +0300 Subject: Add damage check to PW screencasts Avoids unnecessary frames. --- src/niri.rs | 10 ++++------ src/pw_utils.rs | 30 ++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/niri.rs b/src/niri.rs index 27696749..431a42f8 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -3657,9 +3657,8 @@ impl Niri { let elements = elements.get_or_insert_with(|| { self.render(renderer, output, true, RenderTarget::Screencast) }); - let elements = elements.iter().rev(); - if cast.dequeue_buffer_and_render(renderer, elements, size, scale) { + if cast.dequeue_buffer_and_render(renderer, &elements, size, scale) { cast.last_frame_time = target_presentation_time; } } @@ -3717,9 +3716,9 @@ impl Niri { } // FIXME: pointer. - let elements = mapped.render_for_screen_cast(renderer, scale).rev(); + let elements: Vec<_> = mapped.render_for_screen_cast(renderer, scale).collect(); - if cast.dequeue_buffer_and_render(renderer, elements, bbox.size, scale) { + if cast.dequeue_buffer_and_render(renderer, &elements, bbox.size, scale) { cast.last_frame_time = target_presentation_time; } } @@ -3802,9 +3801,8 @@ impl Niri { .rev() .collect::>() }); - let elements = elements.iter(); - if cast.dequeue_buffer_and_render(renderer, elements, bbox.size, scale) { + if cast.dequeue_buffer_and_render(renderer, &elements, bbox.size, scale) { cast.last_frame_time = target_presentation_time; } } diff --git a/src/pw_utils.rs b/src/pw_utils.rs index 281fb3a9..d7c3c44d 100644 --- a/src/pw_utils.rs +++ b/src/pw_utils.rs @@ -31,6 +31,7 @@ use smithay::backend::allocator::format::FormatSet; use smithay::backend::allocator::gbm::{GbmBuffer, GbmBufferFlags, GbmDevice}; use smithay::backend::allocator::{Format, Fourcc}; use smithay::backend::drm::DrmDeviceFd; +use smithay::backend::renderer::damage::OutputDamageTracker; use smithay::backend::renderer::element::RenderElement; use smithay::backend::renderer::gles::GlesRenderer; use smithay::output::WeakOutput; @@ -87,6 +88,8 @@ pub enum CastState { alpha: bool, modifier: Modifier, plane_count: i32, + // Lazily-initialized to keep the initialization to a single place. + damage_tracker: Option, }, } @@ -417,6 +420,7 @@ impl PipeWire { alpha, modifier, plane_count, + .. } if *alpha == format_has_alpha && *modifier == Modifier::from(format.modifier()) => { @@ -425,6 +429,13 @@ impl PipeWire { let modifier = *modifier; let plane_count = *plane_count; + let damage_tracker = + if let CastState::Ready { damage_tracker, .. } = &mut *state { + damage_tracker.take() + } else { + None + }; + debug!("pw stream: moving to ready state"); *state = CastState::Ready { @@ -432,6 +443,7 @@ impl PipeWire { alpha, modifier, plane_count, + damage_tracker, }; plane_count @@ -464,6 +476,7 @@ impl PipeWire { alpha: format_has_alpha, modifier, plane_count: plane_count as i32, + damage_tracker: None, }; plane_count as i32 @@ -733,10 +746,23 @@ impl Cast { pub fn dequeue_buffer_and_render( &mut self, renderer: &mut GlesRenderer, - elements: impl Iterator>, + elements: &[impl RenderElement], size: Size, scale: Scale, ) -> bool { + let CastState::Ready { damage_tracker, .. } = &mut *self.state.borrow_mut() else { + error!("cast must be in Ready state to render"); + return false; + }; + let damage_tracker = damage_tracker + .get_or_insert_with(|| OutputDamageTracker::new(size, scale, Transform::Normal)); + + let (damage, _states) = damage_tracker.damage_output(1, elements).unwrap(); + if damage.is_none() { + trace!("no damage, skipping frame"); + return false; + } + let mut buffer = match self.stream.dequeue_buffer() { Some(buffer) => buffer, None => { @@ -754,7 +780,7 @@ impl Cast { size, scale, Transform::Normal, - elements, + elements.iter().rev(), ) { warn!("error rendering to dmabuf: {err:?}"); return false; -- cgit