git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit68db40e5ddb758ba1cdb4dbd3775fd8abc8c8c3d
parent85e52d9fd7
authorLucas Galante <[email protected]>
date2026-09-04 10:38
perf(pan): skip the status-bar backdrop measurement while the camera is moving

measure_status_backdrops ran on every output frame, before the
needs-frame early-out, so a pan pushed a backdrop update (and a bar
repaint) on most frames as the lattice slid under each segment — and,
worse, a window under a segment moved its sampled region every frame,
which defeated the per-(window, region) readback cache: a GPU texture
readback inside the render path, per pan frame. The measurement now
waits for the camera to settle; the settle's full repaint frame measures
once with the final camera, so the bar's tint still follows every pan.

A/B in a headless shadow with the nine bar segments, cce-grid and
cce-fonts, four 60-notch pans: render mean 2078us / p95 3507us / max
12.3ms before, 1504us / 2254us / 3.4ms after.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

 src/server/output.rs | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/server/output.rs b/src/server/output.rs
index 0e60309..fb68875 100644
--- a/src/server/output.rs
+++ b/src/server/output.rs
@@ -536,10 +536,18 @@ impl Output {
         self.draw_grid();
         self.draw_adjust_overlay();
         // Right after draw_grid, whose geometry this reuses, and BEFORE the
-        // needs-frame early-out: a camera pan slides the lattice under a
+        // needs-frame early-out: a camera move slides the lattice under a
         // segment that has no damage of its own, and the bar still has to
-        // hear about it.
-        self.measure_status_backdrops();
+        // hear about it — once the camera has SETTLED. During the motion
+        // itself the measurement is skipped: the sliding lattice changed the
+        // quantized reading on most frames (a push and a bar repaint each),
+        // and a window under a segment moved its sampled region every frame,
+        // defeating the per-(window, region) readback cache — a GPU texture
+        // readback inside the render path, per pan frame. The settle's full
+        // repaint frame runs the measurement with the final camera.
+        if !(*self.server).wm.viewport_is_active {
+            self.measure_status_backdrops();
+        }
 
         // A parked `ccectl screenshot` targeting this output forces a render
         // even without damage so there is a fresh buffer to read back.