From 0a44a680ff702bb4488c345db84a35c190be345e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Feb 2017 15:27:47 +1000 Subject: [PATCH] vulkan/wsi/x11: add support to detect if we can support rendering (v3) This adds support to radv_GetPhysicalDeviceXlibPresentationSupportKHR and radv_GetPhysicalDeviceXcbPresentationSupportKHR to check if the local device file descriptor is compatible with the descriptor retrieved from the X server via DRI3. This will stop radv binding to an X server until we have prime support in place. Hopefully apps use this API before trying to render things. v2: drop unneeded function, don't leak memory. (jekstrand) v3: also check in surface_get_support callback. Reviewed-by: Jason Ekstrand Signed-off-by: Dave Airlie --- src/amd/vulkan/radv_device.c | 5 +- src/amd/vulkan/radv_private.h | 1 + src/amd/vulkan/radv_wsi.c | 2 +- src/amd/vulkan/radv_wsi_x11.c | 8 +++- src/intel/vulkan/Makefile.am | 3 +- src/intel/vulkan/anv_device.c | 3 +- src/intel/vulkan/anv_private.h | 1 + src/intel/vulkan/anv_wsi.c | 2 +- src/intel/vulkan/anv_wsi_x11.c | 8 +++- src/vulkan/wsi/Makefile.am | 1 + src/vulkan/wsi/wsi_common.h | 1 + src/vulkan/wsi/wsi_common_wayland.c | 1 + src/vulkan/wsi/wsi_common_x11.c | 71 ++++++++++++++++++++++++++++- src/vulkan/wsi/wsi_common_x11.h | 1 + 14 files changed, 98 insertions(+), 10 deletions(-) diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index 7900ece9c89..3d0e74273e4 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -225,6 +225,8 @@ radv_physical_device_init(struct radv_physical_device *device, result = VK_ERROR_INCOMPATIBLE_DRIVER; goto fail; } + + device->local_fd = fd; device->ws->query_info(device->ws, &device->rad_info); result = radv_init_wsi(device); if (result != VK_SUCCESS) { @@ -249,7 +251,7 @@ radv_physical_device_init(struct radv_physical_device *device, fprintf(stderr, "WARNING: radv is not a conformant vulkan implementation, testing use only.\n"); device->name = device->rad_info.name; - close(fd); + return VK_SUCCESS; fail: @@ -263,6 +265,7 @@ radv_physical_device_finish(struct radv_physical_device *device) radv_extensions_finish(device->instance, &device->extensions); radv_finish_wsi(device); device->ws->destroy(device->ws); + close(device->local_fd); } diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index ac21b075c2c..5fabc409d82 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -280,6 +280,7 @@ struct radv_physical_device { const char * name; uint8_t uuid[VK_UUID_SIZE]; + int local_fd; struct wsi_device wsi_device; struct radv_extensions extensions; }; diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c index 9c9e1bb0a8d..ea8e7849722 100644 --- a/src/amd/vulkan/radv_wsi.c +++ b/src/amd/vulkan/radv_wsi.c @@ -92,7 +92,7 @@ VkResult radv_GetPhysicalDeviceSurfaceSupportKHR( return iface->get_support(surface, &device->wsi_device, &device->instance->alloc, - queueFamilyIndex, pSupported); + queueFamilyIndex, device->local_fd, pSupported); } VkResult radv_GetPhysicalDeviceSurfaceCapabilitiesKHR( diff --git a/src/amd/vulkan/radv_wsi_x11.c b/src/amd/vulkan/radv_wsi_x11.c index 946b99095ac..97d4277c490 100644 --- a/src/amd/vulkan/radv_wsi_x11.c +++ b/src/amd/vulkan/radv_wsi_x11.c @@ -45,7 +45,9 @@ VkBool32 radv_GetPhysicalDeviceXcbPresentationSupportKHR( return wsi_get_physical_device_xcb_presentation_support( &device->wsi_device, &device->instance->alloc, - queueFamilyIndex, connection, visual_id); + queueFamilyIndex, + device->local_fd, + connection, visual_id); } VkBool32 radv_GetPhysicalDeviceXlibPresentationSupportKHR( @@ -59,7 +61,9 @@ VkBool32 radv_GetPhysicalDeviceXlibPresentationSupportKHR( return wsi_get_physical_device_xcb_presentation_support( &device->wsi_device, &device->instance->alloc, - queueFamilyIndex, XGetXCBConnection(dpy), visualID); + queueFamilyIndex, + device->local_fd, + XGetXCBConnection(dpy), visualID); } VkResult radv_CreateXcbSurfaceKHR( diff --git a/src/intel/vulkan/Makefile.am b/src/intel/vulkan/Makefile.am index 4197b0e77c7..93f2ceb00f1 100644 --- a/src/intel/vulkan/Makefile.am +++ b/src/intel/vulkan/Makefile.am @@ -68,6 +68,7 @@ AM_CPPFLAGS += \ endif AM_CPPFLAGS += \ + $(LIBDRM_CFLAGS) \ $(INTEL_CFLAGS) \ $(VALGRIND_CFLAGS) \ $(DEFINES) @@ -93,7 +94,7 @@ VULKAN_SOURCES = \ $(VULKAN_GENERATED_FILES) \ $(VULKAN_FILES) -VULKAN_LIB_DEPS = +VULKAN_LIB_DEPS = $(LIBDRM_LIBS) if HAVE_PLATFORM_X11 AM_CPPFLAGS += \ diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index cae5feff948..dd2a1ea34ad 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -202,7 +202,7 @@ anv_physical_device_init(struct anv_physical_device *device, isl_device_init(&device->isl_dev, &device->info, swizzled); - close(fd); + device->local_fd = fd; return VK_SUCCESS; fail: @@ -215,6 +215,7 @@ anv_physical_device_finish(struct anv_physical_device *device) { anv_finish_wsi(device); ralloc_free(device->compiler); + close(device->local_fd); } static const VkExtensionProperties global_extensions[] = { diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index da1ca29f64c..82e283171ef 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -532,6 +532,7 @@ struct anv_physical_device { uint8_t uuid[VK_UUID_SIZE]; struct wsi_device wsi_device; + int local_fd; }; struct anv_instance { diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c index 3a366988de8..a69a741723b 100644 --- a/src/intel/vulkan/anv_wsi.c +++ b/src/intel/vulkan/anv_wsi.c @@ -94,7 +94,7 @@ VkResult anv_GetPhysicalDeviceSurfaceSupportKHR( return iface->get_support(surface, &device->wsi_device, &device->instance->alloc, - queueFamilyIndex, pSupported); + queueFamilyIndex, device->local_fd, pSupported); } VkResult anv_GetPhysicalDeviceSurfaceCapabilitiesKHR( diff --git a/src/intel/vulkan/anv_wsi_x11.c b/src/intel/vulkan/anv_wsi_x11.c index 60bc568ab0c..30425096a99 100644 --- a/src/intel/vulkan/anv_wsi_x11.c +++ b/src/intel/vulkan/anv_wsi_x11.c @@ -41,7 +41,9 @@ VkBool32 anv_GetPhysicalDeviceXcbPresentationSupportKHR( return wsi_get_physical_device_xcb_presentation_support( &device->wsi_device, &device->instance->alloc, - queueFamilyIndex, connection, visual_id); + queueFamilyIndex, + device->local_fd, + connection, visual_id); } VkBool32 anv_GetPhysicalDeviceXlibPresentationSupportKHR( @@ -55,7 +57,9 @@ VkBool32 anv_GetPhysicalDeviceXlibPresentationSupportKHR( return wsi_get_physical_device_xcb_presentation_support( &device->wsi_device, &device->instance->alloc, - queueFamilyIndex, XGetXCBConnection(dpy), visualID); + queueFamilyIndex, + device->local_fd, + XGetXCBConnection(dpy), visualID); } VkResult anv_CreateXcbSurfaceKHR( diff --git a/src/vulkan/wsi/Makefile.am b/src/vulkan/wsi/Makefile.am index a71279947a9..b5ccf986ac3 100644 --- a/src/vulkan/wsi/Makefile.am +++ b/src/vulkan/wsi/Makefile.am @@ -13,6 +13,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/gallium/include AM_CFLAGS = \ + $(LIBDRM_CFLAGS) \ $(VISIBILITY_CFLAGS) VULKAN_LIB_DEPS = diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h index 394b8fa1914..ae9e5876112 100644 --- a/src/vulkan/wsi/wsi_common.h +++ b/src/vulkan/wsi/wsi_common.h @@ -71,6 +71,7 @@ struct wsi_interface { struct wsi_device *wsi_device, const VkAllocationCallbacks *alloc, uint32_t queueFamilyIndex, + int local_fd, VkBool32* pSupported); VkResult (*get_capabilities)(VkIcdSurfaceBase *surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c index c2dfc657b35..44897366d94 100644 --- a/src/vulkan/wsi/wsi_common_wayland.c +++ b/src/vulkan/wsi/wsi_common_wayland.c @@ -351,6 +351,7 @@ wsi_wl_surface_get_support(VkIcdSurfaceBase *surface, struct wsi_device *wsi_device, const VkAllocationCallbacks *alloc, uint32_t queueFamilyIndex, + int local_fd, VkBool32* pSupported) { *pSupported = true; diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index 64ba92196fc..bec4907adad 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -33,8 +33,9 @@ #include #include #include - +#include #include +#include #include "util/hash_table.h" #include "wsi_common.h" @@ -59,6 +60,66 @@ struct wsi_x11 { struct hash_table *connections; }; + +/** wsi_dri3_open + * + * Wrapper around xcb_dri3_open + */ +static int +wsi_dri3_open(xcb_connection_t *conn, + xcb_window_t root, + uint32_t provider) +{ + xcb_dri3_open_cookie_t cookie; + xcb_dri3_open_reply_t *reply; + int fd; + + cookie = xcb_dri3_open(conn, + root, + provider); + + reply = xcb_dri3_open_reply(conn, cookie, NULL); + if (!reply) + return -1; + + if (reply->nfd != 1) { + free(reply); + return -1; + } + + fd = xcb_dri3_open_reply_fds(conn, reply)[0]; + free(reply); + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + + return fd; +} + +static bool +wsi_x11_check_dri3_compatible(xcb_connection_t *conn, int local_fd) +{ + xcb_screen_iterator_t screen_iter = + xcb_setup_roots_iterator(xcb_get_setup(conn)); + xcb_screen_t *screen = screen_iter.data; + + int dri3_fd = wsi_dri3_open(conn, screen->root, None); + if (dri3_fd != -1) { + char *local_dev = drmGetRenderDeviceNameFromFd(local_fd); + char *dri3_dev = drmGetRenderDeviceNameFromFd(dri3_fd); + int ret; + + close(dri3_fd); + + ret = strcmp(local_dev, dri3_dev); + + free(local_dev); + free(dri3_dev); + + if (ret != 0) + return false; + } + return true; +} + static struct wsi_x11_connection * wsi_x11_connection_create(const VkAllocationCallbacks *alloc, xcb_connection_t *conn) @@ -255,6 +316,7 @@ VkBool32 wsi_get_physical_device_xcb_presentation_support( struct wsi_device *wsi_device, VkAllocationCallbacks *alloc, uint32_t queueFamilyIndex, + int fd, xcb_connection_t* connection, xcb_visualid_t visual_id) { @@ -270,6 +332,9 @@ VkBool32 wsi_get_physical_device_xcb_presentation_support( return false; } + if (!wsi_x11_check_dri3_compatible(connection, fd)) + return false; + unsigned visual_depth; if (!connection_get_visualtype(connection, visual_id, &visual_depth)) return false; @@ -303,6 +368,7 @@ x11_surface_get_support(VkIcdSurfaceBase *icd_surface, struct wsi_device *wsi_device, const VkAllocationCallbacks *alloc, uint32_t queueFamilyIndex, + int local_fd, VkBool32* pSupported) { xcb_connection_t *conn = x11_surface_get_connection(icd_surface); @@ -320,6 +386,9 @@ x11_surface_get_support(VkIcdSurfaceBase *icd_surface, return VK_SUCCESS; } + if (!wsi_x11_check_dri3_compatible(conn, local_fd)) + return false; + unsigned visual_depth; if (!get_visualtype_for_window(conn, window, &visual_depth)) { *pSupported = false; diff --git a/src/vulkan/wsi/wsi_common_x11.h b/src/vulkan/wsi/wsi_common_x11.h index 7166f099fdb..01f1d66eeaa 100644 --- a/src/vulkan/wsi/wsi_common_x11.h +++ b/src/vulkan/wsi/wsi_common_x11.h @@ -29,6 +29,7 @@ VkBool32 wsi_get_physical_device_xcb_presentation_support( struct wsi_device *wsi_device, VkAllocationCallbacks *alloc, uint32_t queueFamilyIndex, + int local_fd, xcb_connection_t* connection, xcb_visualid_t visual_id); -- 2.30.2