Report the panel's active refresh rate to the gndrm daemon
What this fixes
Under gamescope the daemon measures the panel's latch grid (vsync.rs) against the refresh rate the app reports through GameNativeDrm.nativeSetPanelRefreshHz. The app reported detectMaxRefreshRateHz, the fastest mode the panel supports, so on a panel a user holds at 60 Hz the daemon tracked a 120 Hz lattice and told the shim the latch period was 8.33 ms. The ICD's frame cap now places the game's frames on that grid (GameNative/gamenative-drm#34); with the wrong period it snaps to points that are not latch points, and commits land on the edge of the real window. Measured on the Odin 3 (panel at 60 Hz, maximum 120): the shim logged panel grid period=8333us before this change and period=16666us after.
The change
detectActiveRefreshRateHz: the display's current mode (Display.refreshRate), falling back to the maximum only when it cannot be read.- The gamescope branch of session setup reports the active rate ahead of
nativeStart, and registers aDisplayManager.DisplayListenerthat reports it again ononDisplayChanged, so a mode switch mid-session reaches the daemon. The listener is unregistered at session exit, just beforenativeStop. detectMaxRefreshRateHzstays for the limiter's ceiling.
Verification
:app:compileModernDebugKotlinpasses on master.- Odin 3 debug build: the daemon's grid period went from 8333 µs to 16666 µs with the panel at 60 Hz.
Standalone on master; the earlier copy stacked on the scan-out-size branch (joshuatam/GameNative#22) is closed.
Summary by cubic
Reports the panel's active refresh rate and scan-out size to the gndrm daemon so the latch grid and emulated mode track the real display instead of the fastest supported rate and the window's size.
Previously the daemon measured the latch grid against the panel's maximum rate, so a panel held at 60 Hz was tracked as a 120 Hz lattice and gave the shim an 8.33 ms latch period; with the active rate the period matches the real mode (16666 µs on the Odin 3). Separately, the emulated connector advertised the app window's size, so gamescope's -W/-H never matched a mode and the session always scanned out at the panel's pixel count.
- One
detectRefreshRateHzhelper, readingdisplay.refreshRatewith a safe fallback, serves both the daemon and the FPS limiter's ceiling. - A
DisplayManager.DisplayListenerre-reports the rate on mode changes and is unregistered at session exit. nativeSetScanoutGeometrysets the daemon's mode from the Upscaling Resolution; the default is now Off (1:1 at the container's screen size), andscanoutSize()feeds gamescope's-W/-H, the shim's seed, and the daemon from one value.- Payload bumped to 20261030.2 and the DRM
.sorebuilt.
Summary by CodeRabbit
- Bug Fixes
- Improved refresh-rate detection to use the display’s current active mode, with a fallback when the rate is unavailable or invalid.
- Games now receive the active display refresh rate at startup and when the display mode changes, helping keep frame-rate limits aligned with the screen. The display-change listener is also cleaned up when the game exits.