gamescope: the display's rate is the mode, and generation follows the cap and the multiplier

Merged
JO
9d ago
+44-3

The gamescope session's emulated display takes its rate from the display, and the frame generation and the frame counter follow the cap and the multiplier. Together with GameNative/gamenative-drm#41 and GameNative/gamescope#26.

At a 40 cap, changing only the multiplier: x2 produces and counts 80 frames a second, x3 120, x4 160, on a 120 Hz or a 60 Hz display alike, and the mode does not move — it changes only when the display does.

What it does

  • applyPanelRefresh reports the display's own rate to the daemon and nothing else; the cap and the multiplier never enter it. The mode nudge (backend_set_dirty, now allowlisted in the injector) is asked for only by the display listener, so a display change reaches a running session and a QuickMenu change moves nothing.
  • applyLsfgMultiplier reports the rate before the LSFG settings, so the config the shim opens the generator from carries the rate in force.

Measured

Retroid Pocket Nova, Hades II, cap 40, one session per display:

displayx2x3x4mode
120 Hz80.0120.0160.0120 Hz throughout, one selecting mode, no nudges
60 Hz79.8120.0160.060 Hz throughout, 40.3 acquires/s

Forcing the display 120 → 60 mid-session reported 60 and re-selected the mode once, which is the display-change path. The reverse could not be forced on this device (SurfaceFlinger kept the panel at 60 until the session ended), so that direction is unverified rather than verified-working.

Files

  • ui/screen/xserver/XServerScreen.kt — applyPanelRefresh, the change-only nudge, the rate applied before the LSFG settings.
  • display/GamescopeConVar.kt — BACKEND_SET_DIRTY.
  • display/GamescopeCommandQueue.kt — nudgeDisplayMode().
  • display/GamescopePayload.kt — payload 20261101.1.
  • jniLibs/arm64-v8a/libgamenative_drm.so — rebuilt (aa33a6a4) from gamenative-drm#41.

The branch's earlier commits describe two intermediate designs this one replaces (the mode following the cap, then the produced rate); the final state is what the diff shows.


Summary by cubic

The gamescope session now advertises the display's own rate as the emulated mode, so the frame-rate cap and generation multiplier affect only frame production and counting, never the mode. The mode changes when the display does, and a mode nudge is issued only on a display change.

  • applyPanelRefresh reports the display rate alone and nudges the mode only when that rate changes after the first report.
  • applyLsfgMultiplier applies the rate before the LSFG settings so the generator opens with the rate in force.
  • Payload bumps to 20261101.6, replacing 20261101.5's Xwayland (which never signaled ready because it lacked the unversioned-libxcvt fix) with one linked against the payload's libxcvt.so; the rebuilt libgamenative_drm.so no longer halves the source rate on slow panels.

Summary by CodeRabbit

  • Bug Fixes
    • Gamescope sessions now report the active display refresh rate and update the display mode when that rate changes.
    • FPS cap and LSFG changes no longer affect the reported display mode refresh rate.
    • LSFG updates apply the FPS limit before LSFG settings. X11 sessions and invalid refresh rates are unaffected.
  • Updates
    • Updated the Gamescope runtime.