blob: 79f83d8c93941e18ca6b7db93b795b80cd06b122 [file] [log] [blame]
Chia-I Wu1db76e02014-09-15 14:21:14 +08001/*
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002 * Vulkan
Chia-I Wu1db76e02014-09-15 14:21:14 +08003 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Ian Elliott4f299362015-07-06 14:45:11 -060026 * Ian Elliott <ian@lunarg.com>
Chia-I Wu1db76e02014-09-15 14:21:14 +080027 */
28
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <unistd.h>
32#include <fcntl.h>
33#include <xcb/xcb.h>
34#include <xcb/dri3.h>
35#include <xcb/present.h>
36
37#include "kmd/winsys.h"
Chia-I Wu8635e912015-04-09 14:13:57 +080038#include "kmd/libdrm/xf86drmMode.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080039#include "dev.h"
40#include "fence.h"
41#include "gpu.h"
42#include "img.h"
43#include "mem.h"
44#include "queue.h"
Chia-I Wu41858c82015-04-04 16:39:25 +080045#include "wsi.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080046
Chia-I Wu8635e912015-04-09 14:13:57 +080047struct intel_x11_display {
48 struct intel_handle handle;
49
50 int fd;
51 uint32_t connector_id;
52
53 char name[32];
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -060054 VkExtent2D physical_dimension;
55 VkExtent2D physical_resolution;
Chia-I Wu8635e912015-04-09 14:13:57 +080056
57 drmModeModeInfoPtr modes;
58 uint32_t mode_count;
59};
60
Ian Elliott4f299362015-07-06 14:45:11 -060061typedef enum intel_x11_swap_chain_image_state_
62{
63 INTEL_SC_STATE_UNUSED = 0,
64 INTEL_SC_STATE_APP_OWNED = 1,
65 INTEL_SC_STATE_QUEUED_FOR_PRESENT = 2,
66 INTEL_SC_STATE_DISPLAYED = 3,
67} intel_x11_swap_chain_image_state;
68
Chia-I Wu6532d1d2015-04-04 22:16:45 +080069struct intel_x11_swap_chain {
70 struct intel_handle handle;
71
72 xcb_connection_t *c;
73 xcb_window_t window;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080074 bool force_copy;
Ian Elliott4f299362015-07-06 14:45:11 -060075 VkPresentModeWSI present_mode;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080076
77 int dri3_major, dri3_minor;
78 int present_major, present_minor;
Chia-I Wu1db76e02014-09-15 14:21:14 +080079
80 xcb_present_event_t present_special_event_id;
81 xcb_special_event_t *present_special_event;
82
Chia-I Wu5b66aa52015-04-16 22:02:10 +080083 struct intel_img **persistent_images;
84 uint32_t persistent_image_count;
Ian Elliott4f299362015-07-06 14:45:11 -060085 intel_x11_swap_chain_image_state *image_state;
86 uint32_t *present_queue;
87 uint32_t present_queue_length;
Mike Stroyanf9f6dd72015-07-28 11:00:50 -060088 uint32_t present_serial;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080089
Chia-I Wu1db76e02014-09-15 14:21:14 +080090 struct {
91 uint32_t serial;
92 } local;
93
94 struct {
95 uint32_t serial;
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -060096 uint64_t msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +080097 } remote;
98};
99
Chia-I Wu41858c82015-04-04 16:39:25 +0800100struct intel_x11_img_data {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800101 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +0800102 struct intel_mem *mem;
103 int prime_fd;
104 uint32_t pixmap;
105};
106
107struct intel_x11_fence_data {
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800108 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +0800109 uint32_t serial;
110};
111
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800112/* these are what DDX expects */
113static const VkFormat x11_presentable_formats[] = {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800114 VK_FORMAT_B8G8R8A8_UNORM,
115 VK_FORMAT_B8G8R8A8_SRGB,
Ian Elliott32536f92015-04-21 16:41:02 -0600116 VK_FORMAT_B5G6R5_UNORM,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800117};
118
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800119static inline struct intel_x11_swap_chain *x11_swap_chain(VkSwapChainWSI sc)
120{
Ian Elliott4f299362015-07-06 14:45:11 -0600121 return (struct intel_x11_swap_chain *) sc.handle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800122}
123
Chia-I Wufcbc5252015-04-08 11:44:26 +0800124static bool x11_is_format_presentable(const struct intel_dev *dev,
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600125 VkFormat format)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800126{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800127 uint32_t i;
128
129 for (i = 0; i < ARRAY_SIZE(x11_presentable_formats); i++) {
130 if (x11_presentable_formats[i] == format)
131 return true;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800132 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800133
134 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800135}
136
Chia-I Wu030b2db2015-04-08 13:46:29 +0800137static int x11_export_prime_fd(struct intel_dev *dev,
138 struct intel_bo *bo,
139 const struct intel_layout *layout)
140{
141 struct intel_winsys_handle export;
142 enum intel_tiling_mode tiling;
143
144 export.type = INTEL_WINSYS_HANDLE_FD;
145
146 switch (layout->tiling) {
147 case GEN6_TILING_X:
148 tiling = INTEL_TILING_X;
149 break;
150 case GEN6_TILING_Y:
151 tiling = INTEL_TILING_Y;
152 break;
153 default:
154 assert(layout->tiling == GEN6_TILING_NONE);
155 tiling = INTEL_TILING_NONE;
156 break;
157 }
158
159 if (intel_bo_set_tiling(bo, tiling, layout->bo_stride))
160 return -1;
161
162 if (intel_winsys_export_handle(dev->winsys, bo, tiling,
163 layout->bo_stride, layout->bo_height, &export))
164 return -1;
165
166 return (int) export.handle;
167}
168
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800169/**
Chia-I Wufcbc5252015-04-08 11:44:26 +0800170 * Return true if fd points to the primary or render node of the GPU.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800171 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800172static bool x11_gpu_match_fd(const struct intel_gpu *gpu, int fd)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800173{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800174 struct stat fd_stat, gpu_stat;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800175
Chia-I Wufcbc5252015-04-08 11:44:26 +0800176 if (fstat(fd, &fd_stat))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800177 return false;
178
179 /* is it the primary node? */
180 if (!stat(gpu->primary_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800181 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800182 return true;
183
184 /* is it the render node? */
185 if (gpu->render_node && !stat(gpu->render_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800186 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800187 return true;
188
189 return false;
190}
191
Chia-I Wufcbc5252015-04-08 11:44:26 +0800192/*
193 * Return the depth of \p drawable.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800194 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800195static int x11_get_drawable_depth(xcb_connection_t *c,
196 xcb_drawable_t drawable)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800197{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800198 xcb_get_geometry_cookie_t cookie;
199 xcb_get_geometry_reply_t *reply;
200 uint8_t depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800201
Chia-I Wufcbc5252015-04-08 11:44:26 +0800202 cookie = xcb_get_geometry(c, drawable);
203 reply = xcb_get_geometry_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800204
Chia-I Wufcbc5252015-04-08 11:44:26 +0800205 if (reply) {
206 depth = reply->depth;
207 free(reply);
208 } else {
209 depth = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800210 }
211
Chia-I Wufcbc5252015-04-08 11:44:26 +0800212 return depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800213}
214
Ian Elliott4f299362015-07-06 14:45:11 -0600215static VkResult x11_get_surface_properties(
216 const VkSurfaceDescriptionWSI *pSurfaceDescription,
217 VkSurfacePropertiesWSI *pSurfaceProperties)
218{
219 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
220 (VkSurfaceDescriptionWindowWSI*) pSurfaceDescription;
221 VkPlatformHandleXcbWSI *pPlatformHandleXcb = (VkPlatformHandleXcbWSI *)
222 pSurfaceDescriptionWindow->pPlatformHandle;
223 xcb_connection_t *c = (xcb_connection_t *)
224 pPlatformHandleXcb->connection;
225 xcb_window_t window = *((xcb_window_t *)
226 pSurfaceDescriptionWindow->pPlatformWindow);
227 xcb_get_geometry_cookie_t cookie;
228 xcb_get_geometry_reply_t *reply;
229
230 cookie = xcb_get_geometry(c, window);
231 reply = xcb_get_geometry_reply(c, cookie, NULL);
232
233 if (reply) {
234 pSurfaceProperties->currentExtent.width = reply->width;
235 pSurfaceProperties->currentExtent.height = reply->height;
236 free(reply);
237 } else {
238 pSurfaceProperties->currentExtent.width = 0;
239 pSurfaceProperties->currentExtent.height = 0;
240 }
241
242 pSurfaceProperties->minImageCount = 2;
243 pSurfaceProperties->maxImageCount = 0;
244
245 pSurfaceProperties->minImageExtent.width =
246 pSurfaceProperties->currentExtent.width;
247 pSurfaceProperties->minImageExtent.height =
248 pSurfaceProperties->currentExtent.height;
249 pSurfaceProperties->maxImageExtent.width =
250 pSurfaceProperties->currentExtent.width;
251 pSurfaceProperties->maxImageExtent.height =
252 pSurfaceProperties->currentExtent.height;
253 pSurfaceProperties->supportedTransforms = VK_SURFACE_TRANSFORM_NONE_BIT_WSI;
254 pSurfaceProperties->currentTransform = VK_SURFACE_TRANSFORM_NONE_WSI;
255 pSurfaceProperties->maxImageArraySize = 0;
256 pSurfaceProperties->supportedUsageFlags =
257 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
258
259 return VK_SUCCESS;
260}
261
Chia-I Wu1db76e02014-09-15 14:21:14 +0800262/**
263 * Return true if DRI3 and Present are supported by the server.
264 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800265static bool x11_is_dri3_and_present_supported(xcb_connection_t *c)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800266{
267 const xcb_query_extension_reply_t *ext;
268
Chia-I Wufcbc5252015-04-08 11:44:26 +0800269 xcb_prefetch_extension_data(c, &xcb_dri3_id);
270 xcb_prefetch_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800271
Chia-I Wufcbc5252015-04-08 11:44:26 +0800272 ext = xcb_get_extension_data(c, &xcb_dri3_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800273 if (!ext || !ext->present)
274 return false;
275
Chia-I Wufcbc5252015-04-08 11:44:26 +0800276 ext = xcb_get_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800277 if (!ext || !ext->present)
278 return false;
279
280 return true;
281}
282
283/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800284 * Send a DRI3Open to get the server GPU fd.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800285 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800286static int x11_dri3_open(xcb_connection_t *c,
287 xcb_drawable_t drawable,
288 xcb_randr_provider_t provider)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800289{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800290 xcb_dri3_open_cookie_t cookie;
291 xcb_dri3_open_reply_t *reply;
292 int fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800293
Chia-I Wufcbc5252015-04-08 11:44:26 +0800294 cookie = xcb_dri3_open(c, drawable, provider);
295 reply = xcb_dri3_open_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800296 if (!reply)
Chia-I Wufcbc5252015-04-08 11:44:26 +0800297 return -1;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800298
Chia-I Wufcbc5252015-04-08 11:44:26 +0800299 fd = (reply->nfd == 1) ? xcb_dri3_open_reply_fds(c, reply)[0] : -1;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800300 free(reply);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800301
Chia-I Wufcbc5252015-04-08 11:44:26 +0800302 return fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800303}
304
305/**
Chia-I Wu030b2db2015-04-08 13:46:29 +0800306 * Send a DRI3PixmapFromBuffer to create a pixmap from \p prime_fd.
307 */
308static xcb_pixmap_t x11_dri3_pixmap_from_buffer(xcb_connection_t *c,
309 xcb_drawable_t drawable,
310 uint8_t depth, int prime_fd,
311 const struct intel_layout *layout)
312{
313 xcb_pixmap_t pixmap;
314
315 pixmap = xcb_generate_id(c);
316
317 xcb_dri3_pixmap_from_buffer(c, pixmap, drawable,
318 layout->bo_stride * layout->bo_height,
319 layout->width0, layout->height0,
320 layout->bo_stride, depth,
321 layout->block_size * 8, prime_fd);
322
323 return pixmap;
324}
325
326/**
Chia-I Wu41858c82015-04-04 16:39:25 +0800327 * Send DRI3QueryVersion and PresentQueryVersion to query extension versions.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800328 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800329static bool x11_swap_chain_dri3_and_present_query_version(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800330{
331 xcb_dri3_query_version_cookie_t dri3_cookie;
332 xcb_dri3_query_version_reply_t *dri3_reply;
333 xcb_present_query_version_cookie_t present_cookie;
334 xcb_present_query_version_reply_t *present_reply;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800335
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800336 dri3_cookie = xcb_dri3_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800337 XCB_DRI3_MAJOR_VERSION, XCB_DRI3_MINOR_VERSION);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800338 present_cookie = xcb_present_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800339 XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION);
340
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800341 dri3_reply = xcb_dri3_query_version_reply(sc->c, dri3_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800342 if (!dri3_reply)
343 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800344
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800345 sc->dri3_major = dri3_reply->major_version;
346 sc->dri3_minor = dri3_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800347 free(dri3_reply);
348
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800349 present_reply = xcb_present_query_version_reply(sc->c, present_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800350 if (!present_reply)
351 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800352
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800353 sc->present_major = present_reply->major_version;
354 sc->present_minor = present_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800355 free(present_reply);
356
Chia-I Wu41858c82015-04-04 16:39:25 +0800357 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800358}
359
360/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800361 * Send a PresentSelectInput to select interested events.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800362 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800363static bool x11_swap_chain_present_select_input(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800364{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800365 xcb_void_cookie_t cookie;
366 xcb_generic_error_t *error;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800367
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800368 /* create the event queue */
369 sc->present_special_event_id = xcb_generate_id(sc->c);
370 sc->present_special_event = xcb_register_for_special_xge(sc->c,
371 &xcb_present_id, sc->present_special_event_id, NULL);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800372
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800373 cookie = xcb_present_select_input_checked(sc->c,
374 sc->present_special_event_id, sc->window,
375 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800376
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800377 error = xcb_request_check(sc->c, cookie);
378 if (error) {
379 free(error);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800380 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800381 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800382
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800383 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800384}
385
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800386static struct intel_img *x11_swap_chain_create_persistent_image(struct intel_x11_swap_chain *sc,
387 struct intel_dev *dev,
388 const VkImageCreateInfo *img_info)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800389{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800390 struct intel_img *img;
391 struct intel_mem *mem;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800392 struct intel_x11_img_data *data;
393 VkMemoryAllocInfo mem_info;
394 int prime_fd;
395 xcb_pixmap_t pixmap;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600396 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800397
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800398 ret = intel_img_create(dev, img_info, true, &img);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600399 if (ret != VK_SUCCESS)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800400 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800401
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800402 memset(&mem_info, 0, sizeof(mem_info));
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600403 mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800404 mem_info.allocationSize = img->total_size;
Mark Lobodzinski72346292015-07-02 16:49:40 -0600405 mem_info.memoryTypeIndex = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800406
407 ret = intel_mem_alloc(dev, &mem_info, &mem);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600408 if (ret != VK_SUCCESS) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800409 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800410 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800411 }
412
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800413 prime_fd = x11_export_prime_fd(dev, mem->bo, &img->layout);
414 if (prime_fd < 0) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800415 intel_mem_free(mem);
416 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800417 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800418 }
419
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800420 pixmap = x11_dri3_pixmap_from_buffer(sc->c, sc->window,
421 x11_get_drawable_depth(sc->c, sc->window),
422 prime_fd, &img->layout);
423
424 data = (struct intel_x11_img_data *) img->wsi_data;
425 data->swap_chain = sc;
426 data->mem = mem;
427 data->prime_fd = prime_fd;
428 data->pixmap = pixmap;
429
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800430 intel_obj_bind_mem(&img->obj, mem, 0);
431
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800432 return img;
433}
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800434
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800435static bool x11_swap_chain_create_persistent_images(struct intel_x11_swap_chain *sc,
436 struct intel_dev *dev,
437 const VkSwapChainCreateInfoWSI *info)
438{
439 struct intel_img **images;
Ian Elliott4f299362015-07-06 14:45:11 -0600440 intel_x11_swap_chain_image_state *image_state;
441 uint32_t *present_queue;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800442 VkImageCreateInfo img_info;
443 uint32_t i;
444
Ian Elliott4f299362015-07-06 14:45:11 -0600445 images = intel_alloc(sc, sizeof(*images) * info->minImageCount,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800446 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
447 if (!images)
448 return false;
Ian Elliott4f299362015-07-06 14:45:11 -0600449 image_state = intel_alloc(
450 sc, sizeof(intel_x11_swap_chain_image_state) * info->minImageCount,
451 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
452 if (!image_state) {
453 for (i = 0; i < info->minImageCount; i++) {
454 intel_img_destroy(images[i]);
455 }
456 intel_free(sc, images);
457 return false;
458 }
459 present_queue = intel_alloc(
460 sc, sizeof(uint32_t) * info->minImageCount,
461 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
462 if (!present_queue) {
463 for (i = 0; i < info->minImageCount; i++) {
464 intel_img_destroy(images[i]);
465 }
466 intel_free(sc, images);
467 intel_free(sc, image_state);
468 return false;
469 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800470
471 memset(&img_info, 0, sizeof(img_info));
472 img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
473 img_info.imageType = VK_IMAGE_TYPE_2D;
474 img_info.format = info->imageFormat;
475 img_info.extent.width = info->imageExtent.width;
476 img_info.extent.height = info->imageExtent.height;
477 img_info.extent.depth = 1;
478 img_info.mipLevels = 1;
479 img_info.arraySize = info->imageArraySize;
480 img_info.samples = 1;
481 img_info.tiling = VK_IMAGE_TILING_OPTIMAL;
482 img_info.usage = info->imageUsageFlags;
483 img_info.flags = 0;
484
Ian Elliott4f299362015-07-06 14:45:11 -0600485 for (i = 0; i < info->minImageCount; i++) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800486 images[i] = x11_swap_chain_create_persistent_image(sc,
487 dev, &img_info);
488 if (!images[i])
489 break;
Ian Elliott4f299362015-07-06 14:45:11 -0600490 image_state[i] = INTEL_SC_STATE_UNUSED;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800491 }
492
Ian Elliott4f299362015-07-06 14:45:11 -0600493 if (i < info->minImageCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800494 uint32_t j;
495 for (j = 0; j < i; j++)
Ian Elliott4f299362015-07-06 14:45:11 -0600496 intel_img_destroy(images[j]);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800497
498 intel_free(sc, images);
499
Ian Elliott4f299362015-07-06 14:45:11 -0600500 if (image_state) {
501 intel_free(sc, image_state);
502 }
503
504 if (present_queue) {
505 intel_free(sc, present_queue);
506 }
507
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800508 return false;
509 }
510
511 sc->persistent_images = images;
Ian Elliott4f299362015-07-06 14:45:11 -0600512 sc->persistent_image_count = info->minImageCount;
513 sc->image_state = image_state;
514 sc->present_queue = present_queue;
515 sc->present_queue_length = 0;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800516
517 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800518}
519
520/**
521 * Send a PresentPixmap.
522 */
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600523static VkResult x11_swap_chain_present_pixmap(struct intel_x11_swap_chain *sc,
Ian Elliott4f299362015-07-06 14:45:11 -0600524 struct intel_img *img)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800525{
Chia-I Wu41858c82015-04-04 16:39:25 +0800526 struct intel_x11_img_data *data =
527 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800528 uint32_t options = XCB_PRESENT_OPTION_NONE;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800529 uint32_t target_msc, divisor, remainder;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800530 xcb_void_cookie_t cookie;
531 xcb_generic_error_t *err;
532
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800533 target_msc = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600534 divisor = 1;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800535 remainder = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600536 if (sc->present_mode == VK_PRESENT_MODE_IMMEDIATE_WSI) {
Chia-I Wu1db76e02014-09-15 14:21:14 +0800537 options |= XCB_PRESENT_OPTION_ASYNC;
Ian Elliott4f299362015-07-06 14:45:11 -0600538 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800539
540 if (sc->force_copy)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800541 options |= XCB_PRESENT_OPTION_COPY;
542
Chia-I Wuf689c602015-04-28 10:55:52 +0800543 cookie = xcb_present_pixmap_checked(sc->c,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800544 sc->window,
Chia-I Wu41858c82015-04-04 16:39:25 +0800545 data->pixmap,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800546 ++sc->local.serial,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800547 0, /* valid-area */
548 0, /* update-area */
549 0, /* x-off */
550 0, /* y-off */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800551 0, /* crtc */
Chia-I Wu1db76e02014-09-15 14:21:14 +0800552 0, /* wait-fence */
553 0, /* idle-fence */
554 options,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800555 target_msc,
556 divisor,
557 remainder,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800558 0, NULL);
559
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800560 err = xcb_request_check(sc->c, cookie);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800561 if (err) {
562 free(err);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600563 return VK_ERROR_UNKNOWN;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800564 }
565
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600566 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800567}
568
569/**
Chia-I Wu1db76e02014-09-15 14:21:14 +0800570 * Handle a Present event.
571 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800572static void x11_swap_chain_present_event(struct intel_x11_swap_chain *sc,
573 const xcb_present_generic_event_t *ev)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800574{
575 union {
576 const xcb_present_generic_event_t *ev;
577 const xcb_present_complete_notify_event_t *complete;
578 } u = { .ev = ev };
579
580 switch (u.ev->evtype) {
581 case XCB_PRESENT_COMPLETE_NOTIFY:
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800582 sc->remote.serial = u.complete->serial;
583 sc->remote.msc = u.complete->msc;
Ian Elliott4f299362015-07-06 14:45:11 -0600584 assert(sc->present_queue_length > 0);
585 if (sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_DISPLAYED) {
586 // Remove the previously-displayed image from the present queue:
587 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_UNUSED;
588 sc->present_queue_length--;
589 for (int j = 0; j < sc->present_queue_length; j++) {
590 sc->present_queue[j] = sc->present_queue[j+1];
591 }
592 }
593 assert(sc->present_queue_length > 0);
594 assert(sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_QUEUED_FOR_PRESENT);
595 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_DISPLAYED;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800596 break;
597 default:
598 break;
599 }
600}
601
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600602static VkResult x11_swap_chain_wait(struct intel_x11_swap_chain *sc,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800603 uint32_t serial, int64_t timeout)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800604{
605 const bool wait = (timeout != 0);
606
607 while (sc->remote.serial < serial) {
608 xcb_present_generic_event_t *ev;
Mike Stroyan4a387162015-04-27 15:42:41 -0600609 xcb_intern_atom_reply_t *reply;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800610
611 if (wait) {
612 ev = (xcb_present_generic_event_t *)
613 xcb_wait_for_special_event(sc->c, sc->present_special_event);
Mike Stroyan4a387162015-04-27 15:42:41 -0600614 /* use xcb_intern_atom_reply just to wake other threads waiting on sc->c */
615 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
616 if (reply) {
617 free(reply);
618 }
619
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800620 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600621 return VK_ERROR_UNKNOWN;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800622 } else {
Mike Stroyan4a387162015-04-27 15:42:41 -0600623 /* use xcb_intern_atom_reply just to check socket for special event */
624 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
625 if (reply) {
626 free(reply);
627 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800628 ev = (xcb_present_generic_event_t *)
629 xcb_poll_for_special_event(sc->c, sc->present_special_event);
630 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600631 return VK_NOT_READY;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800632 }
633
634 x11_swap_chain_present_event(sc, ev);
635
636 free(ev);
637 }
638
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600639 return VK_SUCCESS;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800640}
641
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800642static void x11_swap_chain_destroy(struct intel_x11_swap_chain *sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800643{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800644 if (sc->persistent_images) {
645 uint32_t i;
646
647 for (i = 0; i < sc->persistent_image_count; i++)
648 intel_img_destroy(sc->persistent_images[i]);
649 intel_free(sc, sc->persistent_images);
650 }
651
Ian Elliott4f299362015-07-06 14:45:11 -0600652 if (sc->image_state) {
653 intel_free(sc, sc->image_state);
654 }
655
656 if (sc->present_queue) {
657 intel_free(sc, sc->present_queue);
658 }
659
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800660 if (sc->present_special_event)
661 xcb_unregister_for_special_event(sc->c, sc->present_special_event);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800662
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800663 intel_free(sc, sc);
664}
665
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800666static VkResult x11_swap_chain_create(struct intel_dev *dev,
667 const VkSwapChainCreateInfoWSI *info,
668 struct intel_x11_swap_chain **sc_ret)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800669{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800670 const xcb_randr_provider_t provider = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600671 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
672 (VkSurfaceDescriptionWindowWSI*) info->pSurfaceDescription;
673 VkPlatformHandleXcbWSI *pPlatformHandleXcb = (VkPlatformHandleXcbWSI *)
674 pSurfaceDescriptionWindow->pPlatformHandle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800675 xcb_connection_t *c = (xcb_connection_t *)
Ian Elliott4f299362015-07-06 14:45:11 -0600676 pPlatformHandleXcb->connection;
677 xcb_window_t window = *((xcb_window_t *)
678 pSurfaceDescriptionWindow->pPlatformWindow);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800679 struct intel_x11_swap_chain *sc;
680 int fd;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800681
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800682 if (!x11_is_format_presentable(dev, info->imageFormat)) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600683 intel_dev_log(dev, VK_DBG_REPORT_ERROR_BIT,
684 VK_NULL_HANDLE, 0, 0, "invalid presentable image format");
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800685 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800686 }
687
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800688 if (!x11_is_dri3_and_present_supported(c))
689 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800690
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800691 fd = x11_dri3_open(c, window, provider);
692 if (fd < 0 || !x11_gpu_match_fd(dev->gpu, fd)) {
Chia-I Wufcbc5252015-04-08 11:44:26 +0800693 if (fd >= 0)
694 close(fd);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800695 return VK_ERROR_INVALID_VALUE;
Chia-I Wufcbc5252015-04-08 11:44:26 +0800696 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800697
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800698 close(fd);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800699
Tony Barbour8205d902015-04-16 15:59:00 -0600700 sc = intel_alloc(dev, sizeof(*sc), 0, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800701 if (!sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800702 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800703
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800704 memset(sc, 0, sizeof(*sc));
Courtney Goeltzenleuchter9ecf6852015-06-09 08:22:48 -0600705 intel_handle_init(&sc->handle, VK_OBJECT_TYPE_SWAP_CHAIN_WSI, dev->base.handle.instance);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800706
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800707 sc->c = c;
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800708 sc->window = window;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800709
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800710 /* always copy unless flip bit is set */
Ian Elliott4f299362015-07-06 14:45:11 -0600711 sc->present_mode = info->presentMode;
712 sc->force_copy = true;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800713
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800714 if (!x11_swap_chain_dri3_and_present_query_version(sc) ||
715 !x11_swap_chain_present_select_input(sc) ||
716 !x11_swap_chain_create_persistent_images(sc, dev, info)) {
717 x11_swap_chain_destroy(sc);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600718 return VK_ERROR_UNKNOWN;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800719 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800720
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800721 *sc_ret = sc;
Chia-I Wu41858c82015-04-04 16:39:25 +0800722
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600723 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800724}
725
Chia-I Wu8635e912015-04-09 14:13:57 +0800726static void x11_display_destroy(struct intel_x11_display *dpy)
727{
728 intel_free(dpy, dpy->modes);
729 intel_free(dpy, dpy);
730}
731
Chia-I Wu41858c82015-04-04 16:39:25 +0800732void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
733{
Chia-I Wu8635e912015-04-09 14:13:57 +0800734 if (gpu->displays) {
735 uint32_t i;
Chia-I Wu41858c82015-04-04 16:39:25 +0800736
Chia-I Wu8635e912015-04-09 14:13:57 +0800737 for (i = 0; i < gpu->display_count; i++) {
738 struct intel_x11_display *dpy =
739 (struct intel_x11_display *) gpu->displays[i];
740 x11_display_destroy(dpy);
741 }
742 intel_free(gpu, gpu->displays);
743 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800744}
745
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600746VkResult intel_wsi_img_init(struct intel_img *img)
Chia-I Wu41858c82015-04-04 16:39:25 +0800747{
748 struct intel_x11_img_data *data;
749
Tony Barbour8205d902015-04-16 15:59:00 -0600750 data = intel_alloc(img, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800751 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600752 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800753
754 memset(data, 0, sizeof(*data));
755
756 assert(!img->wsi_data);
757 img->wsi_data = data;
758
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600759 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800760}
761
762void intel_wsi_img_cleanup(struct intel_img *img)
763{
764 struct intel_x11_img_data *data =
765 (struct intel_x11_img_data *) img->wsi_data;
766
767 if (data->mem) {
768 close(data->prime_fd);
769 intel_mem_free(data->mem);
770 }
771
772 intel_free(img, img->wsi_data);
773}
774
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600775VkResult intel_wsi_fence_init(struct intel_fence *fence)
Chia-I Wu41858c82015-04-04 16:39:25 +0800776{
777 struct intel_x11_fence_data *data;
778
Tony Barbour8205d902015-04-16 15:59:00 -0600779 data = intel_alloc(fence, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800780 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600781 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800782
783 memset(data, 0, sizeof(*data));
784
785 assert(!fence->wsi_data);
786 fence->wsi_data = data;
787
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600788 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800789}
790
791void intel_wsi_fence_cleanup(struct intel_fence *fence)
792{
793 intel_free(fence, fence->wsi_data);
794}
795
796void intel_wsi_fence_copy(struct intel_fence *fence,
797 const struct intel_fence *src)
798{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600799 if (!fence->wsi_data) {
800 return;
801 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800802 memcpy(fence->wsi_data, src->wsi_data,
803 sizeof(struct intel_x11_fence_data));
804}
805
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600806VkResult intel_wsi_fence_wait(struct intel_fence *fence,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800807 int64_t timeout_ns)
Chia-I Wu41858c82015-04-04 16:39:25 +0800808{
809 struct intel_x11_fence_data *data =
810 (struct intel_x11_fence_data *) fence->wsi_data;
811
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600812 if (!data)
813 return VK_SUCCESS;
814
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800815 if (!data->swap_chain)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600816 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800817
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800818 return x11_swap_chain_wait(data->swap_chain, data->serial, timeout_ns);
Chia-I Wu41858c82015-04-04 16:39:25 +0800819}
820
Ian Elliott4f299362015-07-06 14:45:11 -0600821ICD_EXPORT VkResult VKAPI vkGetPhysicalDeviceSurfaceSupportWSI(
822 VkPhysicalDevice physicalDevice,
823 uint32_t queueNodeIndex,
824 const VkSurfaceDescriptionWSI* pSurfaceDescription,
825 VkBool32* pSupported)
826{
827 VkResult ret = VK_SUCCESS;
828 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
829 (VkSurfaceDescriptionWindowWSI*) pSurfaceDescription;
830
831 *pSupported = false;
832
833 // TODO: Move this check to a validation layer (i.e. the driver should
834 // assume the correct data type, and not check):
835 if (pSurfaceDescriptionWindow->sType != VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI) {
836 return VK_ERROR_INVALID_VALUE;
837 }
838
839 // TODO: NEED TO ALSO CHECK:
840 // - queueNodeIndex
841 // - pSurfaceDescriptionWindow->pPlatformHandle (can try to use it)
842 // - pSurfaceDescriptionWindow->pPlatformWindow (can try to use it)
843 if (pSurfaceDescriptionWindow->platform == VK_PLATFORM_XCB_WSI) {
844 *pSupported = true;
845 }
846
847 return ret;
848}
849
850VkResult VKAPI vkGetSurfaceInfoWSI(
851 VkDevice device,
852 const VkSurfaceDescriptionWSI* pSurfaceDescription,
853 VkSurfaceInfoTypeWSI infoType,
854 size_t* pDataSize,
855 void* pData)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800856{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800857 VkResult ret = VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800858
Ian Elliott4f299362015-07-06 14:45:11 -0600859 // TODO: Move this check to a validation layer (i.e. the driver should
860 // assume the correct data type, and not check):
861 if (!pDataSize) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800862 return VK_ERROR_INVALID_POINTER;
Ian Elliott4f299362015-07-06 14:45:11 -0600863 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800864
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800865 switch (infoType) {
Ian Elliott4f299362015-07-06 14:45:11 -0600866 case VK_SURFACE_INFO_TYPE_PROPERTIES_WSI:
867 *pDataSize = sizeof(VkSurfacePropertiesWSI);
868 if (pData) {
869 ret = x11_get_surface_properties(pSurfaceDescription, pData);
870 }
871 break;
872 case VK_SURFACE_INFO_TYPE_FORMATS_WSI:
873 *pDataSize = (sizeof(VkSurfaceFormatPropertiesWSI) *
874 ARRAY_SIZE(x11_presentable_formats));
875 if (pData) {
876 VkSurfaceFormatPropertiesWSI *dst = pData;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800877 uint32_t i;
Ian Elliott4f299362015-07-06 14:45:11 -0600878 uint32_t num_formats = ARRAY_SIZE(x11_presentable_formats);
879 for (i = 0; i < num_formats; i++) {
880 dst[i].format = x11_presentable_formats[i];
881 }
882 }
883 break;
884 case VK_SURFACE_INFO_TYPE_PRESENT_MODES_WSI:
885 *pDataSize = sizeof(VkSurfacePresentModePropertiesWSI) * 2;
886 if (pData) {
887 VkSurfacePresentModePropertiesWSI *dst = pData;
888 dst[0].presentMode = VK_PRESENT_MODE_IMMEDIATE_WSI;
889 dst[1].presentMode = VK_PRESENT_MODE_FIFO_WSI;
890 // TODO: Consider adding VK_PRESENT_MODE_MAILBOX_WSI sometime
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800891 }
892 break;
893 default:
894 ret = VK_ERROR_INVALID_VALUE;
895 break;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800896 }
897
898 return ret;
899}
900
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800901ICD_EXPORT VkResult VKAPI vkCreateSwapChainWSI(
902 VkDevice device,
903 const VkSwapChainCreateInfoWSI* pCreateInfo,
904 VkSwapChainWSI* pSwapChain)
905{
906 struct intel_dev *dev = intel_dev(device);
907
Ian Elliott4f299362015-07-06 14:45:11 -0600908 if (pCreateInfo->oldSwapChain.handle) {
909 // TODO: Eventually, do more than simply up-front destroy the
910 // oldSwapChain (but just do that for now):
911 struct intel_x11_swap_chain *sc =
912 x11_swap_chain(pCreateInfo->oldSwapChain);
913
914 x11_swap_chain_destroy(sc);
915 }
916
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800917 return x11_swap_chain_create(dev, pCreateInfo,
918 (struct intel_x11_swap_chain **) pSwapChain);
919}
920
921ICD_EXPORT VkResult VKAPI vkDestroySwapChainWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600922 VkDevice device,
923 VkSwapChainWSI swapChain)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800924{
925 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
926
927 x11_swap_chain_destroy(sc);
928
929 return VK_SUCCESS;
930}
931
932ICD_EXPORT VkResult VKAPI vkGetSwapChainInfoWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600933 VkDevice device,
934 VkSwapChainWSI swapChain,
935 VkSwapChainInfoTypeWSI infoType,
936 size_t* pDataSize,
937 void* pData)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800938{
939 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
940 VkResult ret = VK_SUCCESS;
941
Ian Elliott4f299362015-07-06 14:45:11 -0600942 // TODO: Move this check to a validation layer (i.e. the driver should
943 // assume the correct data type, and not check):
944 if (!pDataSize) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800945 return VK_ERROR_INVALID_POINTER;
Ian Elliott4f299362015-07-06 14:45:11 -0600946 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800947
948 switch (infoType) {
Ian Elliott4f299362015-07-06 14:45:11 -0600949 case VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI:
950 *pDataSize = (sizeof(VkSwapChainImagePropertiesWSI) *
951 sc->persistent_image_count);
952 if (pData) {
953 VkSwapChainImagePropertiesWSI *images =
954 (VkSwapChainImagePropertiesWSI *) pData;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800955 uint32_t i;
956
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800957 for (i = 0; i < sc->persistent_image_count; i++) {
Tony Barbourde4124d2015-07-03 10:33:54 -0600958 images[i].image.handle = (uint64_t) sc->persistent_images[i];
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800959 }
960 }
961 break;
962 default:
963 ret = VK_ERROR_INVALID_VALUE;
964 break;
965 }
966
967 return ret;
968}
969
Ian Elliott4f299362015-07-06 14:45:11 -0600970ICD_EXPORT VkResult VKAPI vkAcquireNextImageWSI(
971 VkDevice device,
972 VkSwapChainWSI swapChain,
973 uint64_t timeout,
974 VkSemaphore semaphore,
975 uint32_t* pImageIndex)
976{
977 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
978 VkResult ret = VK_SUCCESS;
979
Ian Elliott4f299362015-07-06 14:45:11 -0600980 // Find an unused image to return:
981 for (int i = 0; i < sc->persistent_image_count; i++) {
982 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
983 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
984 *pImageIndex = i;
985 return ret;
986 }
987 }
988
Mike Stroyanf9f6dd72015-07-28 11:00:50 -0600989 // If no image is ready, wait for a present to finish
990 ret = x11_swap_chain_wait(sc, sc->present_serial, timeout);
991 if (ret != VK_SUCCESS) {
992 return ret;
993 }
Ian Elliott4f299362015-07-06 14:45:11 -0600994
Mike Stroyanf9f6dd72015-07-28 11:00:50 -0600995 // Find an unused image to return:
996 for (int i = 0; i < sc->persistent_image_count; i++) {
997 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
998 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
999 *pImageIndex = i;
1000 return ret;
1001 }
1002 }
1003 // NOTE: Should never get here, but in case we do, do something:
1004 assert(0);
1005 return VK_ERROR_UNKNOWN;
Ian Elliott4f299362015-07-06 14:45:11 -06001006}
1007
1008
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001009ICD_EXPORT VkResult VKAPI vkQueuePresentWSI(
Ian Elliott4f299362015-07-06 14:45:11 -06001010 VkQueue queue_,
1011 VkPresentInfoWSI* pPresentInfo)
Chia-I Wu1db76e02014-09-15 14:21:14 +08001012{
1013 struct intel_queue *queue = intel_queue(queue_);
Ian Elliott4f299362015-07-06 14:45:11 -06001014 uint32_t i;
1015 uint32_t num_swapchains = pPresentInfo->swapChainCount;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001016
Ian Elliott4f299362015-07-06 14:45:11 -06001017 for (i = 0; i < num_swapchains; i++) {
1018 struct intel_x11_swap_chain *sc =
1019 x11_swap_chain(pPresentInfo->swapChains[i]);
1020 struct intel_img *img =
1021 sc->persistent_images[pPresentInfo->imageIndices[i]];
1022 struct intel_x11_fence_data *data =
1023 (struct intel_x11_fence_data *) queue->fence->wsi_data;
1024 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001025
Ian Elliott4f299362015-07-06 14:45:11 -06001026 ret = x11_swap_chain_present_pixmap(sc, img);
1027 if (ret != VK_SUCCESS) {
1028 return ret;
1029 }
1030
1031 // Record the state change for this image, and add this image to the
1032 // present queue for the swap chain:
1033 sc->image_state[pPresentInfo->imageIndices[i]] =
1034 INTEL_SC_STATE_QUEUED_FOR_PRESENT;
1035 sc->present_queue[sc->present_queue_length++] =
1036 pPresentInfo->imageIndices[i];
1037
1038 data->swap_chain = sc;
1039 data->serial = sc->local.serial;
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001040 sc->present_serial = sc->local.serial;
Ian Elliott4f299362015-07-06 14:45:11 -06001041 intel_fence_set_seqno(queue->fence, img->obj.mem->bo);
1042 }
Chia-I Wubda4f622015-02-25 15:06:15 -07001043
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001044 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001045}