diff --git a/android/patches/gamescope/0050-A52-fps-limit-on-the-vblank-time-grid.patch b/android/patches/disabled/0050-A52-fps-limit-on-the-vblank-time-grid.patch similarity index 89% rename from android/patches/gamescope/0050-A52-fps-limit-on-the-vblank-time-grid.patch rename to android/patches/disabled/0050-A52-fps-limit-on-the-vblank-time-grid.patch index afd5c7953..ec02a8402 100644 --- a/android/patches/gamescope/0050-A52-fps-limit-on-the-vblank-time-grid.patch +++ b/android/patches/disabled/0050-A52-fps-limit-on-the-vblank-time-grid.patch @@ -4,13 +4,13 @@ The non-VRR frame-rate limit counted compositor wakeups: a window got its frame callback on every (refresh / target)th wakeup, which equals every Nth vblank only while no wakeup is ever late. The timer re-arms by stepping to the next vblank after "now", so a wakeup that comes more than one vblank late skips the vblanks -in between, and those never count. On the 1200 Hz grid a session runs on -(-r 1200, the nested refresh), a wakeup is late by a vblank after 0.83 ms of -scheduling delay, and every late one holds the next frame a whole vblank -longer: a 60 cap then reads 50-57, a 30 cap 25-28, in proportion to the wakeups -lost -- the flat 18-21 ms frames users saw with the CPU and the GPU idle -- and -it sinks further as the device throttles and the compositor thread is scheduled -later still. +in between, and those never count. The finer the session grid, the sooner a +wakeup is late: on the fine grid the launcher used to pass, a sub-millisecond +scheduling delay already cost a whole vblank, and every late wakeup held the +next frame a vblank longer: a 60 cap then read 50-57, a 30 cap 25-28, in +proportion to the wakeups lost -- the flat 18-21 ms frames users saw with the +CPU and the GPU idle -- and it sinks further as the device throttles and the +compositor thread is scheduled later still. The limiter now keeps a release grid in time: the next release is the previous one plus the target period, and a frame is released on the first vblank whose diff --git a/android/patches/gamescope/0034-A47-drm-mode-lookup-by-size.patch b/android/patches/gamescope/0034-A47-drm-mode-lookup-by-size.patch index d041aac61..3e6fc9f0c 100644 --- a/android/patches/gamescope/0034-A47-drm-mode-lookup-by-size.patch +++ b/android/patches/gamescope/0034-A47-drm-mode-lookup-by-size.patch @@ -1,29 +1,27 @@ -A47 — take `-r` as the grid, not as the mode's refresh +A47 — resolve the mode by size when no mode carries the requested refresh -`-r` is the session's vblank grid, while the panel's real rate is what the DRM -mode advertises. `init_drm` hands the grid to `preferred_refresh`, and the mode -search requires `mode->vrefresh` to equal it, so a grid that matches no mode -falls through to the first mode on the connector — with `-r 1200` it matches -nothing. +`init_drm` hands `-r`, when the launcher gives one, to `preferred_refresh`, and +the mode search requires `mode->vrefresh` to equal it. A connector whose one mode +carries the display's real rate would then yield no output at all for any other +preferred refresh. The lookup now re-finds by the requested size with the refresh unconstrained, so -the nested refresh is free to differ from the mode's rate and a connector whose -modes all carry the real rate still yields an output. +a preferred refresh the connector does not advertise still resolves the mode, and +the launch line stays free to pass one. This is the second half of the old A34, kept when A34's fps cap was parked: the -cap no longer exists, but the grid argument does. +cap no longer exists, and the size-based lookup stays as insurance. --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp -@@ -1385,6 +1385,16 @@ +@@ -1385,6 +1385,15 @@ mode = find_mode(best->GetModeConnector(), drm->preferred_width, drm->preferred_height, gamescope::ConvertmHzToHz( drm->preferred_refresh )); } -+ // gamenative A47: -r is the session's vblank grid, not the mode's rate: the -+ // panel's real refresh is what the connector advertises, so the grid matches -+ // no mode. Re-find by size alone rather than let the grid pick the mode, so -+ // the nested refresh is free to differ from the mode's rate and a connector -+ // whose only modes carry the real rate still yields an output. ++ // gamenative A47: the mode is the display's rate and the connector ++ // advertises only that, so a preferred refresh it does not carry would find ++ // no mode at all. Re-find by size alone rather than let the preference pick ++ // the mode, so the launch line stays free to pass one. + if (!mode && drm->preferred_refresh != 0) + { + mode = find_mode(best->GetModeConnector(), drm->preferred_width, drm->preferred_height, 0);