Blob Blame History Raw
From 3ead05d4587991b75dc704444b1b1365c08af5ce Mon Sep 17 00:00:00 2001
From: Erik Kurzinger <ekurzinger@nvidia.com>
Date: Fri, 14 Jul 2023 14:07:25 -0700
Subject: [PATCH 1/2] egl-wayland: destroy all proxies before destroying their
 queues

The latest version of libwayland-client.so will print a warning if a
queue is destroyed while a proxy is still assigned to it. This warning
is triggered during EGL termination by our linux_dmabuf object and the
default dmabuf feedback object for the display. It is also triggered
during EGLSurface destruction by the surface's dmabuf feedback object.
That last object never gets destroyed at all, in fact.

This change ensures that the above objects are all destroyed *before*
their queues.
---
 include/wayland-egldisplay.h |  1 +
 src/wayland-egldisplay.c     | 17 +++++++++--------
 src/wayland-eglsurface.c     |  4 ++++
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/include/wayland-egldisplay.h b/include/wayland-egldisplay.h
index 4fe0418..e038668 100644
--- a/include/wayland-egldisplay.h
+++ b/include/wayland-egldisplay.h
@@ -186,6 +186,7 @@ typedef struct WlEventQueueRec {
 } WlEventQueue;
 
 int WlEglRegisterFeedback(WlEglDmaBufFeedback *feedback);
+void wlEglDestroyFeedback(WlEglDmaBufFeedback *feedback);
 EGLBoolean wlEglIsValidNativeDisplayExport(void *data, void *nativeDpy);
 EGLBoolean wlEglBindDisplaysHook(void *data, EGLDisplay dpy, void *nativeDpy);
 EGLBoolean wlEglUnbindDisplaysHook(EGLDisplay dpy, void *nativeDpy);
diff --git a/src/wayland-egldisplay.c b/src/wayland-egldisplay.c
index 3907892..3e7d74e 100644
--- a/src/wayland-egldisplay.c
+++ b/src/wayland-egldisplay.c
@@ -144,7 +144,7 @@ typedef caddr_t pointer_t;
 typedef void *pointer_t;
 #endif
 
-static void
+void
 wlEglDestroyFeedback(WlEglDmaBufFeedback *feedback)
 {
     wlEglFeedbackResetTranches(feedback);
@@ -619,6 +619,9 @@ static EGLBoolean terminateDisplay(WlEglDisplay *display, EGLBoolean globalTeard
      * destroy the display connection itself */
     wlEglDestroyAllSurfaces(display);
 
+    wlEglDestroyFormatSet(&display->formatSet);
+    wlEglDestroyFeedback(&display->defaultFeedback);
+
     if (!globalTeardown || display->ownNativeDpy) {
         if (display->wlRegistry) {
             wl_registry_destroy(display->wlRegistry);
@@ -636,19 +639,17 @@ static EGLBoolean terminateDisplay(WlEglDisplay *display, EGLBoolean globalTeard
             wp_presentation_destroy(display->wpPresentation);
             display->wpPresentation = NULL;
         }
-        if (display->wlEventQueue) {
-            wl_event_queue_destroy(display->wlEventQueue);
-            display->wlEventQueue = NULL;
-        }
         if (display->wlDmaBuf) {
             zwp_linux_dmabuf_v1_destroy(display->wlDmaBuf);
             display->wlDmaBuf = NULL;
         }
+        /* all proxies using the queue must be destroyed first! */
+        if (display->wlEventQueue) {
+            wl_event_queue_destroy(display->wlEventQueue);
+            display->wlEventQueue = NULL;
+        }
     }
 
-    wlEglDestroyFormatSet(&display->formatSet);
-    wlEglDestroyFeedback(&display->defaultFeedback);
-
     return EGL_TRUE;
 }
 
diff --git a/src/wayland-eglsurface.c b/src/wayland-eglsurface.c
index decde98..7b9ddd7 100644
--- a/src/wayland-eglsurface.c
+++ b/src/wayland-eglsurface.c
@@ -2149,6 +2149,8 @@ static EGLBoolean wlEglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
         free(surface->attribs);
     }
 
+    wlEglDestroyFeedback(&surface->feedback);
+
     if (surface->presentFeedbackQueue != NULL) {
         wl_event_queue_destroy(surface->presentFeedbackQueue);
         surface->presentFeedbackQueue = NULL;
@@ -2157,6 +2159,8 @@ static EGLBoolean wlEglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
         wl_callback_destroy(surface->throttleCallback);
         surface->throttleCallback = NULL;
     }
+
+    /* all proxies using the queue must be destroyed first! */
     if (surface->wlEventQueue != NULL) {
         wl_event_queue_destroy(surface->wlEventQueue);
         surface->wlEventQueue = NULL;

From ea70449fd94b5f866ea6189bf4f41f7c230cccfa Mon Sep 17 00:00:00 2001
From: Erik Kurzinger <ekurzinger@nvidia.com>
Date: Fri, 14 Jul 2023 13:43:43 -0700
Subject: [PATCH 2/2] egl-wayland: handle multiple tranches for the same device

To determine the set of format modifiers to use when creating a surface
we will find the first tranche for our DRM device, or else the
compositor's main device, and then look for our DRM format in that
tranche's list of formats to find the modifier list. If our format is
not in the list, then we won't use explicit modifiers when creating the
surface.

However, some compositors will advertise multiple tranches for a given
DRM device with a different set of formats in each one. Kwin is one
example. In that case, the tranche we select above might not contain our
format, but it could still be in one of the other tranches for the same
device.

Instead of simply picking the first tranche for the desired device, with
this change we will loop over the format list of each of that device's
tranches until we find a tranche that contains the format we want.
---
 src/wayland-eglsurface.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/src/wayland-eglsurface.c b/src/wayland-eglsurface.c
index 7b9ddd7..cd8ed1e 100644
--- a/src/wayland-eglsurface.c
+++ b/src/wayland-eglsurface.c
@@ -1265,12 +1265,18 @@ EGLint wlEglHandleImageStreamEvents(WlEglSurface *surface)
 }
 
 static WlEglDmaBufFormatSet *
-WlEglGetFormatSetForDev(WlEglDmaBufFeedback *feedback, dev_t dev)
+WlEglGetFormatSetForDev(WlEglDmaBufFeedback *feedback, dev_t dev, uint32_t format)
 {
     /* find the dev_t in our feedback's list of tranches */
     for (int i = 0; i < (int)feedback->numTranches; i++) {
         if (feedback->tranches[i].drmDev == dev) {
-            return &feedback->tranches[i].formatSet;
+            /* check if this tranche contains our format */
+            WlEglDmaBufFormatSet *formatSet = &feedback->tranches[i].formatSet;
+            for (int j = 0; j < (int)formatSet->numFormats; ++j) {
+                if (formatSet->dmaBufFormats[j].format == format) {
+                    return formatSet;
+                }
+            }
         }
     }
 
@@ -1354,7 +1360,7 @@ static EGLint create_surface_stream_local(WlEglSurface *surface)
     EGLint err = EGL_SUCCESS;
     EGLint numModifiers = 0;
     EGLuint64KHR *modifiers = NULL;
-    EGLint format;
+    uint32_t format;
     WlEglDmaBufFormatSet *formatSet = NULL;
     WlEglDmaBufFeedback *feedback = NULL;
 
@@ -1395,10 +1401,10 @@ static EGLint create_surface_stream_local(WlEglSurface *surface)
                 feedback = &display->defaultFeedback;
             }
 
-            formatSet = WlEglGetFormatSetForDev(feedback, display->devDpy->dev);
+            formatSet = WlEglGetFormatSetForDev(feedback, display->devDpy->dev, format);
             if (!formatSet) {
                 /* try again and see if there is a matching tranche for the render node */
-                formatSet = WlEglGetFormatSetForDev(feedback, display->devDpy->renderNode);
+                formatSet = WlEglGetFormatSetForDev(feedback, display->devDpy->renderNode, format);
             }
 
             /*
@@ -1407,14 +1413,14 @@ static EGLint create_surface_stream_local(WlEglSurface *surface)
              * us to check if the main device supports the linear modifier.
              */
             if (!formatSet && display->primeRenderOffload) {
-                formatSet = WlEglGetFormatSetForDev(feedback, feedback->mainDev);
+                formatSet = WlEglGetFormatSetForDev(feedback, feedback->mainDev, format);
             }
         }
 
         /* grab the modifier array */
         if (formatSet) {
             for (int i = 0; i < (int)formatSet->numFormats; i++) {
-                if (formatSet->dmaBufFormats[i].format == (uint32_t)format) {
+                if (formatSet->dmaBufFormats[i].format == format) {
                     modifiers = formatSet->dmaBufFormats[i].modifiers;
                     numModifiers = formatSet->dmaBufFormats[i].numModifiers;
                     break;