diff options
author | Mario Kleiner <mario.kleiner.de@gmail.com> | 2021-08-28 02:27:20 +0200 |
---|---|---|
committer | Povilas Kanapickas <povilas@radix.lt> | 2021-09-07 09:21:39 +0000 |
commit | 8f8ebf870b55c9875b7cfd8ef69c1df02d589b4a (patch) | |
tree | f42b59234c39c2926078cdfcadb87497789fbae9 | |
parent | 7d34b1f2b7c612c3171e0b9758b5fc094bc33f63 (diff) |
modesetting: Allow Present flips with mismatched stride on atomic drivers.
When using DRI3+Present with PRIME render offload, sometimes there is
a mismatch between the stride of the to-be-presented Pixmap and the
frontbuffer. The current code would reject a pageflip present in this
case if atomic modesetting is not enabled, ie. always, as atomic
modesetting is disabled by default due to brokeness in the current
modesetting-ddx.
Fullscreen presents without page flipping however trigger the copy
path as fallback, which causes not only unreliable presentation timing
and degraded performance, but also massive tearing artifacts due to
rendering to the framebuffer without any hardware sync to vblank.
Tearing is extra awful on modesetting-ddx because glamor afaics seems
to use drawing of a textured triangle strip for the copy implementation,
not a dedicated blitter engine. The rasterization pattern creates extra
awful tearing artifacts.
We can do better: According to a tip from Michel Daenzer (thanks!),
at least atomic modesetting capable kms drivers should be able to
reliably change scanout stride during a pageflip, even if atomic
modesetting is not actually enabled for the modesetting client.
This commit adds detection logic to find out if the underlying kms
driver is atomic_modeset_capable, and if so, it no longer rejects
page flip presents on mismatched stride between new Pixmap and
frontbuffer.
We (ab)use a call to drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 0);
for this purpose. The call itself has no practical effect, as it
requests disabling atomic mode, although atomic mode is disabled by
default. However, the return value of drmSetClientCap() tells us if the
underlying kms driver is atomic modesetting capable: An atomic driver
will return 0 for success. A legacy non-atomic driver will return a
non-zero error code, either -EINVAL for early atomic Linux versions
4.0 - 4.19 (or for non-atomic Linux 3.x and earlier), or -EOPNOTSUPP
for Linux 4.20 and later.
Testing on a MacBookPro 2017 with Intel Kabylake display server gpu +
AMD Polaris11 as prime renderoffload gpu, X-Server master + Mesa 21.0.3
show improvement from unbearable tearing to perfect, despite a stride
mismatch between display gpu and Pixmap of 11776 Bytes vs. 11520
Bytes. That this is correct behaviour was also confirmed by comparing the
behaviour and .check_flip implementation of the patched modesetting-ddx
against the current intel-ddx SNA Present implementation.
Please consider merging this patch before the server-1.21 branch point.
This patch could also be cherry-picked into the server 1.20 branch to
fix the same limitation.
Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
-rw-r--r-- | hw/xfree86/drivers/modesetting/driver.c | 8 | ||||
-rw-r--r-- | hw/xfree86/drivers/modesetting/driver.h | 1 | ||||
-rw-r--r-- | hw/xfree86/drivers/modesetting/present.c | 7 |
3 files changed, 14 insertions, 2 deletions
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c index df1abea17..fde65e0e5 100644 --- a/hw/xfree86/drivers/modesetting/driver.c +++ b/hw/xfree86/drivers/modesetting/driver.c @@ -1220,6 +1220,14 @@ PreInit(ScrnInfoPtr pScrn, int flags) #endif } + /* + * Use "atomic modesetting disable" request to detect if the kms driver is + * atomic capable, regardless if we will actually use atomic modesetting. + * This is effectively a no-op, we only care about the return status code. + */ + ret = drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 0); + ms->atomic_modeset_capable = (ret == 0); + if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_ATOMIC, FALSE)) { ret = drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 1); ms->atomic_modeset = (ret == 0); diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h index 114971048..6217a0e64 100644 --- a/hw/xfree86/drivers/modesetting/driver.h +++ b/hw/xfree86/drivers/modesetting/driver.h @@ -116,6 +116,7 @@ typedef struct _modesettingRec { * Page flipping stuff. * @{ */ + Bool atomic_modeset_capable; Bool atomic_modeset; Bool pending_modeset; /** @} */ diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c index 916a15303..b90a1b8ac 100644 --- a/hw/xfree86/drivers/modesetting/present.c +++ b/hw/xfree86/drivers/modesetting/present.c @@ -267,8 +267,11 @@ ms_present_check_unflip(RRCrtcPtr crtc, if (num_crtcs_on == 0) return FALSE; - /* Check stride, can't change that on flip */ - if (!ms->atomic_modeset && + /* + * Check stride, can't change that reliably on flip on some drivers, unless + * the kms driver is atomic_modeset_capable. + */ + if (!ms->atomic_modeset_capable && pixmap->devKind != drmmode_bo_get_pitch(&ms->drmmode.front_bo)) return FALSE; |