[Mesa-dev] [PATCH mesa 07/21] vulkan: Add EXT_acquire_xlib_display [v2]
Keith Packard
keithp at keithp.com
Thu Mar 8 07:25:05 UTC 2018
This extension adds the ability to borrow an X RandR output for
temporary use directly by a Vulkan application. For DRM, we use the
Linux resource leasing mechanism.
v2:
Clean up xlib_lease detection
* Use separate temporary '_xlib_lease' variable to hold the
option value to avoid changin the type of a variable.
* Use boolean expressions instead of additional if statements
to compute resulting with_xlib_lease value.
* Simplify addition of VK_USE_PLATFORM_XLIB_XRANDR_KHR to
vulkan_wsi_args
Suggested-by: Eric Engestrom <eric.engestrom at imgtec.com>
Move mode list from wsi_display to wsi_display_connector
Fix scope for wsi_display_mode and wsi_display_connector allocs
Suggested-by: Jason Ekstrand <jason at jlekstrand.net>
Signed-off-by: Keith Packard <keithp at keithp.com>
---
configure.ac | 32 +++
meson.build | 11 +
meson_options.txt | 7 +
src/vulkan/Makefile.am | 5 +
src/vulkan/wsi/meson.build | 5 +
src/vulkan/wsi/wsi_common_display.c | 470 ++++++++++++++++++++++++++++++++++++
src/vulkan/wsi/wsi_common_display.h | 17 ++
7 files changed, 547 insertions(+)
diff --git a/configure.ac b/configure.ac
index 7fcb3220eaa..bf649f9fed7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1560,6 +1560,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],
@@ -1853,6 +1854,18 @@ if test x"$enable_dri3" = xyes; then
PKG_CHECK_MODULES([XCB_DRI3], [$dri3_modules])
fi
+
+if echo "$platforms" | grep -q 'x11' && echo "$platforms" | grep -q 'drm'; then
+ have_xlease=yes
+else
+ have_xlease=no
+fi
+
+if test x"$have_xlease" = xyes; then
+ 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')
@@ -1860,6 +1873,25 @@ AM_CONDITIONAL(HAVE_PLATFORM_DISPLAY, echo "$platforms" | grep -q 'drm')
AM_CONDITIONAL(HAVE_PLATFORM_SURFACELESS, echo "$platforms" | grep -q 'surfaceless')
AM_CONDITIONAL(HAVE_PLATFORM_ANDROID, echo "$platforms" | grep -q 'android')
+AC_ARG_ENABLE(xlib-lease,
+ [AS_HELP_STRING([--enable-xlib-lease]
+ [enable VK_acquire_xlib_display using X leases])],
+ [enable_xlib_lease=$enableval], [enable_xlib_lease=auto])
+case "x$enable_xlib_lease" in
+xyes)
+ ;;
+xno)
+ ;;
+*)
+ if echo "$platforms" | grep -q 'x11' && echo "$platforms" | grep -q 'drm'; then
+ enable_xlib_lease=yes
+ else
+ enable_xlib_lease=no
+ fi
+esac
+
+AM_CONDITIONAL(HAVE_XLIB_LEASE, test "x$enable_xlib_lease" = xyes)
+
dnl
dnl More DRI setup
dnl
diff --git a/meson.build b/meson.build
index 788aed6e159..68081e9fcc3 100644
--- a/meson.build
+++ b/meson.build
@@ -265,6 +265,13 @@ if _platforms != ''
egl_native_platform = _split[0]
endif
+_xlib_lease = get_option('xlib-lease')
+if _xlib_lease == 'auto'
+ with_xlib_lease = with_platform_x11 and with_platform_display
+else
+ with_xlib_lease = _xlib_lease == 'true'
+endif
+
with_glx = get_option('glx')
if with_glx == 'auto'
if with_dri
@@ -1202,6 +1209,7 @@ dep_xcb_present = []
dep_xcb_sync = []
dep_xcb_xfixes = []
dep_xshmfence = []
+dep_xcb_xrandr = []
if with_platform_x11
if with_glx == 'xlib' or with_glx == 'gallium-xlib'
dep_x11 = dependency('x11')
@@ -1241,6 +1249,9 @@ if with_platform_x11
if with_egl
dep_xcb_xfixes = dependency('xcb-xfixes')
endif
+ if with_xlib_lease
+ dep_xcb_xrandr = dependency('xcb-randr', version : '>= 1.12')
+ endif
endif
if get_option('gallium-extra-hud')
diff --git a/meson_options.txt b/meson_options.txt
index a573290b774..70318e1041f 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -286,3 +286,10 @@ option(
value : '',
description : 'Comma delimited list of tools to build. choices : freedreno,glsl,intel,nir,nouveau or all'
)
+option(
+ 'xlib-lease',
+ type : 'combo',
+ value : 'auto',
+ choices : ['auto', 'true', 'false'],
+ description : 'Enable VK_EXT_acquire_xlib_display.'
+)
diff --git a/src/vulkan/Makefile.am b/src/vulkan/Makefile.am
index 075eb58c82c..c8f425f286a 100644
--- a/src/vulkan/Makefile.am
+++ b/src/vulkan/Makefile.am
@@ -65,6 +65,11 @@ AM_CPPFLAGS += \
VULKAN_WSI_SOURCES += $(VULKAN_WSI_DISPLAY_FILES)
endif
+if HAVE_XLIB_LEASE
+AM_CPPFLAGS += \
+ -DVK_USE_PLATFORM_XLIB_XRANDR_EXT
+endif
+
CLEANFILES = $(BUILT_SOURCES)
WL_DRM_XML = $(top_srcdir)/src/egl/wayland/wayland-drm/wayland-drm.xml
diff --git a/src/vulkan/wsi/meson.build b/src/vulkan/wsi/meson.build
index 776e596984d..3085118337c 100644
--- a/src/vulkan/wsi/meson.build
+++ b/src/vulkan/wsi/meson.build
@@ -67,6 +67,11 @@ if with_platform_display
)
endif
+if with_xlib_lease
+ vulkan_wsi_deps += dep_xcb_xrandr
+ vulkan_wsi_args += '-DVK_USE_PLATFORM_XLIB_XRANDR_EXT'
+endif
+
libvulkan_wsi = static_library(
'vulkan_wsi',
files_vulkan_wsi,
diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c
index 45626541022..087e8d18dba 100644
--- a/src/vulkan/wsi/wsi_common_display.c
+++ b/src/vulkan/wsi/wsi_common_display.c
@@ -33,6 +33,10 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <drm_fourcc.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"
@@ -75,6 +79,9 @@ typedef struct wsi_display_connector {
struct list_head display_modes;
wsi_display_mode *current_mode;
drmModeModeInfo current_drm_mode;
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ xcb_randr_output_t output;
+#endif
} wsi_display_connector;
struct wsi_display {
@@ -1414,5 +1421,468 @@ wsi_release_display(VkPhysicalDevice physical_device,
close(wsi->fd);
wsi->fd = -1;
}
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ wsi_display_connector_from_handle(display)->output = None;
+#endif
+
+ 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 bool
+wsi_display_mode_matches_x(struct wsi_display_mode *wsi,
+ xcb_randr_mode_info_t *xcb)
+{
+ return wsi->clock == (xcb->dot_clock + 500) / 1000 &&
+ wsi->hdisplay == xcb->width &&
+ wsi->hsync_start == xcb->hsync_start &&
+ wsi->hsync_end == xcb->hsync_end &&
+ wsi->htotal == xcb->htotal &&
+ wsi->hskew == xcb->hskew &&
+ wsi->vdisplay == xcb->height &&
+ wsi->vsync_start == xcb->vsync_start &&
+ wsi->vsync_end == xcb->vsync_end &&
+ wsi->vtotal == xcb->vtotal &&
+ wsi->flags == xcb->mode_flags;
+}
+
+static struct wsi_display_mode *
+wsi_display_find_x_mode(struct wsi_device *wsi_device,
+ struct wsi_display_connector *connector,
+ xcb_randr_mode_info_t *mode)
+{
+ struct wsi_display_mode *display_mode;
+
+ LIST_FOR_EACH_ENTRY(display_mode, &connector->display_modes, list) {
+ if (wsi_display_mode_matches_x(display_mode, mode))
+ return display_mode;
+ }
+ return NULL;
+}
+
+static VkResult
+wsi_display_register_x_mode(struct wsi_device *wsi_device,
+ struct wsi_display_connector *connector,
+ xcb_randr_mode_info_t *x_mode,
+ bool preferred)
+{
+ struct wsi_display *wsi = (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
+ struct wsi_display_mode *display_mode;
+
+ display_mode = wsi_display_find_x_mode(wsi_device, connector, x_mode);
+
+ if (display_mode) {
+ display_mode->valid = true;
+ return VK_SUCCESS;
+ }
+
+ display_mode = vk_zalloc(wsi->alloc, sizeof (struct wsi_display_mode), 8, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (!display_mode)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ display_mode->connector = connector;
+ display_mode->valid = true;
+ display_mode->preferred = preferred;
+ display_mode->clock = (x_mode->dot_clock + 500) / 1000; /* kHz */
+ display_mode->hdisplay = x_mode->width;
+ display_mode->hsync_start = x_mode->hsync_start;
+ display_mode->hsync_end = x_mode->hsync_end;
+ display_mode->htotal = x_mode->htotal;
+ display_mode->hskew = x_mode->hskew;
+ display_mode->vdisplay = x_mode->height;
+ display_mode->vsync_start = x_mode->vsync_start;
+ display_mode->vsync_end = x_mode->vsync_end;
+ display_mode->vtotal = x_mode->vtotal;
+ display_mode->vscan = 0;
+ if (x_mode->mode_flags & XCB_RANDR_MODE_FLAG_DOUBLE_SCAN)
+ display_mode->vscan = 1;
+ display_mode->flags = x_mode->mode_flags;
+
+ LIST_ADDTAIL(&display_mode->list, &connector->display_modes);
+ return VK_SUCCESS;
+}
+
+static struct wsi_display_connector *
+wsi_display_get_output(struct wsi_device *wsi_device,
+ xcb_connection_t *connection,
+ RROutput output)
+{
+ struct wsi_display *wsi = (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
+ struct wsi_display_connector *connector;
+ uint32_t connector_id;
+ xcb_window_t root;
+ xcb_randr_get_screen_resources_cookie_t src;
+ xcb_randr_get_screen_resources_reply_t *srr;
+ xcb_randr_get_output_info_cookie_t oic;
+ xcb_randr_get_output_info_reply_t *oir;
+ xcb_randr_mode_t *x_modes;
+ int m;
+
+ root = wsi_display_output_to_root(connection, output);
+ if (!root)
+ return NULL;
+
+ src = xcb_randr_get_screen_resources(connection, root);
+ oic = xcb_randr_get_output_info(connection, output, XCB_CURRENT_TIME);
+ srr = xcb_randr_get_screen_resources_reply(connection, src, NULL);
+ oir = xcb_randr_get_output_info_reply(connection, oic, NULL);
+
+ /* See if we already have a connector for this output */
+ connector = wsi_display_find_output(wsi_device, output);
+
+ if (!connector) {
+ xcb_atom_t connector_id_atom = 0;
+
+ /*
+ * Go get the kernel connector ID for this X output
+ */
+ connector_id = wsi_display_output_to_connector_id(connection, &connector_id_atom, output);
+
+ /* Any X server with lease support will have this atom */
+ if (!connector_id) {
+ free(oir);
+ free(srr);
+ return NULL;
+ }
+
+ if (!connector) {
+ /* See if we already have a connector for this id */
+ connector = wsi_display_find_connector(wsi_device, connector_id);
+
+ if (connector)
+ connector->output = output;
+ }
+ }
+
+ if (!connector) {
+ connector = wsi_display_alloc_connector(wsi, connector_id);
+ if (!connector) {
+ free(oir);
+ free(srr);
+ return NULL;
+ }
+ LIST_ADDTAIL(&connector->list, &wsi->connectors);
+ connector->output = output;
+ }
+
+ if (oir && srr) {
+ /* Get X modes and add them */
+
+ connector->connected = oir->connection != XCB_RANDR_CONNECTION_DISCONNECTED;
+
+ wsi_display_invalidate_connector_modes(wsi_device, connector);
+
+ x_modes = xcb_randr_get_output_info_modes(oir);
+ for (m = 0; m < oir->num_modes; m++) {
+ xcb_randr_mode_info_iterator_t i = xcb_randr_get_screen_resources_modes_iterator(srr);
+ while (i.rem) {
+ xcb_randr_mode_info_t *mi = i.data;
+ if (mi->id == x_modes[m]) {
+ VkResult result = wsi_display_register_x_mode(wsi_device, connector, mi, m < oir->num_preferred);
+ if (result != VK_SUCCESS) {
+ free(oir);
+ free(srr);
+ return NULL;
+ }
+ break;
+ }
+ xcb_randr_mode_info_next(&i);
+ }
+ }
+ }
+
+ free(oir);
+ free(srr);
+ 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->fd = fd;
+
+ 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
diff --git a/src/vulkan/wsi/wsi_common_display.h b/src/vulkan/wsi/wsi_common_display.h
index 5fbb6925e4a..1997c2a3c40 100644
--- a/src/vulkan/wsi/wsi_common_display.h
+++ b/src/vulkan/wsi/wsi_common_display.h
@@ -74,4 +74,21 @@ 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 */
+
#endif
--
2.16.2
More information about the mesa-dev
mailing list