WIP: backend/native: Add support for variable refresh rate
I decided to open this MR in a WIP state to get some feedback on the general approach, so any feedback is highly appreciated. This MR includes a few workarounds for some issues that should be solved properly first. (see Prerequisites below)
This MR adds the logic required to detect monitors that are capable of VRR and the ability to activate it using KMS properties.
It also adds the ability to enable or disable VRR on capable monitors using the
DisplayConfig DBus API, and makes this configuration persist via
Finally, once configured to be enabled, VRR is actually activated on a monitor when a window that supports it covers the entire monitor on the visible workspace, doesn't have any transitions or animations, and isn't covered by any shell UI elements.
Missing Wayland Protocol
Support for VRR isn't advertised by Wayland (and Xwayland) clients at the moment since there is no Wayland protocol that allows this support to be advertised. (wayland/wayland/issues/84) There are also alternative solutions being proposed. (https://lists.freedesktop.org/archives/dri-devel/2020-March/258940.html)
Instead, for the purpose of testing, top-level Xwayland windows that support VRR are detected by querying for the X property "_VARIABLE_REFRESH". This property is set by Mesa on X windows that support VRR, and is used by the X server in X sessions to detect windows that support VRR.
Unlike the X server, child windows of top-level windows can't be detected using this technique since Mutter doesn't track their X properties. This does prevent some windows from being detected correctly.
Doesn't Always Prevent Stutter
There are still some limitations in Mutter that are expected to cause stutter, and VRR isn't going to help in these cases. In fact, it may cause the stutter to appear slightly more severe. The following are the ones that were identified so far.
Stutter in Multi-Monitor Setups
Mutter only has one frame clock for the entire stage (#903 (closed)). In multi-monitor setups, the frame rate of the stage is changed based on the draw rate of the individual windows across all monitor, regardless of their refresh rate. Stutter is expected to happen with monitors that have different refresh rates, and even more so when only one of them supports variable refresh rate.
Stutter with Non-throttled Applications
Mutter does not perform any kind of fencing on buffers sent by its clients (#1162), which means that its own frame rate is often lower than the frame rate of its clients when they perform heavy rendering without any kind of frame throttling. To work around this issue, the rendering of such clients should be throttled to allow Mutter to render its own frames in time. The easiest way to to this is to enable VSync at the application level.
- WIP commits either require more testing, additional logic or a different approach.
- Temporary commits are used for testing purposes or work around issues that should be solved in a different way. Each of them has its reasoning in its commit message.
- Some commits were taken from !798 (merged) as prerequisites and slightly modified to only include the required logic.
gnome-control-center!734 – Adds a switch for
Variable Refresh Ratein
This MR is blocked by the following issues:
#903 (closed) – Variable refresh rate requires the compositor to draw and perform a page flip as soon as the relevant client commits its own frame. This allows the compositor to properly communicate the draw frequency of the client to the kernel driver responsible for dynamically adjusting the refresh rate of the monitor. However, Mutter does not currently allow individual outputs to drive its draw frequency, so it's not simple to know when VRR is enabled on an output and adjust the draw frequency accordingly.
- A workaround for this issue is included in this MR, but it is expected to create jitter in non-VRR scenarios. (see commit message for more details)
#1255 – Even if Mutter would allow drawing at different frequencies on different outputs, Wayland clients would still only get input events once for every stage redraw. This means that in the common VRR scenario, where the frame rate of the client is lower than the maximum refresh rate of the monitor, the resolution of input events would be lower than usual, creating input stutter from the point of view of the client.
- A proposed solution for this issue is included in this MR (!1241).