daemon: send the page-flip event when SurfaceFlinger latches the frame

UT
9d ago
+645-104

Problem

The daemon reported a page flip as soon as the transaction was applied, before SurfaceFlinger had shown the frame. gamescope releases the replaced client buffer on that event, so the client could render into a buffer still on the panel. The event was also stamped from the daemon's own vblank grid rather than the real latch.

Change

A commit with a new framebuffer is armed on a small ordered gate and its event leaves when SurfaceFlinger's completion callback for that transaction arrives, stamped with the latch time (clamped to now, monotonic), and once the release fence delivered with the previous completion has signalled (that is the buffer gamescope A56 releases at this event; in steady state it has already signalled, waits are counted as prev_release_waits=). Exactly one event per commit, in commit order; a later completion completes earlier commits; a commit the presenter showed nothing for completes at once; a 50 ms valve after publish, logged rate-limited. Commits with no new framebuffer are immediate as before. Release-fence storage, hide, overlay counting and present-done are unchanged.

Pairs with gamescope A56 (release the framebuffers a flip replaced at the next flip).

Measured (Retroid Pocket 6)

  • SteamWorld Dig 2, cap 60: 59.9 fps, 84 % of intervals on the 2-vsync grid (69 % on the shipped build), valve never hit.
  • Blazing Chrome (DXVK), cap 60: 59.5 fps, no stalls; Dave the Diver with frame generation: unchanged.

Tests: 75 unit + 8 + 36 golden; clippy clean.