vk/wsi/x11: Actually block on X so we don't re-use busy buffers
authorJason Ekstrand <jason.ekstrand@intel.com>
Tue, 8 Sep 2015 18:51:47 +0000 (11:51 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 8 Sep 2015 18:51:47 +0000 (11:51 -0700)
src/vulkan/anv_wsi_x11.c

index b412a2bab32a4ec0abfd60ef8b5020cc444d48ec..be4677ae7ed58c93208015e2083763d0948a2a0d 100644 (file)
@@ -50,7 +50,7 @@ x11_get_window_supported(struct anv_wsi_implementation *impl,
 static VkResult
 x11_get_surface_info(struct anv_wsi_implementation *impl,
                      struct anv_device *device,
-                     VkSurfaceDescriptionWindowWSI *window,
+                     VkSurfaceDescriptionWindowWSI *vk_window,
                      VkSurfaceInfoTypeWSI infoType,
                      size_t* pDataSize, void* pData)
 {
@@ -68,11 +68,21 @@ x11_get_surface_info(struct anv_wsi_implementation *impl,
 
       assert(*pDataSize >= sizeof(*props));
 
+      VkPlatformHandleXcbWSI *vk_xcb_handle = vk_window->pPlatformHandle;
+      xcb_connection_t *conn = vk_xcb_handle->connection;
+      xcb_window_t win = (xcb_window_t)(uintptr_t)vk_window->pPlatformWindow;
+
+      xcb_get_geometry_cookie_t cookie = xcb_get_geometry(conn, win);
+      xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(conn, cookie,
+                                                              NULL);
+      VkExtent2D extent = { geom->width, geom->height };
+      free(geom);
+
       props->minImageCount = 2;
       props->maxImageCount = 4;
-      props->currentExtent = (VkExtent2D) { -1, -1 };
-      props->minImageExtent = (VkExtent2D) { 1, 1 };
-      props->maxImageExtent = (VkExtent2D) { INT16_MAX, INT16_MAX };
+      props->currentExtent = extent;
+      props->minImageExtent = extent;
+      props->maxImageExtent = extent;
       props->supportedTransforms = VK_SURFACE_TRANSFORM_NONE_BIT_WSI;
       props->currentTransform = VK_SURFACE_TRANSFORM_NONE_WSI;
       props->maxImageArraySize = 1;
@@ -109,6 +119,14 @@ x11_get_surface_info(struct anv_wsi_implementation *impl,
    }
 }
 
+struct x11_image {
+   struct anv_image *                        image;
+   struct anv_device_memory *                memory;
+   xcb_pixmap_t                              pixmap;
+   xcb_get_geometry_cookie_t                 geom_cookie;
+   bool                                      busy;
+};
+
 struct x11_swap_chain {
    struct anv_swap_chain                        base;
 
@@ -118,11 +136,7 @@ struct x11_swap_chain {
    VkExtent2D                                   extent;
    uint32_t                                     image_count;
    uint32_t                                     next_image;
-   struct {
-      struct anv_image *                        image;
-      struct anv_device_memory *                memory;
-      xcb_pixmap_t                              pixmap;
-   }                                            images[0];
+   struct x11_image                             images[0];
 };
 
 static VkResult
@@ -165,8 +179,21 @@ x11_acquire_next_image(struct anv_swap_chain *anv_chain,
                        uint32_t *image_index)
 {
    struct x11_swap_chain *chain = (struct x11_swap_chain *)anv_chain;
+   struct x11_image *image = &chain->images[chain->next_image];
+
+   if (image->busy) {
+      xcb_get_geometry_reply_t *geom =
+         xcb_get_geometry_reply(chain->conn, image->geom_cookie, NULL);
+      image->busy = false;
+
+      if (geom->width != chain->extent.width ||
+          geom->height != chain->extent.height) {
+         free(geom);
+         return VK_ERROR_OUT_OF_DATE_WSI;
+      }
+      free(geom);
+   }
 
-   anv_finishme("Implement real blocking AcquireNextImage");
    *image_index = chain->next_image;
    chain->next_image = (chain->next_image + 1) % chain->image_count;
    return VK_SUCCESS;
@@ -178,16 +205,14 @@ x11_queue_present(struct anv_swap_chain *anv_chain,
                   uint32_t image_index)
 {
    struct x11_swap_chain *chain = (struct x11_swap_chain *)anv_chain;
+   struct x11_image *image = &chain->images[image_index];
 
-   xcb_void_cookie_t cookie;
-
-   xcb_pixmap_t pixmap = chain->images[image_index].pixmap;
+   assert(image_index < chain->image_count);
 
-   if (pixmap == XCB_NONE)
-      return vk_error(VK_ERROR_INVALID_VALUE);
+   xcb_void_cookie_t cookie;
 
    cookie = xcb_copy_area(chain->conn,
-                          pixmap,
+                          image->pixmap,
                           chain->window,
                           chain->gc,
                           0, 0,
@@ -196,15 +221,33 @@ x11_queue_present(struct anv_swap_chain *anv_chain,
                           chain->extent.height);
    xcb_discard_reply(chain->conn, cookie.sequence);
 
+   image->geom_cookie = xcb_get_geometry(chain->conn, chain->window);
+   image->busy = true;
+
    xcb_flush(chain->conn);
 
    return VK_SUCCESS;
 }
 
 static VkResult
-x11_destroy_swap_chain(struct anv_swap_chain *chain)
+x11_destroy_swap_chain(struct anv_swap_chain *anv_chain)
 {
-   anv_device_free(chain->device, chain);
+   struct x11_swap_chain *chain = (struct x11_swap_chain *)anv_chain;
+   xcb_void_cookie_t cookie;
+
+   for (uint32_t i = 0; i < chain->image_count; i++) {
+      struct x11_image *image = &chain->images[i];
+
+      if (image->busy)
+         xcb_discard_reply(chain->conn, image->geom_cookie.sequence);
+
+      cookie = xcb_free_pixmap(chain->conn, image->pixmap);
+      xcb_discard_reply(chain->conn, cookie.sequence);
+
+      /* TODO: Delete images and free memory */
+   }
+
+   anv_device_free(chain->base.device, chain);
 
    return VK_SUCCESS;
 }
@@ -329,6 +372,7 @@ x11_create_swap_chain(struct anv_wsi_implementation *impl,
       chain->images[i].image = image;
       chain->images[i].memory = memory;
       chain->images[i].pixmap = pixmap;
+      chain->images[i].busy = false;
 
       xcb_discard_reply(chain->conn, cookie.sequence);
    }