wsi/x11: Implement EXT_swapchain_maintenance1.
authorHans-Kristian Arntzen <post@arntzen-software.no>
Thu, 8 Dec 2022 16:08:21 +0000 (17:08 +0100)
committerMarge Bot <emma+marge@anholt.net>
Fri, 3 Mar 2023 03:59:13 +0000 (03:59 +0000)
Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
Reviewed-by: Joshua Ashton <joshua@froggi.es>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20235>

src/vulkan/wsi/wsi_common_x11.c

index 3c620be..1b3d5ae 100644 (file)
@@ -658,9 +658,15 @@ x11_get_min_image_count(const struct wsi_device *wsi_device, bool is_xwayland)
    return is_xwayland && wsi_device->x11.extra_xwayland_image ? 4 : 3;
 }
 
+static unsigned
+x11_get_min_image_count_for_present_mode(struct wsi_device *wsi_device,
+                                         struct wsi_x11_connection *wsi_conn,
+                                         VkPresentModeKHR present_mode);
+
 static VkResult
 x11_surface_get_capabilities(VkIcdSurfaceBase *icd_surface,
                              struct wsi_device *wsi_device,
+                             const VkSurfacePresentModeEXT *present_mode,
                              VkSurfaceCapabilitiesKHR *caps)
 {
    xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
@@ -703,7 +709,12 @@ x11_surface_get_capabilities(VkIcdSurfaceBase *icd_surface,
                                       VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
    }
 
-   caps->minImageCount = x11_get_min_image_count(wsi_device, wsi_conn->is_xwayland);
+   if (present_mode) {
+      caps->minImageCount = x11_get_min_image_count_for_present_mode(wsi_device, wsi_conn, present_mode->presentMode);
+   } else {
+      caps->minImageCount = x11_get_min_image_count(wsi_device, wsi_conn->is_xwayland);
+   }
+
    /* There is no real maximum */
    caps->maxImageCount = 0;
 
@@ -729,8 +740,10 @@ x11_surface_get_capabilities2(VkIcdSurfaceBase *icd_surface,
 {
    assert(caps->sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR);
 
+   const VkSurfacePresentModeEXT *present_mode = vk_find_struct_const(info_next, SURFACE_PRESENT_MODE_EXT);
+
    VkResult result =
-      x11_surface_get_capabilities(icd_surface, wsi_device,
+      x11_surface_get_capabilities(icd_surface, wsi_device, present_mode,
                                    &caps->surfaceCapabilities);
 
    if (result != VK_SUCCESS)
@@ -744,6 +757,33 @@ x11_surface_get_capabilities2(VkIcdSurfaceBase *icd_surface,
          break;
       }
 
+      case VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT: {
+         /* Unsupported. */
+         VkSurfacePresentScalingCapabilitiesEXT *scaling = (void *)ext;
+         scaling->supportedPresentScaling = 0;
+         scaling->supportedPresentGravityX = 0;
+         scaling->supportedPresentGravityY = 0;
+         scaling->minScaledImageExtent = caps->surfaceCapabilities.minImageExtent;
+         scaling->maxScaledImageExtent = caps->surfaceCapabilities.maxImageExtent;
+         break;
+      }
+
+      case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT: {
+         /* To be able to toggle between FIFO and non-FIFO, we would need a rewrite to always use FIFO thread
+          * mechanism. For now, only return the input, making this effectively unsupported. */
+         assert(present_mode);
+         VkSurfacePresentModeCompatibilityEXT *compat = (void *)ext;
+         if (compat->pPresentModes) {
+            if (compat->presentModeCount) {
+               compat->pPresentModes[0] = present_mode->presentMode;
+               compat->presentModeCount = 1;
+            }
+         } else {
+            compat->presentModeCount = 1;
+         }
+         break;
+      }
+
       default:
          /* Ignored */
          break;
@@ -1645,6 +1685,34 @@ x11_present_to_x11(struct x11_swapchain *chain, uint32_t image_index,
    return result;
 }
 
+static VkResult
+x11_release_images(struct wsi_swapchain *wsi_chain,
+                   uint32_t count, const uint32_t *indices)
+{
+   struct x11_swapchain *chain = (struct x11_swapchain *)wsi_chain;
+   if (chain->status == VK_ERROR_SURFACE_LOST_KHR)
+      return chain->status;
+
+   for (uint32_t i = 0; i < count; i++) {
+      uint32_t index = indices[i];
+      assert(index < chain->base.image_count);
+
+      if (chain->has_acquire_queue) {
+         wsi_queue_push(&chain->acquire_queue, index);
+      } else {
+         assert(chain->images[index].busy);
+         chain->images[index].busy = false;
+      }
+   }
+
+   if (!chain->has_acquire_queue) {
+      assert(chain->present_poll_acquire_count >= count);
+      chain->present_poll_acquire_count -= count;
+   }
+
+   return VK_SUCCESS;
+}
+
 /**
  * Acquire a ready-to-use image from the swapchain.
  *
@@ -2441,6 +2509,17 @@ static VkResult x11_wait_for_present(struct wsi_swapchain *wsi_chain,
    return result;
 }
 
+static unsigned
+x11_get_min_image_count_for_present_mode(struct wsi_device *wsi_device,
+                                         struct wsi_x11_connection *wsi_conn,
+                                         VkPresentModeKHR present_mode)
+{
+   if (x11_needs_wait_for_fences(wsi_device, wsi_conn, present_mode))
+      return 5;
+   else
+      return x11_get_min_image_count(wsi_device, wsi_conn->is_xwayland);
+}
+
 /**
  * Create the swapchain.
  *
@@ -2569,6 +2648,7 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
    chain->base.acquire_next_image = x11_acquire_next_image;
    chain->base.queue_present = x11_queue_present;
    chain->base.wait_for_present = x11_wait_for_present;
+   chain->base.release_images = x11_release_images;
    chain->base.present_mode = present_mode;
    chain->base.image_count = num_images;
    chain->conn = conn;