diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 6d0143dd78f..29047d7a84a 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -59,6 +59,7 @@ #ifdef HAVE_X11_PLATFORM #include "X11/Xlibint.h" #include "x11_dri3.h" +#include "x11_display.h" #endif #include "GL/mesa_glinterop.h" @@ -125,11 +126,9 @@ dri_is_thread_safe(UNUSED void *loaderPrivate) /* Check Xlib is running in thread safe mode when running on EGL/X11-xlib * platform - * - * 'lock_fns' is the XLockDisplay function pointer of the X11 display 'dpy'. - * It will be NULL if XInitThreads wasn't called. */ - if (display->Platform == _EGL_PLATFORM_X11 && xdpy && !xdpy->lock_fns) + if (display->Platform == _EGL_PLATFORM_X11 && xdpy && + !x11_xlib_display_is_thread_safe(xdpy)) return false; #endif diff --git a/src/glx/dri_common.c b/src/glx/dri_common.c index 2ca9521c6ed..634f18d5a8c 100644 --- a/src/glx/dri_common.c +++ b/src/glx/dri_common.c @@ -45,6 +45,7 @@ #include #include "dri_util.h" #include "pipe-loader/pipe_loader.h" +#include "x11_display.h" #define __ATTRIB(attrib, field) \ { attrib, offsetof(struct glx_config, field) } @@ -747,12 +748,7 @@ static GLboolean driIsThreadSafe(void *loaderPrivate) { struct glx_context *pcp = (struct glx_context *) loaderPrivate; - /* Check Xlib is running in thread safe mode - * - * 'lock_fns' is the XLockDisplay function pointer of the X11 display 'dpy'. - * It will be NULL if XInitThreads wasn't called. - */ - return pcp->psc->dpy->lock_fns != NULL; + return x11_xlib_display_is_thread_safe(pcp->psc->dpy); } const __DRIbackgroundCallableExtension driBackgroundCallable = { diff --git a/src/vulkan/wsi/meson.build b/src/vulkan/wsi/meson.build index ba609ab3151..38a83d08eab 100644 --- a/src/vulkan/wsi/meson.build +++ b/src/vulkan/wsi/meson.build @@ -11,6 +11,7 @@ endif if with_platform_x11 files_vulkan_wsi += files('wsi_common_x11.c') + links_vulkan_wsi += libloader_x11 endif if with_platform_wayland diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index 0c4cb9d7d42..7e3db6d6317 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -21,7 +21,6 @@ * IN THE SOFTWARE. */ -#include #include #include #define XK_MISCELLANY @@ -54,6 +53,7 @@ #include "util/u_thread.h" #include "util/xmlconfig.h" #include "util/timespec.h" +#include "x11/x11_display.h" #include "vk_format.h" #include "vk_instance.h" @@ -610,15 +610,6 @@ wsi_GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice, return true; } -static bool -xlib_display_is_thread_safe(Display *dpy) -{ - /* 'lock_fns' is the XLockDisplay function pointer of the X11 display 'dpy'. - * It will be NULL if XInitThreads wasn't called. - */ - return dpy->lock_fns != NULL; -} - VKAPI_ATTR VkBool32 VKAPI_CALL wsi_GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, @@ -628,7 +619,7 @@ wsi_GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice, /* Our WSI implementation for X11 relies on threads. Check Xlib is running * in thread safe mode before advertising support. */ - if (!xlib_display_is_thread_safe(dpy)) + if (!x11_xlib_display_is_thread_safe(dpy)) return false; return wsi_GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, @@ -641,7 +632,7 @@ static bool x11_surface_is_thread_safe(VkIcdSurfaceBase *icd_surface) { if (icd_surface->platform == VK_ICD_WSI_PLATFORM_XLIB) - return xlib_display_is_thread_safe(((VkIcdSurfaceXlib *)icd_surface)->dpy); + return x11_xlib_display_is_thread_safe(((VkIcdSurfaceXlib *)icd_surface)->dpy); else return true; } @@ -2588,11 +2579,8 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, /* We really shouldn't get here as we return no WSI support for XLib when * it's not threadsafe. However, one final check doesn't cost much. */ - if (!x11_surface_is_thread_safe(icd_surface)) { - fprintf(stderr, "vulkan: xlib Display is not thread-safe. Call " - "XInitThreads() in your app\n"); + if (!x11_surface_is_thread_safe(icd_surface)) return VK_ERROR_UNKNOWN; - } /* Get xcb connection from the icd_surface and from that our internal struct * representing it. diff --git a/src/x11/meson.build b/src/x11/meson.build index b63f7c59674..f289fd05f96 100644 --- a/src/x11/meson.build +++ b/src/x11/meson.build @@ -3,19 +3,23 @@ inc_loader_x11 = include_directories('.') +loader_x11_files = files( + 'x11_display.c', +) + if with_dri_platform == 'drm' - libloader_x11 = static_library( - 'loader_x11', - 'x11_dri3.c', - gnu_symbol_visibility : 'hidden', - include_directories : [inc_include, inc_src, inc_gallium], - dependencies : [ - idep_mesautil, - dep_libdrm, dep_xcb_dri3, dep_xcb_present, dep_xcb_sync, dep_xshmfence, - dep_xcb_xfixes, - ], - build_by_default : false, - ) -else - libloader_x11 = [] + loader_x11_files += files('x11_dri3.c') endif + +libloader_x11 = static_library( + 'loader_x11', + loader_x11_files, + gnu_symbol_visibility : 'hidden', + include_directories : [inc_include, inc_src, inc_gallium], + dependencies : [ + idep_mesautil, + dep_libdrm, dep_xcb_dri3, dep_xcb_present, dep_xcb_sync, dep_xshmfence, + dep_xcb_xfixes, + ], + build_by_default : false, +) diff --git a/src/x11/x11_display.c b/src/x11/x11_display.c new file mode 100644 index 00000000000..f7c9a94fdc9 --- /dev/null +++ b/src/x11/x11_display.c @@ -0,0 +1,49 @@ +/* + * Copyright © 2025 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include "x11_display.h" + +#include "util/macros.h" + +#include +#include + +bool +x11_xlib_display_is_thread_safe(Display *dpy) +{ + static bool warned = false; + + /* 'lock_fns' is the XLockDisplay function pointer of the X11 display 'dpy'. + * It will be NULL if XInitThreads wasn't called. + */ + if (likely(dpy->lock_fns != NULL)) + return true; + + if (unlikely(!warned)) { + fprintf(stderr, "Xlib is not thread-safe. This should never be the " + "case starting with XLib 1.8. Either upgrade XLib " + "or call XInitThreads() from your app.\n"); + warned = true; + } + + return false; +} diff --git a/src/x11/x11_display.h b/src/x11/x11_display.h new file mode 100644 index 00000000000..a669de3dbdf --- /dev/null +++ b/src/x11/x11_display.h @@ -0,0 +1,40 @@ +/* + * Copyright © 2025 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _UTIL_X11_H +#define _UTIL_X11_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool x11_xlib_display_is_thread_safe(Display *dpy); + +#ifdef __cplusplus +} /* extern C */ +#endif + +#endif /* _UTIL_X11_H */