mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2024-12-29 11:06:18 +00:00
c/main: Implement WINDOW_DIRECT_WAYLAND
This commit is contained in:
parent
26c684d42f
commit
47be806428
|
@ -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}")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -44,6 +44,7 @@ enum window_type
|
|||
WINDOW_AUTO,
|
||||
WINDOW_XCB,
|
||||
WINDOW_WAYLAND,
|
||||
WINDOW_DIRECT_WAYLAND,
|
||||
WINDOW_DIRECT_RANDR,
|
||||
WINDOW_DIRECT_NVIDIA,
|
||||
WINDOW_ANDROID,
|
||||
|
|
|
@ -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
|
||||
|
|
459
src/xrt/compositor/main/comp_window_direct_wayland.c
Normal file
459
src/xrt/compositor/main/comp_window_direct_wayland.c
Normal 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, ®istry_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;
|
||||
}
|
|
@ -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(
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue