From 4d0c49096d06ed6a46827e3140aecd01486dfd3f Mon Sep 17 00:00:00 2001 From: Lubosz Sarnecki Date: Tue, 31 Mar 2020 17:15:57 +0200 Subject: [PATCH] comp/window_direct_mode: Use XCB/Xlib interop. Since there currently is no Vulkan extension that takes XCB handles to aqcuire the display Xlib interop needs to be used. Before this patch Monado was opening connections for both APIs, which introduced overhead. Even though all XCB handles can be casted to Xlib ones, this cannot be done with the main xcb_connection_t / Display. In it's design the interop between both APIs can create a xcb_connection_t from a XCB handle, but not the other way round. So in an interop case the Xlib connection is the main one, since it's on a higher level. More information on this can be found here: https://xcb.freedesktop.org/MixingCalls/ Unfortunately the clean solution for this would be to specify a Vulkan extension that takes XCB handles. This would make sense since Vulkan is aware of XCB in other parts of the API as well. In Mesa the Xlib structs will be ultimately casted to XCB. --- CMakeLists.txt | 2 +- meson.build | 3 +- .../main/comp_window_direct_mode.cpp | 42 +++++++++---------- src/xrt/compositor/meson.build | 2 +- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ada44a51e..f22b70cab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") find_package(udev REQUIRED) set(BUILD_DRIVER_V4L2 TRUE) if(PKGCONFIG_FOUND) - pkg_check_modules(XCB xcb xcb-randr) + pkg_check_modules(XCB xcb xcb-randr x11-xcb) pkg_search_module(WAYLAND wayland-client) pkg_search_module(WAYLAND_SCANNER wayland-scanner) diff --git a/meson.build b/meson.build index b648a3978..50258bd87 100644 --- a/meson.build +++ b/meson.build @@ -81,6 +81,7 @@ endif # TODO: make these behave well when not present x11 = dependency('x11', required: get_option('xlib')) +x11_xcb = dependency('x11-xcb', required: get_option('xlib')) xcb = dependency('xcb', required: get_option('xcb')) xcb_randr = dependency('xcb-randr', required: get_option('xcb')) @@ -116,7 +117,7 @@ if get_option('xcb').enabled() or get_option('xcb').auto() build_xcb = xcb.found() endif -build_xcb_xrandr_direct = build_xcb and build_xlib and xcb_randr.found() +build_xcb_xrandr_direct = build_xcb and build_xlib and xcb_randr.found() and x11_xcb.found() build_wayland = false if get_option('wayland').enabled() or get_option('wayland').auto() diff --git a/src/xrt/compositor/main/comp_window_direct_mode.cpp b/src/xrt/compositor/main/comp_window_direct_mode.cpp index c953a1107..efb819f7c 100644 --- a/src/xrt/compositor/main/comp_window_direct_mode.cpp +++ b/src/xrt/compositor/main/comp_window_direct_mode.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -58,7 +59,6 @@ struct comp_window_direct struct comp_window base = comp_window(); Display *dpy = nullptr; - xcb_connection_t *connection = nullptr; xcb_screen_t *screen = nullptr; std::map randr_modes = {}; @@ -191,9 +191,9 @@ comp_window_direct_destroy(struct comp_window *w) d->display = VK_NULL_HANDLE; } - if (w_direct->connection) { - xcb_disconnect(w_direct->connection); - w_direct->connection = nullptr; + if (w_direct->dpy) { + XCloseDisplay(w_direct->dpy); + w_direct->dpy = nullptr; } delete reinterpret_cast(w); @@ -228,8 +228,10 @@ comp_window_direct_init_randr(struct comp_window *w) return false; } + xcb_connection_t *connection = XGetXCBConnection(w_direct->dpy); + xcb_screen_iterator_t iter = - xcb_setup_roots_iterator(xcb_get_setup(w_direct->connection)); + xcb_setup_roots_iterator(xcb_get_setup(connection)); w_direct->screen = iter.data; @@ -676,10 +678,7 @@ comp_window_direct_connect(struct comp_window_direct *w) COMP_ERROR(w->base.c, "Could not open X display."); return false; } - - //! @todo only open one connection and use XGetXCBConnection. - w->connection = xcb_connect(nullptr, nullptr); - return !xcb_connection_has_error(w->connection); + return true; } static VkResult @@ -743,11 +742,12 @@ comp_window_direct_enumerate_randr_modes( static void comp_window_direct_get_randr_outputs(struct comp_window_direct *w) { + xcb_connection_t *connection = XGetXCBConnection(w->dpy); xcb_randr_query_version_cookie_t version_cookie = - xcb_randr_query_version(w->connection, XCB_RANDR_MAJOR_VERSION, + xcb_randr_query_version(connection, XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION); xcb_randr_query_version_reply_t *version_reply = - xcb_randr_query_version_reply(w->connection, version_cookie, NULL); + xcb_randr_query_version_reply(connection, version_cookie, NULL); if (version_reply == nullptr) { COMP_ERROR(w->base.c, "Could not get RandR version."); @@ -766,9 +766,9 @@ comp_window_direct_get_randr_outputs(struct comp_window_direct *w) xcb_generic_error_t *error = nullptr; xcb_intern_atom_cookie_t non_desktop_cookie = xcb_intern_atom( - w->connection, 1, strlen("non-desktop"), "non-desktop"); + connection, 1, strlen("non-desktop"), "non-desktop"); xcb_intern_atom_reply_t *non_desktop_reply = - xcb_intern_atom_reply(w->connection, non_desktop_cookie, &error); + xcb_intern_atom_reply(connection, non_desktop_cookie, &error); if (error != nullptr) { COMP_ERROR(w->base.c, "xcb_intern_atom_reply returned error %d", @@ -787,10 +787,10 @@ comp_window_direct_get_randr_outputs(struct comp_window_direct *w) } xcb_randr_get_screen_resources_cookie_t resources_cookie = - xcb_randr_get_screen_resources(w->connection, w->screen->root); + xcb_randr_get_screen_resources(connection, w->screen->root); xcb_randr_get_screen_resources_reply_t *resources_reply = - xcb_randr_get_screen_resources_reply(w->connection, - resources_cookie, nullptr); + xcb_randr_get_screen_resources_reply(connection, resources_cookie, + nullptr); xcb_randr_output_t *xcb_outputs = xcb_randr_get_screen_resources_outputs(resources_reply); @@ -804,11 +804,11 @@ comp_window_direct_get_randr_outputs(struct comp_window_direct *w) for (int i = 0; i < count; i++) { xcb_randr_get_output_info_cookie_t output_cookie = - xcb_randr_get_output_info(w->connection, xcb_outputs[i], + xcb_randr_get_output_info(connection, xcb_outputs[i], XCB_CURRENT_TIME); xcb_randr_get_output_info_reply_t *output_reply = - xcb_randr_get_output_info_reply(w->connection, - output_cookie, nullptr); + xcb_randr_get_output_info_reply(connection, output_cookie, + nullptr); // Only outputs with an available mode should be used // (it is possible to see 'ghost' outputs with non-desktop=1). @@ -828,11 +828,11 @@ comp_window_direct_get_randr_outputs(struct comp_window_direct *w) // Find the first output that has the non-desktop property set. xcb_randr_get_output_property_cookie_t prop_cookie; prop_cookie = xcb_randr_get_output_property( - w->connection, xcb_outputs[i], non_desktop_reply->atom, + connection, xcb_outputs[i], non_desktop_reply->atom, XCB_ATOM_NONE, 0, 4, 0, 0); xcb_randr_get_output_property_reply_t *prop_reply = nullptr; prop_reply = xcb_randr_get_output_property_reply( - w->connection, prop_cookie, &error); + connection, prop_cookie, &error); if (error != nullptr) { COMP_ERROR(w->base.c, "xcb_randr_get_output_property_reply " diff --git a/src/xrt/compositor/meson.build b/src/xrt/compositor/meson.build index 74ce8898c..371871cff 100644 --- a/src/xrt/compositor/meson.build +++ b/src/xrt/compositor/meson.build @@ -34,7 +34,7 @@ endif if build_xcb_xrandr_direct compositor_srcs += ['main/comp_window_direct_mode.cpp'] - compositor_deps += [xcb_randr] + compositor_deps += [xcb_randr, x11_xcb] endif if build_opengl