From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dylan Baker Subject: Re: [PATCH 3/7] vulkan: Add EXT_acquire_xlib_display Date: Mon, 12 Feb 2018 16:16:07 -0800 Message-ID: <151848096763.9321.765467999860210360@localhost.localdomain> References: <20180210044516.16944-1-keithp@keithp.com> <20180210044516.16944-4-keithp@keithp.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1040037386==" Return-path: In-Reply-To: <20180210044516.16944-4-keithp@keithp.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: mesa-dev@lists.freedesktop.org Cc: Keith Packard , dri-devel@lists.freedesktop.org List-Id: dri-devel@lists.freedesktop.org --===============1040037386== Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg="pgp-sha512"; boundary="===============7835429488807615716==" Content-Disposition: inline --===============7835429488807615716== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Quoting Keith Packard (2018-02-09 20:45:12) > 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. > = > Signed-off-by: Keith Packard > --- > configure.ac | 25 ++ > meson.build | 17 ++ > meson_options.txt | 7 + > src/amd/vulkan/Makefile.am | 7 + > src/amd/vulkan/meson.build | 7 + > src/amd/vulkan/radv_extensions.py | 11 +- > src/amd/vulkan/radv_wsi_display.c | 30 +++ > src/intel/Makefile.vulkan.am | 7 + > src/intel/vulkan/anv_extensions.py | 1 + > src/intel/vulkan/anv_extensions_gen.py | 10 +- > src/intel/vulkan/anv_wsi_display.c | 30 +++ > src/intel/vulkan/meson.build | 7 + > src/vulkan/Makefile.am | 5 + > src/vulkan/wsi/meson.build | 7 + > src/vulkan/wsi/wsi_common_display.c | 472 +++++++++++++++++++++++++++= ++++++ > src/vulkan/wsi/wsi_common_display.h | 17 ++ > 16 files changed, 650 insertions(+), 10 deletions(-) > = > diff --git a/configure.ac b/configure.ac > index 46318365603..9effd15e8c5 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -1547,6 +1547,7 @@ AM_CONDITIONAL(HAVE_APPLEDRI, test "x$enable_dri" = =3D xyes -a "x$dri_platform" =3D x > AM_CONDITIONAL(HAVE_LMSENSORS, test "x$enable_lmsensors" =3D xyes ) > AM_CONDITIONAL(HAVE_GALLIUM_EXTRA_HUD, test "x$enable_gallium_extra_hud"= =3D xyes ) > AM_CONDITIONAL(HAVE_WINDOWSDRI, test "x$enable_dri" =3D xyes -a "x$dri_p= latform" =3D xwindows ) > +AM_CONDITIONAL(HAVE_XLEASE, test "x$have_xlease" =3D xyes ) > = > AC_ARG_ENABLE([shared-glapi], > [AS_HELP_STRING([--enable-shared-glapi], > @@ -1846,6 +1847,11 @@ if test x"$enable_dri3" =3D xyes; then > PKG_CHECK_MODULES([XCB_DRI3], [$dri3_modules]) > fi > = > +if test x"$have_xlease" =3D xyes; then > + randr_modules=3D"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 'wayla= nd') > AM_CONDITIONAL(HAVE_PLATFORM_DRM, echo "$platforms" | grep -q 'drm') > @@ -1853,6 +1859,25 @@ AM_CONDITIONAL(HAVE_PLATFORM_DISPLAY, echo "$platf= orms" | grep -q 'drm') > AM_CONDITIONAL(HAVE_PLATFORM_SURFACELESS, echo "$platforms" | grep -q 's= urfaceless') > AM_CONDITIONAL(HAVE_PLATFORM_ANDROID, echo "$platforms" | grep -q 'andro= id') > = > +AC_ARG_ENABLE(xlib-lease, > + [AS_HELP_STRING([--enable-xlib-lease] > + [enable VK_acquire_xlib_display using X leases])], > + [enable_xlib_lease=3D$enableval], [enable_xlib_lease=3Dauto]) > +case "x$enable_xlib_lease" in > +xyes) > + ;; > +xno) > + ;; > +*) > + if echo "$platforms" | grep -q 'x11' && echo "$platforms" | grep -q = 'drm'; > + enable_xlib_lease=3Dyes > + else > + enable_xlib_lease=3Dno > + fi > +esac > + > +AM_CONDITIONAL(HAVE_XLIB_LEASE, test "x$enable_xlib_lease" =3D xyes) > + > dnl > dnl More DRI setup > dnl > diff --git a/meson.build b/meson.build > index aeb7f5e2917..595b0f66cd7 100644 > --- a/meson.build > +++ b/meson.build > @@ -262,6 +262,19 @@ if _platforms !=3D '' > egl_native_platform =3D _split[0] > endif > = > +with_xlib_lease =3D get_option('xlib-lease') > +if with_xlib_lease =3D=3D 'auto' > + if with_platform_x11 and with_platform_display > + with_xlib_lease =3D true > + else > + with_xlib_lease =3D false > + endif You could simplify this to with_xlib_lease =3D with_platform_x11 and with_platform_display > +elif with_xlib_lease =3D=3D 'true' We should probably error here if we don't have the correct platforms. > + with_xlib_lease =3D true > +else > + with_xlib_lease =3D false > +endif > + > with_glx =3D get_option('glx') > if with_glx =3D=3D 'auto' > if with_dri > @@ -1151,6 +1164,7 @@ dep_xcb_present =3D [] > dep_xcb_sync =3D [] > dep_xcb_xfixes =3D [] > dep_xshmfence =3D [] > +dep_xcb_xrandr =3D [] > if with_platform_x11 > if with_glx =3D=3D 'xlib' or with_glx =3D=3D 'gallium-xlib' > dep_x11 =3D dependency('x11') > @@ -1190,6 +1204,9 @@ if with_platform_x11 > if with_egl > dep_xcb_xfixes =3D dependency('xcb-xfixes') > endif > + if with_xlib_lease > + dep_xcb_xrandr =3D dependency('xcb-randr', version : '>=3D 1.12') > + endif > endif > = > if get_option('gallium-extra-hud') > diff --git a/meson_options.txt b/meson_options.txt > index 7fafe2deaac..d38c9aa6149 100644 > --- a/meson_options.txt > +++ b/meson_options.txt > @@ -286,3 +286,10 @@ option( > value : '', > description : 'Comma delimited list of tools to build. choices : freed= reno,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/amd/vulkan/Makefile.am b/src/amd/vulkan/Makefile.am > index 061b8144b88..94ece06e99e 100644 > --- a/src/amd/vulkan/Makefile.am > +++ b/src/amd/vulkan/Makefile.am > @@ -81,7 +81,14 @@ AM_CPPFLAGS +=3D \ > -DVK_USE_PLATFORM_DISPLAY_KHR > = > VULKAN_SOURCES +=3D $(VULKAN_WSI_DISPLAY_FILES) > +endif > + > +if HAVE_XLIB_LEASE > +AM_CPPFLAGS +=3D \ > + -DVK_USE_PLATFORM_XLIB_XRANDR_EXT \ > + $(XCB_RANDR_CFLAGS) > = > +VULKAN_LIB_DEPS +=3D $(XCB_RANDR_LIBS) > endif > = > if HAVE_PLATFORM_X11 > diff --git a/src/amd/vulkan/meson.build b/src/amd/vulkan/meson.build > index b7bb1075e7d..0b92a1763a1 100644 > --- a/src/amd/vulkan/meson.build > +++ b/src/amd/vulkan/meson.build > @@ -119,6 +119,13 @@ if with_platform_display > libradv_files +=3D files('radv_wsi_display.c') > endif > = > +if with_xlib_lease > + radv_deps +=3D dep_xcb_xrandr Since this is a stub when not building, we don't we just put his in the deps unconditionally > + radv_flags +=3D [ > + '-DVK_USE_PLATFORM_XLIB_XRANDR_EXT', > + ] no [] needed here. > +endif > + > libvulkan_radeon =3D shared_library( > 'vulkan_radeon', > [libradv_files, radv_entrypoints, radv_extensions_c, vk_format_table_c= ], > diff --git a/src/amd/vulkan/radv_extensions.py b/src/amd/vulkan/radv_exte= nsions.py > index f784681ff57..2d804afed35 100644 > --- a/src/amd/vulkan/radv_extensions.py > +++ b/src/amd/vulkan/radv_extensions.py > @@ -83,6 +83,7 @@ EXTENSIONS =3D [ > Extension('VK_KHR_xlib_surface', 6, 'VK_USE_PLA= TFORM_XLIB_KHR'), > Extension('VK_KHR_display', 1, 'VK_USE_PLA= TFORM_DISPLAY_KHR'), > Extension('VK_EXT_direct_mode_display', 1, 'VK_USE_PLA= TFORM_DISPLAY_KHR'), > + Extension('VK_EXT_acquire_xlib_display', 1, 'VK_USE_PLA= TFORM_XLIB_XRANDR_EXT'), > Extension('VK_KHX_multiview', 1, '!ANDROID'), > Extension('VK_EXT_debug_report', 9, True), > Extension('VK_EXT_discard_rectangles', 1, True), > @@ -170,12 +171,12 @@ _TEMPLATE =3D Template(COPYRIGHT + """ > #include "vk_util.h" > = > /* Convert the VK_USE_PLATFORM_* defines to booleans */ > -%for platform in ['ANDROID', 'WAYLAND', 'XCB', 'XLIB', 'DISPLAY']: > -#ifdef VK_USE_PLATFORM_${platform}_KHR > -# undef VK_USE_PLATFORM_${platform}_KHR > -# define VK_USE_PLATFORM_${platform}_KHR true > +%for platform in ['ANDROID_KHR', 'WAYLAND_KHR', 'XCB_KHR', 'XLIB_KHR', '= DISPLAY_KHR', 'XLIB_XRANDR_EXT']: > +#ifdef VK_USE_PLATFORM_${platform} > +# undef VK_USE_PLATFORM_${platform} > +# define VK_USE_PLATFORM_${platform} true > #else > -# define VK_USE_PLATFORM_${platform}_KHR false > +# define VK_USE_PLATFORM_${platform} false > #endif > %endfor > = > diff --git a/src/amd/vulkan/radv_wsi_display.c b/src/amd/vulkan/radv_wsi_= display.c > index 0051f5ac865..9b76ce623b0 100644 > --- a/src/amd/vulkan/radv_wsi_display.c > +++ b/src/amd/vulkan/radv_wsi_display.c > @@ -152,3 +152,33 @@ radv_ReleaseDisplayEXT(VkPhysicalDevice physical_dev= ice, > &pdevice->wsi_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 */ > diff --git a/src/intel/Makefile.vulkan.am b/src/intel/Makefile.vulkan.am > index 7c428a799d7..0f0d3815097 100644 > --- a/src/intel/Makefile.vulkan.am > +++ b/src/intel/Makefile.vulkan.am > @@ -194,6 +194,13 @@ VULKAN_CPPFLAGS +=3D \ > VULKAN_SOURCES +=3D $(VULKAN_WSI_DISPLAY_FILES) > endif > = > +if HAVE_XLIB_LEASE > +VULKAN_CPPFLAGS +=3D \ > + -DVK_USE_PLATFORM_XLIB_XRANDR_EXT \ > + $(XCB_RANDR_CFLAGS) > +VULKAN_LIB_DEPS +=3D $(XCB_RANDR_LIBS) > +endif > + > noinst_LTLIBRARIES +=3D vulkan/libvulkan_common.la > vulkan_libvulkan_common_la_SOURCES =3D $(VULKAN_SOURCES) > vulkan_libvulkan_common_la_CFLAGS =3D $(VULKAN_CFLAGS) > diff --git a/src/intel/vulkan/anv_extensions.py b/src/intel/vulkan/anv_ex= tensions.py > index 633e378e605..32a240acdcb 100644 > --- a/src/intel/vulkan/anv_extensions.py > +++ b/src/intel/vulkan/anv_extensions.py > @@ -85,6 +85,7 @@ EXTENSIONS =3D [ > Extension('VK_KHR_xlib_surface', 6, 'VK_USE_PLA= TFORM_XLIB_KHR'), > Extension('VK_KHR_display', 1, 'VK_USE_PLA= TFORM_DISPLAY_KHR'), > Extension('VK_EXT_direct_mode_display', 1, 'VK_USE_PLA= TFORM_DISPLAY_KHR'), > + Extension('VK_EXT_acquire_xlib_display', 1, 'VK_USE_PLA= TFORM_XLIB_XRANDR_EXT'), > Extension('VK_KHX_multiview', 1, True), > Extension('VK_EXT_debug_report', 8, True), > Extension('VK_EXT_external_memory_dma_buf', 1, True), > diff --git a/src/intel/vulkan/anv_extensions_gen.py b/src/intel/vulkan/an= v_extensions_gen.py > index 84d07f9767a..025907aff72 100644 > --- a/src/intel/vulkan/anv_extensions_gen.py > +++ b/src/intel/vulkan/anv_extensions_gen.py > @@ -113,12 +113,12 @@ _TEMPLATE_C =3D Template(COPYRIGHT + """ > #include "vk_util.h" > = > /* Convert the VK_USE_PLATFORM_* defines to booleans */ > -%for platform in ['ANDROID', 'WAYLAND', 'XCB', 'XLIB', 'DISPLAY']: > -#ifdef VK_USE_PLATFORM_${platform}_KHR > -# undef VK_USE_PLATFORM_${platform}_KHR > -# define VK_USE_PLATFORM_${platform}_KHR true > +%for platform in ['ANDROID_KHR', 'WAYLAND_KHR', 'XCB_KHR', 'XLIB_KHR', '= DISPLAY_KHR', 'XLIB_XRANDR_EXT']: > +#ifdef VK_USE_PLATFORM_${platform} > +# undef VK_USE_PLATFORM_${platform} > +# define VK_USE_PLATFORM_${platform} true > #else > -# define VK_USE_PLATFORM_${platform}_KHR false > +# define VK_USE_PLATFORM_${platform} false > #endif > %endfor > = > diff --git a/src/intel/vulkan/anv_wsi_display.c b/src/intel/vulkan/anv_ws= i_display.c > index e6f67f7dec9..e87aed49f7d 100644 > --- a/src/intel/vulkan/anv_wsi_display.c > +++ b/src/intel/vulkan/anv_wsi_display.c > @@ -138,3 +138,33 @@ anv_ReleaseDisplayEXT(VkPhysicalDevice physical_devi= ce, > &pdevice->wsi_device, > display); > } > + > +#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT > +VkResult > +anv_AcquireXlibDisplayEXT(VkPhysicalDevice physical_device, > + Display *dpy, > + VkDisplayKHR display) > +{ > + ANV_FROM_HANDLE(anv_physical_device, pdevice, physical_device); > + > + return wsi_acquire_xlib_display(physical_device, > + &pdevice->wsi_device, > + dpy, > + display); > +} > + > +VkResult > +anv_GetRandROutputDisplayEXT(VkPhysicalDevice physical_device, > + Display *dpy, > + RROutput output, > + VkDisplayKHR *display) > +{ > + ANV_FROM_HANDLE(anv_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 */ > diff --git a/src/intel/vulkan/meson.build b/src/intel/vulkan/meson.build > index 2e2ab8f7ecd..d3ab5ac8a64 100644 > --- a/src/intel/vulkan/meson.build > +++ b/src/intel/vulkan/meson.build > @@ -178,6 +178,13 @@ if with_platform_display > libanv_files +=3D files('anv_wsi_display.c') > endif > = > +if with_xlib_lease > + anv_deps +=3D dep_xcb_xrandr > + anv_flags +=3D [ > + '-DVK_USE_PLATFORM_XLIB_XRANDR_EXT', > + ] > +endif Same here > + > libanv_common =3D static_library( > 'anv_common', > [libanv_files, anv_entrypoints, anv_extensions_c, anv_extensions_h], > diff --git a/src/vulkan/Makefile.am b/src/vulkan/Makefile.am > index c33ac5758f7..e96ef68972c 100644 > --- a/src/vulkan/Makefile.am > +++ b/src/vulkan/Makefile.am > @@ -64,6 +64,11 @@ AM_CPPFLAGS +=3D \ > VULKAN_WSI_SOURCES +=3D $(VULKAN_WSI_DISPLAY_FILES) > endif > = > +if HAVE_XLIB_LEASE > +AM_CPPFLAGS +=3D \ > + -DVK_USE_PLATFORM_XLIB_XRANDR_EXT > +endif > + > BUILT_SOURCES +=3D $(VULKAN_WSI_WAYLAND_GENERATED_FILES) > CLEANFILES =3D $(BUILT_SOURCES) > = > diff --git a/src/vulkan/wsi/meson.build b/src/vulkan/wsi/meson.build > index 743631a6113..5e3d43a2748 100644 > --- a/src/vulkan/wsi/meson.build > +++ b/src/vulkan/wsi/meson.build > @@ -67,6 +67,13 @@ if with_platform_display > ) > endif > = > +if with_xlib_lease > + vulkan_wsi_deps +=3D dep_xcb_xrandr > + vulkan_wsi_args +=3D [ > + '-DVK_USE_PLATFORM_XLIB_XRANDR_EXT', > + ] > +endif ditto > + > libvulkan_wsi =3D static_library( > 'vulkan_wsi', > files_vulkan_wsi, > diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_com= mon_display.c > index 5c123e6465e..29d64b21aff 100644 > --- a/src/vulkan/wsi/wsi_common_display.c > +++ b/src/vulkan/wsi/wsi_common_display.c > @@ -32,6 +32,10 @@ > #include > #include > #include > +#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT > +#include > +#include > +#endif > #include "util/hash_table.h" > #include "util/list.h" > = > @@ -73,6 +77,9 @@ typedef struct wsi_display_connector { > bool active; > 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 { > @@ -1381,5 +1388,470 @@ wsi_release_display(VkPhysicalDevice p= hysical_device, > close(wsi->master_fd); > wsi->master_fd =3D -1; > } > +#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT > + wsi_display_connector_from_handle(display)->output =3D 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 =3D (struct wsi_display *) wsi_devi= ce->wsi[VK_ICD_WSI_PLATFORM_DISPLAY]; > + struct wsi_display_connector *connector; > + > + connector =3D NULL; > + LIST_FOR_EACH_ENTRY(connector, &wsi->connectors, list) { > + if (connector->output =3D=3D 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_at= om_p, > + RROutput output) > +{ > + uint32_t connector_id =3D 0; > + xcb_atom_t connector_id_atom =3D *connector_id_atom= _p; > + > + if (connector_id_atom =3D=3D 0) { > + /* Go dig out the CONNECTOR_ID property */ > + xcb_intern_atom_cookie_t ia_c =3D xcb_intern_atom(connection, > + true, > + 12, > + "CONNECTOR_ID"= ); > + xcb_intern_atom_reply_t *ia_r =3D xcb_intern_atom_reply(conne= ction, > + ia_c, > + NULL); > + if (ia_r) { > + *connector_id_atom_p =3D connector_id_atom =3D 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 =3D xcb_randr_query= _version(connection, 1, 6); > + xcb_randr_get_output_property_cookie_t gop_c =3D xcb_randr_get_= output_property(connection, > + = output, > + = connector_id_atom, > + = 0, > + = 0, > + = 0xffffffffUL, > + = 0, > + = 0); > + xcb_randr_query_version_reply_t *qv_r =3D xcb_randr_quer= y_version_reply(connection, qv_c, NULL); > + free(qv_r); > + xcb_randr_get_output_property_reply_t *gop_r =3D xcb_randr_get= _output_property_reply(connection, > + = gop_c, > + = NULL); > + if (gop_r) { > + if (gop_r->num_items =3D=3D 1 && gop_r->format =3D=3D 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 =3D xcb_randr_query_version= (connection, 1, 6); > + xcb_randr_query_version_reply_t *qv_r =3D xcb_randr_query_versio= n_reply(connection, qv_c, NULL); > + bool ret =3D false; > + > + if (!qv_r) > + return false; > + > + /* Check for version 1.6 or newer */ > + ret =3D qv_r->major_version > 1 || (qv_r->major_version =3D=3D 1 && q= v_r->minor_version >=3D 6); > + > + free(qv_r); > + return ret; > +} > + > +/* > + * Given a kernel connector id, find the associated RandR output using t= he > + * 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 =3D xcb_get_setup(connect= ion); > + > + xcb_atom_t connector_id_atom =3D 0; > + xcb_randr_output_t output =3D 0; > + > + /* Search all of the screens for the provided output */ > + xcb_screen_iterator_t iter; > + for (iter =3D xcb_setup_roots_iterator(setup); output =3D=3D 0 && ite= r.rem; xcb_screen_next(&iter)) { > + > + xcb_randr_get_screen_resources_cookie_t gsr_c =3D xcb_randr_g= et_screen_resources(connection, iter.data->root); > + xcb_randr_get_screen_resources_reply_t *gsr_r =3D xcb_randr_= get_screen_resources_reply(connection, gsr_c, NULL); > + > + if (!gsr_r) > + return 0; > + > + xcb_randr_output_t *ro =3D xcb_randr_get_screen_resources_o= utputs(gsr_r); > + int o; > + > + for (o =3D 0; o < gsr_r->num_outputs; o++) { > + if (wsi_display_output_to_connector_id(connection, &connector_i= d_atom, ro[o]) =3D=3D connector_id) { > + output =3D 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 =3D xcb_get_setup(connect= ion); > + xcb_window_t root =3D 0; > + > + /* Search all of the screens for the provided output */ > + xcb_screen_iterator_t iter; > + for (iter =3D xcb_setup_roots_iterator(setup); root =3D=3D 0 && iter.= rem; xcb_screen_next(&iter)) { > + xcb_randr_get_screen_resources_cookie_t gsr_c =3D xcb_randr_g= et_screen_resources(connection, iter.data->root); > + xcb_randr_get_screen_resources_reply_t *gsr_r =3D xcb_randr_= get_screen_resources_reply(connection, gsr_c, NULL); > + > + if (!gsr_r) > + return 0; > + > + xcb_randr_output_t *ro =3D xcb_randr_get_screen_resources_o= utputs(gsr_r); > + int o; > + > + for (o =3D 0; o < gsr_r->num_outputs; o++) { > + if (ro[o] =3D=3D output) { > + root =3D 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 =3D=3D (xcb->dot_clock + 500) / 1000 && > + wsi->hdisplay =3D=3D xcb->width && > + wsi->hsync_start =3D=3D xcb->hsync_start && > + wsi->hsync_end =3D=3D xcb->hsync_end && > + wsi->htotal =3D=3D xcb->htotal && > + wsi->hskew =3D=3D xcb->hskew && > + wsi->vdisplay =3D=3D xcb->height && > + wsi->vsync_start =3D=3D xcb->vsync_start && > + wsi->vsync_end =3D=3D xcb->vsync_end && > + wsi->vtotal =3D=3D xcb->vtotal && > + wsi->flags =3D=3D 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 *wsi =3D (struct wsi_display *) wsi_devi= ce->wsi[VK_ICD_WSI_PLATFORM_DISPLAY]; > + struct wsi_display_mode *display_mode; > + > + LIST_FOR_EACH_ENTRY(display_mode, &wsi->display_modes, list) { > + if (display_mode->connector =3D=3D connector && > + wsi_display_mode_matches_x(display_mode, mode)) > + return display_mode; > + } > + return NULL; > +} > + > +static VkResult > +wsi_display_register_x_mode(struct wsi_device *wsi_dev= ice, > + struct wsi_display_connector *connect= or, > + xcb_randr_mode_info_t *x_mode, > + bool preferre= d) > +{ > + struct wsi_display *wsi =3D (struct wsi_display *) wsi_devi= ce->wsi[VK_ICD_WSI_PLATFORM_DISPLAY]; > + struct wsi_display_mode *display_mode; > + > + display_mode =3D wsi_display_find_x_mode(wsi_device, connector, x_mod= e); > + > + if (display_mode) { > + display_mode->valid =3D true; > + return VK_SUCCESS; > + } > + > + display_mode =3D vk_alloc(wsi->alloc, sizeof (struct wsi_display_mode= ), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); > + if (!display_mode) > + return VK_ERROR_OUT_OF_HOST_MEMORY; > + > + display_mode->connector =3D connector; > + display_mode->valid =3D true; > + display_mode->preferred =3D preferred; > + display_mode->clock =3D (x_mode->dot_clock + 500) / 1000; /* kHz */ > + display_mode->hdisplay =3D x_mode->width; > + display_mode->hsync_start =3D x_mode->hsync_start; > + display_mode->hsync_end =3D x_mode->hsync_end; > + display_mode->htotal =3D x_mode->htotal; > + display_mode->hskew =3D x_mode->hskew; > + display_mode->vdisplay =3D x_mode->height; > + display_mode->vsync_start =3D x_mode->vsync_start; > + display_mode->vsync_end =3D x_mode->vsync_end; > + display_mode->vtotal =3D x_mode->vtotal; > + display_mode->vscan =3D 0; > + if (x_mode->mode_flags & XCB_RANDR_MODE_FLAG_DOUBLE_SCAN) > + display_mode->vscan =3D 1; > + display_mode->flags =3D x_mode->mode_flags; > + > + LIST_ADDTAIL(&display_mode->list, &wsi->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 =3D (struct wsi_dis= play *) 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 =3D wsi_display_output_to_root(connection, output); > + if (!root) > + return NULL; > + > + src =3D xcb_randr_get_screen_resources(connection, root); > + oic =3D xcb_randr_get_output_info(connection, output, XCB_CURRENT_TIM= E); > + srr =3D xcb_randr_get_screen_resources_reply(connection, src, NULL); > + oir =3D xcb_randr_get_output_info_reply(connection, oic, NULL); > + > + /* See if we already have a connector for this output */ > + connector =3D wsi_display_find_output(wsi_device, output); > + > + if (!connector) { > + xcb_atom_t connector_id_atom =3D 0; > + > + /* > + * Go get the kernel connector ID for this X output > + */ > + connector_id =3D wsi_display_output_to_connector_id(connection, &c= onnector_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 =3D wsi_display_find_connector(wsi_device, connector_= id); > + > + if (connector) > + connector->output =3D output; > + } > + } > + > + if (!connector) { > + connector =3D wsi_display_alloc_connector(wsi, connector_id); > + if (!connector) { > + free(oir); > + free(srr); > + return NULL; > + } > + LIST_ADDTAIL(&connector->list, &wsi->connectors); > + connector->output =3D output; > + } > + > + if (oir && srr) { > + /* Get X modes and add them */ > + > + connector->connected =3D oir->connection !=3D XCB_RANDR_CONNECTION= _DISCONNECTED; > + > + wsi_display_invalidate_connector_modes(wsi_device, connector); > + > + x_modes =3D xcb_randr_get_output_info_modes(oir); > + for (m =3D 0; m < oir->num_modes; m++) { > + xcb_randr_mode_info_iterator_t i =3D xcb_randr_get_screen_resou= rces_modes_iterator(srr); > + while (i.rem) { > + xcb_randr_mode_info_t *mi =3D i.data; > + if (mi->id =3D=3D x_modes[m]) { > + VkResult result =3D wsi_display_register_x_mode(wsi_devic= e, connector, mi, m < oir->num_preferred); > + if (result !=3D 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 =3D xcb_randr_get_= screen_resources(connection, root); > + xcb_randr_get_screen_resources_reply_t *gsr_r =3D xcb_randr_get= _screen_resources_reply(connection, gsr_c, NULL); > + > + if (!gsr_r) > + return 0; > + > + xcb_randr_crtc_t *rc =3D xcb_randr_get_screen_resources_crtcs(gsr= _r); > + xcb_randr_crtc_t idle_crtc =3D 0; > + xcb_randr_crtc_t active_crtc =3D 0; > + > + /* Find either a crtc already connected to the desired output or idle= */ > + int c; > + for (c =3D 0; active_crtc =3D=3D 0 && c < gsr_r->num_crtcs; c++) { > + xcb_randr_get_crtc_info_cookie_t gci_c =3D xcb_randr_get_crtc_info= (connection, rc[c], gsr_r->config_timestamp); > + xcb_randr_get_crtc_info_reply_t *gci_r =3D xcb_randr_get_crtc_info= _reply(connection, gci_c, NULL); > + if (gci_r) { > + if (gci_r->mode) { > + int num_outputs =3D xcb_randr_get_crtc_info_outputs_length(g= ci_r); > + xcb_randr_output_t *outputs =3D xcb_randr_get_crtc_info_outp= uts(gci_r); > + for (int o =3D 0; o < num_outputs; o++) > + if (outputs[o] =3D=3D output && num_outputs =3D=3D 1) { > + active_crtc =3D rc[c]; > + break; > + } > + } else if (idle_crtc =3D=3D 0) { > + int num_possible =3D xcb_randr_get_crtc_info_possible_length= (gci_r); > + xcb_randr_output_t *possible =3D xcb_randr_get_crtc_info_pos= sible(gci_r); > + for (int p =3D 0; p < num_possible; p++) > + if (possible[p] =3D=3D output) { > + idle_crtc =3D 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 =3D (struct wsi_display *) wsi_devi= ce->wsi[VK_ICD_WSI_PLATFORM_DISPLAY]; > + xcb_connection_t *connection =3D XGetXCBConnection(dpy); > + struct wsi_display_connector *connector =3D wsi_display_connector_fro= m_handle(display); > + xcb_window_t root; > + > + if (!connector->output) { > + connector->output =3D wsi_display_connector_id_to_output(connectio= n, connector->id); > + > + /* Check and see if we found the output */ > + if (!connector->output) > + return VK_ERROR_OUT_OF_DATE_KHR; > + } > + > + root =3D wsi_display_output_to_root(connection, connector->output); > + if (!root) > + return VK_ERROR_OUT_OF_DATE_KHR; > + > + xcb_randr_crtc_t crtc =3D wsi_display_find_crtc_f= or_output(connection, > + = root, > + = connector->output); > + > + if (!crtc) > + return VK_ERROR_OUT_OF_DATE_KHR; > + > + xcb_randr_lease_t lease =3D xcb_generate_id(connec= tion); > + xcb_randr_create_lease_cookie_t cl_c =3D xcb_randr_create_lease(= connection, > + ro= ot, > + le= ase, > + 1, > + 1, > + &c= rtc, > + &c= onnector->output); > + xcb_randr_create_lease_reply_t *cl_r =3D xcb_randr_create_lease= _reply(connection, cl_c, NULL); > + if (!cl_r) > + return VK_ERROR_OUT_OF_DATE_KHR; > + > + int fd =3D -1; > + if (cl_r->nfd > 0) { > + int *rcl_f =3D xcb_randr_create_lease_reply_fds(connection, cl_r); > + > + fd =3D rcl_f[0]; > + } > + free (cl_r); > + if (fd < 0) > + return VK_ERROR_OUT_OF_DATE_KHR; > + > + wsi->master_fd =3D 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 =3D XGetXCBConnection(dpy); > + struct wsi_display_connector *connector =3D wsi_display_get_output(ws= i_device, connection, output); > + > + if (connector) > + *display =3D wsi_display_connector_to_handle(connector); > + else > + *display =3D NULL; > + return VK_SUCCESS; > +} > + > +#endif > diff --git a/src/vulkan/wsi/wsi_common_display.h b/src/vulkan/wsi/wsi_com= mon_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 physic= al_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.15.1 > = > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel --===============7835429488807615716== MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Description: signature Content-Type: application/pgp-signature; name="signature.asc"; charset="us-ascii" -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRxxLdWILx1cItL2yVMlfqrPrBz7AUCWoIuRwAKCRBMlfqrPrBz 7OZ0AQCpW8ne6OudEIcVgSW24rk9JmVqb2nGai0IJNj/eEZm2wD/aGYxrE0NI7po vTokXm3wQQLoGuunP2794H14TmZQtwA= =/9Bi -----END PGP SIGNATURE----- --===============7835429488807615716==-- --===============1040037386== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KZHJpLWRldmVs IG1haWxpbmcgbGlzdApkcmktZGV2ZWxAbGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlz dHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vZHJpLWRldmVsCg== --===============1040037386==--