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.
This commit is contained in:
Lubosz Sarnecki 2020-03-31 17:15:57 +02:00
parent 20f281631b
commit 4d0c49096d
4 changed files with 25 additions and 24 deletions

View file

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

View file

@ -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()

View file

@ -10,6 +10,7 @@
#include <xcb/xcb.h>
#include <xcb/randr.h>
#include <X11/Xlib-xcb.h>
#include <X11/extensions/Xrandr.h>
#include <map>
@ -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<uint32_t, xcb_randr_mode_info_t> 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<struct comp_window_direct *>(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 "

View file

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