194 lines
8.0 KiB
Diff
194 lines
8.0 KiB
Diff
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;
|