renderer: skip wakeup-driven drawFrame when animation timer is running

renderCallback (fired on any libghostty wakeup) always called
drawFrame at the end, on top of the 125 FPS animation timer that
runs whenever custom-shader-animation is engaged. Under busy
terminal output the wakeup rate stacks on top of the timer rate,
multiplying the per-frame Wayland commit + GPU submit work on
both threads with no visible benefit (the timer already presents
within DRAW_INTERVAL of the cell rebuild).

When draw_active, the timer is the authoritative present clock —
let renderCallback do updateFrame (cells need rebuilding regardless)
but skip drawFrame and trust the next timer tick to pick up the
new cells. When draw_active is false (no shader animation), wakeups
are the only present trigger so the draw still has to happen here.

Cuts host-thread CPU substantially under high-output scenarios
(seq, yes, log tailing) — bounded total drawFrame rate at the
animation interval instead of summing wakeups + timer ticks.

Co-Authored-By: claude-flow <ruv@ruv.net>
pull/12846/head
Nathan 2026-05-25 21:22:27 -05:00
parent 88788948fa
commit 96d4d67af3
1 changed files with 9 additions and 2 deletions

View File

@ -623,8 +623,15 @@ fn renderCallback(
) catch |err|
log.warn("error rendering err={}", .{err});
// Draw
t.drawFrame(false);
// Draw. When the animation draw timer is already running
// (custom-shader-animation engaged), it will pick up the
// newly-updated cells at its next DRAW_INTERVAL tick drawing
// here too would double-up frames during animated-shader periods
// and burn host-thread CPU (per-frame Wayland buffer attach +
// commit on the Qt apprt) for no visible benefit. Without the
// timer, wakeup-driven draws are the only way frames reach the
// host, so we always draw in that case.
if (!t.draw_active) t.drawFrame(false);
return .disarm;
}