blob: d9d05cef43387f650edbc8ccf78adc6ce4e7b16b [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;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080088
Chia-I Wu1db76e02014-09-15 14:21:14 +080089 struct {
90 uint32_t serial;
91 } local;
92
93 struct {
94 uint32_t serial;
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -060095 uint64_t msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +080096 } remote;
97};
98
Chia-I Wu41858c82015-04-04 16:39:25 +080099struct intel_x11_img_data {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800100 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +0800101 struct intel_mem *mem;
102 int prime_fd;
103 uint32_t pixmap;
104};
105
106struct intel_x11_fence_data {
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800107 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +0800108 uint32_t serial;
109};
110
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800111/* these are what DDX expects */
112static const VkFormat x11_presentable_formats[] = {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800113 VK_FORMAT_B8G8R8A8_UNORM,
114 VK_FORMAT_B8G8R8A8_SRGB,
Ian Elliott32536f92015-04-21 16:41:02 -0600115 VK_FORMAT_B5G6R5_UNORM,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800116};
117
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800118static inline struct intel_x11_swap_chain *x11_swap_chain(VkSwapChainWSI sc)
119{
Ian Elliott4f299362015-07-06 14:45:11 -0600120 return (struct intel_x11_swap_chain *) sc.handle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800121}
122
Chia-I Wufcbc5252015-04-08 11:44:26 +0800123static bool x11_is_format_presentable(const struct intel_dev *dev,
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600124 VkFormat format)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800125{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800126 uint32_t i;
127
128 for (i = 0; i < ARRAY_SIZE(x11_presentable_formats); i++) {
129 if (x11_presentable_formats[i] == format)
130 return true;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800131 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800132
133 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800134}
135
Chia-I Wu030b2db2015-04-08 13:46:29 +0800136static int x11_export_prime_fd(struct intel_dev *dev,
137 struct intel_bo *bo,
138 const struct intel_layout *layout)
139{
140 struct intel_winsys_handle export;
141 enum intel_tiling_mode tiling;
142
143 export.type = INTEL_WINSYS_HANDLE_FD;
144
145 switch (layout->tiling) {
146 case GEN6_TILING_X:
147 tiling = INTEL_TILING_X;
148 break;
149 case GEN6_TILING_Y:
150 tiling = INTEL_TILING_Y;
151 break;
152 default:
153 assert(layout->tiling == GEN6_TILING_NONE);
154 tiling = INTEL_TILING_NONE;
155 break;
156 }
157
158 if (intel_bo_set_tiling(bo, tiling, layout->bo_stride))
159 return -1;
160
161 if (intel_winsys_export_handle(dev->winsys, bo, tiling,
162 layout->bo_stride, layout->bo_height, &export))
163 return -1;
164
165 return (int) export.handle;
166}
167
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800168/**
Chia-I Wufcbc5252015-04-08 11:44:26 +0800169 * Return true if fd points to the primary or render node of the GPU.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800170 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800171static bool x11_gpu_match_fd(const struct intel_gpu *gpu, int fd)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800172{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800173 struct stat fd_stat, gpu_stat;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800174
Chia-I Wufcbc5252015-04-08 11:44:26 +0800175 if (fstat(fd, &fd_stat))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800176 return false;
177
178 /* is it the primary node? */
179 if (!stat(gpu->primary_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800180 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800181 return true;
182
183 /* is it the render node? */
184 if (gpu->render_node && !stat(gpu->render_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800185 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800186 return true;
187
188 return false;
189}
190
Chia-I Wufcbc5252015-04-08 11:44:26 +0800191/*
192 * Return the depth of \p drawable.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800193 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800194static int x11_get_drawable_depth(xcb_connection_t *c,
195 xcb_drawable_t drawable)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800196{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800197 xcb_get_geometry_cookie_t cookie;
198 xcb_get_geometry_reply_t *reply;
199 uint8_t depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800200
Chia-I Wufcbc5252015-04-08 11:44:26 +0800201 cookie = xcb_get_geometry(c, drawable);
202 reply = xcb_get_geometry_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800203
Chia-I Wufcbc5252015-04-08 11:44:26 +0800204 if (reply) {
205 depth = reply->depth;
206 free(reply);
207 } else {
208 depth = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800209 }
210
Chia-I Wufcbc5252015-04-08 11:44:26 +0800211 return depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800212}
213
Ian Elliott4f299362015-07-06 14:45:11 -0600214static VkResult x11_get_surface_properties(
215 const VkSurfaceDescriptionWSI *pSurfaceDescription,
216 VkSurfacePropertiesWSI *pSurfaceProperties)
217{
218 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
219 (VkSurfaceDescriptionWindowWSI*) pSurfaceDescription;
220 VkPlatformHandleXcbWSI *pPlatformHandleXcb = (VkPlatformHandleXcbWSI *)
221 pSurfaceDescriptionWindow->pPlatformHandle;
222 xcb_connection_t *c = (xcb_connection_t *)
223 pPlatformHandleXcb->connection;
224 xcb_window_t window = *((xcb_window_t *)
225 pSurfaceDescriptionWindow->pPlatformWindow);
226 xcb_get_geometry_cookie_t cookie;
227 xcb_get_geometry_reply_t *reply;
228
229 cookie = xcb_get_geometry(c, window);
230 reply = xcb_get_geometry_reply(c, cookie, NULL);
231
232 if (reply) {
233 pSurfaceProperties->currentExtent.width = reply->width;
234 pSurfaceProperties->currentExtent.height = reply->height;
235 free(reply);
236 } else {
237 pSurfaceProperties->currentExtent.width = 0;
238 pSurfaceProperties->currentExtent.height = 0;
239 }
240
241 pSurfaceProperties->minImageCount = 2;
242 pSurfaceProperties->maxImageCount = 0;
243
244 pSurfaceProperties->minImageExtent.width =
245 pSurfaceProperties->currentExtent.width;
246 pSurfaceProperties->minImageExtent.height =
247 pSurfaceProperties->currentExtent.height;
248 pSurfaceProperties->maxImageExtent.width =
249 pSurfaceProperties->currentExtent.width;
250 pSurfaceProperties->maxImageExtent.height =
251 pSurfaceProperties->currentExtent.height;
252 pSurfaceProperties->supportedTransforms = VK_SURFACE_TRANSFORM_NONE_BIT_WSI;
253 pSurfaceProperties->currentTransform = VK_SURFACE_TRANSFORM_NONE_WSI;
254 pSurfaceProperties->maxImageArraySize = 0;
255 pSurfaceProperties->supportedUsageFlags =
256 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
257
258 return VK_SUCCESS;
259}
260
Chia-I Wu1db76e02014-09-15 14:21:14 +0800261/**
262 * Return true if DRI3 and Present are supported by the server.
263 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800264static bool x11_is_dri3_and_present_supported(xcb_connection_t *c)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800265{
266 const xcb_query_extension_reply_t *ext;
267
Chia-I Wufcbc5252015-04-08 11:44:26 +0800268 xcb_prefetch_extension_data(c, &xcb_dri3_id);
269 xcb_prefetch_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800270
Chia-I Wufcbc5252015-04-08 11:44:26 +0800271 ext = xcb_get_extension_data(c, &xcb_dri3_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800272 if (!ext || !ext->present)
273 return false;
274
Chia-I Wufcbc5252015-04-08 11:44:26 +0800275 ext = xcb_get_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800276 if (!ext || !ext->present)
277 return false;
278
279 return true;
280}
281
282/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800283 * Send a DRI3Open to get the server GPU fd.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800284 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800285static int x11_dri3_open(xcb_connection_t *c,
286 xcb_drawable_t drawable,
287 xcb_randr_provider_t provider)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800288{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800289 xcb_dri3_open_cookie_t cookie;
290 xcb_dri3_open_reply_t *reply;
291 int fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800292
Chia-I Wufcbc5252015-04-08 11:44:26 +0800293 cookie = xcb_dri3_open(c, drawable, provider);
294 reply = xcb_dri3_open_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800295 if (!reply)
Chia-I Wufcbc5252015-04-08 11:44:26 +0800296 return -1;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800297
Chia-I Wufcbc5252015-04-08 11:44:26 +0800298 fd = (reply->nfd == 1) ? xcb_dri3_open_reply_fds(c, reply)[0] : -1;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800299 free(reply);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800300
Chia-I Wufcbc5252015-04-08 11:44:26 +0800301 return fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800302}
303
304/**
Chia-I Wu030b2db2015-04-08 13:46:29 +0800305 * Send a DRI3PixmapFromBuffer to create a pixmap from \p prime_fd.
306 */
307static xcb_pixmap_t x11_dri3_pixmap_from_buffer(xcb_connection_t *c,
308 xcb_drawable_t drawable,
309 uint8_t depth, int prime_fd,
310 const struct intel_layout *layout)
311{
312 xcb_pixmap_t pixmap;
313
314 pixmap = xcb_generate_id(c);
315
316 xcb_dri3_pixmap_from_buffer(c, pixmap, drawable,
317 layout->bo_stride * layout->bo_height,
318 layout->width0, layout->height0,
319 layout->bo_stride, depth,
320 layout->block_size * 8, prime_fd);
321
322 return pixmap;
323}
324
325/**
Chia-I Wu41858c82015-04-04 16:39:25 +0800326 * Send DRI3QueryVersion and PresentQueryVersion to query extension versions.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800327 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800328static bool x11_swap_chain_dri3_and_present_query_version(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800329{
330 xcb_dri3_query_version_cookie_t dri3_cookie;
331 xcb_dri3_query_version_reply_t *dri3_reply;
332 xcb_present_query_version_cookie_t present_cookie;
333 xcb_present_query_version_reply_t *present_reply;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800334
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800335 dri3_cookie = xcb_dri3_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800336 XCB_DRI3_MAJOR_VERSION, XCB_DRI3_MINOR_VERSION);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800337 present_cookie = xcb_present_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800338 XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION);
339
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800340 dri3_reply = xcb_dri3_query_version_reply(sc->c, dri3_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800341 if (!dri3_reply)
342 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800343
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800344 sc->dri3_major = dri3_reply->major_version;
345 sc->dri3_minor = dri3_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800346 free(dri3_reply);
347
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800348 present_reply = xcb_present_query_version_reply(sc->c, present_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800349 if (!present_reply)
350 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800351
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800352 sc->present_major = present_reply->major_version;
353 sc->present_minor = present_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800354 free(present_reply);
355
Chia-I Wu41858c82015-04-04 16:39:25 +0800356 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800357}
358
359/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800360 * Send a PresentSelectInput to select interested events.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800361 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800362static bool x11_swap_chain_present_select_input(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800363{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800364 xcb_void_cookie_t cookie;
365 xcb_generic_error_t *error;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800366
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800367 /* create the event queue */
368 sc->present_special_event_id = xcb_generate_id(sc->c);
369 sc->present_special_event = xcb_register_for_special_xge(sc->c,
370 &xcb_present_id, sc->present_special_event_id, NULL);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800371
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800372 cookie = xcb_present_select_input_checked(sc->c,
373 sc->present_special_event_id, sc->window,
374 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800375
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800376 error = xcb_request_check(sc->c, cookie);
377 if (error) {
378 free(error);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800379 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800380 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800381
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800382 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800383}
384
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800385static struct intel_img *x11_swap_chain_create_persistent_image(struct intel_x11_swap_chain *sc,
386 struct intel_dev *dev,
387 const VkImageCreateInfo *img_info)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800388{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800389 struct intel_img *img;
390 struct intel_mem *mem;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800391 struct intel_x11_img_data *data;
392 VkMemoryAllocInfo mem_info;
393 int prime_fd;
394 xcb_pixmap_t pixmap;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600395 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800396
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800397 ret = intel_img_create(dev, img_info, true, &img);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600398 if (ret != VK_SUCCESS)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800399 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800400
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800401 memset(&mem_info, 0, sizeof(mem_info));
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600402 mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800403 mem_info.allocationSize = img->total_size;
Mark Lobodzinski72346292015-07-02 16:49:40 -0600404 mem_info.memoryTypeIndex = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800405
406 ret = intel_mem_alloc(dev, &mem_info, &mem);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600407 if (ret != VK_SUCCESS) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800408 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800409 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800410 }
411
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800412 prime_fd = x11_export_prime_fd(dev, mem->bo, &img->layout);
413 if (prime_fd < 0) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800414 intel_mem_free(mem);
415 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800416 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800417 }
418
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800419 pixmap = x11_dri3_pixmap_from_buffer(sc->c, sc->window,
420 x11_get_drawable_depth(sc->c, sc->window),
421 prime_fd, &img->layout);
422
423 data = (struct intel_x11_img_data *) img->wsi_data;
424 data->swap_chain = sc;
425 data->mem = mem;
426 data->prime_fd = prime_fd;
427 data->pixmap = pixmap;
428
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800429 intel_obj_bind_mem(&img->obj, mem, 0);
430
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800431 return img;
432}
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800433
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800434static bool x11_swap_chain_create_persistent_images(struct intel_x11_swap_chain *sc,
435 struct intel_dev *dev,
436 const VkSwapChainCreateInfoWSI *info)
437{
438 struct intel_img **images;
Ian Elliott4f299362015-07-06 14:45:11 -0600439 intel_x11_swap_chain_image_state *image_state;
440 uint32_t *present_queue;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800441 VkImageCreateInfo img_info;
442 uint32_t i;
443
Ian Elliott4f299362015-07-06 14:45:11 -0600444 images = intel_alloc(sc, sizeof(*images) * info->minImageCount,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800445 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
446 if (!images)
447 return false;
Ian Elliott4f299362015-07-06 14:45:11 -0600448 image_state = intel_alloc(
449 sc, sizeof(intel_x11_swap_chain_image_state) * info->minImageCount,
450 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
451 if (!image_state) {
452 for (i = 0; i < info->minImageCount; i++) {
453 intel_img_destroy(images[i]);
454 }
455 intel_free(sc, images);
456 return false;
457 }
458 present_queue = intel_alloc(
459 sc, sizeof(uint32_t) * info->minImageCount,
460 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
461 if (!present_queue) {
462 for (i = 0; i < info->minImageCount; i++) {
463 intel_img_destroy(images[i]);
464 }
465 intel_free(sc, images);
466 intel_free(sc, image_state);
467 return false;
468 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800469
470 memset(&img_info, 0, sizeof(img_info));
471 img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
472 img_info.imageType = VK_IMAGE_TYPE_2D;
473 img_info.format = info->imageFormat;
474 img_info.extent.width = info->imageExtent.width;
475 img_info.extent.height = info->imageExtent.height;
476 img_info.extent.depth = 1;
477 img_info.mipLevels = 1;
478 img_info.arraySize = info->imageArraySize;
479 img_info.samples = 1;
480 img_info.tiling = VK_IMAGE_TILING_OPTIMAL;
481 img_info.usage = info->imageUsageFlags;
482 img_info.flags = 0;
483
Ian Elliott4f299362015-07-06 14:45:11 -0600484 for (i = 0; i < info->minImageCount; i++) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800485 images[i] = x11_swap_chain_create_persistent_image(sc,
486 dev, &img_info);
487 if (!images[i])
488 break;
Ian Elliott4f299362015-07-06 14:45:11 -0600489 image_state[i] = INTEL_SC_STATE_UNUSED;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800490 }
491
Ian Elliott4f299362015-07-06 14:45:11 -0600492 if (i < info->minImageCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800493 uint32_t j;
494 for (j = 0; j < i; j++)
Ian Elliott4f299362015-07-06 14:45:11 -0600495 intel_img_destroy(images[j]);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800496
497 intel_free(sc, images);
498
Ian Elliott4f299362015-07-06 14:45:11 -0600499 if (image_state) {
500 intel_free(sc, image_state);
501 }
502
503 if (present_queue) {
504 intel_free(sc, present_queue);
505 }
506
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800507 return false;
508 }
509
510 sc->persistent_images = images;
Ian Elliott4f299362015-07-06 14:45:11 -0600511 sc->persistent_image_count = info->minImageCount;
512 sc->image_state = image_state;
513 sc->present_queue = present_queue;
514 sc->present_queue_length = 0;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800515
516 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800517}
518
519/**
520 * Send a PresentPixmap.
521 */
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600522static VkResult x11_swap_chain_present_pixmap(struct intel_x11_swap_chain *sc,
Ian Elliott4f299362015-07-06 14:45:11 -0600523 struct intel_img *img)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800524{
Chia-I Wu41858c82015-04-04 16:39:25 +0800525 struct intel_x11_img_data *data =
526 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800527 uint32_t options = XCB_PRESENT_OPTION_NONE;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800528 uint32_t target_msc, divisor, remainder;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800529 xcb_void_cookie_t cookie;
530 xcb_generic_error_t *err;
531
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800532 target_msc = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600533 divisor = 1;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800534 remainder = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600535 if (sc->present_mode == VK_PRESENT_MODE_IMMEDIATE_WSI) {
Chia-I Wu1db76e02014-09-15 14:21:14 +0800536 options |= XCB_PRESENT_OPTION_ASYNC;
Ian Elliott4f299362015-07-06 14:45:11 -0600537 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800538
539 if (sc->force_copy)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800540 options |= XCB_PRESENT_OPTION_COPY;
541
Chia-I Wuf689c602015-04-28 10:55:52 +0800542 cookie = xcb_present_pixmap_checked(sc->c,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800543 sc->window,
Chia-I Wu41858c82015-04-04 16:39:25 +0800544 data->pixmap,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800545 ++sc->local.serial,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800546 0, /* valid-area */
547 0, /* update-area */
548 0, /* x-off */
549 0, /* y-off */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800550 0, /* crtc */
Chia-I Wu1db76e02014-09-15 14:21:14 +0800551 0, /* wait-fence */
552 0, /* idle-fence */
553 options,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800554 target_msc,
555 divisor,
556 remainder,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800557 0, NULL);
558
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800559 err = xcb_request_check(sc->c, cookie);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800560 if (err) {
561 free(err);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600562 return VK_ERROR_UNKNOWN;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800563 }
564
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600565 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800566}
567
568/**
Chia-I Wu1db76e02014-09-15 14:21:14 +0800569 * Handle a Present event.
570 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800571static void x11_swap_chain_present_event(struct intel_x11_swap_chain *sc,
572 const xcb_present_generic_event_t *ev)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800573{
574 union {
575 const xcb_present_generic_event_t *ev;
576 const xcb_present_complete_notify_event_t *complete;
577 } u = { .ev = ev };
578
579 switch (u.ev->evtype) {
580 case XCB_PRESENT_COMPLETE_NOTIFY:
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800581 sc->remote.serial = u.complete->serial;
582 sc->remote.msc = u.complete->msc;
Ian Elliott4f299362015-07-06 14:45:11 -0600583 assert(sc->present_queue_length > 0);
584 if (sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_DISPLAYED) {
585 // Remove the previously-displayed image from the present queue:
586 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_UNUSED;
587 sc->present_queue_length--;
588 for (int j = 0; j < sc->present_queue_length; j++) {
589 sc->present_queue[j] = sc->present_queue[j+1];
590 }
591 }
592 assert(sc->present_queue_length > 0);
593 assert(sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_QUEUED_FOR_PRESENT);
594 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_DISPLAYED;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800595 break;
596 default:
597 break;
598 }
599}
600
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600601static VkResult x11_swap_chain_wait(struct intel_x11_swap_chain *sc,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800602 uint32_t serial, int64_t timeout)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800603{
604 const bool wait = (timeout != 0);
605
606 while (sc->remote.serial < serial) {
607 xcb_present_generic_event_t *ev;
Mike Stroyan4a387162015-04-27 15:42:41 -0600608 xcb_intern_atom_reply_t *reply;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800609
610 if (wait) {
611 ev = (xcb_present_generic_event_t *)
612 xcb_wait_for_special_event(sc->c, sc->present_special_event);
Mike Stroyan4a387162015-04-27 15:42:41 -0600613 /* use xcb_intern_atom_reply just to wake other threads waiting on sc->c */
614 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
615 if (reply) {
616 free(reply);
617 }
618
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800619 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600620 return VK_ERROR_UNKNOWN;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800621 } else {
Mike Stroyan4a387162015-04-27 15:42:41 -0600622 /* use xcb_intern_atom_reply just to check socket for special event */
623 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
624 if (reply) {
625 free(reply);
626 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800627 ev = (xcb_present_generic_event_t *)
628 xcb_poll_for_special_event(sc->c, sc->present_special_event);
629 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600630 return VK_NOT_READY;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800631 }
632
633 x11_swap_chain_present_event(sc, ev);
634
635 free(ev);
636 }
637
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600638 return VK_SUCCESS;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800639}
640
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800641static void x11_swap_chain_destroy(struct intel_x11_swap_chain *sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800642{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800643 if (sc->persistent_images) {
644 uint32_t i;
645
646 for (i = 0; i < sc->persistent_image_count; i++)
647 intel_img_destroy(sc->persistent_images[i]);
648 intel_free(sc, sc->persistent_images);
649 }
650
Ian Elliott4f299362015-07-06 14:45:11 -0600651 if (sc->image_state) {
652 intel_free(sc, sc->image_state);
653 }
654
655 if (sc->present_queue) {
656 intel_free(sc, sc->present_queue);
657 }
658
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800659 if (sc->present_special_event)
660 xcb_unregister_for_special_event(sc->c, sc->present_special_event);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800661
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800662 intel_free(sc, sc);
663}
664
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800665static VkResult x11_swap_chain_create(struct intel_dev *dev,
666 const VkSwapChainCreateInfoWSI *info,
667 struct intel_x11_swap_chain **sc_ret)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800668{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800669 const xcb_randr_provider_t provider = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600670 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
671 (VkSurfaceDescriptionWindowWSI*) info->pSurfaceDescription;
672 VkPlatformHandleXcbWSI *pPlatformHandleXcb = (VkPlatformHandleXcbWSI *)
673 pSurfaceDescriptionWindow->pPlatformHandle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800674 xcb_connection_t *c = (xcb_connection_t *)
Ian Elliott4f299362015-07-06 14:45:11 -0600675 pPlatformHandleXcb->connection;
676 xcb_window_t window = *((xcb_window_t *)
677 pSurfaceDescriptionWindow->pPlatformWindow);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800678 struct intel_x11_swap_chain *sc;
679 int fd;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800680
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800681 if (!x11_is_format_presentable(dev, info->imageFormat)) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600682 intel_dev_log(dev, VK_DBG_REPORT_ERROR_BIT,
683 VK_NULL_HANDLE, 0, 0, "invalid presentable image format");
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800684 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800685 }
686
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800687 if (!x11_is_dri3_and_present_supported(c))
688 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800689
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800690 fd = x11_dri3_open(c, window, provider);
691 if (fd < 0 || !x11_gpu_match_fd(dev->gpu, fd)) {
Chia-I Wufcbc5252015-04-08 11:44:26 +0800692 if (fd >= 0)
693 close(fd);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800694 return VK_ERROR_INVALID_VALUE;
Chia-I Wufcbc5252015-04-08 11:44:26 +0800695 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800696
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800697 close(fd);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800698
Tony Barbour8205d902015-04-16 15:59:00 -0600699 sc = intel_alloc(dev, sizeof(*sc), 0, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800700 if (!sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800701 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800702
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800703 memset(sc, 0, sizeof(*sc));
Courtney Goeltzenleuchter9ecf6852015-06-09 08:22:48 -0600704 intel_handle_init(&sc->handle, VK_OBJECT_TYPE_SWAP_CHAIN_WSI, dev->base.handle.instance);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800705
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800706 sc->c = c;
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800707 sc->window = window;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800708
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800709 /* always copy unless flip bit is set */
Ian Elliott4f299362015-07-06 14:45:11 -0600710 sc->present_mode = info->presentMode;
711 sc->force_copy = true;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800712
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800713 if (!x11_swap_chain_dri3_and_present_query_version(sc) ||
714 !x11_swap_chain_present_select_input(sc) ||
715 !x11_swap_chain_create_persistent_images(sc, dev, info)) {
716 x11_swap_chain_destroy(sc);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600717 return VK_ERROR_UNKNOWN;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800718 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800719
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800720 *sc_ret = sc;
Chia-I Wu41858c82015-04-04 16:39:25 +0800721
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600722 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800723}
724
Chia-I Wu8635e912015-04-09 14:13:57 +0800725static void x11_display_destroy(struct intel_x11_display *dpy)
726{
727 intel_free(dpy, dpy->modes);
728 intel_free(dpy, dpy);
729}
730
Chia-I Wu41858c82015-04-04 16:39:25 +0800731void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
732{
Chia-I Wu8635e912015-04-09 14:13:57 +0800733 if (gpu->displays) {
734 uint32_t i;
Chia-I Wu41858c82015-04-04 16:39:25 +0800735
Chia-I Wu8635e912015-04-09 14:13:57 +0800736 for (i = 0; i < gpu->display_count; i++) {
737 struct intel_x11_display *dpy =
738 (struct intel_x11_display *) gpu->displays[i];
739 x11_display_destroy(dpy);
740 }
741 intel_free(gpu, gpu->displays);
742 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800743}
744
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600745VkResult intel_wsi_img_init(struct intel_img *img)
Chia-I Wu41858c82015-04-04 16:39:25 +0800746{
747 struct intel_x11_img_data *data;
748
Tony Barbour8205d902015-04-16 15:59:00 -0600749 data = intel_alloc(img, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800750 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600751 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800752
753 memset(data, 0, sizeof(*data));
754
755 assert(!img->wsi_data);
756 img->wsi_data = data;
757
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600758 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800759}
760
761void intel_wsi_img_cleanup(struct intel_img *img)
762{
763 struct intel_x11_img_data *data =
764 (struct intel_x11_img_data *) img->wsi_data;
765
766 if (data->mem) {
767 close(data->prime_fd);
768 intel_mem_free(data->mem);
769 }
770
771 intel_free(img, img->wsi_data);
772}
773
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600774VkResult intel_wsi_fence_init(struct intel_fence *fence)
Chia-I Wu41858c82015-04-04 16:39:25 +0800775{
776 struct intel_x11_fence_data *data;
777
Tony Barbour8205d902015-04-16 15:59:00 -0600778 data = intel_alloc(fence, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800779 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600780 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800781
782 memset(data, 0, sizeof(*data));
783
784 assert(!fence->wsi_data);
785 fence->wsi_data = data;
786
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600787 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800788}
789
790void intel_wsi_fence_cleanup(struct intel_fence *fence)
791{
792 intel_free(fence, fence->wsi_data);
793}
794
795void intel_wsi_fence_copy(struct intel_fence *fence,
796 const struct intel_fence *src)
797{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600798 if (!fence->wsi_data) {
799 return;
800 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800801 memcpy(fence->wsi_data, src->wsi_data,
802 sizeof(struct intel_x11_fence_data));
803}
804
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600805VkResult intel_wsi_fence_wait(struct intel_fence *fence,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800806 int64_t timeout_ns)
Chia-I Wu41858c82015-04-04 16:39:25 +0800807{
808 struct intel_x11_fence_data *data =
809 (struct intel_x11_fence_data *) fence->wsi_data;
810
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600811 if (!data)
812 return VK_SUCCESS;
813
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800814 if (!data->swap_chain)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600815 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800816
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800817 return x11_swap_chain_wait(data->swap_chain, data->serial, timeout_ns);
Chia-I Wu41858c82015-04-04 16:39:25 +0800818}
819
Ian Elliott4f299362015-07-06 14:45:11 -0600820ICD_EXPORT VkResult VKAPI vkGetPhysicalDeviceSurfaceSupportWSI(
821 VkPhysicalDevice physicalDevice,
822 uint32_t queueNodeIndex,
823 const VkSurfaceDescriptionWSI* pSurfaceDescription,
824 VkBool32* pSupported)
825{
826 VkResult ret = VK_SUCCESS;
827 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
828 (VkSurfaceDescriptionWindowWSI*) pSurfaceDescription;
829
830 *pSupported = false;
831
832 // TODO: Move this check to a validation layer (i.e. the driver should
833 // assume the correct data type, and not check):
834 if (pSurfaceDescriptionWindow->sType != VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI) {
835 return VK_ERROR_INVALID_VALUE;
836 }
837
838 // TODO: NEED TO ALSO CHECK:
839 // - queueNodeIndex
840 // - pSurfaceDescriptionWindow->pPlatformHandle (can try to use it)
841 // - pSurfaceDescriptionWindow->pPlatformWindow (can try to use it)
842 if (pSurfaceDescriptionWindow->platform == VK_PLATFORM_XCB_WSI) {
843 *pSupported = true;
844 }
845
846 return ret;
847}
848
849VkResult VKAPI vkGetSurfaceInfoWSI(
850 VkDevice device,
851 const VkSurfaceDescriptionWSI* pSurfaceDescription,
852 VkSurfaceInfoTypeWSI infoType,
853 size_t* pDataSize,
854 void* pData)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800855{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800856 VkResult ret = VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800857
Ian Elliott4f299362015-07-06 14:45:11 -0600858 // TODO: Move this check to a validation layer (i.e. the driver should
859 // assume the correct data type, and not check):
860 if (!pDataSize) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800861 return VK_ERROR_INVALID_POINTER;
Ian Elliott4f299362015-07-06 14:45:11 -0600862 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800863
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800864 switch (infoType) {
Ian Elliott4f299362015-07-06 14:45:11 -0600865 case VK_SURFACE_INFO_TYPE_PROPERTIES_WSI:
866 *pDataSize = sizeof(VkSurfacePropertiesWSI);
867 if (pData) {
868 ret = x11_get_surface_properties(pSurfaceDescription, pData);
869 }
870 break;
871 case VK_SURFACE_INFO_TYPE_FORMATS_WSI:
872 *pDataSize = (sizeof(VkSurfaceFormatPropertiesWSI) *
873 ARRAY_SIZE(x11_presentable_formats));
874 if (pData) {
875 VkSurfaceFormatPropertiesWSI *dst = pData;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800876 uint32_t i;
Ian Elliott4f299362015-07-06 14:45:11 -0600877 uint32_t num_formats = ARRAY_SIZE(x11_presentable_formats);
878 for (i = 0; i < num_formats; i++) {
879 dst[i].format = x11_presentable_formats[i];
880 }
881 }
882 break;
883 case VK_SURFACE_INFO_TYPE_PRESENT_MODES_WSI:
884 *pDataSize = sizeof(VkSurfacePresentModePropertiesWSI) * 2;
885 if (pData) {
886 VkSurfacePresentModePropertiesWSI *dst = pData;
887 dst[0].presentMode = VK_PRESENT_MODE_IMMEDIATE_WSI;
888 dst[1].presentMode = VK_PRESENT_MODE_FIFO_WSI;
889 // TODO: Consider adding VK_PRESENT_MODE_MAILBOX_WSI sometime
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800890 }
891 break;
892 default:
893 ret = VK_ERROR_INVALID_VALUE;
894 break;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800895 }
896
897 return ret;
898}
899
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800900ICD_EXPORT VkResult VKAPI vkCreateSwapChainWSI(
901 VkDevice device,
902 const VkSwapChainCreateInfoWSI* pCreateInfo,
903 VkSwapChainWSI* pSwapChain)
904{
905 struct intel_dev *dev = intel_dev(device);
906
Ian Elliott4f299362015-07-06 14:45:11 -0600907 if (pCreateInfo->oldSwapChain.handle) {
908 // TODO: Eventually, do more than simply up-front destroy the
909 // oldSwapChain (but just do that for now):
910 struct intel_x11_swap_chain *sc =
911 x11_swap_chain(pCreateInfo->oldSwapChain);
912
913 x11_swap_chain_destroy(sc);
914 }
915
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800916 return x11_swap_chain_create(dev, pCreateInfo,
917 (struct intel_x11_swap_chain **) pSwapChain);
918}
919
920ICD_EXPORT VkResult VKAPI vkDestroySwapChainWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600921 VkDevice device,
922 VkSwapChainWSI swapChain)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800923{
924 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
925
926 x11_swap_chain_destroy(sc);
927
928 return VK_SUCCESS;
929}
930
931ICD_EXPORT VkResult VKAPI vkGetSwapChainInfoWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600932 VkDevice device,
933 VkSwapChainWSI swapChain,
934 VkSwapChainInfoTypeWSI infoType,
935 size_t* pDataSize,
936 void* pData)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800937{
938 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
939 VkResult ret = VK_SUCCESS;
940
Ian Elliott4f299362015-07-06 14:45:11 -0600941 // TODO: Move this check to a validation layer (i.e. the driver should
942 // assume the correct data type, and not check):
943 if (!pDataSize) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800944 return VK_ERROR_INVALID_POINTER;
Ian Elliott4f299362015-07-06 14:45:11 -0600945 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800946
947 switch (infoType) {
Ian Elliott4f299362015-07-06 14:45:11 -0600948 case VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI:
949 *pDataSize = (sizeof(VkSwapChainImagePropertiesWSI) *
950 sc->persistent_image_count);
951 if (pData) {
952 VkSwapChainImagePropertiesWSI *images =
953 (VkSwapChainImagePropertiesWSI *) pData;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800954 uint32_t i;
955
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800956 for (i = 0; i < sc->persistent_image_count; i++) {
Tony Barbourde4124d2015-07-03 10:33:54 -0600957 images[i].image.handle = (uint64_t) sc->persistent_images[i];
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800958 }
959 }
960 break;
961 default:
962 ret = VK_ERROR_INVALID_VALUE;
963 break;
964 }
965
966 return ret;
967}
968
Ian Elliott4f299362015-07-06 14:45:11 -0600969ICD_EXPORT VkResult VKAPI vkAcquireNextImageWSI(
970 VkDevice device,
971 VkSwapChainWSI swapChain,
972 uint64_t timeout,
973 VkSemaphore semaphore,
974 uint32_t* pImageIndex)
975{
976 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
977 VkResult ret = VK_SUCCESS;
978
979// TODO: IMPLEMENT SUPPORT FOR "timeout". MEAN TIME, ASSUME WE'LL ALWAYS HAVE
980// AN IMAGE TO RETURN (OR RETURN IMAGE 0).
981
982 // Find an unused image to return:
983 for (int i = 0; i < sc->persistent_image_count; i++) {
984 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
985 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
986 *pImageIndex = i;
987 return ret;
988 }
989 }
990
991// NOTE: Should never get here, but in case we do, do something:
992 assert(0);
993 *pImageIndex = 0;
994
995 return ret;
996}
997
998
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800999ICD_EXPORT VkResult VKAPI vkQueuePresentWSI(
Ian Elliott4f299362015-07-06 14:45:11 -06001000 VkQueue queue_,
1001 VkPresentInfoWSI* pPresentInfo)
Chia-I Wu1db76e02014-09-15 14:21:14 +08001002{
1003 struct intel_queue *queue = intel_queue(queue_);
Ian Elliott4f299362015-07-06 14:45:11 -06001004 uint32_t i;
1005 uint32_t num_swapchains = pPresentInfo->swapChainCount;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001006
Ian Elliott4f299362015-07-06 14:45:11 -06001007 for (i = 0; i < num_swapchains; i++) {
1008 struct intel_x11_swap_chain *sc =
1009 x11_swap_chain(pPresentInfo->swapChains[i]);
1010 struct intel_img *img =
1011 sc->persistent_images[pPresentInfo->imageIndices[i]];
1012 struct intel_x11_fence_data *data =
1013 (struct intel_x11_fence_data *) queue->fence->wsi_data;
1014 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001015
Ian Elliott4f299362015-07-06 14:45:11 -06001016 ret = x11_swap_chain_present_pixmap(sc, img);
1017 if (ret != VK_SUCCESS) {
1018 return ret;
1019 }
1020
1021 // Record the state change for this image, and add this image to the
1022 // present queue for the swap chain:
1023 sc->image_state[pPresentInfo->imageIndices[i]] =
1024 INTEL_SC_STATE_QUEUED_FOR_PRESENT;
1025 sc->present_queue[sc->present_queue_length++] =
1026 pPresentInfo->imageIndices[i];
1027
1028 data->swap_chain = sc;
1029 data->serial = sc->local.serial;
1030 intel_fence_set_seqno(queue->fence, img->obj.mem->bo);
1031 }
Chia-I Wubda4f622015-02-25 15:06:15 -07001032
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001033 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001034}