From dad5a08c1f427e21c2a17af21b6cf95ae3ae9292 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sat, 13 Jun 2026 11:28:11 +0000 Subject: [PATCH] =?UTF-8?q?chore(capture):=20tidy=20the=20GNOME=20flash=20?= =?UTF-8?q?diagnostic=20=E2=80=94=20it's=20the=20CORRUPTED=20skip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live confirmation on worker-3: the flash was Mutter's CORRUPTED, size-0 cursor-update buffers (chunk_flags=CORRUPTED) carrying recycled old frames — drained=1 always, so latest-frame-only draining wasn't the lever, the CORRUPTED skip was (OBS issue 8630). Demote the verbose drain diagnostic to a rate-limited debug line and document the root cause inline. Validated: zero-copy back on GNOME (dmabuf->CUDA, 5120x1440) AND flash-free with FORCE_SHM off. Co-Authored-By: Claude Opus 4.8 (1M context) --- crates/punktfunk-host/src/capture/linux.rs | 31 +++++++++------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/crates/punktfunk-host/src/capture/linux.rs b/crates/punktfunk-host/src/capture/linux.rs index 3f66186..9b6b103 100644 --- a/crates/punktfunk-host/src/capture/linux.rs +++ b/crates/punktfunk-host/src/capture/linux.rs @@ -1106,28 +1106,23 @@ mod pipewire { let corrupted = (hdr_flags & spa::sys::SPA_META_HEADER_FLAG_CORRUPTED) != 0 || (chunk_flags & spa::sys::SPA_CHUNK_FLAG_CORRUPTED as i32) != 0; - // Rate-limited diagnostic (~once/sec): drain depth + chunk size/flags + header - // flags. Tells us whether buffers queue up (latest-frame-only helps) and whether - // stale buffers are flagged CORRUPTED or report size 0. - if drained > 1 || chunk_flags != 0 || hdr_flags != 0 { + // THE GNOME FLASH FIX: skip Mutter's CORRUPTED / size-0 cursor-update buffers. + // When the pointer moves (e.g. dragging a window) Mutter sends metadata-only + // buffers flagged CORRUPTED (chunk size 0) that still reference a RECYCLED old + // frame; consuming them encodes "the window at its old position" — the flash. + // Confirmed live on worker-3 (chunk_flags=CORRUPTED, size 0) for both the zero-copy + // and SHM paths. The size-0 half is SHM-only (a real dmabuf legitimately reports + // chunk size 0). `drained` is the latest-frame-only depth — a cheap extra defense + // against bursty delivery, though here Mutter sends one buffer per callback. + if corrupted || (chunk_size == 0 && !is_dmabuf) { ud.dbg_log_n += 1; - if ud.dbg_log_n.is_power_of_two() || ud.dbg_log_n % 60 == 0 { - tracing::info!( + if ud.dbg_log_n.is_power_of_two() { + tracing::debug!( + skipped = ud.dbg_log_n, drained, - chunk_size, - chunk_flags, - hdr_flags, - corrupted, - n = ud.dbg_log_n, - "capture: latest-frame-only drain (diagnostic)" + "capture: skipped a stale CORRUPTED/cursor buffer (GNOME)" ); } - } - - // Skip a CORRUPTED stale buffer (or a size-0 SHM buffer — a dmabuf legitimately - // reports size 0) — requeue it and wait for the next. - if corrupted || (chunk_size == 0 && !is_dmabuf) { - warn_once("capture: skipped a CORRUPTED/size-0 buffer (stale frame)"); unsafe { stream.queue_raw_buffer(newest) }; return; }