vulkan/wsi: Move get_images into common code
[mesa.git] / src / vulkan / wsi / wsi_common_x11.c
index c399aae5afdc3d91f8c3c89bb5df8f22ac4721f1..8860d8edb6e883266ec8dd8a6b352f85ffd08acf 100644 (file)
@@ -38,7 +38,8 @@
 #include <xf86drm.h>
 #include "util/hash_table.h"
 
-#include "wsi_common.h"
+#include "vk_util.h"
+#include "wsi_common_private.h"
 #include "wsi_common_x11.h"
 #include "wsi_common_queue.h"
 
@@ -235,9 +236,9 @@ wsi_x11_get_connection(struct wsi_device *wsi_dev,
    return entry->data;
 }
 
-static const VkSurfaceFormatKHR formats[] = {
-   { .format = VK_FORMAT_B8G8R8A8_SRGB, },
-   { .format = VK_FORMAT_B8G8R8A8_UNORM, },
+static const VkFormat formats[] = {
+   VK_FORMAT_B8G8R8A8_SRGB,
+   VK_FORMAT_B8G8R8A8_UNORM,
 };
 
 static const VkPresentModeKHR present_modes[] = {
@@ -510,22 +511,52 @@ x11_surface_get_capabilities(VkIcdSurfaceBase *icd_surface,
    return VK_SUCCESS;
 }
 
+static VkResult
+x11_surface_get_capabilities2(VkIcdSurfaceBase *icd_surface,
+                              const void *info_next,
+                              VkSurfaceCapabilities2KHR *caps)
+{
+   assert(caps->sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR);
+
+   return x11_surface_get_capabilities(icd_surface, &caps->surfaceCapabilities);
+}
+
 static VkResult
 x11_surface_get_formats(VkIcdSurfaceBase *surface,
                         struct wsi_device *wsi_device,
                         uint32_t *pSurfaceFormatCount,
                         VkSurfaceFormatKHR *pSurfaceFormats)
 {
-   if (pSurfaceFormats == NULL) {
-      *pSurfaceFormatCount = ARRAY_SIZE(formats);
-      return VK_SUCCESS;
+   VK_OUTARRAY_MAKE(out, pSurfaceFormats, pSurfaceFormatCount);
+
+   for (unsigned i = 0; i < ARRAY_SIZE(formats); i++) {
+      vk_outarray_append(&out, f) {
+         f->format = formats[i];
+         f->colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+      }
    }
 
-   *pSurfaceFormatCount = MIN2(*pSurfaceFormatCount, ARRAY_SIZE(formats));
-   typed_memcpy(pSurfaceFormats, formats, *pSurfaceFormatCount);
+   return vk_outarray_status(&out);
+}
+
+static VkResult
+x11_surface_get_formats2(VkIcdSurfaceBase *surface,
+                        struct wsi_device *wsi_device,
+                        const void *info_next,
+                        uint32_t *pSurfaceFormatCount,
+                        VkSurfaceFormat2KHR *pSurfaceFormats)
+{
+   VK_OUTARRAY_MAKE(out, pSurfaceFormats, pSurfaceFormatCount);
 
-   return *pSurfaceFormatCount < ARRAY_SIZE(formats) ?
-      VK_INCOMPLETE : VK_SUCCESS;
+   for (unsigned i = 0; i < ARRAY_SIZE(formats); i++) {
+      vk_outarray_append(&out, f) {
+         assert(f->sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR);
+         f->surfaceFormat.format = formats[i];
+         f->surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+      }
+   }
+
+   return vk_outarray_status(&out);
 }
 
 static VkResult
@@ -584,10 +615,7 @@ VkResult wsi_create_xlib_surface(const VkAllocationCallbacks *pAllocator,
 }
 
 struct x11_image {
-   VkImage image;
-   VkImage linear_image; // for prime
-   VkDeviceMemory memory;
-   VkDeviceMemory linear_memory; // for prime
+   struct wsi_image                          base;
    xcb_pixmap_t                              pixmap;
    bool                                      busy;
    struct xshmfence *                        shm_fence;
@@ -597,6 +625,8 @@ struct x11_image {
 struct x11_swapchain {
    struct wsi_swapchain                        base;
 
+   bool                                         use_prime_blit;
+
    xcb_connection_t *                           conn;
    xcb_window_t                                 window;
    xcb_gc_t                                     gc;
@@ -618,39 +648,11 @@ struct x11_swapchain {
    struct x11_image                             images[0];
 };
 
-static VkResult
-x11_get_images(struct wsi_swapchain *anv_chain,
-               uint32_t* pCount, VkImage *pSwapchainImages)
-{
-   struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain;
-   uint32_t ret_count;
-   VkResult result;
-
-   if (pSwapchainImages == NULL) {
-      *pCount = chain->base.image_count;
-      return VK_SUCCESS;
-   }
-
-   result = VK_SUCCESS;
-   ret_count = chain->base.image_count;
-   if (chain->base.image_count > *pCount) {
-     ret_count = *pCount;
-     result = VK_INCOMPLETE;
-   }
-
-   for (uint32_t i = 0; i < ret_count; i++)
-      pSwapchainImages[i] = chain->images[i].image;
-
-   return result;
-}
-
-static void
-x11_get_image_and_linear(struct wsi_swapchain *drv_chain,
-                         int imageIndex, VkImage *image, VkImage *linear_image)
+static struct wsi_image *
+x11_get_wsi_image(struct wsi_swapchain *wsi_chain, uint32_t image_index)
 {
-   struct x11_swapchain *chain = (struct x11_swapchain *)drv_chain;
-   *image = chain->images[imageIndex].image;
-   *linear_image = chain->images[imageIndex].linear_image;
+   struct x11_swapchain *chain = (struct x11_swapchain *)wsi_chain;
+   return &chain->images[image_index].base;
 }
 
 static VkResult
@@ -860,10 +862,24 @@ x11_acquire_next_image(struct wsi_swapchain *anv_chain,
 
 static VkResult
 x11_queue_present(struct wsi_swapchain *anv_chain,
+                  VkQueue queue,
+                  uint32_t waitSemaphoreCount,
+                  const VkSemaphore *pWaitSemaphores,
                   uint32_t image_index,
                   const VkPresentRegionKHR *damage)
 {
    struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain;
+   VkResult result;
+
+   if (chain->use_prime_blit) {
+      result = wsi_prime_image_blit_to_linear(&chain->base,
+                                              &chain->images[image_index].base,
+                                              queue,
+                                              waitSemaphoreCount,
+                                              pWaitSemaphores);
+      if (result != VK_SUCCESS)
+         return result;
+   }
 
    if (chain->threaded) {
       wsi_queue_push(&chain->present_queue, image_index);
@@ -908,6 +924,7 @@ x11_manage_fifo_queues(void *state)
             goto fail;
 
          result = x11_handle_dri3_present_event(chain, (void *)event);
+         free(event);
          if (result != VK_SUCCESS)
             goto fail;
       }
@@ -928,44 +945,15 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
 {
    xcb_void_cookie_t cookie;
    VkResult result;
-   uint32_t row_pitch;
-   uint32_t offset;
    uint32_t bpp = 32;
-   int fd;
-   uint32_t size;
-
-   result = chain->base.image_fns->create_wsi_image(device_h,
-                                                    pCreateInfo,
-                                                    pAllocator,
-                                                    chain->base.needs_linear_copy,
-                                                    false,
-                                                    &image->image,
-                                                    &image->memory,
-                                                    &size,
-                                                    &offset,
-                                                    &row_pitch,
-                                                    &fd);
-   if (result != VK_SUCCESS)
-      return result;
 
-   if (chain->base.needs_linear_copy) {
-      result = chain->base.image_fns->create_wsi_image(device_h,
-                                                       pCreateInfo,
-                                                       pAllocator,
-                                                       chain->base.needs_linear_copy,
-                                                       true,
-                                                       &image->linear_image,
-                                                       &image->linear_memory,
-                                                       &size,
-                                                       &offset,
-                                                       &row_pitch,
-                                                       &fd);
-      if (result != VK_SUCCESS) {
-         chain->base.image_fns->free_wsi_image(device_h, pAllocator,
-                                               image->image, image->memory);
-         return result;
-      }
+   if (chain->use_prime_blit) {
+      result = wsi_create_prime_image(&chain->base, pCreateInfo, &image->base);
+   } else {
+      result = wsi_create_native_image(&chain->base, pCreateInfo, &image->base);
    }
+   if (result != VK_SUCCESS)
+      return result;
 
    image->pixmap = xcb_generate_id(chain->conn);
 
@@ -973,12 +961,14 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
       xcb_dri3_pixmap_from_buffer_checked(chain->conn,
                                           image->pixmap,
                                           chain->window,
-                                          size,
+                                          image->base.size,
                                           pCreateInfo->imageExtent.width,
                                           pCreateInfo->imageExtent.height,
-                                          row_pitch,
-                                          chain->depth, bpp, fd);
+                                          image->base.row_pitch,
+                                          chain->depth, bpp,
+                                          image->base.fd);
    xcb_discard_reply(chain->conn, cookie.sequence);
+   image->base.fd = -1; /* XCB has now taken ownership of the FD */
 
    int fence_fd = xshmfence_alloc_shm();
    if (fence_fd < 0)
@@ -1007,12 +997,7 @@ fail_pixmap:
    cookie = xcb_free_pixmap(chain->conn, image->pixmap);
    xcb_discard_reply(chain->conn, cookie.sequence);
 
-   if (chain->base.needs_linear_copy) {
-      chain->base.image_fns->free_wsi_image(device_h, pAllocator,
-                                            image->linear_image, image->linear_memory);
-   }
-   chain->base.image_fns->free_wsi_image(device_h, pAllocator,
-                                         image->image, image->memory);
+   wsi_destroy_image(&chain->base, &image->base);
 
    return result;
 }
@@ -1031,12 +1016,7 @@ x11_image_finish(struct x11_swapchain *chain,
    cookie = xcb_free_pixmap(chain->conn, image->pixmap);
    xcb_discard_reply(chain->conn, cookie.sequence);
 
-   if (chain->base.needs_linear_copy) {
-      chain->base.image_fns->free_wsi_image(chain->base.device, pAllocator,
-                                            image->linear_image, image->linear_memory);
-   }
-   chain->base.image_fns->free_wsi_image(chain->base.device, pAllocator,
-                                        image->image, image->memory);
+   wsi_destroy_image(&chain->base, &image->base);
 }
 
 static VkResult
@@ -1064,6 +1044,8 @@ x11_swapchain_destroy(struct wsi_swapchain *anv_chain,
                                              XCB_PRESENT_EVENT_MASK_NO_EVENT);
    xcb_discard_reply(chain->conn, cookie.sequence);
 
+   wsi_swapchain_finish(&chain->base);
+
    vk_free(pAllocator, chain);
 
    return VK_SUCCESS;
@@ -1076,7 +1058,6 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
                              int local_fd,
                              const VkSwapchainCreateInfoKHR *pCreateInfo,
                              const VkAllocationCallbacks* pAllocator,
-                             const struct wsi_image_fns *image_fns,
                              struct wsi_swapchain **swapchain_out)
 {
    struct x11_swapchain *chain;
@@ -1087,43 +1068,47 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
 
    const unsigned num_images = pCreateInfo->minImageCount;
 
-   size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]);
-   chain = vk_alloc(pAllocator, size, 8,
-                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-   if (chain == NULL)
-      return VK_ERROR_OUT_OF_HOST_MEMORY;
-
+   /* Check for whether or not we have a window up-front */
    xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
    xcb_window_t window = x11_surface_get_window(icd_surface);
    xcb_get_geometry_reply_t *geometry =
       xcb_get_geometry_reply(conn, xcb_get_geometry(conn, window), NULL);
-
    if (geometry == NULL)
       return VK_ERROR_SURFACE_LOST_KHR;
+   const uint32_t bit_depth = geometry->depth;
+   free(geometry);
+
+   size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]);
+   chain = vk_alloc(pAllocator, size, 8,
+                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (chain == NULL)
+      return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+   result = wsi_swapchain_init(wsi_device, &chain->base, device,
+                               pCreateInfo, pAllocator);
+   if (result != VK_SUCCESS)
+      goto fail_alloc;
 
-   chain->base.device = device;
    chain->base.destroy = x11_swapchain_destroy;
-   chain->base.get_images = x11_get_images;
-   chain->base.get_image_and_linear = x11_get_image_and_linear;
+   chain->base.get_wsi_image = x11_get_wsi_image;
    chain->base.acquire_next_image = x11_acquire_next_image;
    chain->base.queue_present = x11_queue_present;
-   chain->base.image_fns = image_fns;
    chain->base.present_mode = pCreateInfo->presentMode;
    chain->base.image_count = num_images;
    chain->conn = conn;
    chain->window = window;
-   chain->depth = geometry->depth;
+   chain->depth = bit_depth;
    chain->extent = pCreateInfo->imageExtent;
    chain->send_sbc = 0;
    chain->last_present_msc = 0;
    chain->threaded = false;
    chain->status = VK_SUCCESS;
 
-   free(geometry);
 
-   chain->base.needs_linear_copy = false;
-   if (!wsi_x11_check_dri3_compatible(conn, local_fd))
-       chain->base.needs_linear_copy = true;
+   chain->use_prime_blit = false;
+   if (!wsi_x11_check_dri3_compatible(conn, local_fd)) {
+       chain->use_prime_blit = true;
+   }
 
    chain->event_id = xcb_generate_id(chain->conn);
    xcb_present_select_input(chain->conn, chain->event_id, chain->window,
@@ -1202,6 +1187,9 @@ fail_init_images:
 fail_register:
    xcb_unregister_for_special_event(chain->conn, chain->special_event);
 
+   wsi_swapchain_finish(&chain->base);
+
+fail_alloc:
    vk_free(pAllocator, chain);
 
    return result;
@@ -1242,7 +1230,9 @@ wsi_x11_init_wsi(struct wsi_device *wsi_device,
 
    wsi->base.get_support = x11_surface_get_support;
    wsi->base.get_capabilities = x11_surface_get_capabilities;
+   wsi->base.get_capabilities2 = x11_surface_get_capabilities2;
    wsi->base.get_formats = x11_surface_get_formats;
+   wsi->base.get_formats2 = x11_surface_get_formats2;
    wsi->base.get_present_modes = x11_surface_get_present_modes;
    wsi->base.create_swapchain = x11_surface_create_swapchain;