diff --git a/src/backend/kms/surface/mod.rs b/src/backend/kms/surface/mod.rs index 41d95cf2..e7cc3a24 100644 --- a/src/backend/kms/surface/mod.rs +++ b/src/backend/kms/surface/mod.rs @@ -819,8 +819,12 @@ impl SurfaceThreadState { self.timings.presented(clock); - while let Ok(PendingImageCopyData { frame, damage, .. }) = frames.recv() { - frame.success(self.output.current_transform(), damage, clock); + while let Ok(pending_image_copy_data) = frames.recv() { + pending_image_copy_data.send_success_when_ready( + self.output.current_transform(), + &self.loop_handle, + clock, + ); } } } diff --git a/src/wayland/handlers/screencopy/render.rs b/src/wayland/handlers/screencopy/render.rs index 14263980..6d157660 100644 --- a/src/wayland/handlers/screencopy/render.rs +++ b/src/wayland/handlers/screencopy/render.rs @@ -1,3 +1,4 @@ +use calloop::LoopHandle; use smithay::{ backend::{ allocator::{dmabuf::Dmabuf, format::get_transparent, Buffer, Fourcc}, @@ -60,6 +61,39 @@ pub struct PendingImageCopyData { pub sync: SyncPoint, } +impl PendingImageCopyData { + /// Send `success` to image copy frame, once sync point is reached + pub fn send_success_when_ready( + self, + transform: Transform, + loop_handle: &LoopHandle<'static, LoopData>, + presented: impl Into, + ) { + let presented = presented.into(); + if self.sync.is_reached() { + self.frame.success(transform, self.damage, presented); + } else if let Some(fence_fd) = self.sync.export() { + let source = calloop::generic::Generic::new( + fence_fd, + calloop::Interest::READ, + calloop::Mode::OneShot, + ); + let mut data = Some(self); + loop_handle + .insert_source(source, move |_, _, _| { + let data = data.take().unwrap(); + data.frame.success(transform, data.damage, presented); + Ok(calloop::PostAction::Remove) + }) + .expect("Failed to wait on sync point"); + } else { + // Should be able to export fence; but otherwise wait + let _ = self.sync.wait(); + self.frame.success(transform, self.damage, presented); + } + } +} + pub fn submit_buffer( frame: Frame, renderer: &mut R,