mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-16 03:45:24 +00:00
comp: add VkDisplayKHR window backend
Must be activated/selected with an env var for now: XRT_COMPOSITOR_FORCE_VK_DISPLAY=2
This commit is contained in:
parent
1ea5403435
commit
9481013081
|
@ -250,7 +250,9 @@ endif()
|
|||
if(WIN32)
|
||||
set(VK_USE_PLATFORM_WIN32_KHR TRUE)
|
||||
endif()
|
||||
|
||||
if (XRT_HAVE_VULKAN AND NOT ANDROID)
|
||||
set(VK_USE_PLATFORM_DISPLAY_KHR TRUE)
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic -Wall -Wextra -Wno-unused-parameter")
|
||||
|
|
|
@ -131,6 +131,9 @@ endif
|
|||
|
||||
build_xcb_xrandr_direct = build_xcb and build_xlib and xcb_randr.found() and x11_xcb.found()
|
||||
|
||||
# requires only vulkan
|
||||
build_vk_khr_display = true
|
||||
|
||||
build_wayland = false
|
||||
if get_option('wayland').enabled() or get_option('wayland').auto()
|
||||
build_wayland = wayland.found() and wayland_protos.found() and wayland_scanner.found()
|
||||
|
|
|
@ -119,7 +119,11 @@ if(XRT_FEATURE_COMPOSITOR_MAIN)
|
|||
main/comp_window_mswin.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (VK_USE_PLATFORM_DISPLAY_KHR)
|
||||
list(APPEND MAIN_SOURCE_FILES
|
||||
main/comp_window_vk_display.c
|
||||
)
|
||||
endif()
|
||||
|
||||
# generate wayland protocols
|
||||
if(XRT_HAVE_WAYLAND)
|
||||
|
|
|
@ -694,6 +694,13 @@ static const char *instance_extensions_direct_mode[] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
|
||||
static const char *instance_extensions_vk_display[] = {
|
||||
COMP_INSTANCE_EXTENSIONS_COMMON,
|
||||
VK_KHR_DISPLAY_EXTENSION_NAME,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
||||
static const char *instance_extensions_android[] = {COMP_INSTANCE_EXTENSIONS_COMMON,
|
||||
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME};
|
||||
|
@ -785,6 +792,12 @@ select_instances_extensions(struct comp_compositor *c, const char ***out_exts, u
|
|||
*out_exts = instance_extensions_windows;
|
||||
*out_num = ARRAY_SIZE(instance_extensions_windows);
|
||||
break;
|
||||
#endif
|
||||
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
|
||||
case WINDOW_VK_DISPLAY:
|
||||
*out_exts = instance_extensions_vk_display;
|
||||
*out_num = ARRAY_SIZE(instance_extensions_vk_display);
|
||||
break;
|
||||
#endif
|
||||
default: return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
@ -1106,8 +1119,8 @@ compositor_try_window(struct comp_compositor *c, struct comp_target *ct)
|
|||
static bool
|
||||
compositor_init_window_pre_vulkan(struct comp_compositor *c)
|
||||
{
|
||||
// Nothing to do for nvidia.
|
||||
if (c->settings.window_type == WINDOW_DIRECT_NVIDIA) {
|
||||
// Nothing to do for nvidia and vk_display.
|
||||
if (c->settings.window_type == WINDOW_DIRECT_NVIDIA || c->settings.window_type == WINDOW_VK_DISPLAY) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1197,16 +1210,25 @@ compositor_init_window_pre_vulkan(struct comp_compositor *c)
|
|||
static bool
|
||||
compositor_init_window_post_vulkan(struct comp_compositor *c)
|
||||
{
|
||||
if (c->settings.window_type != WINDOW_DIRECT_NVIDIA) {
|
||||
return true;
|
||||
if (c->settings.window_type == WINDOW_DIRECT_NVIDIA) {
|
||||
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
||||
return compositor_try_window(c, comp_window_direct_nvidia_create(c));
|
||||
#else
|
||||
assert(false && "NVIDIA direct mode depends on the xlib/xrandr direct mode.");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
||||
return compositor_try_window(c, comp_window_direct_nvidia_create(c));
|
||||
if (c->settings.window_type == WINDOW_VK_DISPLAY) {
|
||||
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
|
||||
return compositor_try_window(c, comp_window_vk_display_create(c));
|
||||
#else
|
||||
assert(false && "NVIDIA direct mode depends on the xlib/xrandr direct mode.");
|
||||
return false;
|
||||
assert(false && "VkDisplayKHR direct mode depends on VK_USE_PLATFORM_DISPLAY_KHR.");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
@ -16,6 +16,7 @@ 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_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)
|
||||
DEBUG_GET_ONCE_BOOL_OPTION(force_xcb, "XRT_COMPOSITOR_FORCE_XCB", false)
|
||||
DEBUG_GET_ONCE_BOOL_OPTION(force_wayland, "XRT_COMPOSITOR_FORCE_WAYLAND", false)
|
||||
DEBUG_GET_ONCE_BOOL_OPTION(wireframe, "XRT_COMPOSITOR_WIREFRAME", false)
|
||||
|
@ -60,6 +61,10 @@ comp_settings_init(struct comp_settings *s, struct xrt_device *xdev)
|
|||
}
|
||||
|
||||
s->nvidia_display = debug_get_option_nvidia_display();
|
||||
s->vk_display = debug_get_num_option_vk_display();
|
||||
if (s->vk_display >= 0) {
|
||||
s->window_type = WINDOW_VK_DISPLAY;
|
||||
}
|
||||
|
||||
if (debug_get_bool_option_force_randr()) {
|
||||
s->window_type = WINDOW_DIRECT_RANDR;
|
||||
|
|
|
@ -48,6 +48,7 @@ enum window_type
|
|||
WINDOW_DIRECT_NVIDIA,
|
||||
WINDOW_ANDROID,
|
||||
WINDOW_MSWIN,
|
||||
WINDOW_VK_DISPLAY,
|
||||
};
|
||||
|
||||
|
||||
|
@ -70,6 +71,9 @@ struct comp_settings
|
|||
//! display string forced by user or NULL
|
||||
const char *nvidia_display;
|
||||
|
||||
//! vk display number to use when forcing vk_display
|
||||
int vk_display;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t width;
|
||||
|
|
|
@ -68,6 +68,14 @@ struct comp_target *
|
|||
comp_window_direct_nvidia_create(struct comp_compositor *c);
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Create a direct surface to an HMD on VkDisplay.
|
||||
*
|
||||
* @ingroup comp_main
|
||||
* @public @memberof comp_window_direct_vk_display
|
||||
*/
|
||||
struct comp_target *
|
||||
comp_window_vk_display_create(struct comp_compositor *c);
|
||||
|
||||
#ifdef XRT_OS_ANDROID
|
||||
|
||||
|
|
248
src/xrt/compositor/main/comp_window_vk_display.c
Normal file
248
src/xrt/compositor/main/comp_window_vk_display.c
Normal file
|
@ -0,0 +1,248 @@
|
|||
// Copyright 2019-2021, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Direct mode on PLATFORM_DISPLAY_KHR code.
|
||||
* @author Christoph Haag <christoph.haag@collabora.com>
|
||||
* @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
|
||||
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||
* @ingroup comp_main
|
||||
*/
|
||||
|
||||
#include "util/u_misc.h"
|
||||
|
||||
#include "main/comp_window_direct.h"
|
||||
|
||||
/*
|
||||
*
|
||||
* Private structs
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Probed display.
|
||||
*/
|
||||
struct vk_display
|
||||
{
|
||||
VkDisplayPropertiesKHR display_properties;
|
||||
VkDisplayKHR display;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Direct mode "window" into a device, using PLATFORM_DISPLAY_KHR.
|
||||
*
|
||||
* @implements comp_target_swapchain
|
||||
*/
|
||||
struct comp_window_vk_display
|
||||
{
|
||||
struct comp_target_swapchain base;
|
||||
|
||||
struct vk_display *displays;
|
||||
uint16_t num_displays;
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
* Forward declare functions
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
comp_window_vk_display_destroy(struct comp_target *ct);
|
||||
|
||||
static bool
|
||||
comp_window_vk_display_init(struct comp_target *ct);
|
||||
|
||||
static struct vk_display *
|
||||
comp_window_vk_display_current_display(struct comp_window_vk_display *w);
|
||||
|
||||
static bool
|
||||
comp_window_vk_display_init_swapchain(struct comp_target *ct, uint32_t width, uint32_t height);
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Functions.
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
_flush(struct comp_target *ct)
|
||||
{
|
||||
(void)ct;
|
||||
}
|
||||
|
||||
static void
|
||||
_update_window_title(struct comp_target *ct, const char *title)
|
||||
{
|
||||
(void)ct;
|
||||
(void)title;
|
||||
}
|
||||
|
||||
struct comp_target *
|
||||
comp_window_vk_display_create(struct comp_compositor *c)
|
||||
{
|
||||
struct comp_window_vk_display *w = U_TYPED_CALLOC(struct comp_window_vk_display);
|
||||
|
||||
comp_target_swapchain_init_set_fnptrs(&w->base);
|
||||
|
||||
w->base.base.name = "VkDisplayKHR";
|
||||
w->base.base.destroy = comp_window_vk_display_destroy;
|
||||
w->base.base.flush = _flush;
|
||||
w->base.base.init_pre_vulkan = comp_window_vk_display_init;
|
||||
w->base.base.init_post_vulkan = comp_window_vk_display_init_swapchain;
|
||||
w->base.base.set_title = _update_window_title;
|
||||
w->base.base.c = c;
|
||||
|
||||
return &w->base.base;
|
||||
}
|
||||
|
||||
static void
|
||||
comp_window_vk_display_destroy(struct comp_target *ct)
|
||||
{
|
||||
struct comp_window_vk_display *w_direct = (struct comp_window_vk_display *)ct;
|
||||
|
||||
comp_target_swapchain_cleanup(&w_direct->base);
|
||||
|
||||
for (uint32_t i = 0; i < w_direct->num_displays; i++) {
|
||||
struct vk_display *d = &w_direct->displays[i];
|
||||
d->display = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (w_direct->displays != NULL)
|
||||
free(w_direct->displays);
|
||||
|
||||
free(ct);
|
||||
}
|
||||
|
||||
static bool
|
||||
append_vk_display_entry(struct comp_window_vk_display *w, struct VkDisplayPropertiesKHR *disp)
|
||||
{
|
||||
w->base.base.c->settings.preferred.width = disp->physicalResolution.width;
|
||||
w->base.base.c->settings.preferred.height = disp->physicalResolution.height;
|
||||
struct vk_display d = {.display_properties = *disp, .display = disp->display};
|
||||
|
||||
w->num_displays += 1;
|
||||
|
||||
U_ARRAY_REALLOC_OR_FREE(w->displays, struct vk_display, w->num_displays);
|
||||
|
||||
if (w->displays == NULL)
|
||||
COMP_ERROR(w->base.base.c, "Unable to reallocate vk_display displays");
|
||||
|
||||
w->displays[w->num_displays - 1] = d;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
print_found_displays(struct comp_compositor *c, struct VkDisplayPropertiesKHR *display_props, uint32_t display_count)
|
||||
{
|
||||
COMP_ERROR(c, "== Found Displays ==");
|
||||
for (uint32_t i = 0; i < display_count; i++) {
|
||||
struct VkDisplayPropertiesKHR *p = &display_props[i];
|
||||
|
||||
COMP_ERROR(c, "[%d] %s with resolution %dx%d, dims %dx%d", i, p->displayName,
|
||||
p->physicalResolution.width, p->physicalResolution.height, p->physicalDimensions.width,
|
||||
p->physicalDimensions.height);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
comp_window_vk_display_init(struct comp_target *ct)
|
||||
{
|
||||
struct comp_window_vk_display *w_direct = (struct comp_window_vk_display *)ct;
|
||||
|
||||
// Sanity check.
|
||||
if (ct->c->vk.instance == VK_NULL_HANDLE) {
|
||||
COMP_ERROR(ct->c, "Vulkan not initialized before vk display init!");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct vk_bundle comp_vk = ct->c->vk;
|
||||
|
||||
uint32_t display_count;
|
||||
if (comp_vk.vkGetPhysicalDeviceDisplayPropertiesKHR(comp_vk.physical_device, &display_count, NULL) !=
|
||||
VK_SUCCESS) {
|
||||
COMP_ERROR(ct->c, "Failed to get vulkan display count");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (display_count == 0) {
|
||||
COMP_ERROR(ct->c, "No Vulkan displays found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct VkDisplayPropertiesKHR *display_props = U_TYPED_ARRAY_CALLOC(VkDisplayPropertiesKHR, display_count);
|
||||
|
||||
if (display_props && comp_vk.vkGetPhysicalDeviceDisplayPropertiesKHR(comp_vk.physical_device, &display_count,
|
||||
display_props) != VK_SUCCESS) {
|
||||
COMP_ERROR(ct->c, "Failed to get display properties");
|
||||
free(display_props);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ct->c->settings.vk_display > (int)display_count) {
|
||||
COMP_ERROR(ct->c, "Requested display %d, but only %d found.", ct->c->settings.vk_display,
|
||||
display_count);
|
||||
print_found_displays(ct->c, display_props, display_count);
|
||||
free(display_props);
|
||||
return false;
|
||||
}
|
||||
|
||||
append_vk_display_entry(w_direct, &display_props[ct->c->settings.vk_display]);
|
||||
|
||||
struct vk_display *d = comp_window_vk_display_current_display(w_direct);
|
||||
if (!d) {
|
||||
COMP_ERROR(ct->c, "display not found!");
|
||||
print_found_displays(ct->c, display_props, display_count);
|
||||
free(display_props);
|
||||
return false;
|
||||
}
|
||||
|
||||
free(display_props);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct vk_display *
|
||||
comp_window_vk_display_current_display(struct comp_window_vk_display *w)
|
||||
{
|
||||
int index = w->base.base.c->settings.display;
|
||||
if (index == -1)
|
||||
index = 0;
|
||||
|
||||
if (w->num_displays <= (uint32_t)index)
|
||||
return NULL;
|
||||
|
||||
return &w->displays[index];
|
||||
}
|
||||
|
||||
static bool
|
||||
init_swapchain(struct comp_target_swapchain *cts, VkDisplayKHR display, uint32_t width, uint32_t height)
|
||||
{
|
||||
VkResult ret;
|
||||
|
||||
ret = comp_window_direct_create_surface(cts, display, width, height);
|
||||
if (ret != VK_SUCCESS) {
|
||||
COMP_ERROR(cts->base.c, "Failed to create surface! '%s'", vk_result_string(ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
comp_window_vk_display_init_swapchain(struct comp_target *ct, uint32_t width, uint32_t height)
|
||||
{
|
||||
struct comp_window_vk_display *w_direct = (struct comp_window_vk_display *)ct;
|
||||
|
||||
struct vk_display *d = comp_window_vk_display_current_display(w_direct);
|
||||
if (!d) {
|
||||
COMP_ERROR(ct->c, "display not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
COMP_DEBUG(ct->c, "Will use display: %s", d->display_properties.displayName);
|
||||
|
||||
return init_swapchain(&w_direct->base, d->display, width, height);
|
||||
}
|
|
@ -36,6 +36,10 @@ compositor_srcs = [
|
|||
|
||||
compile_args = []
|
||||
|
||||
if build_vk_khr_display
|
||||
compositor_srcs += ['main/comp_window_vk_display.c']
|
||||
endif
|
||||
|
||||
if build_xcb
|
||||
compositor_srcs += ['main/comp_window_xcb.c']
|
||||
compositor_deps += [xcb]
|
||||
|
|
|
@ -151,6 +151,9 @@ endif
|
|||
if build_xcb_xrandr_direct
|
||||
vulkan_conf.set('VK_USE_PLATFORM_XLIB_XRANDR_EXT', true)
|
||||
endif
|
||||
if build_vk_khr_display
|
||||
vulkan_conf.set('VK_USE_PLATFORM_DISPLAY_KHR', true)
|
||||
endif
|
||||
|
||||
xrt_config_vulkan_h = configure_file(
|
||||
output: 'xrt_config_vulkan.h',
|
||||
|
|
|
@ -14,3 +14,4 @@
|
|||
#cmakedefine VK_USE_PLATFORM_XCB_KHR
|
||||
#cmakedefine VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
||||
#cmakedefine VK_USE_PLATFORM_WIN32_KHR
|
||||
#cmakedefine VK_USE_PLATFORM_DISPLAY_KHR
|
||||
|
|
Loading…
Reference in a new issue