[PATCH xserver] modesetting: Only use modifiers on kms drivers which do support them.
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Fri Apr 20 19:50:18 UTC 2018
Hi,
It seems to do the right thing, so:
On Fri, 2018-04-20 at 19:59 +0200, Mario Kleiner wrote:
> Use the DRM_CAP_ADDFB2_MODIFIERS query to make sure the kms
> driver supports modifiers in the addfb2 ioctl, and fall back
> to addfb ioctl without modifiers if modifiers are unsupported.
>
> E.g., as of Linux 4.17, nouveau-kms so far does not suppport
> modifiers and gets angry if drmModeAddFB2WithModifiers() is
> called (-> failure to set a video mode -> blank screen), but
> Mesa's nvc0+ gallium driver causes gbm_bo_get_modifier() to
> return a valid modifier by translating the default tiling of
> bo's created via gbm_bo_create() into a modifier other than
> DRM_FORMAT_MOD_INVALID (see Mesa's nvc0_miptree_get_modifier()).
>
> Testing for != DRM_FORMAT_MOD_INVALID is apparently not
> sufficient for safe use of drmModeAddFB2WithModifiers.
>
> Bonus: Handle potential failure of populate_format_modifiers().
>
> The required DRM_CAP is defined since libdrm v2.4.65, and we
> require v2.4.89+ for the server, so we can use it unconditionally.
>
> Tested on intel-kms, radeon-kms, nouveau-kms. Fixes failure on
> NVidia Pascal.
>
> Fixes: 2f807c2324b4 ("modesetting: Add support for multi-plane
> pixmaps when page-flipping")
> Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
> Cc: Daniel Stone <daniels at collabora.com>
Reviewed-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
> ---
> hw/xfree86/drivers/modesetting/driver.c | 5 +++++
> hw/xfree86/drivers/modesetting/driver.h | 2 ++
> hw/xfree86/drivers/modesetting/drmmode_display.c | 13 ++++++-------
> 3 files changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/hw/xfree86/drivers/modesetting/driver.c
> b/hw/xfree86/drivers/modesetting/driver.c
> index 7682b24..5d8906d 100644
> --- a/hw/xfree86/drivers/modesetting/driver.c
> +++ b/hw/xfree86/drivers/modesetting/driver.c
> @@ -1018,6 +1018,11 @@ PreInit(ScrnInfoPtr pScrn, int flags)
> ret |= drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 1);
> ms->atomic_modeset = (ret == 0);
>
> + ms->kms_has_modifiers = FALSE;
> + ret = drmGetCap(ms->fd, DRM_CAP_ADDFB2_MODIFIERS, &value);
> + if (ret == 0 && value != 0)
> + ms->kms_has_modifiers = TRUE;
> +
> if (drmmode_pre_init(pScrn, &ms->drmmode, pScrn->bitsPerPixel /
> 8) == FALSE) {
> xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "KMS setup failed\n");
> goto fail;
> diff --git a/hw/xfree86/drivers/modesetting/driver.h
> b/hw/xfree86/drivers/modesetting/driver.h
> index cb8cfe6..b2a4e52 100644
> --- a/hw/xfree86/drivers/modesetting/driver.h
> +++ b/hw/xfree86/drivers/modesetting/driver.h
> @@ -117,6 +117,8 @@ typedef struct _modesettingRec {
> Bool has_queue_sequence;
> Bool tried_queue_sequence;
>
> + Bool kms_has_modifiers;
> +
> } modesettingRec, *modesettingPtr;
>
> #define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate))
> diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c
> b/hw/xfree86/drivers/modesetting/drmmode_display.c
> index 79e91f0..859a21a 100644
> --- a/hw/xfree86/drivers/modesetting/drmmode_display.c
> +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
> @@ -954,7 +954,8 @@ drmmode_bo_import(drmmode_ptr drmmode, drmmode_bo
> *bo,
> uint32_t *fb_id)
> {
> #ifdef GBM_BO_WITH_MODIFIERS
> - if (bo->gbm &&
> + modesettingPtr ms = modesettingPTR(drmmode->scrn);
> + if (bo->gbm && ms->kms_has_modifiers &&
> gbm_bo_get_modifier(bo->gbm) != DRM_FORMAT_MOD_INVALID) {
> int num_fds;
>
> @@ -1974,6 +1975,9 @@ populate_format_modifiers(xf86CrtcPtr crtc,
> const drmModePlane *kplane,
> uint32_t *blob_formats;
> struct drm_format_modifier *blob_modifiers;
>
> + if (!blob_id)
> + return FALSE;
> +
> blob = drmModeGetPropertyBlob(drmmode->fd, blob_id);
> if (!blob)
> return FALSE;
> @@ -1988,7 +1992,6 @@ populate_format_modifiers(xf86CrtcPtr crtc,
> const drmModePlane *kplane,
> uint32_t num_modifiers = 0;
> uint64_t *modifiers = NULL;
> uint64_t *tmp;
> -
> for (j = 0; j < fmt_mod_blob->count_modifiers; j++) {
> struct drm_format_modifier *mod = &blob_modifiers[j];
>
> @@ -2147,11 +2150,7 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc,
> int num)
> drmmode_crtc->num_formats = best_kplane->count_formats;
> drmmode_crtc->formats = calloc(sizeof(drmmode_format_rec),
> best_kplane->count_formats);
> - if (blob_id) {
> - populate_format_modifiers(crtc, best_kplane, blob_id);
> - }
> - else
> - {
> + if (!populate_format_modifiers(crtc, best_kplane, blob_id))
> {
> for (i = 0; i < best_kplane->count_formats; i++)
> drmmode_crtc->formats[i].format = best_kplane-
> >formats[i];
> }
More information about the xorg-devel
mailing list