<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">As with patch 1, I've gone through and made a pile of style changes to bring things back under 80 characters.  You can find it on this branch:<br><br><a href="https://gitlab.freedesktop.org/jekstrand/mesa/commits/wip/drm-lease-v3-whitespace">https://gitlab.freedesktop.org/jekstrand/mesa/commits/wip/drm-lease-v3-whitespace</a><br><br></div><div class="gmail_quote">I also fixed a couple of the comments below.<br></div><div class="gmail_quote"><br>On Wed, Mar 7, 2018 at 11:25 PM, Keith Packard <span dir="ltr"><<a href="mailto:keithp@keithp.com" target="_blank">keithp@keithp.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">This extension adds the ability to borrow an X RandR output for<br>
temporary use directly by a Vulkan application. For DRM, we use the<br>
Linux resource leasing mechanism.<br>
<br>
v2:<br>
        Clean up xlib_lease detection<br>
<br>
        * Use separate temporary '_xlib_lease' variable to hold the<br>
          option value to avoid changin the type of a variable.<br>
<br>
        * Use boolean expressions instead of additional if statements<br>
          to compute resulting with_xlib_lease value.<br>
<br>
        * Simplify addition of VK_USE_PLATFORM_XLIB_XRANDR_<wbr>KHR to<br>
          vulkan_wsi_args<br>
<br>
          Suggested-by: Eric Engestrom <<a href="mailto:eric.engestrom@imgtec.com">eric.engestrom@imgtec.com</a>><br>
<br>
        Move mode list from wsi_display to wsi_display_connector<br>
<br>
        Fix scope for wsi_display_mode and wsi_display_connector allocs<br>
<br>
          Suggested-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
<br>
Signed-off-by: Keith Packard <<a href="mailto:keithp@keithp.com">keithp@keithp.com</a>><br>
---<br>
 <a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a>                        |  32 +++<br>
 meson.build                         |  11 +<br>
 meson_options.txt                   |   7 +<br>
 src/vulkan/Makefile.am              |   5 +<br>
 src/vulkan/wsi/meson.build          |   5 +<br>
 src/vulkan/wsi/wsi_common_<wbr>display.c | 470 ++++++++++++++++++++++++++++++<wbr>++++++<br>
 src/vulkan/wsi/wsi_common_<wbr>display.h |  17 ++<br>
 7 files changed, 547 insertions(+)<br>
<br>
diff --git a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a> b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
index 7fcb3220eaa..bf649f9fed7 100644<br>
--- a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
+++ b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
@@ -1560,6 +1560,7 @@ AM_CONDITIONAL(HAVE_APPLEDRI, test "x$enable_dri" = xyes -a "x$dri_platform" = x<br>
 AM_CONDITIONAL(HAVE_LMSENSORS, test "x$enable_lmsensors" = xyes )<br>
 AM_CONDITIONAL(HAVE_GALLIUM_<wbr>EXTRA_HUD, test "x$enable_gallium_extra_hud" = xyes )<br>
 AM_CONDITIONAL(HAVE_<wbr>WINDOWSDRI, test "x$enable_dri" = xyes -a "x$dri_platform" = xwindows )<br>
+AM_CONDITIONAL(HAVE_XLEASE, test "x$have_xlease" = xyes )<br>
<br>
 AC_ARG_ENABLE([shared-glapi],<br>
     [AS_HELP_STRING([--enable-<wbr>shared-glapi],<br>
@@ -1853,6 +1854,18 @@ if test x"$enable_dri3" = xyes; then<br>
     PKG_CHECK_MODULES([XCB_DRI3], [$dri3_modules])<br>
 fi<br>
<br>
+<br>
+if echo "$platforms" | grep -q 'x11' && echo "$platforms" | grep -q 'drm'; then<br>
+    have_xlease=yes<br>
+else<br>
+    have_xlease=no<br>
+fi<br>
+<br>
+if test x"$have_xlease" = xyes; then<br>
+    randr_modules="x11-xcb xcb-randr"<br>
+    PKG_CHECK_MODULES([XCB_RANDR], [$randr_modules])<br>
+fi<br>
+<br>
 AM_CONDITIONAL(HAVE_PLATFORM_<wbr>X11, echo "$platforms" | grep -q 'x11')<br>
 AM_CONDITIONAL(HAVE_PLATFORM_<wbr>WAYLAND, echo "$platforms" | grep -q 'wayland')<br>
 AM_CONDITIONAL(HAVE_PLATFORM_<wbr>DRM, echo "$platforms" | grep -q 'drm')<br>
@@ -1860,6 +1873,25 @@ AM_CONDITIONAL(HAVE_PLATFORM_<wbr>DISPLAY, echo "$platforms" | grep -q 'drm')<br>
 AM_CONDITIONAL(HAVE_PLATFORM_<wbr>SURFACELESS, echo "$platforms" | grep -q 'surfaceless')<br>
 AM_CONDITIONAL(HAVE_PLATFORM_<wbr>ANDROID, echo "$platforms" | grep -q 'android')<br>
<br>
+AC_ARG_ENABLE(xlib-lease,<br>
+    [AS_HELP_STRING([--enable-<wbr>xlib-lease]<br>
+                    [enable VK_acquire_xlib_display using X leases])],<br>
+    [enable_xlib_lease=$enableval]<wbr>, [enable_xlib_lease=auto])<br>
+case "x$enable_xlib_lease" in<br>
+xyes)<br>
+    ;;<br>
+xno)<br>
+    ;;<br>
+*)<br>
+    if echo "$platforms" | grep -q 'x11' && echo "$platforms" | grep -q 'drm'; then<br>
+        enable_xlib_lease=yes<br>
+    else<br>
+        enable_xlib_lease=no<br>
+    fi<br>
+esac<br>
+<br>
+AM_CONDITIONAL(HAVE_XLIB_<wbr>LEASE, test "x$enable_xlib_lease" = xyes)<br>
+<br>
 dnl<br>
 dnl More DRI setup<br>
 dnl<br>
diff --git a/meson.build b/meson.build<br>
index 788aed6e159..68081e9fcc3 100644<br>
--- a/meson.build<br>
+++ b/meson.build<br>
@@ -265,6 +265,13 @@ if _platforms != ''<br>
   egl_native_platform = _split[0]<br>
 endif<br>
<br>
+_xlib_lease = get_option('xlib-lease')<br>
+if _xlib_lease == 'auto'<br>
+  with_xlib_lease = with_platform_x11 and with_platform_display<br>
+else<br>
+  with_xlib_lease = _xlib_lease == 'true'<br>
+endif<br>
+<br>
 with_glx = get_option('glx')<br>
 if with_glx == 'auto'<br>
   if with_dri<br>
@@ -1202,6 +1209,7 @@ dep_xcb_present = []<br>
 dep_xcb_sync = []<br>
 dep_xcb_xfixes = []<br>
 dep_xshmfence = []<br>
+dep_xcb_xrandr = []<br>
 if with_platform_x11<br>
   if with_glx == 'xlib' or with_glx == 'gallium-xlib'<br>
     dep_x11 = dependency('x11')<br>
@@ -1241,6 +1249,9 @@ if with_platform_x11<br>
   if with_egl<br>
     dep_xcb_xfixes = dependency('xcb-xfixes')<br>
   endif<br>
+  if with_xlib_lease<br>
+    dep_xcb_xrandr = dependency('xcb-randr', version : '>= 1.12')<br>
+  endif<br>
 endif<br>
<br>
 if get_option('gallium-extra-hud'<wbr>)<br>
diff --git a/meson_options.txt b/meson_options.txt<br>
index a573290b774..70318e1041f 100644<br>
--- a/meson_options.txt<br>
+++ b/meson_options.txt<br>
@@ -286,3 +286,10 @@ option(<br>
   value : '',<br>
   description : 'Comma delimited list of tools to build. choices : freedreno,glsl,intel,nir,<wbr>nouveau or all'<br>
 )<br>
+option(<br>
+  'xlib-lease',<br>
+  type : 'combo',<br>
+  value : 'auto',<br>
+  choices : ['auto', 'true', 'false'],<br>
+  description : 'Enable VK_EXT_acquire_xlib_display.'<br>
+)<br>
diff --git a/src/vulkan/Makefile.am b/src/vulkan/Makefile.am<br>
index 075eb58c82c..c8f425f286a 100644<br>
--- a/src/vulkan/Makefile.am<br>
+++ b/src/vulkan/Makefile.am<br>
@@ -65,6 +65,11 @@ AM_CPPFLAGS += \<br>
 VULKAN_WSI_SOURCES += $(VULKAN_WSI_DISPLAY_FILES)<br>
 endif<br>
<br>
+if HAVE_XLIB_LEASE<br>
+AM_CPPFLAGS += \<br>
+       -DVK_USE_PLATFORM_XLIB_XRANDR_<wbr>EXT<br>
+endif<br>
+<br>
 CLEANFILES = $(BUILT_SOURCES)<br>
<br>
 WL_DRM_XML = $(top_srcdir)/src/egl/wayland/<wbr>wayland-drm/wayland-drm.xml<br>
diff --git a/src/vulkan/wsi/meson.build b/src/vulkan/wsi/meson.build<br>
index 776e596984d..3085118337c 100644<br>
--- a/src/vulkan/wsi/meson.build<br>
+++ b/src/vulkan/wsi/meson.build<br>
@@ -67,6 +67,11 @@ if with_platform_display<br>
   )<br>
 endif<br>
<br>
+if with_xlib_lease<br>
+  vulkan_wsi_deps += dep_xcb_xrandr<br>
+  vulkan_wsi_args += '-DVK_USE_PLATFORM_XLIB_<wbr>XRANDR_EXT'<br>
+endif<br>
+<br>
 libvulkan_wsi = static_library(<br>
   'vulkan_wsi',<br>
   files_vulkan_wsi,<br>
diff --git a/src/vulkan/wsi/wsi_common_<wbr>display.c b/src/vulkan/wsi/wsi_common_<wbr>display.c<br>
index 45626541022..087e8d18dba 100644<br>
--- a/src/vulkan/wsi/wsi_common_<wbr>display.c<br>
+++ b/src/vulkan/wsi/wsi_common_<wbr>display.c<br>
@@ -33,6 +33,10 @@<br>
 #include <xf86drm.h><br>
 #include <xf86drmMode.h><br>
 #include <drm_fourcc.h><br>
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_<wbr>EXT<br>
+#include <xcb/randr.h><br>
+#include <X11/Xlib-xcb.h><br>
+#endif<br>
 #include "util/hash_table.h"<br>
 #include "util/list.h"<br>
<br>
@@ -75,6 +79,9 @@ typedef struct wsi_display_connector {<br>
    struct list_head             display_modes;<br>
    wsi_display_mode             *current_mode;<br>
    drmModeModeInfo              current_drm_mode;<br>
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_<wbr>EXT<br>
+   xcb_randr_output_t           output;<br>
+#endif<br>
 } wsi_display_connector;<br>
<br>
 struct wsi_display {<br>
@@ -1414,5 +1421,468 @@ wsi_release_display(<wbr>VkPhysicalDevice            physical_device,<br>
       close(wsi->fd);<br>
       wsi->fd = -1;<br>
    }<br>
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_<wbr>EXT<br>
+   wsi_display_connector_from_<wbr>handle(display)->output = None;<br></blockquote><div><br></div><div>Does this function ever return NULL?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+#endif<br>
+<br>
+   return VK_SUCCESS;<br>
+}<br>
+<br>
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_<wbr>EXT<br>
+<br>
+static struct wsi_display_connector *<br>
+wsi_display_find_output(<wbr>struct wsi_device               *wsi_device,<br>
+                        RROutput                        output)<br></blockquote><div><br></div><div>You're using RROutput here but xcb_rander_output_t elsewhere.  Why not just pick one?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+{<br>
+   struct wsi_display           *wsi = (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_<wbr>PLATFORM_DISPLAY];<br>
+   struct wsi_display_connector *connector;<br>
+<br>
+   connector = NULL;<br>
+   LIST_FOR_EACH_ENTRY(connector, &wsi->connectors, list) {<br>
+      if (connector->output == output)<br>
+         return connector;<br>
+   }<br>
+<br>
+   return NULL;<br>
+}<br>
+<br>
+/*<br>
+ * Given a RandR output, find the associated kernel connector_id by<br>
+ * looking at the CONNECTOR_ID property provided by the X server<br>
+ */<br>
+<br>
+static uint32_t<br>
+wsi_display_output_to_<wbr>connector_id(xcb_connection_t     *connection,<br>
+                                   xcb_atom_t           *connector_id_atom_p,<br>
+                                   RROutput             output)<br>
+{<br>
+   uint32_t                     connector_id = 0;<br>
+   xcb_atom_t                   connector_id_atom = *connector_id_atom_p;<br>
+<br>
+   if (connector_id_atom == 0) {<br>
+   /* Go dig out the CONNECTOR_ID property */<br>
+      xcb_intern_atom_cookie_t     ia_c = xcb_intern_atom(connection,<br>
+                                                          true,<br>
+                                                          12,<br>
+                                                          "CONNECTOR_ID");<br>
+      xcb_intern_atom_reply_t      *ia_r = xcb_intern_atom_reply(<wbr>connection,<br>
+                                                                 ia_c,<br>
+                                                                 NULL);<br></blockquote><div><br></div><div>Things are going way over the usual 80 character limit.  I'm fixing up whitespace as I read and will put a fixup in my branch.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+      if (ia_r) {<br>
+         *connector_id_atom_p = connector_id_atom = ia_r->atom;<br>
+         free(ia_r);<br>
+      }<br>
+   }<br>
+<br>
+   /* If there's an CONNECTOR_ID atom in the server, then there may be a CONNECTOR_ID property. Otherwise,<br>
+    * there will not be and we don't even need to bother.<br>
+    */<br>
+   if (connector_id_atom) {<br>
+<br>
+      xcb_randr_query_version_<wbr>cookie_t          qv_c = xcb_randr_query_version(<wbr>connection, 1, 6);<br>
+      xcb_randr_get_output_property_<wbr>cookie_t    gop_c = xcb_randr_get_output_property(<wbr>connection,<br>
+                                                                                      output,<br>
+                                                                                      connector_id_atom,<br>
+                                                                                      0,<br>
+                                                                                      0,<br>
+                                                                                      0xffffffffUL,<br>
+                                                                                      0,<br>
+                                                                                      0);<br>
+      xcb_randr_query_version_reply_<wbr>t           *qv_r = xcb_randr_query_version_reply(<wbr>connection, qv_c, NULL);<br>
+      free(qv_r);<br></blockquote><div><br></div><div>What's up with the version query?  We're throwing it away without ever using it.  Does this provide us with some error checkint of some sort?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+      xcb_randr_get_output_property_<wbr>reply_t     *gop_r = xcb_randr_get_output_property_<wbr>reply(connection,<br>
+                                                                                             gop_c,<br>
+                                                                                             NULL);<br>
+      if (gop_r) {<br>
+         if (gop_r->num_items == 1 && gop_r->format == 32)<br>
+            memcpy(&connector_id, xcb_randr_get_output_property_<wbr>data(gop_r), 4);<br>
+         free(gop_r);<br>
+      }<br>
+   }<br>
+   return connector_id;<br>
+}<br>
+<br>
+static bool<br>
+wsi_display_check_randr_<wbr>version(xcb_connection_t        *connection)<br>
+{<br>
+   xcb_randr_query_version_<wbr>cookie_t     qv_c = xcb_randr_query_version(<wbr>connection, 1, 6);<br>
+   xcb_randr_query_version_reply_<wbr>t      *qv_r = xcb_randr_query_version_reply(<wbr>connection, qv_c, NULL);<br>
+   bool                                 ret = false;<br>
+<br>
+   if (!qv_r)<br>
+      return false;<br>
+<br>
+   /* Check for version 1.6 or newer */<br>
+   ret = qv_r->major_version > 1 || (qv_r->major_version == 1 && qv_r->minor_version >= 6);<br>
+<br>
+   free(qv_r);<br>
+   return ret;<br>
+}<br>
+<br>
+/*<br>
+ * Given a kernel connector id, find the associated RandR output using the<br>
+ * CONNECTOR_ID property<br>
+ */<br>
+<br>
+static xcb_randr_output_t<br>
+wsi_display_connector_id_to_<wbr>output(xcb_connection_t     *connection,<br>
+                                   uint32_t             connector_id)<br>
+{<br>
+   if (!wsi_display_check_randr_<wbr>version(connection))<br>
+      return 0;<br>
+<br>
+   const xcb_setup_t                    *setup = xcb_get_setup(connection);<br>
+<br>
+   xcb_atom_t                           connector_id_atom = 0;<br>
+   xcb_randr_output_t                   output = 0;<br>
+<br>
+   /* Search all of the screens for the provided output */<br>
+   xcb_screen_iterator_t iter;<br>
+   for (iter = xcb_setup_roots_iterator(<wbr>setup); output == 0 && iter.rem; xcb_screen_next(&iter)) {<br>
+<br>
+      xcb_randr_get_screen_<wbr>resources_cookie_t      gsr_c = xcb_randr_get_screen_<wbr>resources(connection, iter.data->root);<br>
+      xcb_randr_get_screen_<wbr>resources_reply_t       *gsr_r = xcb_randr_get_screen_<wbr>resources_reply(connection, gsr_c, NULL);<br>
+<br>
+      if (!gsr_r)<br>
+         return 0;<br>
+<br>
+      xcb_randr_output_t        *ro = xcb_randr_get_screen_<wbr>resources_outputs(gsr_r);<br>
+      int                       o;<br>
+<br>
+      for (o = 0; o < gsr_r->num_outputs; o++) {<br>
+         if (wsi_display_output_to_<wbr>connector_id(connection, &connector_id_atom, ro[o]) == connector_id) {<br>
+            output = ro[o];<br>
+            break;<br>
+         }<br>
+      }<br>
+      free(gsr_r);<br>
+   }<br>
+   return output;<br>
+}<br>
+<br>
+/*<br>
+ * Given a RandR output, find out which screen it's associated with<br>
+ */<br>
+static xcb_window_t<br>
+wsi_display_output_to_root(<wbr>xcb_connection_t   *connection,<br>
+                           xcb_randr_output_t output)<br>
+{<br>
+   if (!wsi_display_check_randr_<wbr>version(connection))<br>
+      return 0;<br>
+<br>
+   const xcb_setup_t                    *setup = xcb_get_setup(connection);<br>
+   xcb_window_t                         root = 0;<br>
+<br>
+   /* Search all of the screens for the provided output */<br>
+   xcb_screen_iterator_t iter;<br>
+   for (iter = xcb_setup_roots_iterator(<wbr>setup); root == 0 && iter.rem; xcb_screen_next(&iter)) {<br>
+      xcb_randr_get_screen_<wbr>resources_cookie_t      gsr_c = xcb_randr_get_screen_<wbr>resources(connection, iter.data->root);<br>
+      xcb_randr_get_screen_<wbr>resources_reply_t       *gsr_r = xcb_randr_get_screen_<wbr>resources_reply(connection, gsr_c, NULL);<br>
+<br>
+      if (!gsr_r)<br>
+         return 0;<br>
+<br>
+      xcb_randr_output_t        *ro = xcb_randr_get_screen_<wbr>resources_outputs(gsr_r);<br>
+      int                       o;<br>
+<br>
+      for (o = 0; o < gsr_r->num_outputs; o++) {<br>
+         if (ro[o] == output) {<br>
+            root = iter.data->root;<br>
+            break;<br>
+         }<br>
+      }<br>
+      free(gsr_r);<br>
+   }<br>
+   return root;<br>
+}<br>
+<br>
+static bool<br>
+wsi_display_mode_matches_x(<wbr>struct wsi_display_mode      *wsi,<br>
+                           xcb_randr_mode_info_t        *xcb)<br>
+{<br>
+   return wsi->clock == (xcb->dot_clock + 500) / 1000 &&<br>
+      wsi->hdisplay == xcb->width &&<br>
+      wsi->hsync_start == xcb->hsync_start &&<br>
+      wsi->hsync_end == xcb->hsync_end &&<br>
+      wsi->htotal == xcb->htotal &&<br>
+      wsi->hskew == xcb->hskew &&<br>
+      wsi->vdisplay == xcb->height &&<br>
+      wsi->vsync_start == xcb->vsync_start &&<br>
+      wsi->vsync_end == xcb->vsync_end &&<br>
+      wsi->vtotal == xcb->vtotal &&<br>
+      wsi->flags == xcb->mode_flags;<br>
+}<br>
+<br>
+static struct wsi_display_mode *<br>
+wsi_display_find_x_mode(<wbr>struct wsi_device                 *wsi_device,<br>
+                        struct wsi_display_connector      *connector,<br>
+                        xcb_randr_mode_info_t             *mode)<br>
+{<br>
+   struct wsi_display_mode      *display_mode;<br>
+<br>
+   LIST_FOR_EACH_ENTRY(display_<wbr>mode, &connector->display_modes, list) {<br>
+      if (wsi_display_mode_matches_x(<wbr>display_mode, mode))<br>
+         return display_mode;<br>
+   }<br>
+   return NULL;<br>
+}<br>
+<br>
+static VkResult<br>
+wsi_display_register_x_mode(<wbr>struct wsi_device                   *wsi_device,<br>
+                            struct wsi_display_connector        *connector,<br>
+                            xcb_randr_mode_info_t               *x_mode,<br>
+                            bool                                preferred)<br>
+{<br>
+   struct wsi_display           *wsi = (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_<wbr>PLATFORM_DISPLAY];<br>
+   struct wsi_display_mode      *display_mode;<br>
+<br>
+   display_mode = wsi_display_find_x_mode(wsi_<wbr>device, connector, x_mode);<br>
+<br>
+   if (display_mode) {<br>
+      display_mode->valid = true;<br>
+      return VK_SUCCESS;<br>
+   }<br>
+<br>
+   display_mode = vk_zalloc(wsi->alloc, sizeof (struct wsi_display_mode), 8, VK_SYSTEM_ALLOCATION_SCOPE_<wbr>INSTANCE);<br>
+   if (!display_mode)<br>
+      return VK_ERROR_OUT_OF_HOST_MEMORY;<br>
+<br>
+   display_mode->connector = connector;<br>
+   display_mode->valid = true;<br>
+   display_mode->preferred = preferred;<br>
+   display_mode->clock = (x_mode->dot_clock + 500) / 1000; /* kHz */<br>
+   display_mode->hdisplay = x_mode->width;<br>
+   display_mode->hsync_start = x_mode->hsync_start;<br>
+   display_mode->hsync_end = x_mode->hsync_end;<br>
+   display_mode->htotal = x_mode->htotal;<br>
+   display_mode->hskew = x_mode->hskew;<br>
+   display_mode->vdisplay = x_mode->height;<br>
+   display_mode->vsync_start = x_mode->vsync_start;<br>
+   display_mode->vsync_end = x_mode->vsync_end;<br>
+   display_mode->vtotal = x_mode->vtotal;<br>
+   display_mode->vscan = 0;<br>
+   if (x_mode->mode_flags & XCB_RANDR_MODE_FLAG_DOUBLE_<wbr>SCAN)<br>
+      display_mode->vscan = 1;<br>
+   display_mode->flags = x_mode->mode_flags;<br>
+<br>
+   LIST_ADDTAIL(&display_mode-><wbr>list, &connector->display_modes);<br>
+   return VK_SUCCESS;<br>
+}<br>
+<br>
+static struct wsi_display_connector *<br>
+wsi_display_get_output(struct wsi_device        *wsi_device,<br>
+                       xcb_connection_t         *connection,<br>
+                       RROutput                 output)<br>
+{<br>
+   struct wsi_display                           *wsi = (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_<wbr>PLATFORM_DISPLAY];<br>
+   struct wsi_display_connector                 *connector;<br>
+   uint32_t                                     connector_id;<br>
+   xcb_window_t                                 root;<br>
+   xcb_randr_get_screen_<wbr>resources_cookie_t      src;<br>
+   xcb_randr_get_screen_<wbr>resources_reply_t       *srr;<br>
+   xcb_randr_get_output_info_<wbr>cookie_t           oic;<br>
+   xcb_randr_get_output_info_<wbr>reply_t            *oir;<br>
+   xcb_randr_mode_t                             *x_modes;<br>
+   int                                          m;<br>
+<br>
+   root = wsi_display_output_to_root(<wbr>connection, output);<br>
+   if (!root)<br>
+      return NULL;<br>
+<br>
+   src = xcb_randr_get_screen_<wbr>resources(connection, root);<br>
+   oic = xcb_randr_get_output_info(<wbr>connection, output, XCB_CURRENT_TIME);<br>
+   srr = xcb_randr_get_screen_<wbr>resources_reply(connection, src, NULL);<br>
+   oir = xcb_randr_get_output_info_<wbr>reply(connection, oic, NULL);<br>
+<br>
+   /* See if we already have a connector for this output */<br>
+   connector = wsi_display_find_output(wsi_<wbr>device, output);<br>
+<br>
+   if (!connector) {<br>
+      xcb_atom_t        connector_id_atom = 0;<br>
+<br>
+      /*<br>
+       * Go get the kernel connector ID for this X output<br>
+       */<br>
+      connector_id = wsi_display_output_to_<wbr>connector_id(connection, &connector_id_atom, output);<br>
+<br>
+      /* Any X server with lease support will have this atom */<br>
+      if (!connector_id) {<br>
+         free(oir);<br>
+         free(srr);<br>
+         return NULL;<br>
+      }<br>
+<br>
+      if (!connector) {<br></blockquote><div><br></div><div>This is always true.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+         /* See if we already have a connector for this id */<br>
+         connector = wsi_display_find_connector(<wbr>wsi_device, connector_id);<br>
+<br>
+         if (connector)<br>
+            connector->output = output;<br>
+      }<br>
+   }<br>
+<br>
+   if (!connector) {<br></blockquote><div><br></div><div>And this can be merged in.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+      connector = wsi_display_alloc_connector(<wbr>wsi, connector_id);<br>
+      if (!connector) {<br>
+         free(oir);<br>
+         free(srr);<br>
+         return NULL;<br>
+      }<br>
+      LIST_ADDTAIL(&connector->list, &wsi->connectors);<br>
+      connector->output = output;<br>
+   }<br>
+<br>
+   if (oir && srr) {<br>
+      /* Get X modes and add them */<br>
+<br>
+      connector->connected = oir->connection != XCB_RANDR_CONNECTION_<wbr>DISCONNECTED;<br>
+<br>
+      wsi_display_invalidate_<wbr>connector_modes(wsi_device, connector);<br>
+<br>
+      x_modes = xcb_randr_get_output_info_<wbr>modes(oir);<br>
+      for (m = 0; m < oir->num_modes; m++) {<br>
+         xcb_randr_mode_info_iterator_t i = xcb_randr_get_screen_<wbr>resources_modes_iterator(srr);<br>
+         while (i.rem) {<br>
+            xcb_randr_mode_info_t *mi = i.data;<br>
+            if (mi->id == x_modes[m]) {<br>
+               VkResult result = wsi_display_register_x_mode(<wbr>wsi_device, connector, mi, m < oir->num_preferred);<br>
+               if (result != VK_SUCCESS) {<br>
+                  free(oir);<br>
+                  free(srr);<br>
+                  return NULL;<br>
+               }<br>
+               break;<br>
+            }<br>
+            xcb_randr_mode_info_next(&i);<br>
+         }<br>
+      }<br>
+   }<br>
+<br>
+   free(oir);<br>
+   free(srr);<br>
+   return connector;<br>
+}<br>
+<br>
+static xcb_randr_crtc_t<br>
+wsi_display_find_crtc_for_<wbr>output(xcb_connection_t       *connection,<br>
+                                 xcb_window_t           root,<br>
+                                 xcb_randr_output_t     output)<br>
+{<br>
+   xcb_randr_get_screen_<wbr>resources_cookie_t      gsr_c = xcb_randr_get_screen_<wbr>resources(connection, root);<br>
+   xcb_randr_get_screen_<wbr>resources_reply_t       *gsr_r = xcb_randr_get_screen_<wbr>resources_reply(connection, gsr_c, NULL);<br>
+<br>
+   if (!gsr_r)<br>
+      return 0;<br>
+<br>
+   xcb_randr_crtc_t     *rc = xcb_randr_get_screen_<wbr>resources_crtcs(gsr_r);<br>
+   xcb_randr_crtc_t     idle_crtc = 0;<br>
+   xcb_randr_crtc_t     active_crtc = 0;<br>
+<br>
+   /* Find either a crtc already connected to the desired output or idle */<br>
+   int c;<br>
+   for (c = 0; active_crtc == 0 && c < gsr_r->num_crtcs; c++) {<br>
+      xcb_randr_get_crtc_info_<wbr>cookie_t gci_c = xcb_randr_get_crtc_info(<wbr>connection, rc[c], gsr_r->config_timestamp);<br>
+      xcb_randr_get_crtc_info_reply_<wbr>t *gci_r = xcb_randr_get_crtc_info_reply(<wbr>connection, gci_c, NULL);<br>
+      if (gci_r) {<br>
+         if (gci_r->mode) {<br>
+            int num_outputs = xcb_randr_get_crtc_info_<wbr>outputs_length(gci_r);<br>
+            xcb_randr_output_t *outputs = xcb_randr_get_crtc_info_<wbr>outputs(gci_r);<br>
+            for (int o = 0; o < num_outputs; o++)<br>
+               if (outputs[o] == output && num_outputs == 1) {<br></blockquote><div><br></div><div>checking for num_outputs == 1 inside the loop is a bit odd.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+                  active_crtc = rc[c];<br>
+                  break;<br>
+               }<br>
+         } else if (idle_crtc == 0) {<br>
+            int num_possible = xcb_randr_get_crtc_info_<wbr>possible_length(gci_r);<br>
+            xcb_randr_output_t *possible = xcb_randr_get_crtc_info_<wbr>possible(gci_r);<br>
+            for (int p = 0; p < num_possible; p++)<br>
+               if (possible[p] == output) {<br>
+                  idle_crtc = rc[c];<br>
+                  break;<br>
+               }<br>
+         }<br>
+         free(gci_r);<br>
+      }<br>
+   }<br>
+   free(gsr_r);<br>
+<br>
+   if (active_crtc)<br>
+      return active_crtc;<br>
+   return idle_crtc;<br>
+}<br>
+<br>
+VkResult<br>
+wsi_acquire_xlib_display(<wbr>VkPhysicalDevice       physical_device,<br>
+                         struct wsi_device      *wsi_device,<br>
+                         Display                *dpy,<br>
+                         VkDisplayKHR           display)<br>
+{<br>
+   struct wsi_display           *wsi = (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_<wbr>PLATFORM_DISPLAY];<br>
+   xcb_connection_t             *connection = XGetXCBConnection(dpy);<br>
+   struct wsi_display_connector *connector = wsi_display_connector_from_<wbr>handle(display);<br>
+   xcb_window_t                 root;<br>
+<br>
+   if (!connector->output) {<br>
+      connector->output = wsi_display_connector_id_to_<wbr>output(connection, connector->id);<br>
+<br>
+      /* Check and see if we found the output */<br>
+      if (!connector->output)<br>
+         return VK_ERROR_OUT_OF_DATE_KHR;<br>
+   }<br>
+<br>
+   root = wsi_display_output_to_root(<wbr>connection, connector->output);<br>
+   if (!root)<br>
+      return VK_ERROR_OUT_OF_DATE_KHR;<br>
+<br>
+   xcb_randr_crtc_t                     crtc = wsi_display_find_crtc_for_<wbr>output(connection,<br>
+                                                                                root,<br>
+                                                                                connector->output);<br>
+<br>
+   if (!crtc)<br>
+      return VK_ERROR_OUT_OF_DATE_KHR;<br>
+<br>
+   xcb_randr_lease_t                    lease = xcb_generate_id(connection);<br>
+   xcb_randr_create_lease_cookie_<wbr>t      cl_c = xcb_randr_create_lease(<wbr>connection,<br>
+                                                                      root,<br>
+                                                                      lease,<br>
+                                                                      1,<br>
+                                                                      1,<br>
+                                                                      &crtc,<br>
+                                                                      &connector->output);<br>
+   xcb_randr_create_lease_reply_t       *cl_r = xcb_randr_create_lease_reply(<wbr>connection, cl_c, NULL);<br>
+   if (!cl_r)<br>
+      return VK_ERROR_OUT_OF_DATE_KHR;<br>
+<br>
+   int fd = -1;<br>
+   if (cl_r->nfd > 0) {<br>
+      int *rcl_f = xcb_randr_create_lease_reply_<wbr>fds(connection, cl_r);<br>
+<br>
+      fd = rcl_f[0];<br>
+   }<br>
+   free (cl_r);<br>
+   if (fd < 0)<br>
+      return VK_ERROR_OUT_OF_DATE_KHR;<br>
+<br>
+   wsi->fd = fd;<br>
+<br>
+   return VK_SUCCESS;<br>
+}<br>
+<br>
+VkResult<br>
+wsi_get_randr_output_display(<wbr>VkPhysicalDevice   physical_device,<br>
+                             struct wsi_device  *wsi_device,<br>
+                             Display            *dpy,<br>
+                             RROutput           output,<br>
+                             VkDisplayKHR       *display)<br>
+{<br>
+   xcb_connection_t             *connection = XGetXCBConnection(dpy);<br>
+   struct wsi_display_connector *connector = wsi_display_get_output(wsi_<wbr>device, connection, output);<br>
+<br>
+   if (connector)<br>
+      *display = wsi_display_connector_to_<wbr>handle(connector);<br>
+   else<br>
+      *display = NULL;<br>
    return VK_SUCCESS;<br>
 }<br>
+<br>
+#endif<br>
diff --git a/src/vulkan/wsi/wsi_common_<wbr>display.h b/src/vulkan/wsi/wsi_common_<wbr>display.h<br>
index 5fbb6925e4a..1997c2a3c40 100644<br>
--- a/src/vulkan/wsi/wsi_common_<wbr>display.h<br>
+++ b/src/vulkan/wsi/wsi_common_<wbr>display.h<br>
@@ -74,4 +74,21 @@ wsi_release_display(<wbr>VkPhysicalDevice            physical_device,<br>
                     struct wsi_device           *wsi_device,<br>
                     VkDisplayKHR                display);<br>
<br>
+<br>
+#if VK_USE_PLATFORM_XLIB_XRANDR_<wbr>EXT<br>
+VkResult<br>
+wsi_acquire_xlib_display(<wbr>VkPhysicalDevice       physical_device,<br>
+                         struct wsi_device      *wsi_device,<br>
+                         Display                *dpy,<br>
+                         VkDisplayKHR           display);<br>
+<br>
+VkResult<br>
+wsi_get_randr_output_display(<wbr>VkPhysicalDevice   physical_device,<br>
+                             struct wsi_device  *wsi_device,<br>
+                             Display            *dpy,<br>
+                             RROutput           output,<br>
+                             VkDisplayKHR       *display);<br>
+<br>
+#endif /* VK_USE_PLATFORM_XLIB_XRANDR_<wbr>EXT */<br>
+<br>
 #endif<br>
<span class="gmail-HOEnZb"><font color="#888888">--<br>
2.16.2<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>