vulkan/wsi/x11: add support to detect if we can support rendering (v3)
authorDave Airlie <airlied@redhat.com>
Sun, 19 Feb 2017 05:27:47 +0000 (15:27 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 20 Feb 2017 02:53:52 +0000 (12:53 +1000)
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 <jason@jlekstrand.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
14 files changed:
src/amd/vulkan/radv_device.c
src/amd/vulkan/radv_private.h
src/amd/vulkan/radv_wsi.c
src/amd/vulkan/radv_wsi_x11.c
src/intel/vulkan/Makefile.am
src/intel/vulkan/anv_device.c
src/intel/vulkan/anv_private.h
src/intel/vulkan/anv_wsi.c
src/intel/vulkan/anv_wsi_x11.c
src/vulkan/wsi/Makefile.am
src/vulkan/wsi/wsi_common.h
src/vulkan/wsi/wsi_common_wayland.c
src/vulkan/wsi/wsi_common_x11.c
src/vulkan/wsi/wsi_common_x11.h

index 7900ece9c8998db6fc1b64a81dd1b425f8e7fa0b..3d0e74273e423d73083818c16cafbd5f91867cd4 100644 (file)
@@ -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);
 }
 
 
index ac21b075c2c5b8e6b339c157c3257ce4fff144d4..5fabc409d82a2452de506d03dabd7143310c4a1d 100644 (file)
@@ -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;
 };
index 9c9e1bb0a8d94545afbc9c00da62997e60578d54..ea8e7849722c6922f2a42c910e728025d56ee3a0 100644 (file)
@@ -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(
index 946b99095ac3726cf3f6e806360b0c99fcdec135..97d4277c4909c9a9d2a70f3d64c72b068bfb1d3e 100644 (file)
@@ -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(
index 4197b0e77c78f75f0072c4f381acee9167884a68..93f2ceb00f16c2388691b5d4c1aeb26cf1a2bb5a 100644 (file)
@@ -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 += \
index cae5feff948a373f4f2f8d4703dafcadc427bfa8..dd2a1ea34ad35703730e6ffcd825ab30aa03b683 100644 (file)
@@ -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[] = {
index da1ca29f64c3c38086ffa63d9e26d793b0a0a895..82e283171ef9ca8282be64a6f94071a7d8868c5f 100644 (file)
@@ -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 {
index 3a366988de83448e1c79fd15890dc1c2a0ec301c..a69a741723bb47d499d76dbf2a3c70da49fecef1 100644 (file)
@@ -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(
index 60bc568ab0c473d416a2554ad6660afb5c50dbfe..30425096a9944c037c902b32c4bc3fce89c23140 100644 (file)
@@ -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(
index a71279947a98f2ca485c3afb88ac38b4eee629cc..b5ccf986ac32c97756b9e4fbe1d660a4402573fa 100644 (file)
@@ -13,6 +13,7 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/src/gallium/include
 
 AM_CFLAGS = \
+       $(LIBDRM_CFLAGS) \
        $(VISIBILITY_CFLAGS)
 
 VULKAN_LIB_DEPS =
index 394b8fa1914dbed153e15b0c478a847d35c23540..ae9e5876112779bc1898d732e4820ef5d75b126d 100644 (file)
@@ -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);
index c2dfc657b352c28f14a8e84ef730c73094d19612..44897366d94195ee2daaa975dbc20663e4550399 100644 (file)
@@ -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;
index 64ba92196fc7c3b51aaa02d025ed3e7c2c457fef..bec4907adad9437371b1d09b0569c45fdfe4a133 100644 (file)
@@ -33,8 +33,9 @@
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>
-
+#include <fcntl.h>
 #include <poll.h>
+#include <xf86drm.h>
 #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;
index 7166f099fdb4cec7b86c50ef7ae0fed9d749f745..01f1d66eeaa031b075332e9463304f3be8c6bc12 100644 (file)
@@ -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);