ValveSoftware/gamescope

Repaints from cursor movement in DRM/Wayland backends should clamp to the frame rate/refresh rate of a focused window when using VRR

matte-schwartz opened this issue · 1 comments

I think this probably qualifies as a improvement, but maybe it's a bug report. Right now, the cursor within gamescope's DRM and Wayland (with --force-grab-cursor) backends will always repaint at the highest refresh rate, even while utilizing VRR. So for example: gamescope --force-grab-cursor --adaptive-sync -r 120 -f -- vrrtest will grab the cursor, then if you adjust the vrrtest frame limit down, moving the cursor will still repaint at 120hz even while the display is matching vrrtest's refresh rate otherwise. I've tried looking through the gamescope code to see if there was some function that was meant to handle this, but I was not able to pinpoint one.

Ideally, I think we should try and do what KWin does with Plasma 6 Wayland while adaptive sync is set to "Automatic", which is sync the cursor to the frame rate of the content and thus matching the refresh rate of the display. Implementing something like this would let us account for some problematic VRR displays that show pronounced flickering when lighting up between different refresh rates.

@matte-schwartz @misyltoad
I think (tho still w/ less than 100% confidence) that the code that's causing this to happen is in wlserver.cpp in wlserver_oncursorevent(), specifically this line: https://github.com/ValveSoftware/gamescope/blame/38e907427ee3aad2d2e30f7aa1109b4bf4943b7b/src/wlserver.cpp#L2112

wlserver_oncursorevent() currently will always set hasRepaint to true, with no limit for how frequently it does so. And in the code in steamcompmgr that checks if it should paint, it seems like there's no limit for how frequently hasRepaint can cause a repaint.

Note that there's one other cursor-related place in wlserver that also sets repaint to true: wlserver_mousehide(), but I'm pretty sure that function runs a lot less frequently compared to wlserver_oncursorevent()

I'm guessing that the aforementioned function is most frequently called by wlserver_mousemotion(), and from searching here: https://github.com/search?q=repo%3AValveSoftware/gamescope%20wlserver_mousemotion&type=code
it looks like wlserver_mousemotion() is used by the SDL, wayland and openvr backends. Not sure if it's ever used indirectly by the drm backend...