[Mesa-dev] [PATCH 2/3] radv: Add VK_EXT_acquire_xlib_display

Keith Packard keithp at keithp.com
Wed Aug 2 10:12:40 UTC 2017


This uses X leases to provide the same API as nVidia, allowing an
application to discover available display resources and acquire one from
the X server using RandR leases.

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 configure.ac                           |  11 +
 src/amd/vulkan/Makefile.am             |   8 +
 src/amd/vulkan/radv_device.c           |   6 +
 src/amd/vulkan/radv_entrypoints_gen.py |   3 +-
 src/amd/vulkan/radv_wsi_display.c      |  31 +++
 src/vulkan/Makefile.am                 |   8 +
 src/vulkan/wsi/wsi_common_display.c    | 375 +++++++++++++++++++++++++++++++--
 src/vulkan/wsi/wsi_common_display.h    |  16 ++
 8 files changed, 444 insertions(+), 14 deletions(-)

diff --git a/configure.ac b/configure.ac
index d95b915b984..b4a17bc9c67 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1412,6 +1412,10 @@ fi
 AC_SUBST([GL_LIB])
 AC_SUBST([OSMESA_LIB])
 
+# Check for RandR leases
+PKG_CHECK_MODULES([RANDRPROTO], [randrproto >= 1.6.0],
+                  [have_xlease=yes], [have_xlease=no])
+
 # Check for libdrm
 PKG_CHECK_MODULES([LIBDRM], [libdrm >= $LIBDRM_REQUIRED],
                   [have_libdrm=yes], [have_libdrm=no])
@@ -1451,6 +1455,7 @@ AM_CONDITIONAL(HAVE_APPLEDRI, test "x$enable_dri" = xyes -a "x$dri_platform" = x
 AM_CONDITIONAL(HAVE_LMSENSORS, test "x$enable_lmsensors" = xyes )
 AM_CONDITIONAL(HAVE_GALLIUM_EXTRA_HUD, test "x$enable_gallium_extra_hud" = xyes )
 AM_CONDITIONAL(HAVE_WINDOWSDRI, test "x$enable_dri" = xyes -a "x$dri_platform" = xwindows )
+AM_CONDITIONAL(HAVE_XLEASE, test "x$have_xlease" = xyes )
 
 AC_ARG_ENABLE([shared-glapi],
     [AS_HELP_STRING([--enable-shared-glapi],
@@ -1749,6 +1754,12 @@ if test x"$enable_dri3" = xyes; then
     PKG_CHECK_MODULES([XCB_DRI3], [$dri3_modules])
 fi
 
+if test x"$have_xlease" = xyes; then
+    DEFINES="$DEFINES -DHAVE_XLEASE"
+    randr_modules="x11-xcb xcb-randr"
+    PKG_CHECK_MODULES([XCB_RANDR], [$randr_modules])
+fi
+
 AM_CONDITIONAL(HAVE_PLATFORM_X11, echo "$platforms" | grep -q 'x11')
 AM_CONDITIONAL(HAVE_PLATFORM_WAYLAND, echo "$platforms" | grep -q 'wayland')
 AM_CONDITIONAL(HAVE_PLATFORM_DRM, echo "$platforms" | grep -q 'drm')
diff --git a/src/amd/vulkan/Makefile.am b/src/amd/vulkan/Makefile.am
index 3a6ada825b5..5a3c714cc03 100644
--- a/src/amd/vulkan/Makefile.am
+++ b/src/amd/vulkan/Makefile.am
@@ -84,6 +84,14 @@ AM_CPPFLAGS += \
 
 VULKAN_SOURCES += $(VULKAN_WSI_DISPLAY_FILES)
 
+if HAVE_PLATFORM_X11
+if HAVE_XLEASE
+AM_CPPFLAGS += \
+	$(XCB_RANDR_CFLAGS)
+VULKAN_LIB_DEPS += $(XCB_RANDR_LIBS)
+endif
+endif
+
 endif
 
 if HAVE_PLATFORM_X11
diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index da8e7a89f66..db68b0724fd 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -123,6 +123,12 @@ static const VkExtensionProperties instance_extensions[] = {
                 .specVersion = 1,
         },
 #endif
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+        {
+                .extensionName = VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME,
+                .specVersion = 1,
+        },
+#endif
 };
 
 static const VkExtensionProperties common_device_extensions[] = {
diff --git a/src/amd/vulkan/radv_entrypoints_gen.py b/src/amd/vulkan/radv_entrypoints_gen.py
index 48125da2e76..2a151cc701c 100644
--- a/src/amd/vulkan/radv_entrypoints_gen.py
+++ b/src/amd/vulkan/radv_entrypoints_gen.py
@@ -59,7 +59,8 @@ SUPPORTED_EXTENSIONS = [
     'VK_KHR_external_semaphore_fd',
     'VK_KEITHP_kms_display',
     'VK_KHR_display',
-    'VK_EXT_direct_mode_display'
+    'VK_EXT_direct_mode_display',
+    'VK_EXT_acquire_xlib_display'
 ]
 
 # We generate a static hash table for entry point lookup
diff --git a/src/amd/vulkan/radv_wsi_display.c b/src/amd/vulkan/radv_wsi_display.c
index 26fb4bee803..0c9cf7e3315 100644
--- a/src/amd/vulkan/radv_wsi_display.c
+++ b/src/amd/vulkan/radv_wsi_display.c
@@ -137,6 +137,37 @@ radv_ReleaseDisplayEXT(VkPhysicalDevice physical_device,
                               display);
 }
 
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+VkResult
+radv_AcquireXlibDisplayEXT(VkPhysicalDevice     physical_device,
+                           Display              *dpy,
+                           VkDisplayKHR         display)
+{
+   RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
+
+   return wsi_acquire_xlib_display(physical_device,
+                                   &pdevice->wsi_device,
+                                   dpy,
+                                   display);
+}
+
+VkResult
+radv_GetRandROutputDisplayEXT(VkPhysicalDevice  physical_device,
+                              Display           *dpy,
+                              RROutput          output,
+                              VkDisplayKHR      *display)
+{
+   RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
+
+   return wsi_get_randr_output_display(physical_device,
+                                       &pdevice->wsi_device,
+                                       dpy,
+                                       output,
+                                       display);
+}
+
+#endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */
+
 VkResult
 radv_CreateDisplayPlaneSurfaceKHR(VkInstance                            _instance,
                                   const VkDisplaySurfaceCreateInfoKHR   *create_info,
diff --git a/src/vulkan/Makefile.am b/src/vulkan/Makefile.am
index 693b93e0c11..2af6831bde3 100644
--- a/src/vulkan/Makefile.am
+++ b/src/vulkan/Makefile.am
@@ -53,6 +53,14 @@ AM_CPPFLAGS += \
 	-DVK_USE_PLATFORM_DISPLAY
 
 VULKAN_WSI_SOURCES += $(VULKAN_WSI_DISPLAY_FILES)
+
+if HAVE_PLATFORM_X11
+if HAVE_XLEASE
+AM_CPPFLAGS += \
+	-DVK_USE_PLATFORM_XLIB_XRANDR_EXT
+endif
+endif
+
 endif
 
 BUILT_SOURCES += $(VULKAN_WSI_WAYLAND_GENERATED_FILES)
diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c
index 1ec0004be91..81e009c1cc8 100644
--- a/src/vulkan/wsi/wsi_common_display.c
+++ b/src/vulkan/wsi/wsi_common_display.c
@@ -32,6 +32,10 @@
 #include <math.h>
 #include <xf86drm.h>
 #include <xf86drmMode.h>
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+#include <xcb/randr.h>
+#include <X11/Xlib-xcb.h>
+#endif
 #include "util/hash_table.h"
 #include "util/list.h"
 
@@ -67,6 +71,9 @@ typedef struct wsi_display_connector {
    drmModeConnectorPtr          connector;
    uint32_t                     edid_length;
    uint8_t                      *edid;
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+   xcb_randr_output_t           output;
+#endif
 } wsi_display_connector;
 
 struct wsi_display {
@@ -78,6 +85,8 @@ struct wsi_display {
    const struct wsi_callbacks   *cbs;
 
    int                          master_fd;
+   int                          render_fd;
+   bool                         master_is_render;
 
    pthread_mutex_t              wait_mutex;
    pthread_cond_t               wait_cond;
@@ -226,7 +235,7 @@ wsi_display_get_connector(struct wsi_device             *wsi_device,
    struct wsi_display           *wsi = (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
    struct wsi_display_connector *connector;
    drmModeConnectorPtr          drm_connector;
-   int                          drm_fd = wsi->master_fd;
+   int                          drm_fd = wsi->master_fd >= 0 ? wsi->master_fd : wsi->render_fd;
    int                          p, m;
    VkResult                     result;
 
@@ -339,7 +348,7 @@ wsi_display_get_physical_device_display_properties(VkPhysicalDevice
                                                    VkDisplayPropertiesKHR       *properties)
 {
    struct wsi_display           *wsi = (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
-   int                          drm_fd = wsi->master_fd;
+   int                          drm_fd = wsi->master_fd >= 0 ? wsi->master_fd : wsi->render_fd;
    struct wsi_display_connector *connector;
    int                          c;
    uint32_t                     connected = 0;
@@ -568,6 +577,321 @@ wsi_release_display(VkPhysicalDevice            physical_device,
    return VK_SUCCESS;
 }
 
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+static struct wsi_display_connector *
+wsi_display_find_output(struct wsi_device               *wsi_device,
+                        RROutput                        output)
+{
+   struct wsi_display           *wsi = (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
+   struct wsi_display_connector *connector;
+
+   connector = NULL;
+   LIST_FOR_EACH_ENTRY(connector, &wsi->connectors, list) {
+      if (connector->output == output)
+         return connector;
+   }
+
+   return NULL;
+}
+
+/*
+ * Given a RandR output, find the associated kernel connector_id by
+ * looking at the CONNECTOR_ID property provided by the X server
+ */
+
+static uint32_t
+wsi_display_output_to_connector_id(xcb_connection_t     *connection,
+                                   xcb_atom_t           *connector_id_atom_p,
+                                   RROutput             output)
+{
+   uint32_t                     connector_id = 0;
+   xcb_atom_t                   connector_id_atom = *connector_id_atom_p;
+
+   if (connector_id_atom == 0) {
+   /* Go dig out the CONNECTOR_ID property */
+      xcb_intern_atom_cookie_t     ia_c = xcb_intern_atom(connection,
+                                                          true,
+                                                          12,
+                                                          "CONNECTOR_ID");
+      xcb_intern_atom_reply_t      *ia_r = xcb_intern_atom_reply(connection,
+                                                                 ia_c,
+                                                                 NULL);
+      if (ia_r) {
+         *connector_id_atom_p = connector_id_atom = ia_r->atom;
+         free(ia_r);
+      }
+   }
+
+   /* If there's an CONNECTOR_ID atom in the server, then there may be a CONNECTOR_ID property. Otherwise,
+    * there will not be and we don't even need to bother.
+    */
+   if (connector_id_atom) {
+
+      xcb_randr_query_version_cookie_t          qv_c = xcb_randr_query_version(connection, 1, 6);
+      xcb_randr_get_output_property_cookie_t    gop_c = xcb_randr_get_output_property(connection,
+                                                                                      output,
+                                                                                      connector_id_atom,
+                                                                                      0,
+                                                                                      0,
+                                                                                      0xffffffffUL,
+                                                                                      0,
+                                                                                      0);
+      xcb_randr_query_version_reply_t           *qv_r = xcb_randr_query_version_reply(connection, qv_c, NULL);
+      free(qv_r);
+      xcb_randr_get_output_property_reply_t     *gop_r = xcb_randr_get_output_property_reply(connection,
+                                                                                             gop_c,
+                                                                                             NULL);
+      if (gop_r) {
+         if (gop_r->num_items == 1 && gop_r->format == 32)
+            memcpy(&connector_id, xcb_randr_get_output_property_data(gop_r), 4);
+         free(gop_r);
+      }
+   }
+   return connector_id;
+}
+
+static bool
+wsi_display_check_randr_version(xcb_connection_t        *connection)
+{
+   xcb_randr_query_version_cookie_t     qv_c = xcb_randr_query_version(connection, 1, 6);
+   xcb_randr_query_version_reply_t      *qv_r = xcb_randr_query_version_reply(connection, qv_c, NULL);
+   bool                                 ret = false;
+
+   if (!qv_r)
+      return false;
+
+   /* Check for version 1.6 or newer */
+   ret = qv_r->major_version > 1 || (qv_r->major_version == 1 && qv_r->minor_version >= 6);
+
+   free(qv_r);
+   return ret;
+}
+
+/*
+ * Given a kernel connector id, find the associated RandR output using the
+ * CONNECTOR_ID property
+ */
+
+static xcb_randr_output_t
+wsi_display_connector_id_to_output(xcb_connection_t     *connection,
+                                   uint32_t             connector_id)
+{
+   if (!wsi_display_check_randr_version(connection))
+      return 0;
+
+   const xcb_setup_t                    *setup = xcb_get_setup(connection);
+
+   xcb_atom_t                           connector_id_atom = 0;
+   xcb_randr_output_t                   output = 0;
+
+   /* Search all of the screens for the provided output */
+   xcb_screen_iterator_t iter;
+   for (iter = xcb_setup_roots_iterator(setup); output == 0 && iter.rem; xcb_screen_next(&iter)) {
+
+      xcb_randr_get_screen_resources_cookie_t      gsr_c = xcb_randr_get_screen_resources(connection, iter.data->root);
+      xcb_randr_get_screen_resources_reply_t       *gsr_r = xcb_randr_get_screen_resources_reply(connection, gsr_c, NULL);
+
+      if (!gsr_r)
+         return 0;
+
+      xcb_randr_output_t        *ro = xcb_randr_get_screen_resources_outputs(gsr_r);
+      int                       o;
+
+      for (o = 0; o < gsr_r->num_outputs; o++) {
+         if (wsi_display_output_to_connector_id(connection, &connector_id_atom, ro[o]) == connector_id) {
+            output = ro[o];
+            break;
+         }
+      }
+      free(gsr_r);
+   }
+   return output;
+}
+
+/*
+ * Given a RandR output, find out which screen it's associated with
+ */
+static xcb_window_t
+wsi_display_output_to_root(xcb_connection_t   *connection,
+                           xcb_randr_output_t output)
+{
+   if (!wsi_display_check_randr_version(connection))
+      return 0;
+
+   const xcb_setup_t                    *setup = xcb_get_setup(connection);
+   xcb_window_t                         root = 0;
+
+   /* Search all of the screens for the provided output */
+   xcb_screen_iterator_t iter;
+   for (iter = xcb_setup_roots_iterator(setup); root == 0 && iter.rem; xcb_screen_next(&iter)) {
+      xcb_randr_get_screen_resources_cookie_t      gsr_c = xcb_randr_get_screen_resources(connection, iter.data->root);
+      xcb_randr_get_screen_resources_reply_t       *gsr_r = xcb_randr_get_screen_resources_reply(connection, gsr_c, NULL);
+
+      if (!gsr_r)
+         return 0;
+
+      xcb_randr_output_t        *ro = xcb_randr_get_screen_resources_outputs(gsr_r);
+      int                       o;
+
+      for (o = 0; o < gsr_r->num_outputs; o++) {
+         if (ro[o] == output) {
+            root = iter.data->root;
+            break;
+         }
+      }
+      free(gsr_r);
+   }
+   return root;
+}
+
+static struct wsi_display_connector *
+wsi_display_get_output(struct wsi_device        *wsi_device,
+                       xcb_connection_t         *connection,
+                       RROutput                 output)
+{
+   struct wsi_display_connector *connector;
+   uint32_t                     connector_id;
+   xcb_atom_t                   connector_id_atom = 0;
+
+   connector = wsi_display_find_output(wsi_device, output);
+
+   if (connector)
+      return connector;
+
+   connector_id = wsi_display_output_to_connector_id(connection, &connector_id_atom, output);
+   if (connector_id != 0)
+      connector = wsi_display_get_connector(wsi_device, connector_id);
+
+   if (connector)
+      connector->output = output;
+
+   return connector;
+}
+
+static xcb_randr_crtc_t
+wsi_display_find_crtc_for_output(xcb_connection_t       *connection,
+                                 xcb_window_t           root,
+                                 xcb_randr_output_t     output)
+{
+   xcb_randr_get_screen_resources_cookie_t      gsr_c = xcb_randr_get_screen_resources(connection, root);
+   xcb_randr_get_screen_resources_reply_t       *gsr_r = xcb_randr_get_screen_resources_reply(connection, gsr_c, NULL);
+
+   if (!gsr_r)
+      return 0;
+
+   xcb_randr_crtc_t     *rc = xcb_randr_get_screen_resources_crtcs(gsr_r);
+   xcb_randr_crtc_t     idle_crtc = 0;
+   xcb_randr_crtc_t     active_crtc = 0;
+
+   /* Find either a crtc already connected to the desired output or idle */
+   int c;
+   for (c = 0; active_crtc == 0 && c < gsr_r->num_crtcs; c++) {
+      xcb_randr_get_crtc_info_cookie_t gci_c = xcb_randr_get_crtc_info(connection, rc[c], gsr_r->config_timestamp);
+      xcb_randr_get_crtc_info_reply_t *gci_r = xcb_randr_get_crtc_info_reply(connection, gci_c, NULL);
+      if (gci_r) {
+         if (gci_r->mode) {
+            int num_outputs = xcb_randr_get_crtc_info_outputs_length(gci_r);
+            xcb_randr_output_t *outputs = xcb_randr_get_crtc_info_outputs(gci_r);
+            for (int o = 0; o < num_outputs; o++)
+               if (outputs[o] == output && num_outputs == 1) {
+                  active_crtc = rc[c];
+                  break;
+               }
+         } else if (idle_crtc == 0) {
+            int num_possible = xcb_randr_get_crtc_info_possible_length(gci_r);
+            xcb_randr_output_t *possible = xcb_randr_get_crtc_info_possible(gci_r);
+            for (int p = 0; p < num_possible; p++)
+               if (possible[p] == output) {
+                  idle_crtc = rc[c];
+                  break;
+               }
+         }
+         free(gci_r);
+      }
+   }
+   free(gsr_r);
+
+   if (active_crtc)
+      return active_crtc;
+   return idle_crtc;
+}
+
+VkResult
+wsi_acquire_xlib_display(VkPhysicalDevice       physical_device,
+                         struct wsi_device      *wsi_device,
+                         Display                *dpy,
+                         VkDisplayKHR           display)
+{
+   struct wsi_display           *wsi = (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
+   xcb_connection_t             *connection = XGetXCBConnection(dpy);
+   struct wsi_display_connector *connector = wsi_display_connector_from_handle(display);
+   xcb_window_t                 root;
+
+   if (!connector->output) {
+      connector->output = wsi_display_connector_id_to_output(connection, connector->id);
+
+      /* Check and see if we found the output */
+      if (!connector->output)
+         return VK_ERROR_OUT_OF_DATE_KHR;
+   }
+
+   root = wsi_display_output_to_root(connection, connector->output);
+   if (!root)
+      return VK_ERROR_OUT_OF_DATE_KHR;
+
+   xcb_randr_crtc_t                     crtc = wsi_display_find_crtc_for_output(connection,
+                                                                                root,
+                                                                                connector->output);
+
+   if (!crtc)
+      return VK_ERROR_OUT_OF_DATE_KHR;
+
+   xcb_randr_lease_t                    lease = xcb_generate_id(connection);
+   xcb_randr_create_lease_cookie_t      cl_c = xcb_randr_create_lease(connection,
+                                                                      root,
+                                                                      lease,
+                                                                      1,
+                                                                      1,
+                                                                      &crtc,
+                                                                      &connector->output);
+   xcb_randr_create_lease_reply_t       *cl_r = xcb_randr_create_lease_reply(connection, cl_c, NULL);
+   if (!cl_r)
+      return VK_ERROR_OUT_OF_DATE_KHR;
+
+   int fd = -1;
+   if (cl_r->nfd > 0) {
+      int *rcl_f = xcb_randr_create_lease_reply_fds(connection, cl_r);
+
+      fd = rcl_f[0];
+   }
+   free (cl_r);
+   if (fd < 0)
+      return VK_ERROR_OUT_OF_DATE_KHR;
+
+   wsi->master_fd = fd;
+   wsi->master_is_render = false;
+
+   return VK_SUCCESS;
+}
+
+VkResult
+wsi_get_randr_output_display(VkPhysicalDevice   physical_device,
+                             struct wsi_device  *wsi_device,
+                             Display            *dpy,
+                             RROutput           output,
+                             VkDisplayKHR       *display)
+{
+   xcb_connection_t             *connection = XGetXCBConnection(dpy);
+   struct wsi_display_connector *connector = wsi_display_get_output(wsi_device, connection, output);
+
+   if (connector)
+      *display = wsi_display_connector_to_handle(connector);
+   else
+      *display = NULL;
+   return VK_SUCCESS;
+}
+#endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */
+
 VkResult
 wsi_create_display_surface(VkInstance instance,
                            const VkAllocationCallbacks   *allocator,
@@ -605,10 +929,13 @@ wsi_display_surface_get_support(VkIcdSurfaceBase *surface,
                                 bool can_handle_different_gpu,
                                 VkBool32* pSupported)
 {
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+   *pSupported = true;
+#else
    struct wsi_display *wsi = (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
 
    *pSupported = wsi->master_fd >= 0;
-
+#endif
    return VK_SUCCESS;
 }
 
@@ -702,9 +1029,20 @@ wsi_display_image_init(VkDevice                         device_h,
    VkResult                     result;
    uint32_t                     row_pitch;
    uint32_t                     offset;
-   uint32_t                     handle;
    uint32_t                     size;
    int                          ret;
+   int                          image_fd;
+   uint32_t                     image_handle;
+   int                          *image_fd_p;
+   uint32_t                     *image_handle_p;
+
+   if (wsi->master_is_render) {
+      image_fd_p = NULL;
+      image_handle_p = &image_handle;
+   } else {
+      image_fd_p = &image_fd;
+      image_handle_p = NULL;
+   }
 
    memset(image, '\0', sizeof (*image));
    image->chain = chain;
@@ -718,8 +1056,8 @@ wsi_display_image_init(VkDevice                         device_h,
                                                     &size,
                                                     &offset,
                                                     &row_pitch,
-                                                    NULL,
-                                                    &handle);
+                                                    image_fd_p,
+                                                    image_handle_p);
 
    if (result != VK_SUCCESS)
       return result;
@@ -735,19 +1073,27 @@ wsi_display_image_init(VkDevice                         device_h,
                                                        &size,
                                                        &offset,
                                                        &row_pitch,
-                                                       NULL,
-                                                       &handle);
-
+                                                       image_fd_p,
+                                                       image_handle_p);
       if (result != VK_SUCCESS) {
          goto fail_linear;
       }
    }
 
-   image->bo_handle = handle;
+   if (wsi->master_is_render)
+      image->bo_handle = image_handle;
+   else {
+      int ret = drmPrimeFDToHandle(wsi->master_fd, image_fd, &image_handle);
+      close(image_fd);
+      if (ret < 0) {
+         result = VK_ERROR_OUT_OF_HOST_MEMORY;
+         goto fail_fb;
+      }
+   }
 
    /* XXX extract depth and bpp from image somehow */
    ret = drmModeAddFB(wsi->master_fd, create_info->imageExtent.width, create_info->imageExtent.height,
-                      24, 32, row_pitch, handle, &image->fb_id);
+                      24, 32, row_pitch, image_handle, &image->fb_id);
 
    if (ret) {
       result = VK_ERROR_OUT_OF_HOST_MEMORY;
@@ -968,7 +1314,7 @@ wsi_display_crtc_solo(struct wsi_display        *wsi,
                       uint32_t                  crtc_id)
 {
    drmModeResPtr        mode_res = wsi->mode_res;
-   int                  drm_fd = wsi->master_fd;
+   int                  drm_fd = wsi->master_fd >= 0 ? wsi->master_fd : wsi->render_fd;
    int                  c, e;
 
    /* See if any other connectors share the same encoder */
@@ -1007,7 +1353,7 @@ wsi_display_select_crtc(struct wsi_display_connector    *connector)
    struct wsi_display   *wsi = connector->wsi;
    int                  c;
    drmModeResPtr        mode_res = wsi->mode_res;
-   int                  drm_fd = wsi->master_fd;
+   int                  drm_fd = wsi->master_fd >= 0 ? wsi->master_fd : wsi->render_fd;
    uint32_t             crtc_id;
 
    if (!mode_res)
@@ -1218,6 +1564,9 @@ wsi_display_init_wsi(struct wsi_device *wsi_device,
    memset(wsi, '\0', sizeof (*wsi));
 
    wsi->master_fd = master_fd;
+   wsi->render_fd = render_fd;
+   if (master_fd >= 0)
+      wsi->master_is_render = true;
    pthread_mutex_init(&wsi->wait_mutex, NULL);
    wsi->physical_device = physical_device;
    wsi->alloc = alloc;
diff --git a/src/vulkan/wsi/wsi_common_display.h b/src/vulkan/wsi/wsi_common_display.h
index 173c019c4bd..47430aa41e1 100644
--- a/src/vulkan/wsi/wsi_common_display.h
+++ b/src/vulkan/wsi/wsi_common_display.h
@@ -68,6 +68,22 @@ wsi_release_display(VkPhysicalDevice            physical_device,
                     struct wsi_device           *wsi_device,
                     VkDisplayKHR                display);
 
+#if VK_USE_PLATFORM_XLIB_XRANDR_EXT
+VkResult
+wsi_acquire_xlib_display(VkPhysicalDevice       physical_device,
+                         struct wsi_device      *wsi_device,
+                         Display                *dpy,
+                         VkDisplayKHR           display);
+
+VkResult
+wsi_get_randr_output_display(VkPhysicalDevice   physical_device,
+                             struct wsi_device  *wsi_device,
+                             Display            *dpy,
+                             RROutput           output,
+                             VkDisplayKHR       *display);
+
+#endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */
+
 VkResult
 wsi_create_display_surface(VkInstance instance,
                            const VkAllocationCallbacks *pAllocator,
-- 
2.11.0



More information about the mesa-dev mailing list