c/main: Implement WINDOW_DIRECT_WAYLAND

This commit is contained in:
Simon Zeni 2021-09-14 11:11:40 -04:00 committed by Jakob Bornecrantz
parent 26c684d42f
commit 47be806428
10 changed files with 580 additions and 30 deletions

View file

@ -102,6 +102,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
pkg_search_module(WAYLAND wayland-client)
pkg_search_module(WAYLAND_SCANNER wayland-scanner)
pkg_search_module(WAYLAND_PROTOCOLS wayland-protocols)
pkg_search_module(LIBDRM libdrm)
endif()
find_package(OpenGL COMPONENTS GLX)
pkg_search_module(DBUS dbus-1)
@ -132,7 +133,8 @@ option(XRT_FEATURE_COLOR_LOG "Enable logging in color on supported platforms" ON
option(XRT_FEATURE_TRACING "Enable debug tracing on supported platforms" OFF)
cmake_dependent_option(CMAKE_INTERPROCEDURAL_OPTIMIZATION "Enable inter-procedural (link-time) optimization" OFF "HAS_IPO" OFF)
cmake_dependent_option(XRT_HAVE_WAYLAND "Enable Wayland support" ON "WAYLAND_FOUND AND WAYLAND_SCANNER_FOUND AND WAYLAND_PROTOCOLS_FOUND" OFF)
cmake_dependent_option(XRT_HAVE_WAYLAND "Enable Wayland support" ON "WAYLAND_FOUND AND WAYLAND_SCANNER_FOUND AND WAYLAND_PROTOCOLS_FOUND AND LIBDRM_FOUND" OFF)
cmake_dependent_option(XRT_HAVE_WAYLAND_DIRECT "Enable Wayland direct support" ON "XRT_HAVE_WAYLAND AND LIBDRM_FOUND AND WAYLAND_PROTOCOLS_VERSION VERSION_GREATER_EQUAL 1,22" OFF)
cmake_dependent_option(XRT_HAVE_XLIB "Enable xlib support" ON "X11_FOUND" OFF)
cmake_dependent_option(XRT_HAVE_XRANDR "Enable xlib-xrandr support" ON "XRANDR_FOUND" OFF)
cmake_dependent_option(XRT_HAVE_XCB "Enable xcb support" ON "XCB_FOUND" OFF)
@ -345,6 +347,7 @@ message(STATUS "# GIT_DESC: ${GIT_DESC}")
message(STATUS "#")
message(STATUS "# GST (GStreamer): ${XRT_HAVE_GST}")
message(STATUS "# WAYLAND: ${XRT_HAVE_WAYLAND}")
message(STATUS "# WAYLAND_DIRECT: ${XRT_HAVE_WAYLAND_DIRECT}")
message(STATUS "# XLIB: ${XRT_HAVE_XLIB}")
message(STATUS "# XRANDR: ${XRT_HAVE_XRANDR}")
message(STATUS "# XCB: ${XRT_HAVE_XCB}")

View file

@ -103,6 +103,7 @@ xcb_randr = dependency('xcb-randr', required: get_option('xcb'))
wayland = dependency('wayland-client', required: get_option('wayland'))
wayland_protos = dependency('wayland-protocols', required: get_option('wayland'))
wayland_scanner = dependency('wayland-scanner', required: get_option('wayland'))
drm = dependency('libdrm', required: get_option('wayland'))
if wayland_scanner.found()
wayland_scanner = find_program(
@ -143,8 +144,10 @@ build_xcb_xrandr_direct = build_xcb and build_xlib and xcb_randr.found() and x11
build_vk_khr_display = true
build_wayland = false
build_wayland_direct = false
if get_option('wayland').enabled() or get_option('wayland').auto()
build_wayland = wayland.found() and wayland_protos.found() and wayland_scanner.found()
build_wayland_direct = build_wayland and drm.found() and wayland_protos.version().version_compare('>=1.22')
endif
# For now required on Linux
@ -338,6 +341,12 @@ else
message(' wayland: no')
endif
if build_wayland_direct
message('wayland_direct: yes')
else
message('wayland_direct: no')
endif
if not get_option('systemd').disabled() and systemd.found()
message(' systemd: yes')
else

View file

@ -150,27 +150,55 @@ if(XRT_FEATURE_COMPOSITOR_MAIN)
pkg_get_variable(WL_PROTOS_PKG_DIR wayland-protocols pkgdatadir)
pkg_get_variable(WL_SCANNER wayland-scanner wayland_scanner)
set(WL_PROTOS_DIR "${CMAKE_CURRENT_BINARY_DIR}/wayland-protocols/")
set(WL_PROTOS_DIR "${CMAKE_CURRENT_BINARY_DIR}/wayland-protocols")
file(MAKE_DIRECTORY "${WL_PROTOS_DIR}")
set(WL_PROTOS_XML "${WL_PROTOS_PKG_DIR}/stable/xdg-shell/xdg-shell.xml")
set(WL_PROTOS_C "${WL_PROTOS_DIR}/xdg-shell.c")
set(WL_PROTOS_H "${WL_PROTOS_DIR}/xdg-shell-client-protocol.h")
set(WL_PROTOS_XML
${WL_PROTOS_PKG_DIR}/stable/xdg-shell/xdg-shell.xml
)
add_custom_command(
COMMAND
${WL_SCANNER} private-code "${WL_PROTOS_XML}" "${WL_PROTOS_C}"
OUTPUT "${WL_PROTOS_C}" VERBATIM)
add_custom_command(
COMMAND
${WL_SCANNER} client-header "${WL_PROTOS_XML}" "${WL_PROTOS_H}"
OUTPUT "${WL_PROTOS_H}" VERBATIM)
set(WL_PROTOS_SRC ${WL_PROTOS_C} ${WL_PROTOS_H})
list(APPEND MAIN_SOURCE_FILES
main/comp_window_wayland.c
)
if (XRT_HAVE_WAYLAND_DIRECT)
list(APPEND WL_PROTOS_XML
${WL_PROTOS_PKG_DIR}/staging/drm-lease/drm-lease-v1.xml
)
list(APPEND MAIN_SOURCE_FILES
main/comp_window_direct_wayland.c
)
pkg_check_modules(LIBDRM IMPORTED_TARGET libdrm)
set(WAYLAND_DEPS
${WAYLAND_LIBRARIES}
PkgConfig::LIBDRM
)
endif()
foreach(WL_PROTO_XML ${WL_PROTOS_XML})
get_filename_component(WL_PROTO ${WL_PROTO_XML} NAME_WLE)
set(WL_PROTO_C "${WL_PROTOS_DIR}/${WL_PROTO}.c")
set(WL_PROTO_H "${WL_PROTOS_DIR}/${WL_PROTO}-client-protocol.h")
add_custom_command(
COMMAND
${WL_SCANNER} private-code "${WL_PROTO_XML}" "${WL_PROTO_C}"
OUTPUT "${WL_PROTO_C}" VERBATIM)
add_custom_command(
COMMAND
${WL_SCANNER} client-header "${WL_PROTO_XML}" "${WL_PROTO_H}"
OUTPUT "${WL_PROTO_H}" VERBATIM)
list(APPEND MAIN_SOURCE_FILES
${WL_PROTO_C}
${WL_PROTO_H}
)
endforeach()
endif()
if(ANDROID)
list(APPEND MAIN_SOURCE_FILES
@ -178,7 +206,7 @@ if(XRT_FEATURE_COMPOSITOR_MAIN)
)
endif()
add_library(comp_main STATIC ${SHADER_HEADERS} ${MAIN_SOURCE_FILES} ${WL_PROTOS_SRC})
add_library(comp_main STATIC ${SHADER_HEADERS} ${MAIN_SOURCE_FILES})
target_link_libraries(comp_main PUBLIC xrt-interfaces PRIVATE aux_util aux_os aux_vk)
target_include_directories(comp_main PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(comp_main SYSTEM PRIVATE
@ -188,7 +216,9 @@ if(XRT_FEATURE_COMPOSITOR_MAIN)
if(XRT_HAVE_WAYLAND)
target_include_directories(comp_main SYSTEM PRIVATE ${WL_PROTOS_DIR})
target_link_libraries(comp_main PRIVATE ${WAYLAND_LIBRARIES})
target_link_libraries(comp_main PRIVATE
${WAYLAND_DEPS}
)
endif()
if(XRT_HAVE_XCB)
target_include_directories(comp_main SYSTEM PRIVATE ${XCB_INCLUDE_DIRS})

View file

@ -668,7 +668,7 @@ vkGetInstanceProcAddr(VkInstance instance, const char *pName);
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, \
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME, \
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, \
VK_KHR_SURFACE_EXTENSION_NAME
VK_KHR_SURFACE_EXTENSION_NAME \
// clang-format on
static const char *instance_extensions_none[] = {COMP_INSTANCE_EXTENSIONS_COMMON};
@ -678,8 +678,18 @@ static const char *instance_extensions_xcb[] = {COMP_INSTANCE_EXTENSIONS_COMMON,
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
static const char *instance_extensions_wayland[] = {COMP_INSTANCE_EXTENSIONS_COMMON,
VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME};
static const char *instance_extensions_wayland[] = {
COMP_INSTANCE_EXTENSIONS_COMMON,
VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
};
static const char *instance_extensions_direct_wayland[] = {
COMP_INSTANCE_EXTENSIONS_COMMON,
VK_KHR_DISPLAY_EXTENSION_NAME,
VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME,
VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME,
};
#endif
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
@ -764,6 +774,11 @@ select_instances_extensions(struct comp_compositor *c, const char ***out_exts, u
*out_num = ARRAY_SIZE(instance_extensions_none);
break;
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
case WINDOW_DIRECT_WAYLAND:
*out_exts = instance_extensions_direct_wayland;
*out_num = ARRAY_SIZE(instance_extensions_direct_wayland);
break;
case WINDOW_WAYLAND:
*out_exts = instance_extensions_wayland;
*out_num = ARRAY_SIZE(instance_extensions_wayland);
@ -1191,6 +1206,10 @@ compositor_init_window_pre_vulkan(struct comp_compositor *c)
switch (c->settings.window_type) {
case WINDOW_AUTO:
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
if (compositor_try_window(c, comp_window_direct_wayland_create(c))) {
c->settings.window_type = WINDOW_DIRECT_WAYLAND;
return true;
}
if (compositor_try_window(c, comp_window_wayland_create(c))) {
c->settings.window_type = WINDOW_WAYLAND;
return true;
@ -1238,6 +1257,13 @@ compositor_init_window_pre_vulkan(struct comp_compositor *c)
compositor_try_window(c, comp_window_wayland_create(c));
#else
COMP_ERROR(c, "Wayland support not compiled in!");
#endif
break;
case WINDOW_DIRECT_WAYLAND:
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
compositor_try_window(c, comp_window_direct_wayland_create(c));
#else
COMP_ERROR(c, "Wayland direct support not compiled in!");
#endif
break;
case WINDOW_DIRECT_RANDR:

View file

@ -14,6 +14,7 @@
DEBUG_GET_ONCE_LOG_OPTION(log, "XRT_COMPOSITOR_LOG", U_LOGGING_INFO)
DEBUG_GET_ONCE_BOOL_OPTION(print_modes, "XRT_COMPOSITOR_PRINT_MODES", false)
DEBUG_GET_ONCE_BOOL_OPTION(force_randr, "XRT_COMPOSITOR_FORCE_RANDR", false)
DEBUG_GET_ONCE_BOOL_OPTION(force_wayland_direct, "XRT_COMPOSITOR_FORCE_WAYLAND_DIRECT", false)
DEBUG_GET_ONCE_BOOL_OPTION(force_nvidia, "XRT_COMPOSITOR_FORCE_NVIDIA", false)
DEBUG_GET_ONCE_OPTION(nvidia_display, "XRT_COMPOSITOR_FORCE_NVIDIA_DISPLAY", NULL)
DEBUG_GET_ONCE_NUM_OPTION(vk_display, "XRT_COMPOSITOR_FORCE_VK_DISPLAY", -1)
@ -78,6 +79,11 @@ comp_settings_init(struct comp_settings *s, struct xrt_device *xdev)
s->window_type = WINDOW_DIRECT_RANDR;
}
if (debug_get_bool_option_force_wayland_direct()) {
s->window_type = WINDOW_DIRECT_WAYLAND;
}
if (debug_get_bool_option_force_xcb()) {
s->window_type = WINDOW_XCB;
// HMD screen tends to be much larger then monitors.

View file

@ -44,6 +44,7 @@ enum window_type
WINDOW_AUTO,
WINDOW_XCB,
WINDOW_WAYLAND,
WINDOW_DIRECT_WAYLAND,
WINDOW_DIRECT_RANDR,
WINDOW_DIRECT_NVIDIA,
WINDOW_ANDROID,

View file

@ -46,6 +46,15 @@ comp_window_xcb_create(struct comp_compositor *c);
*/
struct comp_target *
comp_window_wayland_create(struct comp_compositor *c);
/*!
* Create a direct surface to a HMD via Wayland.
*
* @ingroup comp
*/
struct comp_target *
comp_window_direct_wayland_create(struct comp_compositor *c);
#endif
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT

View file

@ -0,0 +1,459 @@
// Copyright 2019, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Wayland direct mode code.
* @author Drew DeVault <sir@cmpwn.com>
* @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
* @author Simon Zeni <simon@bl4ckb0ne.ca>
* @ingroup comp
*/
#include <errno.h>
#include <linux/input.h>
#include <poll.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wayland-client.h>
#include <xf86drm.h>
#include "drm-lease-v1-client-protocol.h"
#include "xrt/xrt_compiler.h"
#include "main/comp_window.h"
#include "main/comp_window_direct.h"
#ifndef VK_EXT_acquire_drm_display
#error "Wayland direct requires the Vulkan extension VK_EXT_acquire_drm_display"
#endif
struct direct_wayland_lease
{
struct comp_window_direct_wayland *w;
int leased_fd;
bool finished;
struct wp_drm_lease_v1 *lease;
};
struct direct_wayland_lease_connector
{
struct comp_window_direct_wayland *w;
uint32_t id;
char *name, *description;
struct wp_drm_lease_connector_v1 *connector;
struct direct_wayland_lease_device *dev;
struct direct_wayland_lease_connector *next;
};
struct direct_wayland_lease_device
{
struct comp_window_direct_wayland *w;
int drm_fd;
char *path;
bool done;
struct wp_drm_lease_device_v1 *device;
struct direct_wayland_lease_connector *connectors;
struct direct_wayland_lease_device *next;
};
struct comp_window_direct_wayland
{
struct comp_target_swapchain base;
struct wl_display *display;
struct direct_wayland_lease_device *devices;
struct direct_wayland_lease *lease;
};
static void
direct_wayland_lease_device_destroy(struct direct_wayland_lease_device *dev)
{
struct direct_wayland_lease_connector *conn = dev->connectors, *next_conn;
while (conn) {
next_conn = conn->next;
wp_drm_lease_connector_v1_destroy(conn->connector);
free(conn->name);
free(conn->description);
free(conn);
conn = next_conn;
}
wp_drm_lease_device_v1_destroy(dev->device);
close(dev->drm_fd);
free(dev->path);
free(dev);
}
static void
comp_window_direct_wayland_destroy(struct comp_target *w)
{
struct comp_window_direct_wayland *w_wayland = (struct comp_window_direct_wayland *)w;
comp_target_swapchain_cleanup(&w_wayland->base);
struct direct_wayland_lease_device *dev = w_wayland->devices, *next_dev;
while (dev) {
next_dev = dev->next;
direct_wayland_lease_device_destroy(dev);
dev = next_dev;
}
if (w_wayland->lease) {
close(w_wayland->lease->leased_fd);
wp_drm_lease_v1_destroy(w_wayland->lease->lease);
free(w_wayland->lease);
}
wl_display_disconnect(w_wayland->display);
free(w_wayland);
}
static inline struct vk_bundle *
get_vk(struct comp_window_direct_wayland *cww)
{
return &cww->base.base.c->vk;
}
static void
_lease_fd(void *data, struct wp_drm_lease_v1 *wp_drm_lease_v1, int32_t leased_fd)
{
struct direct_wayland_lease *lease = data;
COMP_DEBUG(lease->w->base.base.c, "Lease granted");
lease->leased_fd = leased_fd;
}
static void
_lease_finished(void *data, struct wp_drm_lease_v1 *wp_drm_lease_v1)
{
struct direct_wayland_lease *lease = data;
if (lease->leased_fd >= 0) {
close(lease->leased_fd);
lease->leased_fd = -1;
}
COMP_DEBUG(lease->w->base.base.c, "Lease has been terminated");
lease->finished = true;
}
static const struct wp_drm_lease_v1_listener lease_listener = {
.lease_fd = _lease_fd,
.finished = _lease_finished,
};
static VkResult
comp_window_direct_wayland_create_surface(struct comp_window_direct_wayland *w,
VkSurfaceKHR *surface,
uint32_t width,
uint32_t height)
{
assert(!w->lease);
struct vk_bundle *vk = get_vk(w);
VkDisplayKHR _display = VK_NULL_HANDLE;
VkResult ret = VK_ERROR_INCOMPATIBLE_DISPLAY_KHR;
/* TODO: Choose the connector with an environment variable or from `ct->c->settings.display` */
/* Pick the first connector available */
struct direct_wayland_lease_device *dev = w->devices;
struct direct_wayland_lease_connector *conn = NULL;
while (dev) {
if (dev->connectors) {
conn = dev->connectors;
COMP_INFO(w->base.base.c, "Using DRM node %s", dev->path);
COMP_INFO(w->base.base.c, "Connector id %d %s (%s)", conn->id, conn->name, conn->description);
break;
}
dev = dev->next;
}
if (!conn) {
COMP_ERROR(w->base.base.c, "Attempted to create wayland direct surface with no connectors");
return VK_ERROR_INITIALIZATION_FAILED;
}
ret = vk->vkGetDrmDisplayEXT(vk->physical_device, dev->drm_fd, conn->id, &_display);
if (ret != VK_SUCCESS) {
COMP_ERROR(w->base.base.c, "vkGetDrmDisplayEXT failed: %s", vk_result_string(ret));
return ret;
}
struct wp_drm_lease_request_v1 *request = wp_drm_lease_device_v1_create_lease_request(dev->device);
if (!request) {
COMP_ERROR(w->base.base.c, "Failed to create lease request");
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
wp_drm_lease_request_v1_request_connector(request, conn->connector);
struct direct_wayland_lease *lease = calloc(1, sizeof(struct direct_wayland_lease));
lease->w = w;
lease->leased_fd = -1;
lease->finished = false;
lease->lease = wp_drm_lease_request_v1_submit(request);
w->lease = lease;
wp_drm_lease_v1_add_listener(lease->lease, &lease_listener, lease);
while (lease->leased_fd < 0 && !lease->finished) {
if (wl_display_dispatch(w->display) == -1) {
COMP_ERROR(w->base.base.c, "wl_display roundtrip failed");
return VK_ERROR_UNKNOWN;
}
}
if (lease->finished) {
COMP_ERROR(w->base.base.c, "Failed to lease connector");
return VK_ERROR_UNKNOWN;
}
ret = vk->vkAcquireDrmDisplayEXT(vk->physical_device, lease->leased_fd, _display);
if (ret != VK_SUCCESS) {
COMP_ERROR(w->base.base.c, "vkAcquireDrmDisplayEXT failed: %s", vk_result_string(ret));
return ret;
}
ret = comp_window_direct_create_surface(&w->base, _display, width, height);
if (ret != VK_SUCCESS) {
COMP_ERROR(w->base.base.c, "Failed to create surface: %s", vk_result_string(ret));
}
return ret;
}
static bool
comp_window_direct_wayland_init_swapchain(struct comp_target *w, uint32_t width, uint32_t height)
{
struct comp_window_direct_wayland *w_wayland = (struct comp_window_direct_wayland *)w;
VkResult ret;
ret = comp_window_direct_wayland_create_surface(w_wayland, &w_wayland->base.surface.handle, width, height);
if (ret != VK_SUCCESS) {
COMP_ERROR(w->c, "Failed to create surface!");
return false;
}
return true;
}
static void
comp_window_direct_wayland_flush(struct comp_target *w)
{
struct comp_window_direct_wayland *w_wayland = (struct comp_window_direct_wayland *)w;
while (wl_display_prepare_read(w_wayland->display) != 0)
wl_display_dispatch_pending(w_wayland->display);
if (wl_display_flush(w_wayland->display) < 0 && errno != EAGAIN) {
wl_display_cancel_read(w_wayland->display);
return;
}
struct pollfd fds[] = {
{
.fd = wl_display_get_fd(w_wayland->display),
.events = POLLIN,
},
};
if (poll(fds, 1, 0) > 0) {
wl_display_read_events(w_wayland->display);
wl_display_dispatch_pending(w_wayland->display);
} else {
wl_display_cancel_read(w_wayland->display);
}
}
static void
_lease_connector_name(void *data, struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1, const char *name)
{
struct direct_wayland_lease_connector *conn = data;
conn->name = strdup(name);
}
static void
_lease_connector_description(void *data,
struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1,
const char *description)
{
struct direct_wayland_lease_connector *conn = data;
if (conn->description) {
free(conn->description);
}
conn->description = strdup(description);
}
static void
_lease_connector_connector_id(void *data,
struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1,
uint32_t connector_id)
{
struct direct_wayland_lease_connector *conn = data;
conn->id = connector_id;
}
static void
_lease_connector_done(void *data, struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1)
{
struct direct_wayland_lease_connector *conn = data;
COMP_DEBUG(conn->w->base.base.c, "[%s] connector %s (%s) id: %d", conn->dev->path, conn->name,
conn->description, conn->id);
}
static void
_lease_connector_withdrawn(void *data, struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1)
{
struct direct_wayland_lease_connector *conn = data;
COMP_ERROR(conn->w->base.base.c, "Connector %s has been withdrawn by the compositor", conn->name);
/* TODO: handle graceful shutdown, remove the connector from the device */
}
static const struct wp_drm_lease_connector_v1_listener lease_connector_listener = {
.name = _lease_connector_name,
.description = _lease_connector_description,
.connector_id = _lease_connector_connector_id,
.done = _lease_connector_done,
.withdrawn = _lease_connector_withdrawn,
};
static void
_drm_lease_device_drm_fd(void *data, struct wp_drm_lease_device_v1 *drm_lease_device, int fd)
{
struct direct_wayland_lease_device *dev = data;
dev->drm_fd = fd;
dev->path = drmGetDeviceNameFromFd2(fd);
COMP_DEBUG(dev->w->base.base.c, "Available DRM lease device: %s", dev->path);
}
static void
_drm_lease_device_connector(void *data,
struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1,
struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1)
{
struct direct_wayland_lease_device *dev = data;
struct direct_wayland_lease_connector *conn = calloc(1, sizeof(struct direct_wayland_lease_connector));
conn->connector = wp_drm_lease_connector_v1;
conn->dev = dev;
conn->w = dev->w;
wp_drm_lease_connector_v1_add_listener(conn->connector, &lease_connector_listener, conn);
conn->next = dev->connectors;
dev->connectors = conn;
}
static void
_drm_lease_device_done(void *data, struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1)
{
struct direct_wayland_lease_device *dev = data;
dev->done = true;
}
static void
_drm_lease_device_released(void *data, struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1)
{
struct direct_wayland_lease_device *dev = data;
COMP_ERROR(dev->w->base.base.c, "Releasing lease device %s", dev->path);
direct_wayland_lease_device_destroy(dev);
}
static const struct wp_drm_lease_device_v1_listener drm_lease_device_listener = {
.drm_fd = _drm_lease_device_drm_fd,
.connector = _drm_lease_device_connector,
.done = _drm_lease_device_done,
.released = _drm_lease_device_released,
};
static void
_registry_global_remove_cb(void *data, struct wl_registry *registry, uint32_t name)
{}
static void
_registry_global_cb(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
{
struct comp_window_direct_wayland *w = data;
if (strcmp(interface, wp_drm_lease_device_v1_interface.name) == 0) {
struct direct_wayland_lease_device *dev = calloc(1, sizeof(struct direct_wayland_lease_device));
dev->device = (struct wp_drm_lease_device_v1 *)wl_registry_bind(registry, name,
&wp_drm_lease_device_v1_interface, 1);
dev->w = w;
dev->drm_fd = -1;
wp_drm_lease_device_v1_add_listener(dev->device, &drm_lease_device_listener, dev);
dev->next = w->devices;
w->devices = dev;
}
}
static const struct wl_registry_listener registry_listener = {
.global = _registry_global_cb,
.global_remove = _registry_global_remove_cb,
};
static bool
comp_window_direct_wayland_init(struct comp_target *w)
{
struct comp_window_direct_wayland *w_wayland = (struct comp_window_direct_wayland *)w;
w_wayland->display = wl_display_connect(NULL);
if (!w_wayland->display) {
COMP_ERROR(w->c, "Failed to connect to Wayland display");
return false;
}
struct wl_registry *registry = wl_display_get_registry(w_wayland->display);
wl_registry_add_listener(registry, &registry_listener, w_wayland);
wl_display_roundtrip(w_wayland->display);
wl_registry_destroy(registry);
if (!w_wayland->devices) {
COMP_ERROR(w->c, "Compositor is missing drm-lease support");
return false;
}
struct direct_wayland_lease_device *dev = w_wayland->devices;
while (dev) {
if (!dev->done) {
wl_display_dispatch(w_wayland->display);
continue;
}
dev = dev->next;
}
return true;
}
static void
_update_window_title(struct comp_target *ct, const char *title)
{
/* Not required in direct mode */
}
struct comp_target *
comp_window_direct_wayland_create(struct comp_compositor *c)
{
struct comp_window_direct_wayland *w = U_TYPED_CALLOC(struct comp_window_direct_wayland);
comp_target_swapchain_init_and_set_fnptrs(&w->base, COMP_TARGET_FORCE_FAKE_DISPLAY_TIMING);
w->base.base.name = "wayland-direct";
w->base.base.destroy = comp_window_direct_wayland_destroy;
w->base.base.flush = comp_window_direct_wayland_flush;
w->base.base.init_pre_vulkan = comp_window_direct_wayland_init;
w->base.base.init_post_vulkan = comp_window_direct_wayland_init_swapchain;
w->base.base.set_title = _update_window_title;
w->base.base.c = c;
return &w->base.base;
}

View file

@ -114,20 +114,27 @@ if build_wayland
wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir')
protocols = [
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
]
foreach p : protocols
xml = join_paths(p)
if build_wayland_direct
protocols += wl_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml'
compositor_srcs += 'main/comp_window_direct_wayland.c'
compositor_deps += drm
endif
compositor_srcs += 'main/comp_window_wayland.c'
foreach path : protocols
wl_protos_src += custom_target(
xml.underscorify() + '_c',
input: xml,
path.underscorify() + '_c',
input: path,
output: '@BASENAME@-protocol.c',
command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'],
)
wl_protos_headers += custom_target(
xml.underscorify() + '_client_h',
input: xml,
path.underscorify() + '_client_h',
input: path,
output: '@BASENAME@-client-protocol.h',
command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'],
)
@ -144,8 +151,8 @@ if build_wayland
sources: wl_protos_headers,
)
compositor_srcs += ['main/comp_window_wayland.c']
compositor_deps += [wayland, wl_protos]
endif
lib_comp = static_library(

View file

@ -69,7 +69,7 @@ if has_v4l2_header and 'v4l2' in drivers
endif
if true
have_conf.set('XRT_HAVE_VULKAN', true)
have_conf.set('XRT_HAVE_VULKAN', true)
endif
if dbus.found() and not get_option('dbus').disabled()