vulkan/wsi/wayland: add support for IMMEDIATE
authorSimon Ser <contact@emersion.fr>
Fri, 26 Aug 2022 09:35:13 +0000 (11:35 +0200)
committerMarge Bot <emma+marge@anholt.net>
Thu, 24 Aug 2023 09:38:54 +0000 (09:38 +0000)
Use the tearing-control-unstable-v1 protocol to indicate to the
Wayland compositor that tearing is acceptable.

Signed-off-by: Simon Ser <contact@emersion.fr>
Reviewed-by: Eric Engestrom <eric@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18268>

meson.build
src/egl/wayland/wayland-drm/meson.build
src/vulkan/wsi/meson.build
src/vulkan/wsi/wsi_common_wayland.c

index d35bc53..4b98666 100644 (file)
@@ -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
index e028eb0..442d7ac 100644 (file)
@@ -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
index dcc7747..9d0db01 100644 (file)
@@ -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
index 8d28034..4402f77 100644 (file)
@@ -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 <util/compiler.h>
 #include <util/hash_table.h>
@@ -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;