xserver: Branch 'xwayland-22.1' - 12 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Mar 8 13:29:49 UTC 2023


 dix/devices.c                     |    1 
 glamor/glamor_egl.c               |    7 ++-
 glx/vndcmds.c                     |    7 +--
 hw/xwayland/xwayland-glamor-gbm.c |   79 +++++++++++++++++++++++++++++++++-----
 hw/xwayland/xwayland-glx.c        |    2 
 hw/xwayland/xwayland-output.c     |   20 +++++++++
 hw/xwayland/xwayland-output.h     |    1 
 hw/xwayland/xwayland-window.c     |    3 -
 present/present_event.c           |    5 +-
 present/present_priv.h            |    7 ++-
 present/present_screen.c          |   11 ++++-
 randr/randrstr.h                  |    8 +++
 randr/rrcrtc.c                    |    3 +
 13 files changed, 133 insertions(+), 21 deletions(-)

New commits:
commit 667afc6f8db59b1da6af5afe74709978496eebf0
Author: Adam Jackson <ajax at redhat.com>
Date:   Thu Feb 2 12:26:27 2023 -0500

    present: Send a PresentConfigureNotify event for destroyed windows
    
    This enables fixing a deadlock case on the client side, where the client
    ends up blocked waiting for a Present event that will never come because
    the window was destroyed. The new PresentWindowDestroyed flag allows the
    client to avoid blocking indefinitely.
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    See-also: https://gitlab.freedesktop.org/mesa/mesa/-/issues/116
    See-also: https://gitlab.freedesktop.org/mesa/mesa/-/issues/6685
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>
    (cherry picked from commit 462b06033e66a32308d940eb5fc47f5e4c914dc0)

diff --git a/present/present_event.c b/present/present_event.c
index 435b26b70..849732dc8 100644
--- a/present/present_event.c
+++ b/present/present_event.c
@@ -102,7 +102,8 @@ present_event_swap(xGenericEvent *from, xGenericEvent *to)
 }
 
 void
-present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling)
+present_send_config_notify(WindowPtr window, int x, int y, int w, int h,
+                           int bw, WindowPtr sibling, CARD32 flags)
 {
     present_window_priv_ptr window_priv = present_window_priv(window);
 
@@ -122,7 +123,7 @@ present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw,
             .off_y = 0,
             .pixmap_width = w,
             .pixmap_height = h,
-            .pixmap_flags = 0
+            .pixmap_flags = flags
         };
         present_event_ptr event;
 
diff --git a/present/present_priv.h b/present/present_priv.h
index 6ebd009a2..4ad729864 100644
--- a/present/present_priv.h
+++ b/present/present_priv.h
@@ -43,6 +43,11 @@
 #define DebugPresent(x)
 #endif
 
+/* XXX this belongs in presentproto */
+#ifndef PresentWindowDestroyed
+#define PresentWindowDestroyed (1 << 0)
+#endif
+
 extern int present_request;
 
 extern DevPrivateKeyRec present_screen_private_key;
@@ -307,7 +312,7 @@ void
 present_free_events(WindowPtr window);
 
 void
-present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling);
+present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling, CARD32 flags);
 
 void
 present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc);
diff --git a/present/present_screen.c b/present/present_screen.c
index 15684eda4..2c29aafd2 100644
--- a/present/present_screen.c
+++ b/present/present_screen.c
@@ -93,6 +93,15 @@ present_destroy_window(WindowPtr window)
     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
     present_window_priv_ptr window_priv = present_window_priv(window);
 
+    present_send_config_notify(window,
+                               window->drawable.x,
+                               window->drawable.y,
+                               window->drawable.width,
+                               window->drawable.height,
+                               window->borderWidth,
+                               window->nextSib,
+                               PresentWindowDestroyed);
+
     if (window_priv) {
         present_clear_window_notifies(window);
         present_free_events(window);
@@ -123,7 +132,7 @@ present_config_notify(WindowPtr window,
     ScreenPtr screen = window->drawable.pScreen;
     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
 
-    present_send_config_notify(window, x, y, w, h, bw, sibling);
+    present_send_config_notify(window, x, y, w, h, bw, sibling, 0);
 
     unwrap(screen_priv, screen, ConfigNotify);
     if (screen->ConfigNotify)
commit f05528524613c1b2ea67fd45d45e84c319a5d6bd
Author: Minh Phan <phanquangminh217 at gmail.com>
Date:   Sun Feb 5 14:38:32 2023 +0700

    xwayland/window: Do not double add window to damage list
    
    The window might be retained in the damage list after
    `xwl_screen_post_damage` in certain conditions. This means we need to
    check if the window is already in the list to avoid adding the same
    window twice which will lead to list corruption resulting in server freeze
    in `xwl_screen_post_damage`.
    
    Signed-off-by: Minh Phan <phanquangminh217 at gmail.com>
    (cherry picked from commit ba644a64a415962956de72936d21b6527ee8cd57)

diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 38992d5c1..ba7d7af0b 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -175,7 +175,8 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
     }
 #endif
 
-    xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
+    if (xorg_list_is_empty(&xwl_window->link_damage))
+        xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
 }
 
 static void
commit 700ddafe0ccd1de1e95900f50aef3c20782369b0
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Thu Feb 9 11:40:07 2023 +0100

    dix: Clear device sprite after free in AttachDevice()
    
    The code in AttachDevice() may free the dev->spriteInfo->sprite under
    some circumstances and later call GetCurrentRootWindow() which uses
    the same dev->spriteInfo->sprite.
    
    While it seems unlikely that this is actually an issue, considering the
    cases where one or the other get called, it still makes the code look
    suspicious.
    
    Make sure to clear set dev->spriteInfo->sprite to NULL  immediately
    after it's freed to avoid any confusion, even if only to clarify the
    code.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1436
    (cherry picked from commit e196535abbf2ef4aa7c1eb0b4b9b67840032b88a)

diff --git a/dix/devices.c b/dix/devices.c
index 5bf956ead..a3fbe8140 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2627,6 +2627,7 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
         screen = miPointerGetScreen(dev);
         screen->DeviceCursorCleanup(dev, screen);
         free(dev->spriteInfo->sprite);
+        dev->spriteInfo->sprite = NULL;
     }
 
     dev->master = master;
commit b2b3f67e09007f38af2066a076678da9e90449e8
Author: Ivan A. Melnikov <iv at altlinux.org>
Date:   Wed Dec 21 18:29:21 2022 +0400

    glamor: Don't initialize on softpipe
    
    There are systems where softpipe is the default renderer,
    e.g. when llvmpipe is not is not available. Using glamor
    on such systems is never a good idea.
    
    This mirrors what commit 0a9415cf793babed1f28c61f8047d51de04f1528
    did for llvmpipe.
    
    Closes: #1417
    
    Signed-off-by: Ivan A. Melnikov <iv at altlinux.org>
    (cherry picked from commit 711d491729d83b17114fd08d784bc0ddfd17ff6a)

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 83a4eccd6..173db3efb 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -1053,6 +1053,11 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
                    "glGetString() returned NULL, your GL is broken\n");
         goto error;
     }
+    if (strstr((const char *)renderer, "softpipe")) {
+        xf86DrvMsg(scrn->scrnIndex, X_INFO,
+                   "Refusing to try glamor on softpipe\n");
+        goto error;
+    }
     if (!strncmp("llvmpipe", (const char *)renderer, strlen("llvmpipe"))) {
         if (scrn->confScreen->num_gpu_devices)
             xf86DrvMsg(scrn->scrnIndex, X_INFO,
diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index 5e2c618ab..93c15cac9 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -1030,6 +1030,10 @@ xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen)
         ErrorF("glGetString() returned NULL, your GL is broken\n");
         goto error;
     }
+    if (strstr((const char *)renderer, "softpipe")) {
+        ErrorF("Refusing to try glamor on softpipe\n");
+        goto error;
+    }
     if (!strncmp("llvmpipe", (const char *)renderer, strlen("llvmpipe"))) {
         ErrorF("Refusing to try glamor on llvmpipe\n");
         goto error;
commit e910626d37eb0030bf38d8595414e97e465e927a
Author: Joshua Ashton <joshua at froggi.es>
Date:   Thu Dec 29 08:05:19 2022 +0000

    xwayland: Don't expose XRandR emulated modes for leaseable displays
    
    Leasable displays do not have any actual associated Wayland output and
    are not available to regular X11 clients and left entirely to the
    application who requests the lease.
    
    As these are not actually managed by the Wayland compositor and left
    entirely to the "lessee" application, the viewporter protocol required
    for the XRandR emulation is not usable on such devices.
    
    We should therefore not advertise the XRandR emulated modes for those
    leasable displays.
    
    This also solves a problem with implementations of glXGetMscRateOML()
    which is used notably by Chromium/Electron. Applications using this
    which will begin lagging/stuttering exponentially over
    time, trying to look up a non-existent mode with 0x0 as returned by
    XF86VidModeGetModeLine() with XRandR emulation for such devices.
    
    See-also: https://github.com/labwc/labwc/issues/553
    Signed-off-by: Joshua Ashton <joshua at froggi.es>
    (cherry picked from commit 0abb5770750e54566d3ce14a3be9dbf15bb578ba)

diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
index 5e05bb35a..f3a272f7f 100644
--- a/hw/xwayland/xwayland-output.c
+++ b/hw/xwayland/xwayland-output.c
@@ -223,6 +223,10 @@ xwl_output_get_emulated_mode_for_client(struct xwl_output *xwl_output,
     if (!xwl_output)
         return NULL;
 
+    /* We don't do XRandr emulation when a fake lease display */
+    if (!xwl_output->output)
+        return NULL;
+
     for (i = 0; i < XWL_CLIENT_MAX_EMULATED_MODES; i++) {
         if (xwl_client->emulated_modes[i].server_output_id ==
             xwl_output->server_output_id)
commit 6c2c2a2437d60c29ab2d2d7d8f7fa58a323880e9
Author: Minh Phan <phanquangminh217 at gmail.com>
Date:   Tue Nov 29 19:37:22 2022 +0700

    xwayland/output: properly return the current emulated mode when queried
    
    This fixes an issue with GLFW-based games failing to set the resolution
    when the user request to switch back to the native display mode.
    
    Signed-off-by: Minh Phan <phanquangminh217 at gmail.com>
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    (cherry picked from commit 511d1686a6ac3e3e0d66fb67b62620ba2a6575c8)

diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
index a351fc9f7..5e05bb35a 100644
--- a/hw/xwayland/xwayland-output.c
+++ b/hw/xwayland/xwayland-output.c
@@ -266,6 +266,7 @@ xwl_output_add_emulated_mode_for_client(struct xwl_output *xwl_output,
     emulated_mode->server_output_id = xwl_output->server_output_id;
     emulated_mode->width  = mode->mode.width;
     emulated_mode->height = mode->mode.height;
+    emulated_mode->id = mode->mode.id;
     emulated_mode->from_vidmode = from_vidmode;
 }
 
@@ -902,6 +903,20 @@ xwl_randr_crtc_set(ScreenPtr pScreen,
     return TRUE;
 }
 
+static void
+xwl_randr_crtc_get(ScreenPtr pScreen,
+                   RRCrtcPtr crtc,
+                   xRRGetCrtcInfoReply *rep)
+{
+    struct xwl_output *xwl_output = crtc->devPrivate;
+
+    struct xwl_emulated_mode *mode = xwl_output_get_emulated_mode_for_client(
+        xwl_output, GetCurrentClient());
+
+    if (mode)
+        rep->mode = mode->id;
+}
+
 static Bool
 xwl_randr_crtc_set_gamma(ScreenPtr pScreen, RRCrtcPtr crtc)
 {
@@ -962,6 +977,7 @@ xwl_screen_init_output(struct xwl_screen *xwl_screen)
 #if RANDR_12_INTERFACE
     rp->rrScreenSetSize = xwl_randr_screen_set_size;
     rp->rrCrtcSet = xwl_randr_crtc_set;
+    rp->rrCrtcGet = xwl_randr_crtc_get;
     rp->rrCrtcSetGamma = xwl_randr_crtc_set_gamma;
     rp->rrCrtcGetGamma = xwl_randr_crtc_get_gamma;
     rp->rrOutputSetProperty = xwl_randr_output_set_property;
diff --git a/hw/xwayland/xwayland-output.h b/hw/xwayland/xwayland-output.h
index 74a46994f..dd0f0a395 100644
--- a/hw/xwayland/xwayland-output.h
+++ b/hw/xwayland/xwayland-output.h
@@ -69,6 +69,7 @@ struct xwl_emulated_mode {
     uint32_t server_output_id;
     int32_t width;
     int32_t height;
+    RRMode id;
     Bool from_vidmode;
 };
 
commit 7d039914ff5baf1ebd5dca1ddcb8d3a74ba3587e
Author: Minh Phan <phanquangminh217 at gmail.com>
Date:   Tue Nov 29 19:35:13 2022 +0700

    randr: introduce rrCrtcGetInfo DDX function
    
    This allows rrCrtcGetInfo to override the values in the XRRCrtcGetInfo
    reply. One use case is to allow Xwayland to return the current emulated
    mode for the specific client instead of the global mode.
    
    Signed-off-by: Minh Phan <phanquangminh217 at gmail.com>
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    (cherry picked from commit 5145742fb6e3d108b05db1521b51112e0dbfb95a)

diff --git a/randr/randrstr.h b/randr/randrstr.h
index 173ecdf4e..545348835 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -218,6 +218,10 @@ typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr pScreen,
                                   Rotation rotation,
                                   int numOutputs, RROutputPtr * outputs);
 
+typedef void (*RRCrtcGetProcPtr) (ScreenPtr pScreen,
+                                  RRCrtcPtr crtc,
+                                  xRRGetCrtcInfoReply *rep);
+
 typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr pScreen, RRCrtcPtr crtc);
 
 typedef Bool (*RRCrtcGetGammaProcPtr) (ScreenPtr pScreen, RRCrtcPtr crtc);
@@ -420,6 +424,10 @@ typedef struct _rrScrPriv {
 
     RRRequestLeaseProcPtr rrRequestLease;
     RRGetLeaseProcPtr rrGetLease;
+
+#if RANDR_12_INTERFACE
+    RRCrtcGetProcPtr rrCrtcGet;
+#endif
 } rrScrPrivRec, *rrScrPrivPtr;
 
 extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index e64f03131..5f85bdfa5 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -1269,6 +1269,9 @@ ProcRRGetCrtcInfo(ClientPtr client)
         }
     }
 
+    if (pScrPriv->rrCrtcGet)
+        pScrPriv->rrCrtcGet(pScreen, crtc, &rep);
+
     if (client->swapped) {
         swaps(&rep.sequenceNumber);
         swapl(&rep.length);
commit cedf933c7cbbc0285e7f9ddb17706b9a8d84f6aa
Author: Doğukan Korkmaztürk <dkorkmazturk at nvidia.com>
Date:   Tue Nov 22 13:43:16 2022 -0500

    GLX: Free the tag of the old context later
    
    In CommonMakeCurrent() function, the tag of the old context is freed
    before the new context is made current. This is problematic because if
    the CommonMakeNewCurrent() function fails, the tag of the old context
    ends up being removed, even though it is still active. This causes
    subsequent glXMakeCurrent() or glXMakeContextCurrent() requests to
    generate a GLXBadContextTag error.
    
    This change moves the function call that frees the old tag to a location
    where the result of CommonMakeNewCurrent() call is known and it is safe
    to free it.
    
    Signed-off-by: Doğukan Korkmaztürk <dkorkmazturk at nvidia.com>
    (cherry picked from commit 4781f2a5a8c2c2b000374e2d87982a6701d5a6b3)

diff --git a/glx/vndcmds.c b/glx/vndcmds.c
index d6d8719e1..d1e088973 100644
--- a/glx/vndcmds.c
+++ b/glx/vndcmds.c
@@ -165,9 +165,6 @@ static int CommonLoseCurrent(ClientPtr client, GlxContextTagInfo *tagInfo)
             tagInfo->tag, // No old context tag,
             None, None, None, 0);
 
-    if (ret == Success) {
-        GlxFreeContextTag(tagInfo);
-    }
     return ret;
 }
 
@@ -259,7 +256,6 @@ static int CommonMakeCurrent(ClientPtr client,
             if (ret != Success) {
                 return ret;
             }
-            oldTag = NULL;
         }
 
         if (newVendor != NULL) {
@@ -270,6 +266,9 @@ static int CommonMakeCurrent(ClientPtr client,
         } else {
             reply.contextTag = 0;
         }
+
+        GlxFreeContextTag(oldTag);
+        oldTag = NULL;
     }
 
     reply.contextTag = GlxCheckSwap(client, reply.contextTag);
commit e982ca4420a6003c97cb076ee40172e904ce290a
Author: Doğukan Korkmaztürk <dkorkmazturk at nvidia.com>
Date:   Tue Nov 8 10:05:59 2022 -0500

    xwayland/glx: Mirror all EGLConfigs
    
    Updated the for-loop that iterates over the received EGLConfigs to
    include the very first EGLConfig with index 0.
    
    Signed-off-by: Doğukan Korkmaztürk <dkorkmazturk at nvidia.com>
    Fixes: 8469241592 - xwayland: Add EGL-backed GLX provider
    (cherry picked from commit 3852b0d10a061348ea8214fbcbef3c5c08cac0b6)

diff --git a/hw/xwayland/xwayland-glx.c b/hw/xwayland/xwayland-glx.c
index a3e85fc2f..4689b9ed6 100644
--- a/hw/xwayland/xwayland-glx.c
+++ b/hw/xwayland/xwayland-glx.c
@@ -339,7 +339,7 @@ egl_mirror_configs(ScreenPtr pScreen, struct egl_screen *screen)
     /* We walk the EGL configs backwards to make building the
      * ->next chain easier.
      */
-    for (i = nconfigs - 1; i > 0; i--)
+    for (i = nconfigs - 1; i >= 0; i--)
         for (j = 0; j < 3; j++) /* direct_color */
             for (k = 0; k < 2; k++) /* double_buffer */ {
                 if (can_srgb)
commit 4303ddfbf98023f33c1067007543df345c68b459
Author: Corentin Noël <corentin.noel at collabora.com>
Date:   Mon Aug 1 16:03:38 2022 +0200

    glamor: Only check for llvmpipe renderer
    
    The virgl driver exposes the name of the host renderer which might be llvmpipe.
    In this case we still need glamor to be initialized.
    
    Only check if the renderer starts with llvmpipe (which is what llvmpipe exposes).
    
    Signed-off-by: Corentin Noël <corentin.noel at collabora.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    (cherry picked from commit fdebbc60d89cdc1b3353424b6568b25a61dcf372)

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 60d0df893..83a4eccd6 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -1053,7 +1053,7 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
                    "glGetString() returned NULL, your GL is broken\n");
         goto error;
     }
-    if (strstr((const char *)renderer, "llvmpipe")) {
+    if (!strncmp("llvmpipe", (const char *)renderer, strlen("llvmpipe"))) {
         if (scrn->confScreen->num_gpu_devices)
             xf86DrvMsg(scrn->scrnIndex, X_INFO,
                        "Allowing glamor on llvmpipe for PRIME\n");
diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index ec5514fd2..5e2c618ab 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -1030,7 +1030,7 @@ xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen)
         ErrorF("glGetString() returned NULL, your GL is broken\n");
         goto error;
     }
-    if (strstr((const char *)renderer, "llvmpipe")) {
+    if (!strncmp("llvmpipe", (const char *)renderer, strlen("llvmpipe"))) {
         ErrorF("Refusing to try glamor on llvmpipe\n");
         goto error;
     }
commit bc288f59a4d6bf5e713f1473e42d9cdb20d879bf
Author: Lucas Stach <l.stach at pengutronix.de>
Date:   Sun Jul 10 17:51:14 2022 +0200

    xwayland: properly get FDs from multiplanar GBM BOs
    
    Multiplanar GBM buffers can point to different objects from each plane.
    Use the _for_plane API when possible to retrieve the correct prime FD
    for each plane.
    
    Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
    Reviewed-by: Simon Ser <contact at emersion.fr>
    Tested-by: Guido Günther <agx at sigxcpu.org>
    (cherry picked from commit 7d5ad2d372cc88648f6744c318a4bee18443689d)

diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index adefc768b..ec5514fd2 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -354,12 +354,15 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
     unsigned short width = pixmap->drawable.width;
     unsigned short height = pixmap->drawable.height;
     uint32_t format;
-    int prime_fd;
     int num_planes;
+    int prime_fds[4];
     uint32_t strides[4];
     uint32_t offsets[4];
     uint64_t modifier;
     int i;
+#ifndef GBM_BO_FD_FOR_PLANE
+    int32_t first_handle;
+#endif
 
     if (xwl_pixmap == NULL)
        return NULL;
@@ -374,20 +377,43 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
 
     format = wl_drm_format_for_depth(pixmap->drawable.depth);
 
-    prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
-    if (prime_fd == -1)
-        return NULL;
-
 #ifdef GBM_BO_WITH_MODIFIERS
     num_planes = gbm_bo_get_plane_count(xwl_pixmap->bo);
     modifier = gbm_bo_get_modifier(xwl_pixmap->bo);
     for (i = 0; i < num_planes; i++) {
+#ifdef GBM_BO_FD_FOR_PLANE
+        prime_fds[i] = gbm_bo_get_fd_for_plane(xwl_pixmap->bo, i);
+#else
+        union gbm_bo_handle plane_handle;
+
+        plane_handle = gbm_bo_get_handle_for_plane(xwl_pixmap->bo, i);
+        if (i == 0)
+            first_handle = plane_handle.s32;
+
+        /* If all planes point to the same object as the first plane, i.e. they
+         * all have the same handle, we can fall back to the non-planar
+         * gbm_bo_get_fd without losing information. If they point to different
+         * objects we are out of luck and need to give up.
+         */
+        if (first_handle == plane_handle.s32)
+            prime_fds[i] = gbm_bo_get_fd(xwl_pixmap->bo);
+        else
+            prime_fds[i] = -1;
+#endif
+        if (prime_fds[i] == -1) {
+            while (--i >= 0)
+                close(prime_fds[i]);
+            return NULL;
+        }
         strides[i] = gbm_bo_get_stride_for_plane(xwl_pixmap->bo, i);
         offsets[i] = gbm_bo_get_offset(xwl_pixmap->bo, i);
     }
 #else
     num_planes = 1;
     modifier = DRM_FORMAT_MOD_INVALID;
+    prime_fds[0] = gbm_bo_get_fd(xwl_pixmap->bo);
+    if (prime_fds[0] == -1)
+        return NULL;
     strides[0] = gbm_bo_get_stride(xwl_pixmap->bo);
     offsets[0] = 0;
 #endif
@@ -398,7 +424,7 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
 
         params = zwp_linux_dmabuf_v1_create_params(xwl_screen->dmabuf);
         for (i = 0; i < num_planes; i++) {
-            zwp_linux_buffer_params_v1_add(params, prime_fd, i,
+            zwp_linux_buffer_params_v1_add(params, prime_fds[i], i,
                                            offsets[i], strides[i],
                                            modifier >> 32, modifier & 0xffffffff);
         }
@@ -409,14 +435,15 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
         zwp_linux_buffer_params_v1_destroy(params);
     } else if (num_planes == 1) {
         xwl_pixmap->buffer =
-            wl_drm_create_prime_buffer(xwl_gbm->drm, prime_fd, width, height,
+            wl_drm_create_prime_buffer(xwl_gbm->drm, prime_fds[0], width, height,
                                        format,
                                        0, gbm_bo_get_stride(xwl_pixmap->bo),
                                        0, 0,
                                        0, 0);
     }
 
-    close(prime_fd);
+    for (i = 0; i < num_planes; i++)
+        close(prime_fds[i]);
 
     /* Add our listener now */
     wl_buffer_add_listener(xwl_pixmap->buffer,
@@ -610,6 +637,9 @@ glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
 {
     struct xwl_pixmap *xwl_pixmap;
 #ifdef GBM_BO_WITH_MODIFIERS
+#ifndef GBM_BO_FD_FOR_PLANE
+    int32_t first_handle;
+#endif
     uint32_t num_fds;
     int i;
 #endif
@@ -627,7 +657,25 @@ glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
     *modifier = gbm_bo_get_modifier(xwl_pixmap->bo);
 
     for (i = 0; i < num_fds; i++) {
-        fds[i] = gbm_bo_get_fd(xwl_pixmap->bo);
+#ifdef GBM_BO_FD_FOR_PLANE
+        fds[i] = gbm_bo_get_fd_for_plane(xwl_pixmap->bo, i);
+#else
+        union gbm_bo_handle plane_handle;
+
+        plane_handle = gbm_bo_get_handle_for_plane(xwl_pixmap->bo, i);
+        if (i == 0)
+            first_handle = plane_handle.s32;
+
+        /* If all planes point to the same object as the first plane, i.e. they
+         * all have the same handle, we can fall back to the non-planar
+         * gbm_bo_get_fd without losing information. If they point to different
+         * objects we are out of luck and need to give up.
+         */
+        if (first_handle == plane_handle.s32)
+            fds[i] = gbm_bo_get_fd(xwl_pixmap->bo);
+        else
+            fds[i] = -1;
+#endif
         if (fds[i] == -1) {
             while (--i >= 0)
                 close(fds[i]);
commit 57db30e637192df0600999cd40ec14edbeb1c68a
Author: Lucas Stach <l.stach at pengutronix.de>
Date:   Thu Jul 28 22:44:59 2022 +0200

    xwayland: handle fd export failure in glamor_egl_fds_from_pixmap
    
    Check the fd for validity before giving a success return code.
    
    Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
    Reviewed-by: Simon Ser <contact at emersion.fr>
    Tested-by: Guido Günther <agx at sigxcpu.org>
    (cherry picked from commit 951502e49797ab4c5db047e9df32c93d050d64af)

diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index 60c63ba99..adefc768b 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -628,6 +628,11 @@ glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
 
     for (i = 0; i < num_fds; i++) {
         fds[i] = gbm_bo_get_fd(xwl_pixmap->bo);
+        if (fds[i] == -1) {
+            while (--i >= 0)
+                close(fds[i]);
+            return 0;
+        }
         strides[i] = gbm_bo_get_stride_for_plane(xwl_pixmap->bo, i);
         offsets[i] = gbm_bo_get_offset(xwl_pixmap->bo, i);
     }
@@ -636,6 +641,8 @@ glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
 #else
     *modifier = DRM_FORMAT_MOD_INVALID;
     fds[0] = gbm_bo_get_fd(xwl_pixmap->bo);
+    if (fds[0] == -1)
+        return 0;
     strides[0] = gbm_bo_get_stride(xwl_pixmap->bo);
     offsets[0] = 0;
     return 1;


More information about the xorg-commit mailing list