x11: Add an x11_xlib_display_is_thread_safe() helper

Even though Xlib 1.8 enables thread-safety by default it's still
theoretically possible that the user's system has an Xlib that has been
built with this turned off.  Warn in that case.  Since this requires
poking at Xlib internals, it's better to have this as a util helper.

Now that libloader_x11 contains more than just dri3 helpers, we build it
unconditionally if with_platform_x11 and just add loader_x11.c if it

Acked-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Reviewed-by: Eric Engestrom <eric@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36123>
This commit is contained in:
Faith Ekstrand 2025-07-14 11:47:15 -04:00 committed by Marge Bot
parent b8ef9bfbf5
commit 950dac6e6c
7 changed files with 117 additions and 40 deletions

View file

@ -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

View file

@ -45,6 +45,7 @@
#include <xcb/xproto.h>
#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 = {

View file

@ -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

View file

@ -21,7 +21,6 @@
* IN THE SOFTWARE.
*/
#include <X11/Xlibint.h>
#include <X11/Xlib-xcb.h>
#include <X11/xshmfence.h>
#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.

View file

@ -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,
)

49
src/x11/x11_display.c Normal file
View file

@ -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 <stdio.h>
#include <X11/Xlibint.h>
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;
}

40
src/x11/x11_display.h Normal file
View file

@ -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 <stdbool.h>
#include <X11/Xlib.h>
#ifdef __cplusplus
extern "C" {
#endif
bool x11_xlib_display_is_thread_safe(Display *dpy);
#ifdef __cplusplus
} /* extern C */
#endif
#endif /* _UTIL_X11_H */