Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libnvidia-egl-wayland for openSUSE:Factory checked in at 2022-04-23 00:25:12 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libnvidia-egl-wayland (Old) and /work/SRC/openSUSE:Factory/.libnvidia-egl-wayland.new.1538 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libnvidia-egl-wayland" Sat Apr 23 00:25:12 2022 rev:6 rq:971815 version:1.1.9 Changes: -------- --- /work/SRC/openSUSE:Factory/libnvidia-egl-wayland/libnvidia-egl-wayland.changes 2022-04-16 00:13:27.869586230 +0200 +++ /work/SRC/openSUSE:Factory/.libnvidia-egl-wayland.new.1538/libnvidia-egl-wayland.changes 2022-04-23 00:25:36.367761517 +0200 @@ -1,0 +2,8 @@ +Thu Apr 21 12:46:29 UTC 2022 - Stefan Dirsch <sndir...@suse.com> + +- U_0001-wayland-Fail-eglGetDisplay-if-wl_drm-is-not-availabl.patch + U_0002-generate-wayland-drm-client-protocol.h.patch + U_0003-egl-wayland-retrieve-DRM-device-name-before-acquirin.patch + * add latest fixes (U_0003-egl-wayland ... fixes boo#1195598) + +------------------------------------------------------------------- New: ---- U_0001-wayland-Fail-eglGetDisplay-if-wl_drm-is-not-availabl.patch U_0002-generate-wayland-drm-client-protocol.h.patch U_0003-egl-wayland-retrieve-DRM-device-name-before-acquirin.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libnvidia-egl-wayland.spec ++++++ --- /var/tmp/diff_new_pack.CgFzXz/_old 2022-04-23 00:25:36.847761859 +0200 +++ /var/tmp/diff_new_pack.CgFzXz/_new 2022-04-23 00:25:36.855761864 +0200 @@ -28,6 +28,9 @@ URL: https://github.com/NVIDIA/egl-wayland Source0: https://github.com/NVIDIA/egl-wayland/archive/%{version}/%{rname}-%{version}.tar.gz Source1: baselibs.conf +Patch1: U_0001-wayland-Fail-eglGetDisplay-if-wl_drm-is-not-availabl.patch +Patch2: U_0002-generate-wayland-drm-client-protocol.h.patch +Patch3: U_0003-egl-wayland-retrieve-DRM-device-name-before-acquirin.patch BuildRequires: gcc-c++ BuildRequires: meson >= 0.50 BuildRequires: ninja @@ -75,7 +78,7 @@ using %{name}. %prep -%autosetup -n %{rname}-%{version} +%autosetup -n %{rname}-%{version} -p1 %build export LDFLAGS="-Wl,-z,noexecstack -Wl,-z,now -Wl,-z,relro %{?_lto_cflags}" ++++++ U_0001-wayland-Fail-eglGetDisplay-if-wl_drm-is-not-availabl.patch ++++++ >From d4937adc5cd04ac7df98fc5616e40319fb52fdee Mon Sep 17 00:00:00 2001 From: Austin Shafer <asha...@nvidia.com> Date: Wed, 27 Oct 2021 06:37:07 -0400 Subject: [PATCH 1/3] wayland: Fail eglGetDisplay if wl_drm is not available This patch does two things: - checks if wl_drm is in use on the server, and uses it to get the name of the drm device the compositor is driving. - Find an EGLDevice that matches the path returned by wl_drm. If wl_drm and the needed extensions are not present, or if a matching EGLDevice is not found, then we fail. Right now we only support running on the same GPU as the compositor, so any of these being missing means that is not the case. --- src/wayland-egldisplay.c | 153 +++++++++++++++++++++++++++++++++++---- 1 file changed, 138 insertions(+), 15 deletions(-) diff --git a/src/wayland-egldisplay.c b/src/wayland-egldisplay.c index a0370a5..8b7394a 100644 --- a/src/wayland-egldisplay.c +++ b/src/wayland-egldisplay.c @@ -29,13 +29,19 @@ #include "wayland-eglsurface.h" #include "wayland-eglhandle.h" #include "wayland-eglutils.h" +#include "wayland-drm-client-protocol.h" #include <string.h> #include <stdlib.h> #include <assert.h> +#include <unistd.h> +#include <fcntl.h> typedef struct WlServerProtocolsRec { EGLBoolean hasEglStream; EGLBoolean hasDmaBuf; + EGLBoolean hasDrm; + struct wl_drm *wldrm; + char *drm_name; } WlServerProtocols; /* TODO: Make global display lists hang off platform data */ @@ -241,6 +247,40 @@ static const struct wl_registry_listener registry_listener = { registry_handle_global_remove }; +static void wl_drm_device(void *data, struct wl_drm *wl_drm, const char *name) +{ + WlServerProtocols *protocols = (WlServerProtocols *)data; + (void) wl_drm; + + protocols->drm_name = strdup(name); +} + +static void wl_drm_authenticated(void *data, struct wl_drm *wl_drm) +{ + (void) data; + (void) wl_drm; +} +static void wl_drm_format(void *data, struct wl_drm *wl_drm, uint32_t format) +{ + (void) data; + (void) wl_drm; + (void) format; +} +static void wl_drm_capabilities(void *data, struct wl_drm *wl_drm, uint32_t value) +{ + (void) data; + (void) wl_drm; + (void) value; +} + +static const struct wl_drm_listener drmListener = { + .device = wl_drm_device, + .authenticated = wl_drm_authenticated, + .format = wl_drm_format, + .capabilities = wl_drm_capabilities, +}; + + static void registry_handle_global_check_protocols( void *data, @@ -262,6 +302,12 @@ registry_handle_global_check_protocols( (version >= 3)) { protocols->hasDmaBuf = EGL_TRUE; } + + if ((strcmp(interface, "wl_drm") == 0) && (version >= 2)) { + protocols->hasDrm = EGL_TRUE; + protocols->wldrm = wl_registry_bind(registry, name, &wl_drm_interface, 2); + wl_drm_add_listener(protocols->wldrm, &drmListener, protocols); + } } static void @@ -389,8 +435,8 @@ EGLBoolean wlEglTerminateHook(EGLDisplay dpy) return res; } -static void checkServerProtocols(struct wl_display *nativeDpy, - WlServerProtocols *protocols) +static void getServerProtocolsInfo(struct wl_display *nativeDpy, + WlServerProtocols *protocols) { struct wl_display *wrapper = NULL; struct wl_registry *wlRegistry = NULL; @@ -418,6 +464,11 @@ static void checkServerProtocols(struct wl_display *nativeDpy, protocols); if (ret == 0) { wl_display_roundtrip_queue(nativeDpy, queue); + if (protocols->hasDrm) { + wl_display_roundtrip_queue(nativeDpy, queue); + /* destroy our wl_drm object */ + wl_drm_destroy(protocols->wldrm); + } } if (queue) { @@ -438,9 +489,13 @@ EGLDisplay wlEglGetPlatformDisplayExport(void *data, WlServerProtocols protocols; EGLint numDevices = 0; int i = 0; + EGLDeviceEXT *eglDeviceList = NULL; EGLDeviceEXT eglDevice = NULL; + EGLDeviceEXT tmpDev = NULL; EGLint err = EGL_SUCCESS; EGLBoolean useInitRefCount = EGL_FALSE; + const char *dev_exts; + const char *dev_name; if (platform != EGL_PLATFORM_WAYLAND_EXT) { wlEglSetError(data, EGL_BAD_PARAMETER); @@ -480,7 +535,6 @@ EGLDisplay wlEglGetPlatformDisplayExport(void *data, display = calloc(1, sizeof(*display)); if (!display) { - wlExternalApiUnlock(); err = EGL_BAD_ALLOC; goto fail; } @@ -498,7 +552,6 @@ EGLDisplay wlEglGetPlatformDisplayExport(void *data, if (!display->nativeDpy) { display->nativeDpy = wl_display_connect(NULL); if (!display->nativeDpy) { - wlExternalApiUnlock(); err = EGL_BAD_ALLOC; goto fail; } @@ -508,26 +561,85 @@ EGLDisplay wlEglGetPlatformDisplayExport(void *data, } memset(&protocols, 0, sizeof(protocols)); - checkServerProtocols(display->nativeDpy, &protocols); + /* + * This is where we check the supported protocols on the compositor, + * and bind to wl_drm to get the device name. + * protocols.drm_name will be allocated here if using wl_drm + */ + getServerProtocolsInfo(display->nativeDpy, &protocols); - if (!protocols.hasEglStream && !protocols.hasDmaBuf) { - wlExternalApiUnlock(); - goto fail; + if (!protocols.hasDrm || (!protocols.hasEglStream && !protocols.hasDmaBuf)) { + goto fail_cleanup_protocols; } - if (!pData->egl.queryDevices(1, &eglDevice, &numDevices) || numDevices == 0) { - wlExternalApiUnlock(); - goto fail; + /* Get the number of devices available */ + if (!pData->egl.queryDevices(-1, NULL, &numDevices) || numDevices == 0) { + goto fail_cleanup_protocols; + } + + eglDeviceList = calloc(numDevices, sizeof(*eglDeviceList)); + if (!eglDeviceList) { + goto fail_cleanup_protocols; + } + + /* + * Now we need to find an EGLDevice. If wl_drm is in use we will try to find one that + * matches the device the compositor is using. We know that device is an nvidia device + * since we just checked that above. + */ + if (!pData->egl.queryDevices(numDevices, eglDeviceList, &numDevices) || numDevices == 0) { + goto fail_cleanup_devices; } + + if (protocols.drm_name) { + for (int i = 0; i < numDevices; i++) { + tmpDev = eglDeviceList[i]; + + /* + * To check against the wl_drm name, we need to check if we can use + * the drm extension + */ + dev_exts = display->data->egl.queryDeviceString(tmpDev, + EGL_EXTENSIONS); + if (dev_exts) { + if (wlEglFindExtension("EGL_EXT_device_drm_render_node", dev_exts)) { + dev_name = + display->data->egl.queryDeviceString(tmpDev, + EGL_DRM_RENDER_NODE_FILE_EXT); + + if (dev_name) { + /* + * At this point we have gotten the name from wl_drm, gotten + * the drm node from the EGLDevice. If they match, then + * this is the final device to use, since it is the compositor's + * device. + */ + if (strcmp(dev_name, protocols.drm_name) == 0) { + eglDevice = eglDeviceList[0]; + break; + } + } + } + } + } + } + + /* + * Right now we are pretty much limited to running on the same GPU as the + * compositor. If we couldn't find an EGLDevice that has EGL_EXT_device_drm_render_node + * and the same DRM device path, then fail. + */ + if (!eglDevice) { + goto fail_cleanup_devices; + } + display->devDpy = wlGetInternalDisplay(pData, eglDevice); if (display->devDpy == NULL) { - wlExternalApiUnlock(); - goto fail; + goto fail_cleanup_devices; } if (!wlEglInitializeMutex(&display->mutex)) { - wlExternalApiUnlock(); - goto fail; + goto fail_cleanup_devices; } display->refCount = 1; WL_LIST_INIT(&display->wlEglSurfaceList); @@ -537,10 +649,21 @@ EGLDisplay wlEglGetPlatformDisplayExport(void *data, // in wlEglDisplayList. wl_list_insert(&wlEglDisplayList, &display->link); + free(eglDeviceList); + if (protocols.drm_name) { + free(protocols.drm_name); + } wlExternalApiUnlock(); return display; +fail_cleanup_devices: + free(eglDeviceList); +fail_cleanup_protocols: + if (protocols.drm_name) { + free(protocols.drm_name); + } fail: + wlExternalApiUnlock(); if (display->ownNativeDpy) { wl_display_disconnect(display->nativeDpy); -- 2.34.1 ++++++ U_0002-generate-wayland-drm-client-protocol.h.patch ++++++ >From daab8546eca8428543a4d958a2c53fc747f70672 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov <adamant-...@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:13:04 +0200 Subject: [PATCH 2/3] generate wayland-drm-client-protocol.h --- Makefile.am | 3 ++- src/meson.build | 1 + wayland-drm/meson.build | 6 ++++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 8129539..9463349 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,7 +49,8 @@ libnvidia_egl_wayland_la_built_private_protocols = \ libnvidia_egl_wayland_la_built_client_headers = \ wayland-eglstream/wayland-eglstream-client-protocol.h \ - wayland-eglstream/wayland-eglstream-controller-client-protocol.h + wayland-eglstream/wayland-eglstream-controller-client-protocol.h \ + wayland-drm/wayland-drm-client-protocol.h libnvidia_egl_wayland_la_built_server_headers = \ wayland-eglstream/wayland-eglstream-server-protocol.h \ diff --git a/src/meson.build b/src/meson.build index a489fa3..6f69e09 100644 --- a/src/meson.build +++ b/src/meson.build @@ -47,6 +47,7 @@ src = [ wayland_eglstream_controller_protocol_c, wayland_eglstream_controller_client_protocol_h, wayland_drm_protocol_c, + wayland_drm_client_protocol_h, wayland_drm_server_protocol_h, ] diff --git a/wayland-drm/meson.build b/wayland-drm/meson.build index b3b3bcb..2a29afe 100644 --- a/wayland-drm/meson.build +++ b/wayland-drm/meson.build @@ -1,5 +1,7 @@ -foreach output_type: ['server-header', 'public-code'] - if output_type == 'server-header' +foreach output_type: ['client-header', 'server-header', 'public-code'] + if output_type == 'client-header' + output_file = 'wayland-drm-client-protocol.h' + elif output_type == 'server-header' output_file = 'wayland-drm-server-protocol.h' else output_file = 'wayland-drm-protocol.c' -- 2.34.1 ++++++ U_0003-egl-wayland-retrieve-DRM-device-name-before-acquirin.patch ++++++ >From 582b2d345abaa0e313cf16c902e602084ea59551 Mon Sep 17 00:00:00 2001 From: Erik Kurzinger <ekurzin...@nvidia.com> Date: Tue, 23 Nov 2021 14:15:14 -0500 Subject: [PATCH 3/3] egl-wayland: retrieve DRM device name before acquiring API lock wlEglBindDisplaysHook acquires the external API lock before calling wl_eglstream_display_bind, which in turn calls wl_drm_display_bind. That function calls back into EGL to query the DRM device associated with the given EGLDisplay. Normally this is not a problem since the EGLDisplay passed to eglBindWaylandDisplayWL will be an internal EGL_PLATFORM_DEVICE handle. However, some applications, notably anything WebKit-based, will instead pass in an external EGL_PLATFORM_WAYLAND handle. This means that the eglQueryDisplayAttrib call by wl_drm_display_bind will require EGL to call back into the egl-wayland library to look up the internal handle. This is done by wlEglGetInternalHandleExport, which will attempt to acquire the external API lock a second time, which will fail. To avoid this, add a new function to wayland-drm.c which will retrieve the DRM device name for the given EGLDisplay. wlEglBindDisplaysHook will call this *before* acquiring the external API lock, and then pass it to wl_drm_display_bind via wl_eglstream_display_bind so it can be saved in the wl_eglstream_display struct. --- include/wayland-drm.h | 7 ++++++- include/wayland-eglstream-server.h | 3 ++- src/wayland-drm.c | 33 +++++++++++++++--------------- src/wayland-egldisplay.c | 8 +++++--- src/wayland-eglstream-server.c | 5 +++-- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/include/wayland-drm.h b/include/wayland-drm.h index be363c6..84d0f11 100644 --- a/include/wayland-drm.h +++ b/include/wayland-drm.h @@ -23,9 +23,14 @@ #ifndef WAYLAND_DRM_H #define WAYLAND_DRM_H +extern const char * +wl_drm_get_dev_name(const WlEglPlatformData *data, + EGLDisplay dpy); + extern EGLBoolean wl_drm_display_bind(struct wl_display *display, - struct wl_eglstream_display *wlStreamDpy); + struct wl_eglstream_display *wlStreamDpy, + const char *dev_name); extern void wl_drm_display_unbind(struct wl_eglstream_display *wlStreamDpy); diff --git a/include/wayland-eglstream-server.h b/include/wayland-eglstream-server.h index 76e772c..0f7d477 100644 --- a/include/wayland-eglstream-server.h +++ b/include/wayland-eglstream-server.h @@ -49,7 +49,8 @@ EGLBoolean wl_eglstream_display_bind(WlEglPlatformData *data, struct wl_display *wlDisplay, EGLDisplay eglDisplay, - const char *exts); + const char *exts, + const char *dev_name); /* * wl_eglstream_display_unbind() diff --git a/src/wayland-drm.c b/src/wayland-drm.c index aa6de23..a08d82f 100644 --- a/src/wayland-drm.c +++ b/src/wayland-drm.c @@ -152,37 +152,36 @@ bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) wl_resource_post_event(resource, WL_DRM_CAPABILITIES, 0); } -EGLBoolean -wl_drm_display_bind(struct wl_display *display, - struct wl_eglstream_display *wlStreamDpy) +const char * +wl_drm_get_dev_name(const WlEglPlatformData *data, + EGLDisplay dpy) { - EGLDisplay dpy = wlStreamDpy->eglDisplay; EGLDeviceEXT egl_dev; const char *dev_exts; - const char *dev_name; - if (!wlStreamDpy->data->egl.queryDisplayAttrib(dpy, - EGL_DEVICE_EXT, - (EGLAttribKHR*)&egl_dev)) { - return EGL_FALSE; + if (!data->egl.queryDisplayAttrib(dpy, EGL_DEVICE_EXT, + (EGLAttribKHR*)&egl_dev)) { + return NULL; } - - dev_exts = wlStreamDpy->data->egl.queryDeviceString(egl_dev, - EGL_EXTENSIONS); + dev_exts = data->egl.queryDeviceString(egl_dev, EGL_EXTENSIONS); if (!dev_exts) { - return EGL_FALSE; + return NULL; } if (!wlEglFindExtension("EGL_EXT_device_drm_render_node", dev_exts)) { - return EGL_FALSE; + return NULL; } - dev_name = - wlStreamDpy->data->egl.queryDeviceString(egl_dev, - EGL_DRM_RENDER_NODE_FILE_EXT); + return data->egl.queryDeviceString(egl_dev, EGL_DRM_RENDER_NODE_FILE_EXT); +} +EGLBoolean +wl_drm_display_bind(struct wl_display *display, + struct wl_eglstream_display *wlStreamDpy, + const char *dev_name) +{ if (!dev_name) { return EGL_FALSE; } diff --git a/src/wayland-egldisplay.c b/src/wayland-egldisplay.c index 8b7394a..d285bf7 100644 --- a/src/wayland-egldisplay.c +++ b/src/wayland-egldisplay.c @@ -30,6 +30,7 @@ #include "wayland-eglhandle.h" #include "wayland-eglutils.h" #include "wayland-drm-client-protocol.h" +#include "wayland-drm.h" #include <string.h> #include <stdlib.h> #include <assert.h> @@ -70,15 +71,16 @@ EGLBoolean wlEglIsValidNativeDisplayExport(void *data, void *nativeDpy) EGLBoolean wlEglBindDisplaysHook(void *data, EGLDisplay dpy, void *nativeDpy) { - /* Retrieve extension string before taking external API lock */ - const char *exts = ((WlEglPlatformData *)data)->egl.queryString(dpy, EGL_EXTENSIONS); + /* Retrieve extension string and device name before taking external API lock */ + const char *exts = ((WlEglPlatformData *)data)->egl.queryString(dpy, EGL_EXTENSIONS), + *dev_name = wl_drm_get_dev_name(data, dpy); EGLBoolean res = EGL_FALSE; wlExternalApiLock(); res = wl_eglstream_display_bind((WlEglPlatformData *)data, (struct wl_display *)nativeDpy, - dpy, exts); + dpy, exts, dev_name); wlExternalApiUnlock(); diff --git a/src/wayland-eglstream-server.c b/src/wayland-eglstream-server.c index b1baa08..1dfd7ce 100644 --- a/src/wayland-eglstream-server.c +++ b/src/wayland-eglstream-server.c @@ -289,7 +289,8 @@ EGLBoolean wl_eglstream_display_bind(WlEglPlatformData *data, struct wl_display *wlDisplay, EGLDisplay eglDisplay, - const char *exts) + const char *exts, + const char *dev_name) { struct wl_eglstream_display *wlStreamDpy = NULL; char *env = NULL; @@ -355,7 +356,7 @@ wl_eglstream_display_bind(WlEglPlatformData *data, wl_eglstream_display_global_bind); /* Failure is not fatal */ - wl_drm_display_bind(wlDisplay, wlStreamDpy); + wl_drm_display_bind(wlDisplay, wlStreamDpy, dev_name); wl_list_insert(&wlStreamDpyList, &wlStreamDpy->link); -- 2.34.1