backend-drm: More aggressively avoid the stale timestamp workaround

At first we always used this workaround, and then we stopped using it when
VRR was in use.

Turns out it also hurts presentation times when starting the repaint loop,
which makes the commit-timing protocol difficult to implement.

Completely avoid the workaround on any kernel newer than 4.12, based on a
capability check for DRM_CAP_CRTC_IN_VBLANK_EVENT, and log a warning at
startup.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
This commit is contained in:
Derek Foreman 2025-10-07 13:32:52 -05:00
parent fc2e365c1d
commit d88efaea66
3 changed files with 36 additions and 9 deletions

View file

@ -261,6 +261,9 @@ struct drm_backend {
struct wl_event_source *pageflip_timer_counter;
bool timer_armed;
} perf_page_flips_stats;
/* True if we need a workaround for some very old kernels */
bool stale_timestamp_workaround;
};
struct drm_mode {

View file

@ -992,17 +992,22 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
*
* However, if we're using VRR, the time since the last
* vblank could be the display's longest possible frame
* time, which is longer than rfresh_nsec. That looks
* time, which is longer than refresh_nsec. That looks
* exactly like the bug we need to work around here, and
* the page flip workaround would result in an unnecessary
* delay.
*
* We know that the kernel bug was fixed in v4.1, before the
* much later introduction of the vrr_capable property we
* use to detect VRR. So we only need the bug fix if we don't
* have VRR.
* The workaround can cause other unexpected delays when
* starting the repaint loop.
*
* We keep the workaround in place, based on the presence of
* DRM_CAP_CRTC_IN_VBLANK_EVENT, which was introduced in
* Linux 4.12, to keep things working for Very Old Kernels.
*
* Anyone needing precise frame timings is encouraged to
* upgrade.
*/
if (output->base.vrr_mode == WESTON_VRR_MODE_NONE) {
if (output->backend->stale_timestamp_workaround) {
struct timespec vbl2now;
int64_t refresh_nsec;

View file

@ -1994,10 +1994,29 @@ init_kms_caps(struct drm_device *device)
return -1;
}
if (!getenv("WESTON_DISABLE_ATOMIC")) {
ret = drmGetCap(device->drm.fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &cap);
if (ret != 0)
cap = 0;
/* Between Linux 3.16 and Linux 4.1 there was a bug that
* could result in a stale timestamp being returned.
*
* The workaround for this has can make it impossible
* to display images with precise timing.
*
* It's somewhat difficult to determine whether we need
* that workaround or not, but we know that the
* DRM_CAP_CRTC_IN_VBLANK_EVENT drm cap exists in 4.12
* and on. We'll use its presence to gate the workaround.
*/
if (!cap) {
weston_log("DRM Warning: stale timestamp workaround for Kernel older than 4.12\n");
device->backend->stale_timestamp_workaround = true;
} else {
device->backend->stale_timestamp_workaround = false;
}
if (!getenv("WESTON_DISABLE_ATOMIC")) {
ret = drmSetClientCap(device->drm.fd, DRM_CLIENT_CAP_ATOMIC, 1);
device->atomic_modeset = ((ret == 0) && (cap == 1));
}