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