Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
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.