From 29b771818e961ae1f5dd80d66509d8966caf8288 Mon Sep 17 00:00:00 2001 From: Lubosz Sarnecki Date: Wed, 8 Apr 2020 16:40:58 +0200 Subject: [PATCH] c/direct: Move common direct mode code to comp_window_direct. Create code file for common direct mode code. Make common functions take generic parameters. Use common code in randr and nvidia back ends. Remove redunant includes. --- src/xrt/compositor/CMakeLists.txt | 1 + src/xrt/compositor/main/comp_window_direct.c | 262 +++++++++++++ src/xrt/compositor/main/comp_window_direct.h | 39 ++ .../main/comp_window_direct_nvidia.c | 318 ++-------------- .../main/comp_window_direct_randr.c | 343 ++---------------- src/xrt/compositor/meson.build | 3 +- 6 files changed, 358 insertions(+), 608 deletions(-) create mode 100644 src/xrt/compositor/main/comp_window_direct.c create mode 100644 src/xrt/compositor/main/comp_window_direct.h diff --git a/src/xrt/compositor/CMakeLists.txt b/src/xrt/compositor/CMakeLists.txt index b70f9bf12..a0c41e394 100644 --- a/src/xrt/compositor/CMakeLists.txt +++ b/src/xrt/compositor/CMakeLists.txt @@ -86,6 +86,7 @@ if(BUILD_COMPOSITOR_MAIN) endif() if(BUILD_WITH_XCB AND BUILD_WITH_XLIB) list(APPEND MAIN_SOURCE_FILES + main/comp_window_direct.c main/comp_window_direct_randr.c main/comp_window_direct_nvidia.c ) diff --git a/src/xrt/compositor/main/comp_window_direct.c b/src/xrt/compositor/main/comp_window_direct.c new file mode 100644 index 000000000..98d8c9f11 --- /dev/null +++ b/src/xrt/compositor/main/comp_window_direct.c @@ -0,0 +1,262 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Common direct mode window code. + * @author Lubosz Sarnecki + * @author Jakob Bornecrantz + * @ingroup comp_main + */ + +#include + +#include "comp_window_direct.h" + +#include "util/u_misc.h" + +static int +choose_best_vk_mode_auto(struct comp_window *w, + VkDisplayModePropertiesKHR *mode_properties, + int mode_count) +{ + if (mode_count == 1) + return 0; + + int best_index = 0; + + // First priority: choose mode that maximizes rendered pixels. + // Second priority: choose mode with highest refresh rate. + for (int i = 1; i < mode_count; i++) { + VkDisplayModeParametersKHR current = + mode_properties[i].parameters; + COMP_DEBUG(w->c, "Available Vk direct mode %d: %dx%d@%.2f", i, + current.visibleRegion.width, + current.visibleRegion.height, + (float)current.refreshRate / 1000.); + + + VkDisplayModeParametersKHR best = + mode_properties[best_index].parameters; + + int best_pixels = + best.visibleRegion.width * best.visibleRegion.height; + int pixels = + current.visibleRegion.width * current.visibleRegion.height; + if (pixels > best_pixels) { + best_index = i; + } else if (pixels == best_pixels && + current.refreshRate > best.refreshRate) { + best_index = i; + } + } + VkDisplayModeParametersKHR best = + mode_properties[best_index].parameters; + COMP_DEBUG(w->c, "Auto choosing Vk direct mode %d: %dx%d@%.2f", + best_index, best.visibleRegion.width, + best.visibleRegion.width, (float)best.refreshRate / 1000.); + return best_index; +} + +static void +print_modes(struct comp_window *w, + VkDisplayModePropertiesKHR *mode_properties, + int mode_count) +{ + COMP_PRINT_MODE(w->c, "Available Vk modes for direct mode"); + for (int i = 0; i < mode_count; i++) { + VkDisplayModePropertiesKHR props = mode_properties[i]; + uint16_t width = props.parameters.visibleRegion.width; + uint16_t height = props.parameters.visibleRegion.height; + float refresh = (float)props.parameters.refreshRate / 1000.; + + COMP_PRINT_MODE(w->c, "| %2d | %dx%d@%.2f", i, width, height, + refresh); + } + COMP_PRINT_MODE(w->c, "Listed %d modes", mode_count); +} + +VkDisplayModeKHR +comp_window_direct_get_primary_display_mode(struct comp_window *w, + VkDisplayKHR display) +{ + struct vk_bundle *vk = w->swapchain.vk; + uint32_t mode_count; + VkResult ret; + + ret = vk->vkGetDisplayModePropertiesKHR(vk->physical_device, display, + &mode_count, NULL); + if (ret != VK_SUCCESS) { + COMP_ERROR(w->c, "vkGetDisplayModePropertiesKHR: %s", + vk_result_string(ret)); + return VK_NULL_HANDLE; + } + + COMP_DEBUG(w->c, "Found %d modes", mode_count); + + VkDisplayModePropertiesKHR *mode_properties = + U_TYPED_ARRAY_CALLOC(VkDisplayModePropertiesKHR, mode_count); + ret = vk->vkGetDisplayModePropertiesKHR(vk->physical_device, display, + &mode_count, mode_properties); + if (ret != VK_SUCCESS) { + COMP_ERROR(w->c, "vkGetDisplayModePropertiesKHR: %s", + vk_result_string(ret)); + free(mode_properties); + return VK_NULL_HANDLE; + } + + print_modes(w, mode_properties, mode_count); + + + int chosen_mode = 0; + + int desired_mode = w->c->settings.desired_mode; + if (desired_mode + 1 > (int)mode_count) { + COMP_ERROR(w->c, + "Requested mode index %d, but max is %d. Falling " + "back to automatic mode selection", + desired_mode, mode_count); + chosen_mode = + choose_best_vk_mode_auto(w, mode_properties, mode_count); + } else if (desired_mode < 0) { + chosen_mode = + choose_best_vk_mode_auto(w, mode_properties, mode_count); + } else { + COMP_DEBUG(w->c, "Using manually chosen mode %d", desired_mode); + chosen_mode = desired_mode; + } + + VkDisplayModePropertiesKHR props = mode_properties[chosen_mode]; + + COMP_DEBUG(w->c, "found display mode %dx%d@%.2f", + props.parameters.visibleRegion.width, + props.parameters.visibleRegion.height, + (float)props.parameters.refreshRate / 1000.); + + int64_t new_frame_interval = + 1000. * 1000. * 1000. * 1000. / props.parameters.refreshRate; + + COMP_DEBUG( + w->c, + "Updating compositor settings nominal frame interval from %" PRIu64 + " (%f Hz) to %" PRIu64 " (%f Hz)", + w->c->settings.nominal_frame_interval_ns, + 1000. * 1000. * 1000. / + (float)w->c->settings.nominal_frame_interval_ns, + new_frame_interval, (float)props.parameters.refreshRate / 1000.); + + w->c->settings.nominal_frame_interval_ns = new_frame_interval; + + free(mode_properties); + + return props.displayMode; +} + +static VkDisplayPlaneAlphaFlagBitsKHR +choose_alpha_mode(VkDisplayPlaneAlphaFlagsKHR flags) +{ + if (flags & VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR) { + return VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR; + } + if (flags & VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR) { + return VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR; + } + return VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR; +} + +VkResult +comp_window_direct_create_surface(struct comp_window *w, + VkDisplayKHR display, + uint32_t width, + uint32_t height) +{ + struct vk_bundle *vk = w->swapchain.vk; + + // Get plane properties + uint32_t plane_property_count; + VkResult ret = vk->vkGetPhysicalDeviceDisplayPlanePropertiesKHR( + w->swapchain.vk->physical_device, &plane_property_count, NULL); + if (ret != VK_SUCCESS) { + COMP_ERROR(w->c, + "vkGetPhysicalDeviceDisplayPlanePropertiesKHR: %s", + vk_result_string(ret)); + return ret; + } + + COMP_DEBUG(w->c, "Found %d plane properites.", plane_property_count); + + VkDisplayPlanePropertiesKHR *plane_properties = U_TYPED_ARRAY_CALLOC( + VkDisplayPlanePropertiesKHR, plane_property_count); + + ret = vk->vkGetPhysicalDeviceDisplayPlanePropertiesKHR( + w->swapchain.vk->physical_device, &plane_property_count, + plane_properties); + if (ret != VK_SUCCESS) { + COMP_ERROR(w->c, + "vkGetPhysicalDeviceDisplayPlanePropertiesKHR: %s", + vk_result_string(ret)); + free(plane_properties); + return ret; + } + + uint32_t plane_index = 0; + + VkDisplayModeKHR display_mode = + comp_window_direct_get_primary_display_mode(w, display); + + VkDisplayPlaneCapabilitiesKHR plane_caps; + vk->vkGetDisplayPlaneCapabilitiesKHR(w->swapchain.vk->physical_device, + display_mode, plane_index, + &plane_caps); + + VkDisplaySurfaceCreateInfoKHR surface_info = { + .sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR, + .pNext = NULL, + .flags = 0, + .displayMode = display_mode, + .planeIndex = plane_index, + .planeStackIndex = plane_properties[plane_index].currentStackIndex, + .transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, + .globalAlpha = 1.0, + .alphaMode = choose_alpha_mode(plane_caps.supportedAlpha), + .imageExtent = + { + .width = width, + .height = height, + }, + }; + + VkResult result = vk->vkCreateDisplayPlaneSurfaceKHR( + vk->instance, &surface_info, NULL, &w->swapchain.surface); + + free(plane_properties); + + return result; +} + +int +comp_window_direct_connect(struct comp_window *w, Display **dpy) +{ + *dpy = XOpenDisplay(NULL); + if (*dpy == NULL) { + COMP_ERROR(w->c, "Could not open X display."); + return false; + } + return true; +} + +VkResult +comp_window_direct_acquire_xlib_display(struct comp_window *w, + Display *dpy, + VkDisplayKHR display) +{ + struct vk_bundle *vk = w->swapchain.vk; + VkResult ret; + + ret = vk->vkAcquireXlibDisplayEXT(w->swapchain.vk->physical_device, dpy, + display); + if (ret != VK_SUCCESS) { + COMP_ERROR(w->c, "vkAcquireXlibDisplayEXT: %s (%p)", + vk_result_string(ret), (void *)display); + } + return ret; +} diff --git a/src/xrt/compositor/main/comp_window_direct.h b/src/xrt/compositor/main/comp_window_direct.h new file mode 100644 index 000000000..ae74387b3 --- /dev/null +++ b/src/xrt/compositor/main/comp_window_direct.h @@ -0,0 +1,39 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Common direct mode window code header. + * @author Lubosz Sarnecki + * @author Jakob Bornecrantz + * @ingroup comp_main + */ + +#pragma once + +#include "main/comp_window.h" + +#ifdef __cplusplus +extern "C" { +#endif + +VkDisplayModeKHR +comp_window_direct_get_primary_display_mode(struct comp_window *w, + VkDisplayKHR display); + +VkResult +comp_window_direct_create_surface(struct comp_window *w, + VkDisplayKHR display, + uint32_t width, + uint32_t height); + +int +comp_window_direct_connect(struct comp_window *w, Display **dpy); + +VkResult +comp_window_direct_acquire_xlib_display(struct comp_window *w, + Display *dpy, + VkDisplayKHR display); + +#ifdef __cplusplus +} +#endif diff --git a/src/xrt/compositor/main/comp_window_direct_nvidia.c b/src/xrt/compositor/main/comp_window_direct_nvidia.c index 2cbd746cf..246d55ede 100644 --- a/src/xrt/compositor/main/comp_window_direct_nvidia.c +++ b/src/xrt/compositor/main/comp_window_direct_nvidia.c @@ -8,13 +8,9 @@ * @ingroup comp_main */ -#include - #include "util/u_misc.h" -#include "xrt/xrt_compiler.h" -#include "main/comp_window.h" - +#include "main/comp_window_direct.h" /* * @@ -62,32 +58,11 @@ comp_window_direct_nvidia_init(struct comp_window *w); static struct comp_window_direct_nvidia_display * comp_window_direct_nvidia_current_display(struct comp_window_direct_nvidia *w); -static VkDisplayModeKHR -comp_window_direct_nvidia_get_primary_display_mode( - struct comp_window_direct_nvidia *w, VkDisplayKHR display); - -static VkDisplayPlaneAlphaFlagBitsKHR -choose_alpha_mode(VkDisplayPlaneAlphaFlagsKHR flags); - -static VkResult -comp_window_direct_nvidia_create_surface(struct comp_window_direct_nvidia *w, - VkInstance instance, - VkSurfaceKHR *surface, - uint32_t width, - uint32_t height); - static bool comp_window_direct_nvidia_init_swapchain(struct comp_window *w, uint32_t width, uint32_t height); -static int -comp_window_direct_nvidia_connect(struct comp_window_direct_nvidia *w); - -static VkResult -comp_window_direct_nvidia_acquire_xlib_display( - struct comp_window_direct_nvidia *w, VkDisplayKHR display); - /* * * Functions. @@ -193,7 +168,7 @@ comp_window_direct_nvidia_init(struct comp_window *w) struct comp_window_direct_nvidia *w_direct = (struct comp_window_direct_nvidia *)w; - if (!comp_window_direct_nvidia_connect(w_direct)) { + if (!comp_window_direct_connect(w, &w_direct->dpy)) { return false; } @@ -269,246 +244,6 @@ comp_window_direct_nvidia_current_display(struct comp_window_direct_nvidia *w) return &w->nv_displays[index]; } -static int -choose_best_vk_mode_auto(struct comp_window_direct_nvidia *w, - VkDisplayModePropertiesKHR *mode_properties, - int mode_count) -{ - if (mode_count == 1) - return 0; - - int best_index = 0; - - // First priority: choose mode that maximizes rendered pixels. - // Second priority: choose mode with highest refresh rate. - for (int i = 1; i < mode_count; i++) { - VkDisplayModeParametersKHR current = - mode_properties[i].parameters; - COMP_DEBUG(w->base.c, "Available Vk direct mode %d: %dx%d@%.2f", - i, current.visibleRegion.width, - current.visibleRegion.height, - (float)current.refreshRate / 1000.); - - - VkDisplayModeParametersKHR best = - mode_properties[best_index].parameters; - - int best_pixels = - best.visibleRegion.width * best.visibleRegion.height; - int pixels = - current.visibleRegion.width * current.visibleRegion.height; - if (pixels > best_pixels) { - best_index = i; - } else if (pixels == best_pixels && - current.refreshRate > best.refreshRate) { - best_index = i; - } - } - VkDisplayModeParametersKHR best = - mode_properties[best_index].parameters; - COMP_DEBUG(w->base.c, "Auto choosing Vk direct mode %d: %dx%d@%.2f", - best_index, best.visibleRegion.width, - best.visibleRegion.width, (float)best.refreshRate / 1000.); - return best_index; -} - -static void -print_modes(struct comp_window_direct_nvidia *w, - VkDisplayModePropertiesKHR *mode_properties, - int mode_count) -{ - COMP_PRINT_MODE(w->base.c, "Available Vk modes for direct mode"); - for (int i = 0; i < mode_count; i++) { - VkDisplayModePropertiesKHR props = mode_properties[i]; - uint16_t width = props.parameters.visibleRegion.width; - uint16_t height = props.parameters.visibleRegion.height; - float refresh = (float)props.parameters.refreshRate / 1000.; - - COMP_PRINT_MODE(w->base.c, "| %2d | %dx%d@%.2f", i, width, - height, refresh); - } - COMP_PRINT_MODE(w->base.c, "Listed %d modes", mode_count); -} - -static VkDisplayModeKHR -comp_window_direct_nvidia_get_primary_display_mode( - struct comp_window_direct_nvidia *w, VkDisplayKHR display) -{ - struct vk_bundle *vk = w->base.swapchain.vk; - uint32_t mode_count; - VkResult ret; - - ret = vk->vkGetDisplayModePropertiesKHR( - w->base.swapchain.vk->physical_device, display, &mode_count, NULL); - if (ret != VK_SUCCESS) { - COMP_ERROR(w->base.c, "vkGetDisplayModePropertiesKHR: %s", - vk_result_string(ret)); - return VK_NULL_HANDLE; - } - - COMP_DEBUG(w->base.c, "Found %d modes", mode_count); - - VkDisplayModePropertiesKHR *mode_properties = - U_TYPED_ARRAY_CALLOC(VkDisplayModePropertiesKHR, mode_count); - ret = vk->vkGetDisplayModePropertiesKHR( - w->base.swapchain.vk->physical_device, display, &mode_count, - mode_properties); - if (ret != VK_SUCCESS) { - COMP_ERROR(w->base.c, "vkGetDisplayModePropertiesKHR: %s", - vk_result_string(ret)); - free(mode_properties); - return VK_NULL_HANDLE; - } - - print_modes(w, mode_properties, mode_count); - - - int chosen_mode = 0; - - int desired_mode = w->base.c->settings.desired_mode; - if (desired_mode + 1 > (int)mode_count) { - COMP_ERROR(w->base.c, - "Requested mode index %d, but max is %d. Falling " - "back to automatic mode selection", - desired_mode, mode_count); - chosen_mode = - choose_best_vk_mode_auto(w, mode_properties, mode_count); - } else if (desired_mode < 0) { - chosen_mode = - choose_best_vk_mode_auto(w, mode_properties, mode_count); - } else { - COMP_DEBUG(w->base.c, "Using manually chosen mode %d", - desired_mode); - chosen_mode = desired_mode; - } - - VkDisplayModePropertiesKHR props = mode_properties[chosen_mode]; - - COMP_DEBUG(w->base.c, "found display mode %dx%d@%.2f", - props.parameters.visibleRegion.width, - props.parameters.visibleRegion.height, - (float)props.parameters.refreshRate / 1000.); - - int64_t new_frame_interval = - 1000. * 1000. * 1000. * 1000. / props.parameters.refreshRate; - - COMP_DEBUG( - w->base.c, - "Updating compositor settings nominal frame interval from %" PRIu64 - " (%f Hz) to %" PRIu64 " (%f Hz)", - w->base.c->settings.nominal_frame_interval_ns, - 1000. * 1000. * 1000. / - (float)w->base.c->settings.nominal_frame_interval_ns, - new_frame_interval, (float)props.parameters.refreshRate / 1000.); - - w->base.c->settings.nominal_frame_interval_ns = new_frame_interval; - - free(mode_properties); - - return props.displayMode; -} - -static VkDisplayPlaneAlphaFlagBitsKHR -choose_alpha_mode(VkDisplayPlaneAlphaFlagsKHR flags) -{ - if (flags & VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR) { - return VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR; - } - if (flags & VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR) { - return VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR; - } - return VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR; -} - -static VkResult -comp_window_direct_nvidia_create_surface(struct comp_window_direct_nvidia *w, - VkInstance instance, - VkSurfaceKHR *surface, - uint32_t width, - uint32_t height) -{ - struct comp_window_direct_nvidia_display *nvd = - comp_window_direct_nvidia_current_display(w); - struct vk_bundle *vk = w->base.swapchain.vk; - - VkResult ret = VK_ERROR_INCOMPATIBLE_DISPLAY_KHR; - VkDisplayKHR _display = VK_NULL_HANDLE; - - if (nvd) { - COMP_DEBUG(w->base.c, "Will use display: %s", nvd->name); - ret = comp_window_direct_nvidia_acquire_xlib_display( - w, nvd->display); - _display = nvd->display; - } - - if (ret != VK_SUCCESS) { - return ret; - } - - - // Get plane properties - uint32_t plane_property_count; - ret = vk->vkGetPhysicalDeviceDisplayPlanePropertiesKHR( - w->base.swapchain.vk->physical_device, &plane_property_count, NULL); - if (ret != VK_SUCCESS) { - COMP_ERROR(w->base.c, - "vkGetPhysicalDeviceDisplayPlanePropertiesKHR: %s", - vk_result_string(ret)); - return ret; - } - - COMP_DEBUG(w->base.c, "Found %d plane properites.", - plane_property_count); - - VkDisplayPlanePropertiesKHR *plane_properties = U_TYPED_ARRAY_CALLOC( - VkDisplayPlanePropertiesKHR, plane_property_count); - - ret = vk->vkGetPhysicalDeviceDisplayPlanePropertiesKHR( - w->base.swapchain.vk->physical_device, &plane_property_count, - plane_properties); - if (ret != VK_SUCCESS) { - COMP_ERROR(w->base.c, - "vkGetPhysicalDeviceDisplayPlanePropertiesKHR: %s", - vk_result_string(ret)); - free(plane_properties); - return ret; - } - - uint32_t plane_index = 0; - - VkDisplayModeKHR display_mode = - comp_window_direct_nvidia_get_primary_display_mode(w, _display); - - VkDisplayPlaneCapabilitiesKHR plane_caps; - vk->vkGetDisplayPlaneCapabilitiesKHR( - w->base.swapchain.vk->physical_device, display_mode, plane_index, - &plane_caps); - - VkDisplaySurfaceCreateInfoKHR surface_info = { - .sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR, - .pNext = NULL, - .flags = 0, - .displayMode = display_mode, - .planeIndex = plane_index, - .planeStackIndex = plane_properties[plane_index].currentStackIndex, - .transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, - .globalAlpha = 1.0, - .alphaMode = choose_alpha_mode(plane_caps.supportedAlpha), - .imageExtent = - { - .width = width, - .height = height, - }, - }; - - VkResult result = vk->vkCreateDisplayPlaneSurfaceKHR( - instance, &surface_info, NULL, surface); - - free(plane_properties); - - return result; -} - static bool comp_window_direct_nvidia_init_swapchain(struct comp_window *w, uint32_t width, @@ -517,9 +252,25 @@ comp_window_direct_nvidia_init_swapchain(struct comp_window *w, struct comp_window_direct_nvidia *w_direct = (struct comp_window_direct_nvidia *)w; - VkResult ret = comp_window_direct_nvidia_create_surface( - w_direct, w->swapchain.vk->instance, &w->swapchain.surface, width, - height); + struct comp_window_direct_nvidia_display *nvd = + comp_window_direct_nvidia_current_display(w_direct); + + VkResult ret = VK_ERROR_INCOMPATIBLE_DISPLAY_KHR; + + VkDisplayKHR _display = VK_NULL_HANDLE; + + if (nvd) { + COMP_DEBUG(w->c, "Will use display: %s", nvd->name); + ret = comp_window_direct_acquire_xlib_display(w, w_direct->dpy, + nvd->display); + _display = nvd->display; + } + + if (ret != VK_SUCCESS) { + return ret; + } + + ret = comp_window_direct_create_surface(w, _display, width, height); if (ret != VK_SUCCESS) { COMP_ERROR(w->c, "Failed to create surface!"); return false; @@ -531,30 +282,3 @@ comp_window_direct_nvidia_init_swapchain(struct comp_window *w, return true; } - -static int -comp_window_direct_nvidia_connect(struct comp_window_direct_nvidia *w) -{ - w->dpy = XOpenDisplay(NULL); - if (w->dpy == NULL) { - COMP_ERROR(w->base.c, "Could not open X display."); - return false; - } - return true; -} - -static VkResult -comp_window_direct_nvidia_acquire_xlib_display( - struct comp_window_direct_nvidia *w, VkDisplayKHR display) -{ - struct vk_bundle *vk = w->base.swapchain.vk; - VkResult ret; - - ret = vk->vkAcquireXlibDisplayEXT(w->base.swapchain.vk->physical_device, - w->dpy, display); - if (ret != VK_SUCCESS) { - COMP_ERROR(w->base.c, "vkAcquireXlibDisplayEXT: %s (%p)", - vk_result_string(ret), (void *)display); - } - return ret; -} diff --git a/src/xrt/compositor/main/comp_window_direct_randr.c b/src/xrt/compositor/main/comp_window_direct_randr.c index c49519dc8..4b558e428 100644 --- a/src/xrt/compositor/main/comp_window_direct_randr.c +++ b/src/xrt/compositor/main/comp_window_direct_randr.c @@ -13,13 +13,9 @@ #include #include -#include - #include "util/u_misc.h" -#include "xrt/xrt_compiler.h" -#include "main/comp_window.h" - +#include "main/comp_window_direct.h" /* * @@ -74,35 +70,14 @@ comp_window_direct_randr_init(struct comp_window *w); static struct comp_window_direct_randr_display * comp_window_direct_randr_current_display(struct comp_window_direct_randr *w); -static VkDisplayModeKHR -comp_window_direct_randr_get_primary_display_mode( - struct comp_window_direct_randr *w, VkDisplayKHR display); - -static VkDisplayPlaneAlphaFlagBitsKHR -choose_alpha_mode(VkDisplayPlaneAlphaFlagsKHR flags); - -static VkResult -comp_window_direct_randr_create_surface(struct comp_window_direct_randr *w, - VkInstance instance, - VkSurfaceKHR *surface, - uint32_t width, - uint32_t height); - static bool comp_window_direct_randr_init_swapchain(struct comp_window *w, uint32_t width, uint32_t height); -static int -comp_window_direct_randr_connect(struct comp_window_direct_randr *w); - -static VkResult -comp_window_direct_randr_acquire_xlib_display( - struct comp_window_direct_randr *w, VkDisplayKHR display); - static VkDisplayKHR -comp_window_direct_randr_get_xlib_randr_output( - struct comp_window_direct_randr *w, RROutput output); +comp_window_direct_randr_get_output(struct comp_window_direct_randr *w, + RROutput output); static void comp_window_direct_randr_get_outputs(struct comp_window_direct_randr *w); @@ -195,7 +170,7 @@ comp_window_direct_randr_init(struct comp_window *w) struct comp_window_direct_randr *w_direct = (struct comp_window_direct_randr *)w; - if (!comp_window_direct_randr_connect(w_direct)) { + if (!comp_window_direct_connect(w, &w_direct->dpy)) { return false; } @@ -255,255 +230,6 @@ comp_window_direct_randr_current_display(struct comp_window_direct_randr *w) return &w->randr_displays[index]; } -static int -choose_best_vk_mode_auto(struct comp_window_direct_randr *w, - VkDisplayModePropertiesKHR *mode_properties, - int mode_count) -{ - if (mode_count == 1) - return 0; - - int best_index = 0; - - // First priority: choose mode that maximizes rendered pixels. - // Second priority: choose mode with highest refresh rate. - for (int i = 1; i < mode_count; i++) { - VkDisplayModeParametersKHR current = - mode_properties[i].parameters; - COMP_DEBUG(w->base.c, "Available Vk direct mode %d: %dx%d@%.2f", - i, current.visibleRegion.width, - current.visibleRegion.height, - (float)current.refreshRate / 1000.); - - - VkDisplayModeParametersKHR best = - mode_properties[best_index].parameters; - - int best_pixels = - best.visibleRegion.width * best.visibleRegion.height; - int pixels = - current.visibleRegion.width * current.visibleRegion.height; - if (pixels > best_pixels) { - best_index = i; - } else if (pixels == best_pixels && - current.refreshRate > best.refreshRate) { - best_index = i; - } - } - VkDisplayModeParametersKHR best = - mode_properties[best_index].parameters; - COMP_DEBUG(w->base.c, "Auto choosing Vk direct mode %d: %dx%d@%.2f", - best_index, best.visibleRegion.width, - best.visibleRegion.width, (float)best.refreshRate / 1000.); - return best_index; -} - -static void -print_modes(struct comp_window_direct_randr *w, - VkDisplayModePropertiesKHR *mode_properties, - int mode_count) -{ - COMP_PRINT_MODE(w->base.c, "Available Vk modes for direct mode"); - for (int i = 0; i < mode_count; i++) { - VkDisplayModePropertiesKHR props = mode_properties[i]; - uint16_t width = props.parameters.visibleRegion.width; - uint16_t height = props.parameters.visibleRegion.height; - float refresh = (float)props.parameters.refreshRate / 1000.; - - COMP_PRINT_MODE(w->base.c, "| %2d | %dx%d@%.2f", i, width, - height, refresh); - } - COMP_PRINT_MODE(w->base.c, "Listed %d modes", mode_count); -} - -static VkDisplayModeKHR -comp_window_direct_randr_get_primary_display_mode( - struct comp_window_direct_randr *w, VkDisplayKHR display) -{ - struct vk_bundle *vk = w->base.swapchain.vk; - uint32_t mode_count; - VkResult ret; - - ret = vk->vkGetDisplayModePropertiesKHR( - w->base.swapchain.vk->physical_device, display, &mode_count, NULL); - if (ret != VK_SUCCESS) { - COMP_ERROR(w->base.c, "vkGetDisplayModePropertiesKHR: %s", - vk_result_string(ret)); - return VK_NULL_HANDLE; - } - - COMP_DEBUG(w->base.c, "Found %d modes", mode_count); - - VkDisplayModePropertiesKHR *mode_properties = - U_TYPED_ARRAY_CALLOC(VkDisplayModePropertiesKHR, mode_count); - ret = vk->vkGetDisplayModePropertiesKHR( - w->base.swapchain.vk->physical_device, display, &mode_count, - mode_properties); - if (ret != VK_SUCCESS) { - COMP_ERROR(w->base.c, "vkGetDisplayModePropertiesKHR: %s", - vk_result_string(ret)); - free(mode_properties); - return VK_NULL_HANDLE; - } - - print_modes(w, mode_properties, mode_count); - - - int chosen_mode = 0; - - int desired_mode = w->base.c->settings.desired_mode; - if (desired_mode + 1 > (int)mode_count) { - COMP_ERROR(w->base.c, - "Requested mode index %d, but max is %d. Falling " - "back to automatic mode selection", - desired_mode, mode_count); - chosen_mode = - choose_best_vk_mode_auto(w, mode_properties, mode_count); - } else if (desired_mode < 0) { - chosen_mode = - choose_best_vk_mode_auto(w, mode_properties, mode_count); - } else { - COMP_DEBUG(w->base.c, "Using manually chosen mode %d", - desired_mode); - chosen_mode = desired_mode; - } - - VkDisplayModePropertiesKHR props = mode_properties[chosen_mode]; - - COMP_DEBUG(w->base.c, "found display mode %dx%d@%.2f", - props.parameters.visibleRegion.width, - props.parameters.visibleRegion.height, - (float)props.parameters.refreshRate / 1000.); - - int64_t new_frame_interval = - 1000. * 1000. * 1000. * 1000. / props.parameters.refreshRate; - - COMP_DEBUG( - w->base.c, - "Updating compositor settings nominal frame interval from %" PRIu64 - " (%f Hz) to %" PRIu64 " (%f Hz)", - w->base.c->settings.nominal_frame_interval_ns, - 1000. * 1000. * 1000. / - (float)w->base.c->settings.nominal_frame_interval_ns, - new_frame_interval, (float)props.parameters.refreshRate / 1000.); - - w->base.c->settings.nominal_frame_interval_ns = new_frame_interval; - - free(mode_properties); - - return props.displayMode; -} - -static VkDisplayPlaneAlphaFlagBitsKHR -choose_alpha_mode(VkDisplayPlaneAlphaFlagsKHR flags) -{ - if (flags & VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR) { - return VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR; - } - if (flags & VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR) { - return VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR; - } - return VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR; -} - -static VkResult -comp_window_direct_randr_create_surface(struct comp_window_direct_randr *w, - VkInstance instance, - VkSurfaceKHR *surface, - uint32_t width, - uint32_t height) -{ - struct comp_window_direct_randr_display *d = - comp_window_direct_randr_current_display(w); - struct vk_bundle *vk = w->base.swapchain.vk; - - VkResult ret = VK_ERROR_INCOMPATIBLE_DISPLAY_KHR; - VkDisplayKHR _display = VK_NULL_HANDLE; - if (d) { - COMP_DEBUG( - w->base.c, "Will use display: %s %dx%d@%.2f", d->name, - d->primary_mode.width, d->primary_mode.height, - (double)d->primary_mode.dot_clock / - (d->primary_mode.htotal * d->primary_mode.vtotal)); - - d->display = comp_window_direct_randr_get_xlib_randr_output( - w, d->output); - if (d->display == VK_NULL_HANDLE) { - return VK_ERROR_INITIALIZATION_FAILED; - } - ret = comp_window_direct_randr_acquire_xlib_display(w, - d->display); - _display = d->display; - } - - if (ret != VK_SUCCESS) { - return ret; - } - - - // Get plane properties - uint32_t plane_property_count; - ret = vk->vkGetPhysicalDeviceDisplayPlanePropertiesKHR( - w->base.swapchain.vk->physical_device, &plane_property_count, NULL); - if (ret != VK_SUCCESS) { - COMP_ERROR(w->base.c, - "vkGetPhysicalDeviceDisplayPlanePropertiesKHR: %s", - vk_result_string(ret)); - return ret; - } - - COMP_DEBUG(w->base.c, "Found %d plane properites.", - plane_property_count); - - VkDisplayPlanePropertiesKHR *plane_properties = U_TYPED_ARRAY_CALLOC( - VkDisplayPlanePropertiesKHR, plane_property_count); - - ret = vk->vkGetPhysicalDeviceDisplayPlanePropertiesKHR( - w->base.swapchain.vk->physical_device, &plane_property_count, - plane_properties); - if (ret != VK_SUCCESS) { - COMP_ERROR(w->base.c, - "vkGetPhysicalDeviceDisplayPlanePropertiesKHR: %s", - vk_result_string(ret)); - free(plane_properties); - return ret; - } - - uint32_t plane_index = 0; - - VkDisplayModeKHR display_mode = - comp_window_direct_randr_get_primary_display_mode(w, _display); - - VkDisplayPlaneCapabilitiesKHR plane_caps; - vk->vkGetDisplayPlaneCapabilitiesKHR( - w->base.swapchain.vk->physical_device, display_mode, plane_index, - &plane_caps); - - VkDisplaySurfaceCreateInfoKHR surface_info = { - .sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR, - .pNext = NULL, - .flags = 0, - .displayMode = display_mode, - .planeIndex = plane_index, - .planeStackIndex = plane_properties[plane_index].currentStackIndex, - .transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, - .globalAlpha = 1.0, - .alphaMode = choose_alpha_mode(plane_caps.supportedAlpha), - .imageExtent = - { - .width = width, - .height = height, - }, - }; - - VkResult result = vk->vkCreateDisplayPlaneSurfaceKHR( - instance, &surface_info, NULL, surface); - - free(plane_properties); - - return result; -} - static bool comp_window_direct_randr_init_swapchain(struct comp_window *w, uint32_t width, @@ -512,9 +238,33 @@ comp_window_direct_randr_init_swapchain(struct comp_window *w, struct comp_window_direct_randr *w_direct = (struct comp_window_direct_randr *)w; - VkResult ret = comp_window_direct_randr_create_surface( - w_direct, w->swapchain.vk->instance, &w->swapchain.surface, width, - height); + struct comp_window_direct_randr_display *d = + comp_window_direct_randr_current_display(w_direct); + + VkResult ret = VK_ERROR_INCOMPATIBLE_DISPLAY_KHR; + VkDisplayKHR _display = VK_NULL_HANDLE; + if (d) { + COMP_DEBUG( + w->c, "Will use display: %s %dx%d@%.2f", d->name, + d->primary_mode.width, d->primary_mode.height, + (double)d->primary_mode.dot_clock / + (d->primary_mode.htotal * d->primary_mode.vtotal)); + + d->display = + comp_window_direct_randr_get_output(w_direct, d->output); + if (d->display == VK_NULL_HANDLE) { + return VK_ERROR_INITIALIZATION_FAILED; + } + ret = comp_window_direct_acquire_xlib_display(w, w_direct->dpy, + d->display); + _display = d->display; + } + + if (ret != VK_SUCCESS) { + return ret; + } + + ret = comp_window_direct_create_surface(w, _display, width, height); if (ret != VK_SUCCESS) { COMP_ERROR(w->c, "Failed to create surface!"); return false; @@ -527,36 +277,9 @@ comp_window_direct_randr_init_swapchain(struct comp_window *w, return true; } -static int -comp_window_direct_randr_connect(struct comp_window_direct_randr *w) -{ - w->dpy = XOpenDisplay(NULL); - if (w->dpy == NULL) { - COMP_ERROR(w->base.c, "Could not open X display."); - return false; - } - return true; -} - -static VkResult -comp_window_direct_randr_acquire_xlib_display( - struct comp_window_direct_randr *w, VkDisplayKHR display) -{ - struct vk_bundle *vk = w->base.swapchain.vk; - VkResult ret; - - ret = vk->vkAcquireXlibDisplayEXT(w->base.swapchain.vk->physical_device, - w->dpy, display); - if (ret != VK_SUCCESS) { - COMP_ERROR(w->base.c, "vkAcquireXlibDisplayEXT: %s (%p)", - vk_result_string(ret), (void *)display); - } - return ret; -} - static VkDisplayKHR -comp_window_direct_randr_get_xlib_randr_output( - struct comp_window_direct_randr *w, RROutput output) +comp_window_direct_randr_get_output(struct comp_window_direct_randr *w, + RROutput output) { struct vk_bundle *vk = w->base.swapchain.vk; VkResult ret; diff --git a/src/xrt/compositor/meson.build b/src/xrt/compositor/meson.build index fdc747a25..fe572b37f 100644 --- a/src/xrt/compositor/meson.build +++ b/src/xrt/compositor/meson.build @@ -33,7 +33,8 @@ if build_xcb endif if build_xcb_xrandr_direct - compositor_srcs += ['main/comp_window_direct_randr.c', + compositor_srcs += ['main/comp_window_direct.c', + 'main/comp_window_direct_randr.c', 'main/comp_window_direct_nvidia.c'] compositor_deps += [xcb_randr, x11_xcb] endif