1971523410fd2235e13c617b6a1569f70486258d7Dave Airlie/*
2971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * Copyright © 2015 Intel Corporation
3971523410fd2235e13c617b6a1569f70486258d7Dave Airlie *
4971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * Permission is hereby granted, free of charge, to any person obtaining a
5971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * copy of this software and associated documentation files (the "Software"),
6971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * to deal in the Software without restriction, including without limitation
7971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * and/or sell copies of the Software, and to permit persons to whom the
9971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * Software is furnished to do so, subject to the following conditions:
10971523410fd2235e13c617b6a1569f70486258d7Dave Airlie *
11971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * The above copyright notice and this permission notice (including the next
12971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * paragraph) shall be included in all copies or substantial portions of the
13971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * Software.
14971523410fd2235e13c617b6a1569f70486258d7Dave Airlie *
15971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21971523410fd2235e13c617b6a1569f70486258d7Dave Airlie * IN THE SOFTWARE.
22971523410fd2235e13c617b6a1569f70486258d7Dave Airlie */
23971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
24971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#include <X11/Xlib-xcb.h>
25971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#include <X11/xshmfence.h>
26971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#include <xcb/xcb.h>
27971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#include <xcb/dri3.h>
28971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#include <xcb/present.h>
29971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
303f7ef2488938d31b5ead043891fadc3cee4c6f05Dave Airlie#include "util/macros.h"
31971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#include <stdlib.h>
32971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#include <stdio.h>
33971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#include <unistd.h>
34971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#include <errno.h>
35971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#include <string.h>
363f7ef2488938d31b5ead043891fadc3cee4c6f05Dave Airlie
37787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie#include <poll.h>
383f7ef2488938d31b5ead043891fadc3cee4c6f05Dave Airlie#include "util/hash_table.h"
393f7ef2488938d31b5ead043891fadc3cee4c6f05Dave Airlie
40971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#include "wsi_common.h"
41971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#include "wsi_common_x11.h"
42e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand#include "wsi_common_queue.h"
43971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
44971523410fd2235e13c617b6a1569f70486258d7Dave Airlie#define typed_memcpy(dest, src, count) ({ \
45a77426fd922259bc37b762fa22b42b91d3ce494aEdward O'Callaghan   STATIC_ASSERT(sizeof(*src) == sizeof(*dest)); \
46971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   memcpy((dest), (src), (count) * sizeof(*(src))); \
47971523410fd2235e13c617b6a1569f70486258d7Dave Airlie})
48971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
49971523410fd2235e13c617b6a1569f70486258d7Dave Airliestruct wsi_x11_connection {
50971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   bool has_dri3;
51971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   bool has_present;
52d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   bool is_proprietary_x11;
53971523410fd2235e13c617b6a1569f70486258d7Dave Airlie};
54971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
55971523410fd2235e13c617b6a1569f70486258d7Dave Airliestruct wsi_x11 {
56ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airlie   struct wsi_interface base;
57971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
58971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   pthread_mutex_t                              mutex;
59971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   /* Hash table of xcb_connection -> wsi_x11_connection mappings */
60971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct hash_table *connections;
61971523410fd2235e13c617b6a1569f70486258d7Dave Airlie};
62971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
63971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic struct wsi_x11_connection *
64971523410fd2235e13c617b6a1569f70486258d7Dave Airliewsi_x11_connection_create(const VkAllocationCallbacks *alloc,
65971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                          xcb_connection_t *conn)
66971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
67d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   xcb_query_extension_cookie_t dri3_cookie, pres_cookie, amd_cookie, nv_cookie;
68d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   xcb_query_extension_reply_t *dri3_reply, *pres_reply, *amd_reply, *nv_reply;
69971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
70971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct wsi_x11_connection *wsi_conn =
71971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      vk_alloc(alloc, sizeof(*wsi_conn), 8,
72971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
73971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (!wsi_conn)
74971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return NULL;
75971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
76971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   dri3_cookie = xcb_query_extension(conn, 4, "DRI3");
77971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   pres_cookie = xcb_query_extension(conn, 7, "PRESENT");
78971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
79d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   /* We try to be nice to users and emit a warning if they try to use a
80d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay    * Vulkan application on a system without DRI3 enabled.  However, this ends
81d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay    * up spewing the warning when a user has, for example, both Intel
82d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay    * integrated graphics and a discrete card with proprietary drivers and are
83d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay    * running on the discrete card with the proprietary DDX.  In this case, we
84d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay    * really don't want to print the warning because it just confuses users.
85d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay    * As a heuristic to detect this case, we check for a couple of proprietary
86d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay    * X11 extensions.
87d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay    */
88d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   amd_cookie = xcb_query_extension(conn, 11, "ATIFGLRXDRI");
89d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   nv_cookie = xcb_query_extension(conn, 10, "NV-CONTROL");
90d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay
91971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   dri3_reply = xcb_query_extension_reply(conn, dri3_cookie, NULL);
92971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   pres_reply = xcb_query_extension_reply(conn, pres_cookie, NULL);
93d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   amd_reply = xcb_query_extension_reply(conn, amd_cookie, NULL);
94d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   nv_reply = xcb_query_extension_reply(conn, nv_cookie, NULL);
95d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   if (!dri3_reply || !pres_reply) {
96971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      free(dri3_reply);
97971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      free(pres_reply);
98d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay      free(amd_reply);
99d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay      free(nv_reply);
100971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      vk_free(alloc, wsi_conn);
101971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return NULL;
102971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
103971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
104971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi_conn->has_dri3 = dri3_reply->present != 0;
105971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi_conn->has_present = pres_reply->present != 0;
106d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   wsi_conn->is_proprietary_x11 = false;
107d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   if (amd_reply && amd_reply->present)
108d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay      wsi_conn->is_proprietary_x11 = true;
109d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   if (nv_reply && nv_reply->present)
110d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay      wsi_conn->is_proprietary_x11 = true;
111971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
112971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   free(dri3_reply);
113971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   free(pres_reply);
114d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   free(amd_reply);
115d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   free(nv_reply);
116971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
117971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return wsi_conn;
118971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
119971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
120971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic void
121971523410fd2235e13c617b6a1569f70486258d7Dave Airliewsi_x11_connection_destroy(const VkAllocationCallbacks *alloc,
122971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                           struct wsi_x11_connection *conn)
123971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
124971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   vk_free(alloc, conn);
125971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
126971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
127d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshaystatic bool
128d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshaywsi_x11_check_for_dri3(struct wsi_x11_connection *wsi_conn)
129d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay{
130d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay  if (wsi_conn->has_dri3)
131d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay    return true;
132d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay  if (!wsi_conn->is_proprietary_x11) {
133d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay    fprintf(stderr, "vulkan: No DRI3 support detected - required for presentation\n"
134d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay                    "Note: you can probably enable DRI3 in your Xorg config\n");
135d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay  }
136d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay  return false;
137d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay}
138d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay
139971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic struct wsi_x11_connection *
140ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airliewsi_x11_get_connection(struct wsi_device *wsi_dev,
141971523410fd2235e13c617b6a1569f70486258d7Dave Airlie		       const VkAllocationCallbacks *alloc,
142971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                       xcb_connection_t *conn)
143971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
144971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct wsi_x11 *wsi =
145971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      (struct wsi_x11 *)wsi_dev->wsi[VK_ICD_WSI_PLATFORM_XCB];
146971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
147971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   pthread_mutex_lock(&wsi->mutex);
148971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
149971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct hash_entry *entry = _mesa_hash_table_search(wsi->connections, conn);
150971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (!entry) {
151971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      /* We're about to make a bunch of blocking calls.  Let's drop the
152971523410fd2235e13c617b6a1569f70486258d7Dave Airlie       * mutex for now so we don't block up too badly.
153971523410fd2235e13c617b6a1569f70486258d7Dave Airlie       */
154971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      pthread_mutex_unlock(&wsi->mutex);
155971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
156971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      struct wsi_x11_connection *wsi_conn =
157971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         wsi_x11_connection_create(alloc, conn);
158fc0e9e3e40e4b044ce1b62c1b757941f4ed4c820Jason Ekstrand      if (!wsi_conn)
159fc0e9e3e40e4b044ce1b62c1b757941f4ed4c820Jason Ekstrand         return NULL;
160971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
161971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      pthread_mutex_lock(&wsi->mutex);
162971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
163971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      entry = _mesa_hash_table_search(wsi->connections, conn);
164971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      if (entry) {
165971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         /* Oops, someone raced us to it */
166971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         wsi_x11_connection_destroy(alloc, wsi_conn);
167971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      } else {
168971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         entry = _mesa_hash_table_insert(wsi->connections, conn, wsi_conn);
169971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      }
170971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
171971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
172971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   pthread_mutex_unlock(&wsi->mutex);
173971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
174971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return entry->data;
175971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
176971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
177971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic const VkSurfaceFormatKHR formats[] = {
178971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   { .format = VK_FORMAT_B8G8R8A8_SRGB, },
179971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   { .format = VK_FORMAT_B8G8R8A8_UNORM, },
180971523410fd2235e13c617b6a1569f70486258d7Dave Airlie};
181971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
182971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic const VkPresentModeKHR present_modes[] = {
183ca035006c86a5055c8e640f49c858f04770681ebDave Airlie   VK_PRESENT_MODE_IMMEDIATE_KHR,
184971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   VK_PRESENT_MODE_MAILBOX_KHR,
185e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   VK_PRESENT_MODE_FIFO_KHR,
186971523410fd2235e13c617b6a1569f70486258d7Dave Airlie};
187971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
188971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic xcb_screen_t *
189971523410fd2235e13c617b6a1569f70486258d7Dave Airlieget_screen_for_root(xcb_connection_t *conn, xcb_window_t root)
190971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
191971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_screen_iterator_t screen_iter =
192971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      xcb_setup_roots_iterator(xcb_get_setup(conn));
193971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
194971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   for (; screen_iter.rem; xcb_screen_next (&screen_iter)) {
195971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      if (screen_iter.data->root == root)
196971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         return screen_iter.data;
197971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
198971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
199971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return NULL;
200971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
201971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
202971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic xcb_visualtype_t *
203971523410fd2235e13c617b6a1569f70486258d7Dave Airliescreen_get_visualtype(xcb_screen_t *screen, xcb_visualid_t visual_id,
204971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                      unsigned *depth)
205971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
206971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_depth_iterator_t depth_iter =
207971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      xcb_screen_allowed_depths_iterator(screen);
208971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
209971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   for (; depth_iter.rem; xcb_depth_next (&depth_iter)) {
210971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      xcb_visualtype_iterator_t visual_iter =
211971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         xcb_depth_visuals_iterator (depth_iter.data);
212971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
213971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) {
214971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         if (visual_iter.data->visual_id == visual_id) {
215971523410fd2235e13c617b6a1569f70486258d7Dave Airlie            if (depth)
216971523410fd2235e13c617b6a1569f70486258d7Dave Airlie               *depth = depth_iter.data->depth;
217971523410fd2235e13c617b6a1569f70486258d7Dave Airlie            return visual_iter.data;
218971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         }
219971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      }
220971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
221971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
222971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return NULL;
223971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
224971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
225971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic xcb_visualtype_t *
226971523410fd2235e13c617b6a1569f70486258d7Dave Airlieconnection_get_visualtype(xcb_connection_t *conn, xcb_visualid_t visual_id,
227971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                          unsigned *depth)
228971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
229971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_screen_iterator_t screen_iter =
230971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      xcb_setup_roots_iterator(xcb_get_setup(conn));
231971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
232971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   /* For this we have to iterate over all of the screens which is rather
233971523410fd2235e13c617b6a1569f70486258d7Dave Airlie    * annoying.  Fortunately, there is probably only 1.
234971523410fd2235e13c617b6a1569f70486258d7Dave Airlie    */
235971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   for (; screen_iter.rem; xcb_screen_next (&screen_iter)) {
236971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      xcb_visualtype_t *visual = screen_get_visualtype(screen_iter.data,
237971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                                       visual_id, depth);
238971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      if (visual)
239971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         return visual;
240971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
241971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
242971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return NULL;
243971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
244971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
245971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic xcb_visualtype_t *
246971523410fd2235e13c617b6a1569f70486258d7Dave Airlieget_visualtype_for_window(xcb_connection_t *conn, xcb_window_t window,
247971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                          unsigned *depth)
248971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
249971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_query_tree_cookie_t tree_cookie;
250971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_get_window_attributes_cookie_t attrib_cookie;
251971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_query_tree_reply_t *tree;
252971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_get_window_attributes_reply_t *attrib;
253971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
254971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   tree_cookie = xcb_query_tree(conn, window);
255971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   attrib_cookie = xcb_get_window_attributes(conn, window);
256971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
257971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   tree = xcb_query_tree_reply(conn, tree_cookie, NULL);
258971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   attrib = xcb_get_window_attributes_reply(conn, attrib_cookie, NULL);
259971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (attrib == NULL || tree == NULL) {
260971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      free(attrib);
261971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      free(tree);
262971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return NULL;
263971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
264971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
265971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_window_t root = tree->root;
266971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_visualid_t visual_id = attrib->visual;
267971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   free(attrib);
268971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   free(tree);
269971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
270971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_screen_t *screen = get_screen_for_root(conn, root);
271971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (screen == NULL)
272971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return NULL;
273971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
274971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return screen_get_visualtype(screen, visual_id, depth);
275971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
276971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
277971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic bool
278971523410fd2235e13c617b6a1569f70486258d7Dave Airlievisual_has_alpha(xcb_visualtype_t *visual, unsigned depth)
279971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
280971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   uint32_t rgb_mask = visual->red_mask |
281971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                       visual->green_mask |
282971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                       visual->blue_mask;
283971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
284971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   uint32_t all_mask = 0xffffffff >> (32 - depth);
285971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
286971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   /* Do we have bits left over after RGB? */
287971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return (all_mask & ~rgb_mask) != 0;
288971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
289971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
290ec0bc14a700c2503d834ac0763f4cfbe312998faDave AirlieVkBool32 wsi_get_physical_device_xcb_presentation_support(
291ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airlie    struct wsi_device *wsi_device,
292971523410fd2235e13c617b6a1569f70486258d7Dave Airlie    VkAllocationCallbacks *alloc,
293971523410fd2235e13c617b6a1569f70486258d7Dave Airlie    uint32_t                                    queueFamilyIndex,
294971523410fd2235e13c617b6a1569f70486258d7Dave Airlie    xcb_connection_t*                           connection,
295971523410fd2235e13c617b6a1569f70486258d7Dave Airlie    xcb_visualid_t                              visual_id)
296971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
297971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct wsi_x11_connection *wsi_conn =
298971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      wsi_x11_get_connection(wsi_device, alloc, connection);
299971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
30099de7b752546c3f87aa8a18f72fd46856270555fArda Coskunses   if (!wsi_conn)
30199de7b752546c3f87aa8a18f72fd46856270555fArda Coskunses      return false;
30299de7b752546c3f87aa8a18f72fd46856270555fArda Coskunses
303d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   if (!wsi_x11_check_for_dri3(wsi_conn))
304971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return false;
305971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
306971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   unsigned visual_depth;
307971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (!connection_get_visualtype(connection, visual_id, &visual_depth))
308971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return false;
309971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
310971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (visual_depth != 24 && visual_depth != 32)
311971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return false;
312971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
313971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return true;
314971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
315971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
316971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic xcb_connection_t*
317971523410fd2235e13c617b6a1569f70486258d7Dave Airliex11_surface_get_connection(VkIcdSurfaceBase *icd_surface)
318971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
319971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (icd_surface->platform == VK_ICD_WSI_PLATFORM_XLIB)
320971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return XGetXCBConnection(((VkIcdSurfaceXlib *)icd_surface)->dpy);
321971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   else
322971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return ((VkIcdSurfaceXcb *)icd_surface)->connection;
323971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
324971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
325971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic xcb_window_t
326971523410fd2235e13c617b6a1569f70486258d7Dave Airliex11_surface_get_window(VkIcdSurfaceBase *icd_surface)
327971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
328971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (icd_surface->platform == VK_ICD_WSI_PLATFORM_XLIB)
329971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return ((VkIcdSurfaceXlib *)icd_surface)->window;
330971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   else
331971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return ((VkIcdSurfaceXcb *)icd_surface)->window;
332971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
333971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
334971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic VkResult
335971523410fd2235e13c617b6a1569f70486258d7Dave Airliex11_surface_get_support(VkIcdSurfaceBase *icd_surface,
336ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airlie                        struct wsi_device *wsi_device,
337971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                        const VkAllocationCallbacks *alloc,
338971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                        uint32_t queueFamilyIndex,
339971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                        VkBool32* pSupported)
340971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
341971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
342971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_window_t window = x11_surface_get_window(icd_surface);
343971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
344971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct wsi_x11_connection *wsi_conn =
345971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      wsi_x11_get_connection(wsi_device, alloc, conn);
346971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (!wsi_conn)
347971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return VK_ERROR_OUT_OF_HOST_MEMORY;
348971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
349d74d7cc0ff517c67c3f2f55a1e625b04c4001591Jacob Lifshay   if (!wsi_x11_check_for_dri3(wsi_conn)) {
350971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      *pSupported = false;
351971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return VK_SUCCESS;
352971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
353971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
354971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   unsigned visual_depth;
355971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (!get_visualtype_for_window(conn, window, &visual_depth)) {
356971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      *pSupported = false;
357971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return VK_SUCCESS;
358971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
359971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
360971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (visual_depth != 24 && visual_depth != 32) {
361971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      *pSupported = false;
362971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return VK_SUCCESS;
363971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
364971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
365971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   *pSupported = true;
366971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return VK_SUCCESS;
367971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
368971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
369971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic VkResult
370971523410fd2235e13c617b6a1569f70486258d7Dave Airliex11_surface_get_capabilities(VkIcdSurfaceBase *icd_surface,
371971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                             VkSurfaceCapabilitiesKHR *caps)
372971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
373971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
374971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_window_t window = x11_surface_get_window(icd_surface);
375971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_get_geometry_cookie_t geom_cookie;
376971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_generic_error_t *err;
377971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_get_geometry_reply_t *geom;
378971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   unsigned visual_depth;
379971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
380971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   geom_cookie = xcb_get_geometry(conn, window);
381971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
382971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   /* This does a round-trip.  This is why we do get_geometry first and
383971523410fd2235e13c617b6a1569f70486258d7Dave Airlie    * wait to read the reply until after we have a visual.
384971523410fd2235e13c617b6a1569f70486258d7Dave Airlie    */
385971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_visualtype_t *visual =
386971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      get_visualtype_for_window(conn, window, &visual_depth);
387971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
38801dd363e671ac3a457bc3ff60b43b04e108c33fcArda Coskunses   if (!visual)
38901dd363e671ac3a457bc3ff60b43b04e108c33fcArda Coskunses      return VK_ERROR_SURFACE_LOST_KHR;
39001dd363e671ac3a457bc3ff60b43b04e108c33fcArda Coskunses
391971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   geom = xcb_get_geometry_reply(conn, geom_cookie, &err);
392971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (geom) {
393971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      VkExtent2D extent = { geom->width, geom->height };
394971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      caps->currentExtent = extent;
395971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      caps->minImageExtent = extent;
396971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      caps->maxImageExtent = extent;
397971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   } else {
398971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      /* This can happen if the client didn't wait for the configure event
399971523410fd2235e13c617b6a1569f70486258d7Dave Airlie       * to come back from the compositor.  In that case, we don't know the
400971523410fd2235e13c617b6a1569f70486258d7Dave Airlie       * size of the window so we just return valid "I don't know" stuff.
401971523410fd2235e13c617b6a1569f70486258d7Dave Airlie       */
402971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      caps->currentExtent = (VkExtent2D) { -1, -1 };
403971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      caps->minImageExtent = (VkExtent2D) { 1, 1 };
404e79043bbb9499b3f29b84acff3664e2a85b95a9dJason Ekstrand      /* This is the maximum supported size on Intel */
405e79043bbb9499b3f29b84acff3664e2a85b95a9dJason Ekstrand      caps->maxImageExtent = (VkExtent2D) { 1 << 14, 1 << 14 };
406971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
407971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   free(err);
408971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   free(geom);
409971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
410971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (visual_has_alpha(visual, visual_depth)) {
411971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      caps->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR |
412971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                      VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
413971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   } else {
414971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      caps->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR |
415971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                      VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
416971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
417971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
4184fa0ca80eeeac813affcbb0129ed61f1534d8df0Jason Ekstrand   /* For true mailbox mode, we need at least 4 images:
4194fa0ca80eeeac813affcbb0129ed61f1534d8df0Jason Ekstrand    *  1) One to scan out from
4204fa0ca80eeeac813affcbb0129ed61f1534d8df0Jason Ekstrand    *  2) One to have queued for scan-out
4214fa0ca80eeeac813affcbb0129ed61f1534d8df0Jason Ekstrand    *  3) One to be currently held by the X server
4224fa0ca80eeeac813affcbb0129ed61f1534d8df0Jason Ekstrand    *  4) One to render to
4234fa0ca80eeeac813affcbb0129ed61f1534d8df0Jason Ekstrand    */
424971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   caps->minImageCount = 2;
4254fa0ca80eeeac813affcbb0129ed61f1534d8df0Jason Ekstrand   /* There is no real maximum */
4264fa0ca80eeeac813affcbb0129ed61f1534d8df0Jason Ekstrand   caps->maxImageCount = 0;
4274fa0ca80eeeac813affcbb0129ed61f1534d8df0Jason Ekstrand
428971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   caps->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
429971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   caps->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
430971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   caps->maxImageArrayLayers = 1;
431971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   caps->supportedUsageFlags =
432971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
433971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      VK_IMAGE_USAGE_SAMPLED_BIT |
434971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      VK_IMAGE_USAGE_TRANSFER_DST_BIT |
435971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
436971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
437971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return VK_SUCCESS;
438971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
439971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
440971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic VkResult
441971523410fd2235e13c617b6a1569f70486258d7Dave Airliex11_surface_get_formats(VkIcdSurfaceBase *surface,
442ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airlie                        struct wsi_device *wsi_device,
443971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                        uint32_t *pSurfaceFormatCount,
444971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                        VkSurfaceFormatKHR *pSurfaceFormats)
445971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
446971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (pSurfaceFormats == NULL) {
447971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      *pSurfaceFormatCount = ARRAY_SIZE(formats);
448971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return VK_SUCCESS;
449971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
450971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
451129da274261b6e79f459e24428591f137bf92ed1Eduardo Lima Mitev   *pSurfaceFormatCount = MIN2(*pSurfaceFormatCount, ARRAY_SIZE(formats));
452971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   typed_memcpy(pSurfaceFormats, formats, *pSurfaceFormatCount);
453971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
454129da274261b6e79f459e24428591f137bf92ed1Eduardo Lima Mitev   return *pSurfaceFormatCount < ARRAY_SIZE(formats) ?
455129da274261b6e79f459e24428591f137bf92ed1Eduardo Lima Mitev      VK_INCOMPLETE : VK_SUCCESS;
456971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
457971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
458971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic VkResult
459971523410fd2235e13c617b6a1569f70486258d7Dave Airliex11_surface_get_present_modes(VkIcdSurfaceBase *surface,
460971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                              uint32_t *pPresentModeCount,
461971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                              VkPresentModeKHR *pPresentModes)
462971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
463971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (pPresentModes == NULL) {
464971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      *pPresentModeCount = ARRAY_SIZE(present_modes);
465971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return VK_SUCCESS;
466971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
467971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
468b677b99db5c48ffd1eeef538b962080ac5fd65d9Eduardo Lima Mitev   *pPresentModeCount = MIN2(*pPresentModeCount, ARRAY_SIZE(present_modes));
469971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   typed_memcpy(pPresentModes, present_modes, *pPresentModeCount);
470971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
471b677b99db5c48ffd1eeef538b962080ac5fd65d9Eduardo Lima Mitev   return *pPresentModeCount < ARRAY_SIZE(present_modes) ?
472b677b99db5c48ffd1eeef538b962080ac5fd65d9Eduardo Lima Mitev      VK_INCOMPLETE : VK_SUCCESS;
473971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
474971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
475ec0bc14a700c2503d834ac0763f4cfbe312998faDave AirlieVkResult wsi_create_xcb_surface(const VkAllocationCallbacks *pAllocator,
476971523410fd2235e13c617b6a1569f70486258d7Dave Airlie				const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
477971523410fd2235e13c617b6a1569f70486258d7Dave Airlie				VkSurfaceKHR *pSurface)
478971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
479971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   VkIcdSurfaceXcb *surface;
480971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
481971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   surface = vk_alloc(pAllocator, sizeof *surface, 8,
482971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
483971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (surface == NULL)
484971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return VK_ERROR_OUT_OF_HOST_MEMORY;
485971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
486971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   surface->base.platform = VK_ICD_WSI_PLATFORM_XCB;
487971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   surface->connection = pCreateInfo->connection;
488971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   surface->window = pCreateInfo->window;
489971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
490c085bfcec9915879e97a33c5235cf21607c72318Chad Versace   *pSurface = VkIcdSurfaceBase_to_handle(&surface->base);
491971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return VK_SUCCESS;
492971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
493971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
494ec0bc14a700c2503d834ac0763f4cfbe312998faDave AirlieVkResult wsi_create_xlib_surface(const VkAllocationCallbacks *pAllocator,
495971523410fd2235e13c617b6a1569f70486258d7Dave Airlie				 const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
496971523410fd2235e13c617b6a1569f70486258d7Dave Airlie				 VkSurfaceKHR *pSurface)
497971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
498971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   VkIcdSurfaceXlib *surface;
499971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
500971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   surface = vk_alloc(pAllocator, sizeof *surface, 8,
501971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
502971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (surface == NULL)
503971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return VK_ERROR_OUT_OF_HOST_MEMORY;
504971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
505971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   surface->base.platform = VK_ICD_WSI_PLATFORM_XLIB;
506971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   surface->dpy = pCreateInfo->dpy;
507971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   surface->window = pCreateInfo->window;
508971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
509c085bfcec9915879e97a33c5235cf21607c72318Chad Versace   *pSurface = VkIcdSurfaceBase_to_handle(&surface->base);
510971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return VK_SUCCESS;
511971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
512971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
513971523410fd2235e13c617b6a1569f70486258d7Dave Airliestruct x11_image {
514971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   VkImage image;
515971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   VkDeviceMemory memory;
516971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_pixmap_t                              pixmap;
517971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   bool                                      busy;
518971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct xshmfence *                        shm_fence;
519971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   uint32_t                                  sync_fence;
520971523410fd2235e13c617b6a1569f70486258d7Dave Airlie};
521971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
522971523410fd2235e13c617b6a1569f70486258d7Dave Airliestruct x11_swapchain {
523ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airlie   struct wsi_swapchain                        base;
524971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
525971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_connection_t *                           conn;
526971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_window_t                                 window;
527971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_gc_t                                     gc;
528972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund   uint32_t                                     depth;
529971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   VkExtent2D                                   extent;
530971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   uint32_t                                     image_count;
531971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
532971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_present_event_t                          event_id;
533971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_special_event_t *                        special_event;
534971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   uint64_t                                     send_sbc;
535e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   uint64_t                                     last_present_msc;
536971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   uint32_t                                     stamp;
537971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
538e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   bool                                         threaded;
539e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   VkResult                                     status;
540e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   struct wsi_queue                             present_queue;
541e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   struct wsi_queue                             acquire_queue;
542e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   pthread_t                                    queue_manager;
543e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
544971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct x11_image                             images[0];
545971523410fd2235e13c617b6a1569f70486258d7Dave Airlie};
546971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
547971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic VkResult
548ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airliex11_get_images(struct wsi_swapchain *anv_chain,
549971523410fd2235e13c617b6a1569f70486258d7Dave Airlie               uint32_t* pCount, VkImage *pSwapchainImages)
550971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
551971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain;
552253fa25d09b77e18f736b97da07d57be0e6c4200Dave Airlie   uint32_t ret_count;
553253fa25d09b77e18f736b97da07d57be0e6c4200Dave Airlie   VkResult result;
554971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
555971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (pSwapchainImages == NULL) {
556971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      *pCount = chain->image_count;
557971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return VK_SUCCESS;
558971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
559971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
560253fa25d09b77e18f736b97da07d57be0e6c4200Dave Airlie   result = VK_SUCCESS;
561253fa25d09b77e18f736b97da07d57be0e6c4200Dave Airlie   ret_count = chain->image_count;
562253fa25d09b77e18f736b97da07d57be0e6c4200Dave Airlie   if (chain->image_count > *pCount) {
563253fa25d09b77e18f736b97da07d57be0e6c4200Dave Airlie     ret_count = *pCount;
564253fa25d09b77e18f736b97da07d57be0e6c4200Dave Airlie     result = VK_INCOMPLETE;
565253fa25d09b77e18f736b97da07d57be0e6c4200Dave Airlie   }
566971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
567253fa25d09b77e18f736b97da07d57be0e6c4200Dave Airlie   for (uint32_t i = 0; i < ret_count; i++)
568253fa25d09b77e18f736b97da07d57be0e6c4200Dave Airlie      pSwapchainImages[i] = chain->images[i].image;
569971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
570253fa25d09b77e18f736b97da07d57be0e6c4200Dave Airlie   return result;
571971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
572971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
573971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic VkResult
574971523410fd2235e13c617b6a1569f70486258d7Dave Airliex11_handle_dri3_present_event(struct x11_swapchain *chain,
575971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                              xcb_present_generic_event_t *event)
576971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
577971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   switch (event->evtype) {
578971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   case XCB_PRESENT_CONFIGURE_NOTIFY: {
579971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      xcb_present_configure_notify_event_t *config = (void *) event;
580971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
581971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      if (config->width != chain->extent.width ||
582971523410fd2235e13c617b6a1569f70486258d7Dave Airlie          config->height != chain->extent.height)
583971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         return VK_ERROR_OUT_OF_DATE_KHR;
584971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
585971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      break;
586971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
587971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
588971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   case XCB_PRESENT_EVENT_IDLE_NOTIFY: {
589971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      xcb_present_idle_notify_event_t *idle = (void *) event;
590971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
591971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      for (unsigned i = 0; i < chain->image_count; i++) {
592971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         if (chain->images[i].pixmap == idle->pixmap) {
593971523410fd2235e13c617b6a1569f70486258d7Dave Airlie            chain->images[i].busy = false;
594e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand            if (chain->threaded)
595e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand               wsi_queue_push(&chain->acquire_queue, i);
596971523410fd2235e13c617b6a1569f70486258d7Dave Airlie            break;
597971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         }
598971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      }
599971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
600971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      break;
601971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
602971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
603e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   case XCB_PRESENT_EVENT_COMPLETE_NOTIFY: {
604e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      xcb_present_complete_notify_event_t *complete = (void *) event;
605e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      if (complete->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP)
606e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         chain->last_present_msc = complete->msc;
607e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      break;
608e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   }
609e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
610971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   default:
611971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      break;
612971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
613971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
614971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return VK_SUCCESS;
615971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
616971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
617787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie
618787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airliestatic uint64_t wsi_get_current_time(void)
619787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie{
620787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie   uint64_t current_time;
621787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie   struct timespec tv;
622787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie
623787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie   clock_gettime(CLOCK_MONOTONIC, &tv);
624787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie   current_time = tv.tv_nsec + tv.tv_sec*1000000000ull;
625787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie   return current_time;
626787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie}
627787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie
628787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airliestatic uint64_t wsi_get_absolute_timeout(uint64_t timeout)
629787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie{
630787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie   uint64_t current_time = wsi_get_current_time();
631787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie
632787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie   timeout = MIN2(UINT64_MAX - current_time, timeout);
633787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie
634787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie   return current_time + timeout;
635787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie}
636787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie
637971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic VkResult
638e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrandx11_acquire_next_image_poll_x11(struct x11_swapchain *chain,
639e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand                                uint32_t *image_index, uint64_t timeout)
640971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
641787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie   xcb_generic_event_t *event;
642787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie   struct pollfd pfds;
643787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie   uint64_t atimeout;
644971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   while (1) {
645971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      for (uint32_t i = 0; i < chain->image_count; i++) {
646971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         if (!chain->images[i].busy) {
647971523410fd2235e13c617b6a1569f70486258d7Dave Airlie            /* We found a non-busy image */
648971523410fd2235e13c617b6a1569f70486258d7Dave Airlie            xshmfence_await(chain->images[i].shm_fence);
649971523410fd2235e13c617b6a1569f70486258d7Dave Airlie            *image_index = i;
650971523410fd2235e13c617b6a1569f70486258d7Dave Airlie            chain->images[i].busy = true;
651971523410fd2235e13c617b6a1569f70486258d7Dave Airlie            return VK_SUCCESS;
652971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         }
653971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      }
654971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
655971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      xcb_flush(chain->conn);
656787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie
657787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie      if (timeout == UINT64_MAX) {
658787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie         event = xcb_wait_for_special_event(chain->conn, chain->special_event);
659787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie         if (!event)
660787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            return VK_ERROR_OUT_OF_DATE_KHR;
661787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie      } else {
662787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie         event = xcb_poll_for_special_event(chain->conn, chain->special_event);
663787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie         if (!event) {
664787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            int ret;
665787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            if (timeout == 0)
666787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie               return VK_NOT_READY;
667787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie
668787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            atimeout = wsi_get_absolute_timeout(timeout);
669787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie
670787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            pfds.fd = xcb_get_file_descriptor(chain->conn);
671787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            pfds.events = POLLIN;
672787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            ret = poll(&pfds, 1, timeout / 1000 / 1000);
673787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            if (ret == 0)
674787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie               return VK_TIMEOUT;
675787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            if (ret == -1)
676787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie               return VK_ERROR_OUT_OF_DATE_KHR;
677787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie
678787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            /* If a non-special event happens, the fd will still
679787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie             * poll. So recalculate the timeout now just in case.
680787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie             */
681787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            uint64_t current_time = wsi_get_current_time();
682787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            if (atimeout > current_time)
683787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie               timeout = atimeout - current_time;
684787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            else
685787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie               timeout = 0;
686787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie            continue;
687787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie         }
688787c172aed0ae88ca6a8c1a193d9dd744fbdc918Dave Airlie      }
689971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
690971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      VkResult result = x11_handle_dri3_present_event(chain, (void *)event);
691971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      free(event);
692971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      if (result != VK_SUCCESS)
693971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         return result;
694971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
695971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
696971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
697971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic VkResult
698e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrandx11_acquire_next_image_from_queue(struct x11_swapchain *chain,
699e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand                                  uint32_t *image_index_out, uint64_t timeout)
700e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand{
701e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   assert(chain->threaded);
702e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
703e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   uint32_t image_index;
704e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   VkResult result = wsi_queue_pull(&chain->acquire_queue,
705e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand                                    &image_index, timeout);
706e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   if (result != VK_SUCCESS) {
707e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      return result;
708e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   } else if (chain->status != VK_SUCCESS) {
709e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      return chain->status;
710e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   }
711e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
712e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   assert(image_index < chain->image_count);
713e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   xshmfence_await(chain->images[image_index].shm_fence);
714e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
715e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   *image_index_out = image_index;
716e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
717e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   return VK_SUCCESS;
718e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand}
719e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
720e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrandstatic VkResult
721e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrandx11_present_to_x11(struct x11_swapchain *chain, uint32_t image_index,
722e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand                   uint32_t target_msc)
723971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
724971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct x11_image *image = &chain->images[image_index];
725971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
726971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   assert(image_index < chain->image_count);
727971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
728971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   uint32_t options = XCB_PRESENT_OPTION_NONE;
729971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
730971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   int64_t divisor = 0;
731971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   int64_t remainder = 0;
732971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
733ca035006c86a5055c8e640f49c858f04770681ebDave Airlie   if (chain->base.present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR)
734ca035006c86a5055c8e640f49c858f04770681ebDave Airlie      options |= XCB_PRESENT_OPTION_ASYNC;
735971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
736971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xshmfence_reset(image->shm_fence);
737971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
738971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   ++chain->send_sbc;
739971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_void_cookie_t cookie =
740971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      xcb_present_pixmap(chain->conn,
741971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         chain->window,
742971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         image->pixmap,
743971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         (uint32_t) chain->send_sbc,
744971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         0,                                    /* valid */
745971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         0,                                    /* update */
746971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         0,                                    /* x_off */
747971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         0,                                    /* y_off */
748971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         XCB_NONE,                             /* target_crtc */
749971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         XCB_NONE,
750971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         image->sync_fence,
751971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         options,
752971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         target_msc,
753971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         divisor,
754971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                         remainder, 0, NULL);
755971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_discard_reply(chain->conn, cookie.sequence);
756971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   image->busy = true;
757971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
758971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_flush(chain->conn);
759971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
760971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return VK_SUCCESS;
761971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
762971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
763971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic VkResult
764e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrandx11_acquire_next_image(struct wsi_swapchain *anv_chain,
765e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand                       uint64_t timeout,
766e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand                       VkSemaphore semaphore,
767e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand                       uint32_t *image_index)
768e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand{
769e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain;
770e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
771e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   if (chain->threaded) {
772e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      return x11_acquire_next_image_from_queue(chain, image_index, timeout);
773e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   } else {
774e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      return x11_acquire_next_image_poll_x11(chain, image_index, timeout);
775e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   }
776e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand}
777e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
778e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrandstatic VkResult
779e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrandx11_queue_present(struct wsi_swapchain *anv_chain,
780e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand                  uint32_t image_index)
781e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand{
782e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain;
783e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
784e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   if (chain->threaded) {
785e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      wsi_queue_push(&chain->present_queue, image_index);
786e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      return chain->status;
787e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   } else {
788e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      return x11_present_to_x11(chain, image_index, 0);
789e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   }
790e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand}
791e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
792e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrandstatic void *
793e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrandx11_manage_fifo_queues(void *state)
794e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand{
795e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   struct x11_swapchain *chain = state;
796e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   VkResult result;
797e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
798e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   assert(chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR);
799e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
800e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   while (chain->status == VK_SUCCESS) {
801e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      /* It should be safe to unconditionally block here.  Later in the loop
802e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand       * we blocks until the previous present has landed on-screen.  At that
803e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand       * point, we should have received IDLE_NOTIFY on all images presented
804e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand       * before that point so the client should be able to acquire any image
805e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand       * other than the currently presented one.
806e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand       */
807e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      uint32_t image_index;
808e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      result = wsi_queue_pull(&chain->present_queue, &image_index, INT64_MAX);
809e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      if (result != VK_SUCCESS) {
810e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         goto fail;
811e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      } else if (chain->status != VK_SUCCESS) {
812e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         return NULL;
813e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      }
814e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
815e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      uint64_t target_msc = chain->last_present_msc + 1;
816e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      result = x11_present_to_x11(chain, image_index, target_msc);
817e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      if (result != VK_SUCCESS)
818e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         goto fail;
819e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
820e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      while (chain->last_present_msc < target_msc) {
821e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         xcb_generic_event_t *event =
822e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand            xcb_wait_for_special_event(chain->conn, chain->special_event);
823e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         if (!event)
824e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand            goto fail;
825e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
826e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         result = x11_handle_dri3_present_event(chain, (void *)event);
827e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         if (result != VK_SUCCESS)
828e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand            goto fail;
829e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      }
830e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   }
831e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
832e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrandfail:
833e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   chain->status = result;
834e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   wsi_queue_push(&chain->acquire_queue, UINT32_MAX);
835e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
836e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   return NULL;
837e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand}
838e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
839e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrandstatic VkResult
840971523410fd2235e13c617b6a1569f70486258d7Dave Airliex11_image_init(VkDevice device_h, struct x11_swapchain *chain,
841971523410fd2235e13c617b6a1569f70486258d7Dave Airlie               const VkSwapchainCreateInfoKHR *pCreateInfo,
842971523410fd2235e13c617b6a1569f70486258d7Dave Airlie               const VkAllocationCallbacks* pAllocator,
843971523410fd2235e13c617b6a1569f70486258d7Dave Airlie               struct x11_image *image)
844971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
845971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_void_cookie_t cookie;
846971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   VkResult result;
847971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   uint32_t row_pitch;
848971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   uint32_t offset;
849971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   uint32_t bpp = 32;
850971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   int fd;
851971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   uint32_t size;
852971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
853971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   result = chain->base.image_fns->create_wsi_image(device_h,
854971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                                    pCreateInfo,
855971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                                    pAllocator,
856971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                                    &image->image,
857971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                                    &image->memory,
858971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                                    &size,
859971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                                    &offset,
860971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                                    &row_pitch,
861971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                                    &fd);
862971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (result != VK_SUCCESS)
863971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return result;
864971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
865971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   image->pixmap = xcb_generate_id(chain->conn);
866971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
867971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   cookie =
868971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      xcb_dri3_pixmap_from_buffer_checked(chain->conn,
869971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                          image->pixmap,
870971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                          chain->window,
871971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                          size,
872971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                          pCreateInfo->imageExtent.width,
873971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                          pCreateInfo->imageExtent.height,
874971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                          row_pitch,
875972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund                                          chain->depth, bpp, fd);
876971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_discard_reply(chain->conn, cookie.sequence);
877971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
878971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   int fence_fd = xshmfence_alloc_shm();
879971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (fence_fd < 0)
880971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      goto fail_pixmap;
881971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
882971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   image->shm_fence = xshmfence_map_shm(fence_fd);
883971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (image->shm_fence == NULL)
884971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      goto fail_shmfence_alloc;
885971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
886971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   image->sync_fence = xcb_generate_id(chain->conn);
887971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_dri3_fence_from_fd(chain->conn,
888971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                          image->pixmap,
889971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                          image->sync_fence,
890971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                          false,
891971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                          fence_fd);
892971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
893971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   image->busy = false;
894971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xshmfence_trigger(image->shm_fence);
895971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
896971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return VK_SUCCESS;
897971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
898971523410fd2235e13c617b6a1569f70486258d7Dave Airliefail_shmfence_alloc:
899971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   close(fence_fd);
900971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
901971523410fd2235e13c617b6a1569f70486258d7Dave Airliefail_pixmap:
902971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   cookie = xcb_free_pixmap(chain->conn, image->pixmap);
903971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_discard_reply(chain->conn, cookie.sequence);
904971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
905971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->base.image_fns->free_wsi_image(device_h, pAllocator,
906971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                        image->image, image->memory);
907971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
908971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return result;
909971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
910971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
911971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic void
912971523410fd2235e13c617b6a1569f70486258d7Dave Airliex11_image_finish(struct x11_swapchain *chain,
913971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                 const VkAllocationCallbacks* pAllocator,
914971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                 struct x11_image *image)
915971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
916971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_void_cookie_t cookie;
917971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
918971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   cookie = xcb_sync_destroy_fence(chain->conn, image->sync_fence);
919971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_discard_reply(chain->conn, cookie.sequence);
920971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xshmfence_unmap_shm(image->shm_fence);
921971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
922971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   cookie = xcb_free_pixmap(chain->conn, image->pixmap);
923971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_discard_reply(chain->conn, cookie.sequence);
924971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
925971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->base.image_fns->free_wsi_image(chain->base.device, pAllocator,
926971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                        image->image, image->memory);
927971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
928971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
929971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic VkResult
930ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airliex11_swapchain_destroy(struct wsi_swapchain *anv_chain,
931971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                      const VkAllocationCallbacks *pAllocator)
932971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
933971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain;
934550cd272b4b97fc06dbd3b5fad2bf0e5d526236dMichel Dänzer   xcb_void_cookie_t cookie;
935550cd272b4b97fc06dbd3b5fad2bf0e5d526236dMichel Dänzer
936971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   for (uint32_t i = 0; i < chain->image_count; i++)
937971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      x11_image_finish(chain, pAllocator, &chain->images[i]);
938971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
939e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   if (chain->threaded) {
940e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      chain->status = VK_ERROR_OUT_OF_DATE_KHR;
941e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      /* Push a UINT32_MAX to wake up the manager */
942e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      wsi_queue_push(&chain->present_queue, UINT32_MAX);
943e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      pthread_join(chain->queue_manager, NULL);
944e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      wsi_queue_destroy(&chain->acquire_queue);
945e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      wsi_queue_destroy(&chain->present_queue);
946e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   }
947e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
948971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_unregister_for_special_event(chain->conn, chain->special_event);
949550cd272b4b97fc06dbd3b5fad2bf0e5d526236dMichel Dänzer   cookie = xcb_present_select_input_checked(chain->conn, chain->event_id,
950550cd272b4b97fc06dbd3b5fad2bf0e5d526236dMichel Dänzer                                             chain->window,
951550cd272b4b97fc06dbd3b5fad2bf0e5d526236dMichel Dänzer                                             XCB_PRESENT_EVENT_MASK_NO_EVENT);
952550cd272b4b97fc06dbd3b5fad2bf0e5d526236dMichel Dänzer   xcb_discard_reply(chain->conn, cookie.sequence);
953971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
954971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   vk_free(pAllocator, chain);
955971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
956971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return VK_SUCCESS;
957971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
958971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
959971523410fd2235e13c617b6a1569f70486258d7Dave Airliestatic VkResult
960971523410fd2235e13c617b6a1569f70486258d7Dave Airliex11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
961971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                             VkDevice device,
962ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airlie                             struct wsi_device *wsi_device,
963971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                             const VkSwapchainCreateInfoKHR *pCreateInfo,
964971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                             const VkAllocationCallbacks* pAllocator,
965ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airlie                             const struct wsi_image_fns *image_fns,
966ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airlie                             struct wsi_swapchain **swapchain_out)
967971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
968971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct x11_swapchain *chain;
969971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_void_cookie_t cookie;
970971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   VkResult result;
971971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
972971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR);
973971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
9744fa0ca80eeeac813affcbb0129ed61f1534d8df0Jason Ekstrand   const unsigned num_images = pCreateInfo->minImageCount;
975971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
976971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]);
977971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain = vk_alloc(pAllocator, size, 8,
978971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
979971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (chain == NULL)
980971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      return VK_ERROR_OUT_OF_HOST_MEMORY;
981971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
982972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund   xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
983972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund   xcb_window_t window = x11_surface_get_window(icd_surface);
984972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund   xcb_get_geometry_reply_t *geometry =
985972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund      xcb_get_geometry_reply(conn, xcb_get_geometry(conn, window), NULL);
986972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund
987972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund   if (geometry == NULL)
988972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund      return VK_ERROR_SURFACE_LOST_KHR;
989972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund
990971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->base.device = device;
991971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->base.destroy = x11_swapchain_destroy;
992971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->base.get_images = x11_get_images;
993971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->base.acquire_next_image = x11_acquire_next_image;
994971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->base.queue_present = x11_queue_present;
995971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->base.image_fns = image_fns;
9961cdca1eb16ab33da338dda076794efd4bf859f7bDave Airlie   chain->base.present_mode = pCreateInfo->presentMode;
997972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund   chain->conn = conn;
998972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund   chain->window = window;
999972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund   chain->depth = geometry->depth;
1000971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->extent = pCreateInfo->imageExtent;
1001971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->image_count = num_images;
1002971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->send_sbc = 0;
1003e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   chain->last_present_msc = 0;
1004e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   chain->threaded = false;
1005e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   chain->status = VK_SUCCESS;
1006971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1007972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund   free(geometry);
1008972670c2007c1c5a51b4f0876d31476858f79351Fredrik Höglund
1009971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->event_id = xcb_generate_id(chain->conn);
1010971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_present_select_input(chain->conn, chain->event_id, chain->window,
1011971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                            XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY |
1012971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                            XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY |
1013971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                            XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);
1014971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1015971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   /* Create an XCB event queue to hold present events outside of the usual
1016971523410fd2235e13c617b6a1569f70486258d7Dave Airlie    * application event queue
1017971523410fd2235e13c617b6a1569f70486258d7Dave Airlie    */
1018971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->special_event =
1019971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      xcb_register_for_special_xge(chain->conn, &xcb_present_id,
1020971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                   chain->event_id, NULL);
1021971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1022971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   chain->gc = xcb_generate_id(chain->conn);
1023971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (!chain->gc) {
1024971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      /* FINISHME: Choose a better error. */
1025971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      result = VK_ERROR_OUT_OF_HOST_MEMORY;
1026971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      goto fail_register;
1027971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
1028971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1029971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   cookie = xcb_create_gc(chain->conn,
1030971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                          chain->gc,
1031971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                          chain->window,
1032971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                          XCB_GC_GRAPHICS_EXPOSURES,
1033971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                          (uint32_t []) { 0 });
1034971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_discard_reply(chain->conn, cookie.sequence);
1035971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1036971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   uint32_t image = 0;
1037971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   for (; image < chain->image_count; image++) {
1038971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      result = x11_image_init(device, chain, pCreateInfo, pAllocator,
1039971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                              &chain->images[image]);
1040971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      if (result != VK_SUCCESS)
1041971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         goto fail_init_images;
1042971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
1043971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1044e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) {
1045e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      chain->threaded = true;
1046e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
1047e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      /* Initialize our queues.  We make them image_count + 1 because we will
1048e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand       * occasionally use UINT32_MAX to signal the other thread that an error
1049e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand       * has occurred and we don't want an overflow.
1050e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand       */
1051e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      int ret;
1052e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      ret = wsi_queue_init(&chain->acquire_queue, chain->image_count + 1);
1053e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      if (ret) {
1054e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         goto fail_init_images;
1055e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      }
1056e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
1057e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      ret = wsi_queue_init(&chain->present_queue, chain->image_count + 1);
1058e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      if (ret) {
1059e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         wsi_queue_destroy(&chain->acquire_queue);
1060e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         goto fail_init_images;
1061e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      }
1062e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
1063e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      for (unsigned i = 0; i < chain->image_count; i++)
1064e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         wsi_queue_push(&chain->acquire_queue, i);
1065e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
1066e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      ret = pthread_create(&chain->queue_manager, NULL,
1067e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand                           x11_manage_fifo_queues, chain);
1068e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      if (ret) {
1069e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         wsi_queue_destroy(&chain->present_queue);
1070e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         wsi_queue_destroy(&chain->acquire_queue);
1071e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand         goto fail_init_images;
1072e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand      }
1073e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand   }
1074e73d136a02308088cacab842790c7670e5d07b23Jason Ekstrand
1075971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   *swapchain_out = &chain->base;
1076971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1077971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return VK_SUCCESS;
1078971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1079971523410fd2235e13c617b6a1569f70486258d7Dave Airliefail_init_images:
1080971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   for (uint32_t j = 0; j < image; j++)
1081971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      x11_image_finish(chain, pAllocator, &chain->images[j]);
1082971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1083971523410fd2235e13c617b6a1569f70486258d7Dave Airliefail_register:
1084971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   xcb_unregister_for_special_event(chain->conn, chain->special_event);
1085971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1086971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   vk_free(pAllocator, chain);
1087971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1088971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return result;
1089971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
1090971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1091971523410fd2235e13c617b6a1569f70486258d7Dave AirlieVkResult
1092ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airliewsi_x11_init_wsi(struct wsi_device *wsi_device,
1093971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                 const VkAllocationCallbacks *alloc)
1094971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
1095971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct wsi_x11 *wsi;
1096971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   VkResult result;
1097971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1098971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi = vk_alloc(alloc, sizeof(*wsi), 8,
1099971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                   VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1100971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (!wsi) {
1101971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      result = VK_ERROR_OUT_OF_HOST_MEMORY;
1102971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      goto fail;
1103971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
1104971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1105971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   int ret = pthread_mutex_init(&wsi->mutex, NULL);
1106971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (ret != 0) {
1107971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      if (ret == ENOMEM) {
1108971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         result = VK_ERROR_OUT_OF_HOST_MEMORY;
1109971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      } else {
1110971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         /* FINISHME: Choose a better error. */
1111971523410fd2235e13c617b6a1569f70486258d7Dave Airlie         result = VK_ERROR_OUT_OF_HOST_MEMORY;
1112971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      }
1113971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1114971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      goto fail_alloc;
1115971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
1116971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1117971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi->connections = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
1118971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                                              _mesa_key_pointer_equal);
1119971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (!wsi->connections) {
1120971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      result = VK_ERROR_OUT_OF_HOST_MEMORY;
1121971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      goto fail_mutex;
1122971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
1123971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1124971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi->base.get_support = x11_surface_get_support;
1125971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi->base.get_capabilities = x11_surface_get_capabilities;
1126971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi->base.get_formats = x11_surface_get_formats;
1127971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi->base.get_present_modes = x11_surface_get_present_modes;
1128971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi->base.create_swapchain = x11_surface_create_swapchain;
1129971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1130971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi_device->wsi[VK_ICD_WSI_PLATFORM_XCB] = &wsi->base;
1131971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi_device->wsi[VK_ICD_WSI_PLATFORM_XLIB] = &wsi->base;
1132971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1133971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return VK_SUCCESS;
1134971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1135971523410fd2235e13c617b6a1569f70486258d7Dave Airliefail_mutex:
1136971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   pthread_mutex_destroy(&wsi->mutex);
1137971523410fd2235e13c617b6a1569f70486258d7Dave Airliefail_alloc:
1138971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   vk_free(alloc, wsi);
1139971523410fd2235e13c617b6a1569f70486258d7Dave Airliefail:
1140971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi_device->wsi[VK_ICD_WSI_PLATFORM_XCB] = NULL;
1141971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   wsi_device->wsi[VK_ICD_WSI_PLATFORM_XLIB] = NULL;
1142971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1143971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   return result;
1144971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
1145971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1146971523410fd2235e13c617b6a1569f70486258d7Dave Airlievoid
1147ec0bc14a700c2503d834ac0763f4cfbe312998faDave Airliewsi_x11_finish_wsi(struct wsi_device *wsi_device,
1148971523410fd2235e13c617b6a1569f70486258d7Dave Airlie                   const VkAllocationCallbacks *alloc)
1149971523410fd2235e13c617b6a1569f70486258d7Dave Airlie{
1150971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   struct wsi_x11 *wsi =
1151971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      (struct wsi_x11 *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_XCB];
1152971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1153971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   if (wsi) {
1154daeb21e47845795d0320811db1e202540fba356bJason Ekstrand      struct hash_entry *entry;
1155daeb21e47845795d0320811db1e202540fba356bJason Ekstrand      hash_table_foreach(wsi->connections, entry)
1156daeb21e47845795d0320811db1e202540fba356bJason Ekstrand         wsi_x11_connection_destroy(alloc, entry->data);
1157daeb21e47845795d0320811db1e202540fba356bJason Ekstrand
1158971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      _mesa_hash_table_destroy(wsi->connections, NULL);
1159971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1160971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      pthread_mutex_destroy(&wsi->mutex);
1161971523410fd2235e13c617b6a1569f70486258d7Dave Airlie
1162971523410fd2235e13c617b6a1569f70486258d7Dave Airlie      vk_free(alloc, wsi);
1163971523410fd2235e13c617b6a1569f70486258d7Dave Airlie   }
1164971523410fd2235e13c617b6a1569f70486258d7Dave Airlie}
1165