forked from unom/punktfunk
The remaining ~21 ms display stage was the conservative release target: the presenter aimed at the first frame timeline whose DEADLINE was still ahead, and the platform's deadline budgets for GPU rendering the app has yet to submit (presDeadline = 11.3 ms on the A024 — more than a full 120 Hz period). A decoded video buffer has no GPU work left; its only real constraint is SurfaceFlinger's own latch lead. Every frame paid a whole extra refresh of waiting for a budget it never used. next_target now gates (and subdivides) on the timeline's EXPECTED PRESENT minus a 4 ms latch margin; the glass budget reopens at that latch instant (expected present − margin) rather than the deadline, which under the aggressive gate can already lie in the past — an instant reopen would let two releases pile onto one vsync. A mis-gamble presents one vsync later, which is exactly what the deadline gate paid on every frame — the trade is one-sided. On-glass (A024, 2800×1260@120 HDR, game load): latch p50 21→8-10 ms, display 26,3→9,5 (pace 0,8 + latch 7,7), e2e 43,7→26,4 p50 / 29,2 p95, released=displays=120, paced≈0, forced=0. The latch now sits under one refresh interval — the vsync-latch floor. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>