From 5ceba97c2e18c848beb23016a7b4c190f0f5178b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 26 Aug 2022 11:35:13 +0200 Subject: [PATCH] vulkan/wsi/wayland: add support for IMMEDIATE Use the tearing-control-unstable-v1 protocol to indicate to the Wayland compositor that tearing is acceptable. Signed-off-by: Simon Ser Reviewed-by: Eric Engestrom Part-of: --- meson.build | 2 +- src/egl/wayland/wayland-drm/meson.build | 1 + src/vulkan/wsi/meson.build | 1 + src/vulkan/wsi/wsi_common_wayland.c | 88 ++++++++++++++++++++----- 4 files changed, 76 insertions(+), 16 deletions(-) diff --git a/meson.build b/meson.build index d35bc534f6e..4b98666b914 100644 --- a/meson.build +++ b/meson.build @@ -1931,7 +1931,7 @@ if with_platform_wayland else wl_scanner_arg = 'code' endif - dep_wl_protocols = dependency('wayland-protocols', version : '>= 1.24') + dep_wl_protocols = dependency('wayland-protocols', version : '>= 1.30') dep_wayland_client = dependency('wayland-client', version : '>=1.18') dep_wayland_server = dependency('wayland-server', version : '>=1.18') if with_egl diff --git a/src/egl/wayland/wayland-drm/meson.build b/src/egl/wayland/wayland-drm/meson.build index e028eb034df..442d7acd9b4 100644 --- a/src/egl/wayland/wayland-drm/meson.build +++ b/src/egl/wayland/wayland-drm/meson.build @@ -61,6 +61,7 @@ wp_dir = dep_wl_protocols.get_variable(pkgconfig : 'pkgdatadir', internal : 'pkg wp_protos = { 'linux-dmabuf-unstable-v1': 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml', 'presentation-time': 'stable/presentation-time/presentation-time.xml', + 'tearing-control-v1': 'staging/tearing-control/tearing-control-v1.xml', } wp_files = {} foreach name, xml : wp_protos diff --git a/src/vulkan/wsi/meson.build b/src/vulkan/wsi/meson.build index dcc7747fcac..9d0db011767 100644 --- a/src/vulkan/wsi/meson.build +++ b/src/vulkan/wsi/meson.build @@ -33,6 +33,7 @@ if with_platform_wayland files_vulkan_wsi += files('wsi_common_wayland.c') files_vulkan_wsi += wp_files['linux-dmabuf-unstable-v1'] files_vulkan_wsi += wp_files['presentation-time'] + files_vulkan_wsi += wp_files['tearing-control-v1'] endif if with_platform_windows diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c index 8d280340091..4402f77d55f 100644 --- a/src/vulkan/wsi/wsi_common_wayland.c +++ b/src/vulkan/wsi/wsi_common_wayland.c @@ -43,6 +43,7 @@ #include "wsi_common_private.h" #include "linux-dmabuf-unstable-v1-client-protocol.h" #include "presentation-time-client-protocol.h" +#include "tearing-control-v1-client-protocol.h" #include #include @@ -100,6 +101,7 @@ struct wsi_wl_display { struct wl_shm *wl_shm; struct zwp_linux_dmabuf_v1 *wl_dmabuf; struct zwp_linux_dmabuf_feedback_v1 *wl_dmabuf_feedback; + struct wp_tearing_control_manager_v1 *tearing_control_manager; struct dmabuf_feedback_format_table format_table; @@ -156,6 +158,7 @@ struct wsi_wl_swapchain { struct wsi_swapchain base; struct wsi_wl_surface *wsi_wl_surface; + struct wp_tearing_control_v1 *tearing_control; struct wl_callback *frame; @@ -795,6 +798,9 @@ registry_handle_global(void *data, struct wl_registry *registry, if (strcmp(interface, wp_presentation_interface.name) == 0) { display->wp_presentation_notwrapped = wl_registry_bind(registry, name, &wp_presentation_interface, 1); + } else if (strcmp(interface, wp_tearing_control_v1_interface.name) == 0) { + display->tearing_control_manager = + wl_registry_bind(registry, name, &wp_tearing_control_manager_v1_interface, 1); } } @@ -821,6 +827,8 @@ wsi_wl_display_finish(struct wsi_wl_display *display) zwp_linux_dmabuf_v1_destroy(display->wl_dmabuf); if (display->wp_presentation_notwrapped) wp_presentation_destroy(display->wp_presentation_notwrapped); + if (display->tearing_control_manager) + wp_tearing_control_manager_v1_destroy(display->tearing_control_manager); if (display->wl_display_wrapper) wl_proxy_wrapper_destroy(display->wl_display_wrapper); if (display->queue) @@ -1008,11 +1016,6 @@ wsi_wl_surface_get_support(VkIcdSurfaceBase *surface, return VK_SUCCESS; } -static const VkPresentModeKHR present_modes[] = { - VK_PRESENT_MODE_MAILBOX_KHR, - VK_PRESENT_MODE_FIFO_KHR, -}; - static uint32_t wsi_wl_surface_get_min_image_count(const VkSurfacePresentModeEXT *present_mode) { @@ -1139,15 +1142,30 @@ wsi_wl_surface_get_capabilities2(VkIcdSurfaceBase *surface, vk_outarray_append_typed(VkPresentModeKHR, &modes, mode) { *mode = present_mode->presentMode; } - for (unsigned i = 0; i < ARRAY_SIZE(present_modes); i++) { - if (present_modes[i] != present_mode->presentMode) { - vk_outarray_append_typed(VkPresentModeKHR, &modes, mode) { - *mode = present_modes[i]; - } + switch (present_mode->presentMode) { + case VK_PRESENT_MODE_MAILBOX_KHR: + vk_outarray_append_typed(VkPresentModeKHR, &modes, mode) { + *mode = VK_PRESENT_MODE_FIFO_KHR; } + break; + case VK_PRESENT_MODE_FIFO_KHR: + vk_outarray_append_typed(VkPresentModeKHR, &modes, mode) { + *mode = VK_PRESENT_MODE_MAILBOX_KHR; + } + break; + default: + break; } } else { - compat->presentModeCount = ARRAY_SIZE(present_modes); + switch (present_mode->presentMode) { + case VK_PRESENT_MODE_MAILBOX_KHR: + case VK_PRESENT_MODE_FIFO_KHR: + compat->presentModeCount = 2; + break; + default: + compat->presentModeCount = 1; + break; + } } break; } @@ -1239,20 +1257,42 @@ wsi_wl_surface_get_formats2(VkIcdSurfaceBase *icd_surface, } static VkResult -wsi_wl_surface_get_present_modes(VkIcdSurfaceBase *surface, +wsi_wl_surface_get_present_modes(VkIcdSurfaceBase *icd_surface, struct wsi_device *wsi_device, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes) { + VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)icd_surface; + struct wsi_wayland *wsi = + (struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND]; + + struct wsi_wl_display display; + if (wsi_wl_display_init(wsi, &display, surface->display, true, + wsi_device->sw)) + return VK_ERROR_SURFACE_LOST_KHR; + + VkPresentModeKHR present_modes[3]; + uint32_t present_modes_count = 0; + + /* The following two modes are always supported */ + present_modes[present_modes_count++] = VK_PRESENT_MODE_MAILBOX_KHR; + present_modes[present_modes_count++] = VK_PRESENT_MODE_FIFO_KHR; + + if (display.tearing_control_manager) + present_modes[present_modes_count++] = VK_PRESENT_MODE_IMMEDIATE_KHR; + + assert(present_modes_count <= ARRAY_SIZE(present_modes)); + wsi_wl_display_finish(&display); + if (pPresentModes == NULL) { - *pPresentModeCount = ARRAY_SIZE(present_modes); + *pPresentModeCount = present_modes_count; return VK_SUCCESS; } - *pPresentModeCount = MIN2(*pPresentModeCount, ARRAY_SIZE(present_modes)); + *pPresentModeCount = MIN2(*pPresentModeCount, present_modes_count); typed_memcpy(pPresentModes, present_modes, *pPresentModeCount); - if (*pPresentModeCount < ARRAY_SIZE(present_modes)) + if (*pPresentModeCount < present_modes_count) return VK_INCOMPLETE; else return VK_SUCCESS; @@ -2145,6 +2185,8 @@ wsi_wl_swapchain_chain_free(struct wsi_wl_swapchain *chain, { if (chain->frame) wl_callback_destroy(chain->frame); + if (chain->tearing_control) + wp_tearing_control_v1_destroy(chain->tearing_control); if (chain->wsi_wl_surface) chain->wsi_wl_surface->chain = NULL; @@ -2216,6 +2258,10 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, if (pCreateInfo->oldSwapchain) { VK_FROM_HANDLE(wsi_wl_swapchain, old_chain, pCreateInfo->oldSwapchain); old_chain->wsi_wl_surface = NULL; + if (old_chain->tearing_control) { + wp_tearing_control_v1_destroy(old_chain->tearing_control); + old_chain->tearing_control = NULL; + } } /* Take ownership of the wsi_wl_surface */ @@ -2226,6 +2272,18 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, if (result != VK_SUCCESS) goto fail; + if (chain->base.present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR) { + chain->tearing_control = + wp_tearing_control_manager_v1_get_tearing_control(wsi_wl_surface->display->tearing_control_manager, + wsi_wl_surface->surface); + if (!chain->tearing_control) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto fail; + } + wp_tearing_control_v1_set_presentation_hint(chain->tearing_control, + WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC); + } + enum wsi_wl_buffer_type buffer_type; struct wsi_base_image_params *image_params = NULL; struct wsi_cpu_image_params cpu_image_params;