blob: 1344b35259b52d5b0c0359fc5ccf66b38e1f70b1 [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
Mike Stroyan2bf17bd2015-09-03 10:20:16 -060029#define _GNU_SOURCE 1
30#include <time.h>
Mike Stroyanc8b6f822015-09-11 13:21:05 -060031#include <poll.h>
Chia-I Wu1db76e02014-09-15 14:21:14 +080032#include <sys/types.h>
33#include <sys/stat.h>
34#include <unistd.h>
35#include <fcntl.h>
36#include <xcb/xcb.h>
37#include <xcb/dri3.h>
38#include <xcb/present.h>
39
40#include "kmd/winsys.h"
Chia-I Wu8635e912015-04-09 14:13:57 +080041#include "kmd/libdrm/xf86drmMode.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080042#include "dev.h"
43#include "fence.h"
44#include "gpu.h"
45#include "img.h"
46#include "mem.h"
47#include "queue.h"
Chia-I Wu41858c82015-04-04 16:39:25 +080048#include "wsi.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080049
Chia-I Wu8635e912015-04-09 14:13:57 +080050struct intel_x11_display {
51 struct intel_handle handle;
52
53 int fd;
54 uint32_t connector_id;
55
56 char name[32];
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -060057 VkExtent2D physical_dimension;
58 VkExtent2D physical_resolution;
Chia-I Wu8635e912015-04-09 14:13:57 +080059
60 drmModeModeInfoPtr modes;
61 uint32_t mode_count;
62};
63
Ian Elliott4f299362015-07-06 14:45:11 -060064typedef enum intel_x11_swap_chain_image_state_
65{
66 INTEL_SC_STATE_UNUSED = 0,
67 INTEL_SC_STATE_APP_OWNED = 1,
68 INTEL_SC_STATE_QUEUED_FOR_PRESENT = 2,
69 INTEL_SC_STATE_DISPLAYED = 3,
70} intel_x11_swap_chain_image_state;
71
Chia-I Wu6532d1d2015-04-04 22:16:45 +080072struct intel_x11_swap_chain {
73 struct intel_handle handle;
74
75 xcb_connection_t *c;
76 xcb_window_t window;
Ian Elliottbe17edb2015-10-19 15:51:06 -060077 uint32_t width; // To compare with XCB_PRESENT_EVENT_CONFIGURE_NOTIFY's
78 uint32_t height; // ditto
79 bool out_of_date;
80 bool being_deleted;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080081 bool force_copy;
Ian Elliott338dedb2015-08-21 15:09:33 -060082 VkPresentModeKHR present_mode;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080083
84 int dri3_major, dri3_minor;
85 int present_major, present_minor;
Chia-I Wu1db76e02014-09-15 14:21:14 +080086
87 xcb_present_event_t present_special_event_id;
88 xcb_special_event_t *present_special_event;
89
Chia-I Wu5b66aa52015-04-16 22:02:10 +080090 struct intel_img **persistent_images;
91 uint32_t persistent_image_count;
Ian Elliott4f299362015-07-06 14:45:11 -060092 intel_x11_swap_chain_image_state *image_state;
93 uint32_t *present_queue;
94 uint32_t present_queue_length;
Mike Stroyanf9f6dd72015-07-28 11:00:50 -060095 uint32_t present_serial;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080096
Chia-I Wu1db76e02014-09-15 14:21:14 +080097 struct {
98 uint32_t serial;
99 } local;
100
101 struct {
102 uint32_t serial;
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600103 uint64_t msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800104 } remote;
105};
106
Chia-I Wu41858c82015-04-04 16:39:25 +0800107struct intel_x11_img_data {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800108 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +0800109 struct intel_mem *mem;
110 int prime_fd;
111 uint32_t pixmap;
112};
113
114struct intel_x11_fence_data {
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800115 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +0800116 uint32_t serial;
117};
118
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800119/* these are what DDX expects */
120static const VkFormat x11_presentable_formats[] = {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800121 VK_FORMAT_B8G8R8A8_UNORM,
122 VK_FORMAT_B8G8R8A8_SRGB,
Ian Elliott32536f92015-04-21 16:41:02 -0600123 VK_FORMAT_B5G6R5_UNORM,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800124};
125
Ian Elliott338dedb2015-08-21 15:09:33 -0600126static inline struct intel_x11_swap_chain *x11_swap_chain(VkSwapchainKHR sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800127{
Ian Elliott4f299362015-07-06 14:45:11 -0600128 return (struct intel_x11_swap_chain *) sc.handle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800129}
130
Chia-I Wufcbc5252015-04-08 11:44:26 +0800131static bool x11_is_format_presentable(const struct intel_dev *dev,
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600132 VkFormat format)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800133{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800134 uint32_t i;
135
136 for (i = 0; i < ARRAY_SIZE(x11_presentable_formats); i++) {
137 if (x11_presentable_formats[i] == format)
138 return true;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800139 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800140
141 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800142}
143
Chia-I Wu030b2db2015-04-08 13:46:29 +0800144static int x11_export_prime_fd(struct intel_dev *dev,
145 struct intel_bo *bo,
146 const struct intel_layout *layout)
147{
148 struct intel_winsys_handle export;
149 enum intel_tiling_mode tiling;
150
151 export.type = INTEL_WINSYS_HANDLE_FD;
152
153 switch (layout->tiling) {
154 case GEN6_TILING_X:
155 tiling = INTEL_TILING_X;
156 break;
157 case GEN6_TILING_Y:
158 tiling = INTEL_TILING_Y;
159 break;
160 default:
161 assert(layout->tiling == GEN6_TILING_NONE);
162 tiling = INTEL_TILING_NONE;
163 break;
164 }
165
166 if (intel_bo_set_tiling(bo, tiling, layout->bo_stride))
167 return -1;
168
169 if (intel_winsys_export_handle(dev->winsys, bo, tiling,
170 layout->bo_stride, layout->bo_height, &export))
171 return -1;
172
173 return (int) export.handle;
174}
175
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800176/**
Chia-I Wufcbc5252015-04-08 11:44:26 +0800177 * Return true if fd points to the primary or render node of the GPU.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800178 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800179static bool x11_gpu_match_fd(const struct intel_gpu *gpu, int fd)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800180{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800181 struct stat fd_stat, gpu_stat;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800182
Chia-I Wufcbc5252015-04-08 11:44:26 +0800183 if (fstat(fd, &fd_stat))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800184 return false;
185
186 /* is it the primary node? */
187 if (!stat(gpu->primary_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800188 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800189 return true;
190
191 /* is it the render node? */
192 if (gpu->render_node && !stat(gpu->render_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800193 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800194 return true;
195
196 return false;
197}
198
Chia-I Wufcbc5252015-04-08 11:44:26 +0800199/*
200 * Return the depth of \p drawable.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800201 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800202static int x11_get_drawable_depth(xcb_connection_t *c,
203 xcb_drawable_t drawable)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800204{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800205 xcb_get_geometry_cookie_t cookie;
206 xcb_get_geometry_reply_t *reply;
207 uint8_t depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800208
Chia-I Wufcbc5252015-04-08 11:44:26 +0800209 cookie = xcb_get_geometry(c, drawable);
210 reply = xcb_get_geometry_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800211
Chia-I Wufcbc5252015-04-08 11:44:26 +0800212 if (reply) {
213 depth = reply->depth;
214 free(reply);
215 } else {
216 depth = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800217 }
218
Chia-I Wufcbc5252015-04-08 11:44:26 +0800219 return depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800220}
221
Ian Elliott4f299362015-07-06 14:45:11 -0600222static VkResult x11_get_surface_properties(
Ian Elliott338dedb2015-08-21 15:09:33 -0600223 const VkSurfaceDescriptionKHR *pSurfaceDescription,
224 VkSurfacePropertiesKHR *pSurfaceProperties)
Ian Elliott4f299362015-07-06 14:45:11 -0600225{
Ian Elliott338dedb2015-08-21 15:09:33 -0600226 const VkSurfaceDescriptionWindowKHR* pSurfaceDescriptionWindow =
227 (VkSurfaceDescriptionWindowKHR*) pSurfaceDescription;
228 VkPlatformHandleXcbKHR *pPlatformHandleXcb = (VkPlatformHandleXcbKHR *)
Ian Elliott4f299362015-07-06 14:45:11 -0600229 pSurfaceDescriptionWindow->pPlatformHandle;
230 xcb_connection_t *c = (xcb_connection_t *)
231 pPlatformHandleXcb->connection;
232 xcb_window_t window = *((xcb_window_t *)
233 pSurfaceDescriptionWindow->pPlatformWindow);
234 xcb_get_geometry_cookie_t cookie;
235 xcb_get_geometry_reply_t *reply;
236
237 cookie = xcb_get_geometry(c, window);
238 reply = xcb_get_geometry_reply(c, cookie, NULL);
239
240 if (reply) {
241 pSurfaceProperties->currentExtent.width = reply->width;
242 pSurfaceProperties->currentExtent.height = reply->height;
243 free(reply);
244 } else {
245 pSurfaceProperties->currentExtent.width = 0;
246 pSurfaceProperties->currentExtent.height = 0;
247 }
248
249 pSurfaceProperties->minImageCount = 2;
250 pSurfaceProperties->maxImageCount = 0;
251
252 pSurfaceProperties->minImageExtent.width =
253 pSurfaceProperties->currentExtent.width;
254 pSurfaceProperties->minImageExtent.height =
255 pSurfaceProperties->currentExtent.height;
256 pSurfaceProperties->maxImageExtent.width =
257 pSurfaceProperties->currentExtent.width;
258 pSurfaceProperties->maxImageExtent.height =
259 pSurfaceProperties->currentExtent.height;
Ian Elliott338dedb2015-08-21 15:09:33 -0600260 pSurfaceProperties->supportedTransforms = VK_SURFACE_TRANSFORM_NONE_BIT_KHR;
261 pSurfaceProperties->currentTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Ian Elliott4f299362015-07-06 14:45:11 -0600262 pSurfaceProperties->maxImageArraySize = 0;
263 pSurfaceProperties->supportedUsageFlags =
Cody Northrop3440c2d2015-08-28 16:40:45 -0600264 VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
Ian Elliott4f299362015-07-06 14:45:11 -0600265 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
266
267 return VK_SUCCESS;
268}
269
Chia-I Wu1db76e02014-09-15 14:21:14 +0800270/**
271 * Return true if DRI3 and Present are supported by the server.
272 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800273static bool x11_is_dri3_and_present_supported(xcb_connection_t *c)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800274{
275 const xcb_query_extension_reply_t *ext;
276
Chia-I Wufcbc5252015-04-08 11:44:26 +0800277 xcb_prefetch_extension_data(c, &xcb_dri3_id);
278 xcb_prefetch_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800279
Chia-I Wufcbc5252015-04-08 11:44:26 +0800280 ext = xcb_get_extension_data(c, &xcb_dri3_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800281 if (!ext || !ext->present)
282 return false;
283
Chia-I Wufcbc5252015-04-08 11:44:26 +0800284 ext = xcb_get_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800285 if (!ext || !ext->present)
286 return false;
287
288 return true;
289}
290
291/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800292 * Send a DRI3Open to get the server GPU fd.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800293 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800294static int x11_dri3_open(xcb_connection_t *c,
295 xcb_drawable_t drawable,
296 xcb_randr_provider_t provider)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800297{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800298 xcb_dri3_open_cookie_t cookie;
299 xcb_dri3_open_reply_t *reply;
300 int fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800301
Chia-I Wufcbc5252015-04-08 11:44:26 +0800302 cookie = xcb_dri3_open(c, drawable, provider);
303 reply = xcb_dri3_open_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800304 if (!reply)
Chia-I Wufcbc5252015-04-08 11:44:26 +0800305 return -1;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800306
Chia-I Wufcbc5252015-04-08 11:44:26 +0800307 fd = (reply->nfd == 1) ? xcb_dri3_open_reply_fds(c, reply)[0] : -1;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800308 free(reply);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800309
Chia-I Wufcbc5252015-04-08 11:44:26 +0800310 return fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800311}
312
313/**
Chia-I Wu030b2db2015-04-08 13:46:29 +0800314 * Send a DRI3PixmapFromBuffer to create a pixmap from \p prime_fd.
315 */
316static xcb_pixmap_t x11_dri3_pixmap_from_buffer(xcb_connection_t *c,
317 xcb_drawable_t drawable,
318 uint8_t depth, int prime_fd,
319 const struct intel_layout *layout)
320{
321 xcb_pixmap_t pixmap;
322
323 pixmap = xcb_generate_id(c);
324
325 xcb_dri3_pixmap_from_buffer(c, pixmap, drawable,
326 layout->bo_stride * layout->bo_height,
327 layout->width0, layout->height0,
328 layout->bo_stride, depth,
329 layout->block_size * 8, prime_fd);
330
331 return pixmap;
332}
333
334/**
Chia-I Wu41858c82015-04-04 16:39:25 +0800335 * Send DRI3QueryVersion and PresentQueryVersion to query extension versions.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800336 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800337static bool x11_swap_chain_dri3_and_present_query_version(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800338{
339 xcb_dri3_query_version_cookie_t dri3_cookie;
340 xcb_dri3_query_version_reply_t *dri3_reply;
341 xcb_present_query_version_cookie_t present_cookie;
342 xcb_present_query_version_reply_t *present_reply;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800343
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800344 dri3_cookie = xcb_dri3_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800345 XCB_DRI3_MAJOR_VERSION, XCB_DRI3_MINOR_VERSION);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800346 present_cookie = xcb_present_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800347 XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION);
348
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800349 dri3_reply = xcb_dri3_query_version_reply(sc->c, dri3_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800350 if (!dri3_reply)
351 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800352
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800353 sc->dri3_major = dri3_reply->major_version;
354 sc->dri3_minor = dri3_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800355 free(dri3_reply);
356
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800357 present_reply = xcb_present_query_version_reply(sc->c, present_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800358 if (!present_reply)
359 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800360
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800361 sc->present_major = present_reply->major_version;
362 sc->present_minor = present_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800363 free(present_reply);
364
Chia-I Wu41858c82015-04-04 16:39:25 +0800365 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800366}
367
368/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800369 * Send a PresentSelectInput to select interested events.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800370 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800371static bool x11_swap_chain_present_select_input(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800372{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800373 xcb_void_cookie_t cookie;
374 xcb_generic_error_t *error;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800375
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800376 /* create the event queue */
377 sc->present_special_event_id = xcb_generate_id(sc->c);
378 sc->present_special_event = xcb_register_for_special_xge(sc->c,
379 &xcb_present_id, sc->present_special_event_id, NULL);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800380
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800381 cookie = xcb_present_select_input_checked(sc->c,
382 sc->present_special_event_id, sc->window,
Ian Elliottbe17edb2015-10-19 15:51:06 -0600383 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY |
384 XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800385
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800386 error = xcb_request_check(sc->c, cookie);
387 if (error) {
388 free(error);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800389 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800390 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800391
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800392 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800393}
394
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800395static struct intel_img *x11_swap_chain_create_persistent_image(struct intel_x11_swap_chain *sc,
396 struct intel_dev *dev,
397 const VkImageCreateInfo *img_info)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800398{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800399 struct intel_img *img;
400 struct intel_mem *mem;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800401 struct intel_x11_img_data *data;
402 VkMemoryAllocInfo mem_info;
403 int prime_fd;
404 xcb_pixmap_t pixmap;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600405 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800406
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800407 ret = intel_img_create(dev, img_info, true, &img);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600408 if (ret != VK_SUCCESS)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800409 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800410
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800411 memset(&mem_info, 0, sizeof(mem_info));
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600412 mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800413 mem_info.allocationSize = img->total_size;
Mark Lobodzinski72346292015-07-02 16:49:40 -0600414 mem_info.memoryTypeIndex = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800415
416 ret = intel_mem_alloc(dev, &mem_info, &mem);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600417 if (ret != VK_SUCCESS) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800418 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800419 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800420 }
421
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800422 prime_fd = x11_export_prime_fd(dev, mem->bo, &img->layout);
423 if (prime_fd < 0) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800424 intel_mem_free(mem);
425 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800426 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800427 }
428
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800429 pixmap = x11_dri3_pixmap_from_buffer(sc->c, sc->window,
430 x11_get_drawable_depth(sc->c, sc->window),
431 prime_fd, &img->layout);
432
433 data = (struct intel_x11_img_data *) img->wsi_data;
434 data->swap_chain = sc;
435 data->mem = mem;
436 data->prime_fd = prime_fd;
437 data->pixmap = pixmap;
438
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800439 intel_obj_bind_mem(&img->obj, mem, 0);
440
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800441 return img;
442}
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800443
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800444static bool x11_swap_chain_create_persistent_images(struct intel_x11_swap_chain *sc,
445 struct intel_dev *dev,
Ian Elliott338dedb2015-08-21 15:09:33 -0600446 const VkSwapchainCreateInfoKHR *info)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800447{
448 struct intel_img **images;
Ian Elliott4f299362015-07-06 14:45:11 -0600449 intel_x11_swap_chain_image_state *image_state;
450 uint32_t *present_queue;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800451 VkImageCreateInfo img_info;
452 uint32_t i;
453
Ian Elliott4f299362015-07-06 14:45:11 -0600454 images = intel_alloc(sc, sizeof(*images) * info->minImageCount,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800455 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
456 if (!images)
457 return false;
Ian Elliott4f299362015-07-06 14:45:11 -0600458 image_state = intel_alloc(
459 sc, sizeof(intel_x11_swap_chain_image_state) * info->minImageCount,
460 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
461 if (!image_state) {
462 for (i = 0; i < info->minImageCount; i++) {
463 intel_img_destroy(images[i]);
464 }
465 intel_free(sc, images);
466 return false;
467 }
468 present_queue = intel_alloc(
469 sc, sizeof(uint32_t) * info->minImageCount,
470 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
471 if (!present_queue) {
472 for (i = 0; i < info->minImageCount; i++) {
473 intel_img_destroy(images[i]);
474 }
475 intel_free(sc, images);
476 intel_free(sc, image_state);
477 return false;
478 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800479
480 memset(&img_info, 0, sizeof(img_info));
481 img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
482 img_info.imageType = VK_IMAGE_TYPE_2D;
483 img_info.format = info->imageFormat;
484 img_info.extent.width = info->imageExtent.width;
485 img_info.extent.height = info->imageExtent.height;
486 img_info.extent.depth = 1;
487 img_info.mipLevels = 1;
Courtney Goeltzenleuchter2ebc2342015-10-21 17:57:31 -0600488 img_info.arrayLayers = info->imageArraySize;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800489 img_info.samples = 1;
490 img_info.tiling = VK_IMAGE_TILING_OPTIMAL;
491 img_info.usage = info->imageUsageFlags;
492 img_info.flags = 0;
493
Ian Elliott4f299362015-07-06 14:45:11 -0600494 for (i = 0; i < info->minImageCount; i++) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800495 images[i] = x11_swap_chain_create_persistent_image(sc,
496 dev, &img_info);
497 if (!images[i])
498 break;
Ian Elliott4f299362015-07-06 14:45:11 -0600499 image_state[i] = INTEL_SC_STATE_UNUSED;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800500 }
501
Ian Elliott4f299362015-07-06 14:45:11 -0600502 if (i < info->minImageCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800503 uint32_t j;
504 for (j = 0; j < i; j++)
Ian Elliott4f299362015-07-06 14:45:11 -0600505 intel_img_destroy(images[j]);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800506
507 intel_free(sc, images);
508
Ian Elliott4f299362015-07-06 14:45:11 -0600509 if (image_state) {
510 intel_free(sc, image_state);
511 }
512
513 if (present_queue) {
514 intel_free(sc, present_queue);
515 }
516
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800517 return false;
518 }
519
520 sc->persistent_images = images;
Ian Elliott4f299362015-07-06 14:45:11 -0600521 sc->persistent_image_count = info->minImageCount;
522 sc->image_state = image_state;
523 sc->present_queue = present_queue;
524 sc->present_queue_length = 0;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800525
526 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800527}
528
529/**
530 * Send a PresentPixmap.
531 */
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600532static VkResult x11_swap_chain_present_pixmap(struct intel_x11_swap_chain *sc,
Ian Elliott4f299362015-07-06 14:45:11 -0600533 struct intel_img *img)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800534{
Chia-I Wu41858c82015-04-04 16:39:25 +0800535 struct intel_x11_img_data *data =
536 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800537 uint32_t options = XCB_PRESENT_OPTION_NONE;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800538 uint32_t target_msc, divisor, remainder;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800539 xcb_void_cookie_t cookie;
540 xcb_generic_error_t *err;
541
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800542 target_msc = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600543 divisor = 1;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800544 remainder = 0;
Ian Elliott338dedb2015-08-21 15:09:33 -0600545 if (sc->present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR) {
Chia-I Wu1db76e02014-09-15 14:21:14 +0800546 options |= XCB_PRESENT_OPTION_ASYNC;
Ian Elliott4f299362015-07-06 14:45:11 -0600547 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800548
549 if (sc->force_copy)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800550 options |= XCB_PRESENT_OPTION_COPY;
551
Chia-I Wuf689c602015-04-28 10:55:52 +0800552 cookie = xcb_present_pixmap_checked(sc->c,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800553 sc->window,
Chia-I Wu41858c82015-04-04 16:39:25 +0800554 data->pixmap,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800555 ++sc->local.serial,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800556 0, /* valid-area */
557 0, /* update-area */
558 0, /* x-off */
559 0, /* y-off */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800560 0, /* crtc */
Chia-I Wu1db76e02014-09-15 14:21:14 +0800561 0, /* wait-fence */
562 0, /* idle-fence */
563 options,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800564 target_msc,
565 divisor,
566 remainder,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800567 0, NULL);
568
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800569 err = xcb_request_check(sc->c, cookie);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600570 /* TODOVV: Can this be validated */
Chia-I Wu1db76e02014-09-15 14:21:14 +0800571 if (err) {
572 free(err);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600573 return VK_ERROR_INITIALIZATION_FAILED;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800574 }
575
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600576 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800577}
578
579/**
Chia-I Wu1db76e02014-09-15 14:21:14 +0800580 * Handle a Present event.
581 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800582static void x11_swap_chain_present_event(struct intel_x11_swap_chain *sc,
583 const xcb_present_generic_event_t *ev)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800584{
585 union {
586 const xcb_present_generic_event_t *ev;
587 const xcb_present_complete_notify_event_t *complete;
Ian Elliottbe17edb2015-10-19 15:51:06 -0600588 const xcb_present_configure_notify_event_t *configure;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800589 } u = { .ev = ev };
590
591 switch (u.ev->evtype) {
592 case XCB_PRESENT_COMPLETE_NOTIFY:
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800593 sc->remote.serial = u.complete->serial;
594 sc->remote.msc = u.complete->msc;
Ian Elliott4f299362015-07-06 14:45:11 -0600595 assert(sc->present_queue_length > 0);
596 if (sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_DISPLAYED) {
597 // Remove the previously-displayed image from the present queue:
598 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_UNUSED;
599 sc->present_queue_length--;
600 for (int j = 0; j < sc->present_queue_length; j++) {
601 sc->present_queue[j] = sc->present_queue[j+1];
602 }
603 }
604 assert(sc->present_queue_length > 0);
605 assert(sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_QUEUED_FOR_PRESENT);
606 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_DISPLAYED;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800607 break;
Ian Elliottbe17edb2015-10-19 15:51:06 -0600608 case XCB_PRESENT_EVENT_CONFIGURE_NOTIFY:
609 if ((u.configure->width != sc->width) ||
610 (u.configure->height != sc->height)) {
611 // The swapchain is now considered "out of date" with the window:
612 sc->out_of_date = true;
613 }
614 break;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800615 default:
616 break;
617 }
618}
619
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600620/*
621 * Wait for an event on a swap chain.
622 * Uses polling because xcb_wait_for_special_event won't time out.
623 */
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600624static VkResult x11_swap_chain_wait(struct intel_x11_swap_chain *sc,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800625 uint32_t serial, int64_t timeout)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800626{
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600627 struct timespec current_time; // current time for planning wait
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600628 struct timespec stop_time; // time when timeout will elapse
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600629 bool wait;
630 if (timeout == 0){
631 wait = false;
632 } else {
633 wait = true;
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600634 clock_gettime(CLOCK_MONOTONIC, &current_time);
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600635 if (timeout == -1) {
636 // wait approximately forever
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600637 stop_time.tv_nsec = current_time.tv_nsec;
638 stop_time.tv_sec = current_time.tv_sec + 10*365*24*60*60;
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600639 } else {
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600640 stop_time.tv_nsec = current_time.tv_nsec + (timeout % 1000000000);
641 stop_time.tv_sec = current_time.tv_sec + (timeout / 1000000000);
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600642 // Carry overflow from tv_nsec to tv_sec
643 while (stop_time.tv_nsec > 1000000000) {
644 stop_time.tv_sec += 1;
645 stop_time.tv_nsec -= 1000000000;
646 }
647 }
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600648 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800649
650 while (sc->remote.serial < serial) {
651 xcb_present_generic_event_t *ev;
Mike Stroyan4a387162015-04-27 15:42:41 -0600652 xcb_intern_atom_reply_t *reply;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800653
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600654 ev = (xcb_present_generic_event_t *)
655 xcb_poll_for_special_event(sc->c, sc->present_special_event);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800656 if (wait) {
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600657 int poll_timeout;
658 struct pollfd fds;
659
660 fds.fd = xcb_get_file_descriptor(sc->c);
661 fds.events = POLLIN;
662
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600663 while (!ev) {
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600664 clock_gettime(CLOCK_MONOTONIC, &current_time);
665 if (current_time.tv_sec > stop_time.tv_sec ||
666 (current_time.tv_sec == stop_time.tv_sec && current_time.tv_nsec > stop_time.tv_nsec)) {
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600667 // Time has run out
668 return VK_TIMEOUT;
669 }
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600670 poll_timeout = 1000/60; // milliseconds for 60 HZ
671 if (current_time.tv_sec >= stop_time.tv_sec-1) { // Remaining timeout may be under 1/60 seconds.
672 int remaining_timeout;
673 remaining_timeout = 1000 * (stop_time.tv_sec - current_time.tv_sec) + (stop_time.tv_nsec - current_time.tv_nsec) / 1000000;
674 if (poll_timeout > remaining_timeout) {
675 poll_timeout = remaining_timeout; // milliseconds for remainder of timeout
676 }
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600677 }
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600678
679 // Wait for any input on the xcb connection or a timeout.
680 // Events may come in and be queued up before poll. Timing out handles that.
681 poll(&fds, 1, poll_timeout);
682
683 // Another thread may have handled events and updated sc->remote.serial
684 if (sc->remote.serial >= serial) {
685 return VK_SUCCESS;
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600686 }
Mike Stroyan4a387162015-04-27 15:42:41 -0600687
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600688 // Use xcb_intern_atom_reply just to make xcb really read events from socket.
689 // Calling xcb_poll_for_special_event fails to actually look for new packets.
690 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
691 if (reply) {
692 free(reply);
693 }
694
695 ev = (xcb_present_generic_event_t *)
696 xcb_poll_for_special_event(sc->c, sc->present_special_event);
Mike Stroyan4a387162015-04-27 15:42:41 -0600697 }
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600698 } else {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800699 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600700 return VK_NOT_READY;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800701 }
702
703 x11_swap_chain_present_event(sc, ev);
704
705 free(ev);
706 }
707
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600708 return VK_SUCCESS;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800709}
710
Ian Elliottbe17edb2015-10-19 15:51:06 -0600711static void x11_swap_chain_destroy_begin(struct intel_x11_swap_chain *sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800712{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800713 if (sc->persistent_images) {
714 uint32_t i;
715
716 for (i = 0; i < sc->persistent_image_count; i++)
717 intel_img_destroy(sc->persistent_images[i]);
718 intel_free(sc, sc->persistent_images);
719 }
720
Ian Elliott4f299362015-07-06 14:45:11 -0600721 if (sc->image_state) {
722 intel_free(sc, sc->image_state);
723 }
724
725 if (sc->present_queue) {
726 intel_free(sc, sc->present_queue);
727 }
728
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800729 if (sc->present_special_event)
730 xcb_unregister_for_special_event(sc->c, sc->present_special_event);
Ian Elliottbe17edb2015-10-19 15:51:06 -0600731}
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800732
Ian Elliottbe17edb2015-10-19 15:51:06 -0600733static void x11_swap_chain_destroy_end(struct intel_x11_swap_chain *sc)
734{
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800735 intel_free(sc, sc);
736}
737
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800738static VkResult x11_swap_chain_create(struct intel_dev *dev,
Ian Elliott338dedb2015-08-21 15:09:33 -0600739 const VkSwapchainCreateInfoKHR *info,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800740 struct intel_x11_swap_chain **sc_ret)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800741{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800742 const xcb_randr_provider_t provider = 0;
Ian Elliott338dedb2015-08-21 15:09:33 -0600743 const VkSurfaceDescriptionWindowKHR* pSurfaceDescriptionWindow =
744 (VkSurfaceDescriptionWindowKHR*) info->pSurfaceDescription;
745 VkPlatformHandleXcbKHR *pPlatformHandleXcb = (VkPlatformHandleXcbKHR *)
Ian Elliott4f299362015-07-06 14:45:11 -0600746 pSurfaceDescriptionWindow->pPlatformHandle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800747 xcb_connection_t *c = (xcb_connection_t *)
Ian Elliott4f299362015-07-06 14:45:11 -0600748 pPlatformHandleXcb->connection;
749 xcb_window_t window = *((xcb_window_t *)
750 pSurfaceDescriptionWindow->pPlatformWindow);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800751 struct intel_x11_swap_chain *sc;
752 int fd;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800753
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600754 /* TODOVV: Add test to validation layer */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800755 if (!x11_is_format_presentable(dev, info->imageFormat)) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600756 intel_dev_log(dev, VK_DBG_REPORT_ERROR_BIT,
757 VK_NULL_HANDLE, 0, 0, "invalid presentable image format");
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600758// return VK_ERROR_INVALID_VALUE;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600759 return VK_ERROR_VALIDATION_FAILED;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800760 }
761
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600762 /* TODOVV: Can we add test to validation layer? */
763 if (!x11_is_dri3_and_present_supported(c)) {
764// return VK_ERROR_INVALID_VALUE;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600765 return VK_ERROR_VALIDATION_FAILED;
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600766 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800767
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600768 /* TODOVV: Can we add test to validation layer? */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800769 fd = x11_dri3_open(c, window, provider);
770 if (fd < 0 || !x11_gpu_match_fd(dev->gpu, fd)) {
Chia-I Wufcbc5252015-04-08 11:44:26 +0800771 if (fd >= 0)
772 close(fd);
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600773// return VK_ERROR_INVALID_VALUE;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600774 return VK_ERROR_VALIDATION_FAILED;
Chia-I Wufcbc5252015-04-08 11:44:26 +0800775 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800776
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800777 close(fd);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800778
Tony Barbour8205d902015-04-16 15:59:00 -0600779 sc = intel_alloc(dev, sizeof(*sc), 0, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800780 if (!sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800781 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800782
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800783 memset(sc, 0, sizeof(*sc));
Ian Elliott338dedb2015-08-21 15:09:33 -0600784 intel_handle_init(&sc->handle, VK_OBJECT_TYPE_SWAPCHAIN_KHR, dev->base.handle.instance);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800785
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800786 sc->c = c;
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800787 sc->window = window;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800788
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800789 /* always copy unless flip bit is set */
Ian Elliott4f299362015-07-06 14:45:11 -0600790 sc->present_mode = info->presentMode;
Ian Elliottbe17edb2015-10-19 15:51:06 -0600791 // Record the swapchain's width and height, so that we can determine when
792 // it is "out of date" w.r.t. the window:
793 sc->width = info->imageExtent.width;
794 sc->height = info->imageExtent.height;
795 sc->out_of_date = false;
796 sc->being_deleted = false;
Ian Elliott4f299362015-07-06 14:45:11 -0600797 sc->force_copy = true;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800798
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800799 if (!x11_swap_chain_dri3_and_present_query_version(sc) ||
800 !x11_swap_chain_present_select_input(sc) ||
801 !x11_swap_chain_create_persistent_images(sc, dev, info)) {
Ian Elliottbe17edb2015-10-19 15:51:06 -0600802 x11_swap_chain_destroy_begin(sc);
803 x11_swap_chain_destroy_end(sc);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600804 return VK_ERROR_VALIDATION_FAILED;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800805 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800806
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800807 *sc_ret = sc;
Chia-I Wu41858c82015-04-04 16:39:25 +0800808
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600809 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800810}
811
Chia-I Wu8635e912015-04-09 14:13:57 +0800812static void x11_display_destroy(struct intel_x11_display *dpy)
813{
814 intel_free(dpy, dpy->modes);
815 intel_free(dpy, dpy);
816}
817
Chia-I Wu41858c82015-04-04 16:39:25 +0800818void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
819{
Chia-I Wu8635e912015-04-09 14:13:57 +0800820 if (gpu->displays) {
821 uint32_t i;
Chia-I Wu41858c82015-04-04 16:39:25 +0800822
Chia-I Wu8635e912015-04-09 14:13:57 +0800823 for (i = 0; i < gpu->display_count; i++) {
824 struct intel_x11_display *dpy =
825 (struct intel_x11_display *) gpu->displays[i];
826 x11_display_destroy(dpy);
827 }
828 intel_free(gpu, gpu->displays);
829 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800830}
831
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600832VkResult intel_wsi_img_init(struct intel_img *img)
Chia-I Wu41858c82015-04-04 16:39:25 +0800833{
834 struct intel_x11_img_data *data;
835
Tony Barbour8205d902015-04-16 15:59:00 -0600836 data = intel_alloc(img, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800837 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600838 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800839
840 memset(data, 0, sizeof(*data));
841
842 assert(!img->wsi_data);
843 img->wsi_data = data;
844
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600845 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800846}
847
848void intel_wsi_img_cleanup(struct intel_img *img)
849{
850 struct intel_x11_img_data *data =
851 (struct intel_x11_img_data *) img->wsi_data;
852
853 if (data->mem) {
854 close(data->prime_fd);
855 intel_mem_free(data->mem);
856 }
857
858 intel_free(img, img->wsi_data);
859}
860
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600861VkResult intel_wsi_fence_init(struct intel_fence *fence)
Chia-I Wu41858c82015-04-04 16:39:25 +0800862{
863 struct intel_x11_fence_data *data;
864
Tony Barbour8205d902015-04-16 15:59:00 -0600865 data = intel_alloc(fence, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800866 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600867 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800868
869 memset(data, 0, sizeof(*data));
870
871 assert(!fence->wsi_data);
872 fence->wsi_data = data;
873
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600874 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800875}
876
877void intel_wsi_fence_cleanup(struct intel_fence *fence)
878{
879 intel_free(fence, fence->wsi_data);
880}
881
882void intel_wsi_fence_copy(struct intel_fence *fence,
883 const struct intel_fence *src)
884{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600885 if (!fence->wsi_data) {
886 return;
887 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800888 memcpy(fence->wsi_data, src->wsi_data,
889 sizeof(struct intel_x11_fence_data));
890}
891
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600892VkResult intel_wsi_fence_wait(struct intel_fence *fence,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800893 int64_t timeout_ns)
Chia-I Wu41858c82015-04-04 16:39:25 +0800894{
895 struct intel_x11_fence_data *data =
896 (struct intel_x11_fence_data *) fence->wsi_data;
897
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600898 if (!data)
899 return VK_SUCCESS;
900
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800901 if (!data->swap_chain)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600902 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800903
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800904 return x11_swap_chain_wait(data->swap_chain, data->serial, timeout_ns);
Chia-I Wu41858c82015-04-04 16:39:25 +0800905}
906
Ian Elliott338dedb2015-08-21 15:09:33 -0600907ICD_EXPORT VkResult VKAPI vkGetPhysicalDeviceSurfaceSupportKHR(
Ian Elliott4f299362015-07-06 14:45:11 -0600908 VkPhysicalDevice physicalDevice,
909 uint32_t queueNodeIndex,
Ian Elliott338dedb2015-08-21 15:09:33 -0600910 const VkSurfaceDescriptionKHR* pSurfaceDescription,
Ian Elliott4f299362015-07-06 14:45:11 -0600911 VkBool32* pSupported)
912{
913 VkResult ret = VK_SUCCESS;
Ian Elliott338dedb2015-08-21 15:09:33 -0600914 const VkSurfaceDescriptionWindowKHR* pSurfaceDescriptionWindow =
915 (VkSurfaceDescriptionWindowKHR*) pSurfaceDescription;
Ian Elliott4f299362015-07-06 14:45:11 -0600916
917 *pSupported = false;
918
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600919 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliott4f299362015-07-06 14:45:11 -0600920 // assume the correct data type, and not check):
Ian Elliott338dedb2015-08-21 15:09:33 -0600921 if (pSurfaceDescriptionWindow->sType != VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR) {
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600922 return VK_ERROR_VALIDATION_FAILED;
Ian Elliott4f299362015-07-06 14:45:11 -0600923 }
924
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600925 // TODOVV: NEED TO ALSO CHECK:
Ian Elliott4f299362015-07-06 14:45:11 -0600926 // - queueNodeIndex
927 // - pSurfaceDescriptionWindow->pPlatformHandle (can try to use it)
928 // - pSurfaceDescriptionWindow->pPlatformWindow (can try to use it)
Ian Elliott338dedb2015-08-21 15:09:33 -0600929 if (pSurfaceDescriptionWindow->platform == VK_PLATFORM_XCB_KHR) {
Ian Elliott4f299362015-07-06 14:45:11 -0600930 *pSupported = true;
931 }
932
933 return ret;
934}
935
Ian Elliott338dedb2015-08-21 15:09:33 -0600936VkResult VKAPI vkGetSurfacePropertiesKHR(
Ian Elliott4f299362015-07-06 14:45:11 -0600937 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -0600938 const VkSurfaceDescriptionKHR* pSurfaceDescription,
939 VkSurfacePropertiesKHR* pSurfaceProperties)
Ian Elliottebda9892015-08-06 17:35:06 -0600940{
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600941 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliottebda9892015-08-06 17:35:06 -0600942 // assume the correct data type, and not check):
943 assert(pSurfaceProperties);
944
945 return x11_get_surface_properties(pSurfaceDescription, pSurfaceProperties);
946}
947
Ian Elliott338dedb2015-08-21 15:09:33 -0600948VkResult VKAPI vkGetSurfaceFormatsKHR(
Ian Elliottebda9892015-08-06 17:35:06 -0600949 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -0600950 const VkSurfaceDescriptionKHR* pSurfaceDescription,
Ian Elliottebda9892015-08-06 17:35:06 -0600951 uint32_t* pCount,
Ian Elliott338dedb2015-08-21 15:09:33 -0600952 VkSurfaceFormatKHR* pSurfaceFormats)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800953{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800954 VkResult ret = VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800955
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600956 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliott4f299362015-07-06 14:45:11 -0600957 // assume the correct data type, and not check):
Ian Elliottebda9892015-08-06 17:35:06 -0600958 if (!pCount) {
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600959// return VK_ERROR_INVALID_POINTER;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600960 return VK_ERROR_VALIDATION_FAILED;
Ian Elliott4f299362015-07-06 14:45:11 -0600961 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800962
Ian Elliottebda9892015-08-06 17:35:06 -0600963 if (pSurfaceFormats) {
964 uint32_t i;
965 for (i = 0; i < *pCount; i++) {
966 pSurfaceFormats[i].format = x11_presentable_formats[i];
Ian Elliott338dedb2015-08-21 15:09:33 -0600967 pSurfaceFormats[i].colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
Ian Elliott4f299362015-07-06 14:45:11 -0600968 }
Ian Elliotte1ea6712015-08-19 16:49:46 -0600969 } else {
970 *pCount = ARRAY_SIZE(x11_presentable_formats);
Ian Elliottebda9892015-08-06 17:35:06 -0600971 }
972
973 return ret;
974}
975
Ian Elliott338dedb2015-08-21 15:09:33 -0600976VkResult VKAPI vkGetSurfacePresentModesKHR(
Ian Elliottebda9892015-08-06 17:35:06 -0600977 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -0600978 const VkSurfaceDescriptionKHR* pSurfaceDescription,
Ian Elliottebda9892015-08-06 17:35:06 -0600979 uint32_t* pCount,
Ian Elliott338dedb2015-08-21 15:09:33 -0600980 VkPresentModeKHR* pPresentModes)
Ian Elliottebda9892015-08-06 17:35:06 -0600981{
982 VkResult ret = VK_SUCCESS;
983
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600984 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliottebda9892015-08-06 17:35:06 -0600985 // assume the correct data type, and not check):
986 if (!pCount) {
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600987// return VK_ERROR_INVALID_POINTER;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600988 return VK_ERROR_VALIDATION_FAILED;
Ian Elliottebda9892015-08-06 17:35:06 -0600989 }
990
Ian Elliottebda9892015-08-06 17:35:06 -0600991 if (pPresentModes) {
Ian Elliott338dedb2015-08-21 15:09:33 -0600992 pPresentModes[0] = VK_PRESENT_MODE_IMMEDIATE_KHR;
993 pPresentModes[1] = VK_PRESENT_MODE_FIFO_KHR;
994 // TODO: Consider adding VK_PRESENT_MODE_MAILBOX_KHR sometime
Ian Elliotte1ea6712015-08-19 16:49:46 -0600995 } else {
996 *pCount = 2;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800997 }
998
999 return ret;
1000}
1001
Ian Elliott338dedb2015-08-21 15:09:33 -06001002ICD_EXPORT VkResult VKAPI vkCreateSwapchainKHR(
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001003 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -06001004 const VkSwapchainCreateInfoKHR* pCreateInfo,
1005 VkSwapchainKHR* pSwapchain)
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001006{
1007 struct intel_dev *dev = intel_dev(device);
1008
Ian Elliott338dedb2015-08-21 15:09:33 -06001009 if (pCreateInfo->oldSwapchain.handle) {
Ian Elliott4f299362015-07-06 14:45:11 -06001010 // TODO: Eventually, do more than simply up-front destroy the
Ian Elliott338dedb2015-08-21 15:09:33 -06001011 // oldSwapchain (but just do that for now):
Ian Elliott4f299362015-07-06 14:45:11 -06001012 struct intel_x11_swap_chain *sc =
Ian Elliott338dedb2015-08-21 15:09:33 -06001013 x11_swap_chain(pCreateInfo->oldSwapchain);
Ian Elliott4f299362015-07-06 14:45:11 -06001014
Ian Elliottbe17edb2015-10-19 15:51:06 -06001015 sc->being_deleted = true;
1016 x11_swap_chain_destroy_begin(sc);
Ian Elliott4f299362015-07-06 14:45:11 -06001017 }
1018
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001019 return x11_swap_chain_create(dev, pCreateInfo,
Ian Elliott338dedb2015-08-21 15:09:33 -06001020 (struct intel_x11_swap_chain **) pSwapchain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001021}
1022
Ian Elliott338dedb2015-08-21 15:09:33 -06001023ICD_EXPORT VkResult VKAPI vkDestroySwapchainKHR(
Ian Elliott4f299362015-07-06 14:45:11 -06001024 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -06001025 VkSwapchainKHR swapchain)
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001026{
Ian Elliott338dedb2015-08-21 15:09:33 -06001027 struct intel_x11_swap_chain *sc = x11_swap_chain(swapchain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001028
Ian Elliottbe17edb2015-10-19 15:51:06 -06001029 if (!sc->being_deleted) {
1030 x11_swap_chain_destroy_begin(sc);
1031 }
1032 x11_swap_chain_destroy_end(sc);
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001033
1034 return VK_SUCCESS;
1035}
1036
Ian Elliott338dedb2015-08-21 15:09:33 -06001037ICD_EXPORT VkResult VKAPI vkGetSwapchainImagesKHR(
Ian Elliott4f299362015-07-06 14:45:11 -06001038 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -06001039 VkSwapchainKHR swapchain,
Ian Elliottebda9892015-08-06 17:35:06 -06001040 uint32_t* pCount,
Ian Elliott338dedb2015-08-21 15:09:33 -06001041 VkImage* pSwapchainImages)
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001042{
Ian Elliott338dedb2015-08-21 15:09:33 -06001043 struct intel_x11_swap_chain *sc = x11_swap_chain(swapchain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001044 VkResult ret = VK_SUCCESS;
1045
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -06001046 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliott4f299362015-07-06 14:45:11 -06001047 // assume the correct data type, and not check):
Ian Elliottebda9892015-08-06 17:35:06 -06001048 if (!pCount) {
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -06001049// return VK_ERROR_INVALID_POINTER;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06001050 return VK_ERROR_VALIDATION_FAILED;
Ian Elliott4f299362015-07-06 14:45:11 -06001051 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001052
Ian Elliott338dedb2015-08-21 15:09:33 -06001053 if (pSwapchainImages) {
Ian Elliottebda9892015-08-06 17:35:06 -06001054 uint32_t i;
Ian Elliotte1ea6712015-08-19 16:49:46 -06001055 for (i = 0; i < *pCount; i++) {
Ian Elliott338dedb2015-08-21 15:09:33 -06001056 pSwapchainImages[i].handle = (uint64_t) sc->persistent_images[i];
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001057 }
Ian Elliotte1ea6712015-08-19 16:49:46 -06001058 } else {
1059 *pCount = sc->persistent_image_count;
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001060 }
1061
1062 return ret;
1063}
1064
Ian Elliott338dedb2015-08-21 15:09:33 -06001065ICD_EXPORT VkResult VKAPI vkAcquireNextImageKHR(
Ian Elliott4f299362015-07-06 14:45:11 -06001066 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -06001067 VkSwapchainKHR swapchain,
Ian Elliott4f299362015-07-06 14:45:11 -06001068 uint64_t timeout,
1069 VkSemaphore semaphore,
1070 uint32_t* pImageIndex)
1071{
Ian Elliott338dedb2015-08-21 15:09:33 -06001072 struct intel_x11_swap_chain *sc = x11_swap_chain(swapchain);
Ian Elliott4f299362015-07-06 14:45:11 -06001073 VkResult ret = VK_SUCCESS;
1074
Ian Elliottbe17edb2015-10-19 15:51:06 -06001075 if (sc->out_of_date) {
1076 // The window was resized, and the swapchain must be re-created:
1077 return VK_ERROR_OUT_OF_DATE_KHR;
1078 }
1079
Ian Elliott4f299362015-07-06 14:45:11 -06001080 // Find an unused image to return:
1081 for (int i = 0; i < sc->persistent_image_count; i++) {
1082 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
1083 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
1084 *pImageIndex = i;
1085 return ret;
1086 }
1087 }
1088
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001089 // If no image is ready, wait for a present to finish
Mike Stroyanb28dd442015-09-03 10:22:15 -06001090 ret = x11_swap_chain_wait(sc, sc->remote.serial+1, timeout);
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001091 if (ret != VK_SUCCESS) {
1092 return ret;
1093 }
Ian Elliott4f299362015-07-06 14:45:11 -06001094
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001095 // Find an unused image to return:
1096 for (int i = 0; i < sc->persistent_image_count; i++) {
1097 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
1098 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
1099 *pImageIndex = i;
1100 return ret;
1101 }
1102 }
1103 // NOTE: Should never get here, but in case we do, do something:
1104 assert(0);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06001105 return VK_ERROR_VALIDATION_FAILED;
Ian Elliott4f299362015-07-06 14:45:11 -06001106}
1107
1108
Ian Elliott338dedb2015-08-21 15:09:33 -06001109ICD_EXPORT VkResult VKAPI vkQueuePresentKHR(
Ian Elliott4f299362015-07-06 14:45:11 -06001110 VkQueue queue_,
Ian Elliott338dedb2015-08-21 15:09:33 -06001111 VkPresentInfoKHR* pPresentInfo)
Chia-I Wu1db76e02014-09-15 14:21:14 +08001112{
1113 struct intel_queue *queue = intel_queue(queue_);
Ian Elliott4f299362015-07-06 14:45:11 -06001114 uint32_t i;
Ian Elliott338dedb2015-08-21 15:09:33 -06001115 uint32_t num_swapchains = pPresentInfo->swapchainCount;
Ian Elliottbe17edb2015-10-19 15:51:06 -06001116 VkResult rtn = VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001117
Mike Stroyan12915ce2015-09-03 10:25:44 -06001118 // Wait for queue to idle before out-of-band xcb present operation.
1119 const VkResult r = intel_queue_wait(queue, -1);
1120 (void) r;
1121
Ian Elliott4f299362015-07-06 14:45:11 -06001122 for (i = 0; i < num_swapchains; i++) {
1123 struct intel_x11_swap_chain *sc =
Ian Elliott338dedb2015-08-21 15:09:33 -06001124 x11_swap_chain(pPresentInfo->swapchains[i]);
Ian Elliott4f299362015-07-06 14:45:11 -06001125 struct intel_img *img =
1126 sc->persistent_images[pPresentInfo->imageIndices[i]];
1127 struct intel_x11_fence_data *data =
1128 (struct intel_x11_fence_data *) queue->fence->wsi_data;
1129 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001130
Ian Elliottbe17edb2015-10-19 15:51:06 -06001131 if (sc->out_of_date) {
1132 // The window was resized, and the swapchain must be re-created:
1133 rtn = VK_ERROR_OUT_OF_DATE_KHR;
1134 // TODO: Potentially change this to match the result of Bug 14952
1135 // (which deals with some of the swapchains being out-of-date, but
1136 // not all of them). For now, just present the swapchains that
1137 // aren't out-of-date, and skip the ones that are out-of-date:
1138 continue;
1139 }
1140
Ian Elliott4f299362015-07-06 14:45:11 -06001141 ret = x11_swap_chain_present_pixmap(sc, img);
1142 if (ret != VK_SUCCESS) {
1143 return ret;
1144 }
1145
1146 // Record the state change for this image, and add this image to the
1147 // present queue for the swap chain:
1148 sc->image_state[pPresentInfo->imageIndices[i]] =
1149 INTEL_SC_STATE_QUEUED_FOR_PRESENT;
1150 sc->present_queue[sc->present_queue_length++] =
1151 pPresentInfo->imageIndices[i];
1152
1153 data->swap_chain = sc;
1154 data->serial = sc->local.serial;
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001155 sc->present_serial = sc->local.serial;
Ian Elliott4f299362015-07-06 14:45:11 -06001156 intel_fence_set_seqno(queue->fence, img->obj.mem->bo);
1157 }
Chia-I Wubda4f622015-02-25 15:06:15 -07001158
Ian Elliottbe17edb2015-10-19 15:51:06 -06001159 return rtn;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001160}