blob: 393b00f1932eb36d1b094d6a9c9fa8691b629d8b [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>
26 */
27
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <xcb/xcb.h>
33#include <xcb/dri3.h>
34#include <xcb/present.h>
35
36#include "kmd/winsys.h"
Chia-I Wu8635e912015-04-09 14:13:57 +080037#include "kmd/libdrm/xf86drmMode.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080038#include "dev.h"
39#include "fence.h"
40#include "gpu.h"
41#include "img.h"
42#include "mem.h"
43#include "queue.h"
Chia-I Wu41858c82015-04-04 16:39:25 +080044#include "wsi.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080045
Chia-I Wu8635e912015-04-09 14:13:57 +080046struct intel_x11_display {
47 struct intel_handle handle;
48
49 int fd;
50 uint32_t connector_id;
51
52 char name[32];
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -060053 VkExtent2D physical_dimension;
54 VkExtent2D physical_resolution;
Chia-I Wu8635e912015-04-09 14:13:57 +080055
56 drmModeModeInfoPtr modes;
57 uint32_t mode_count;
58};
59
Chia-I Wu6532d1d2015-04-04 22:16:45 +080060struct intel_x11_swap_chain {
61 struct intel_handle handle;
62
63 xcb_connection_t *c;
64 xcb_window_t window;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080065 bool force_copy;
66
67 int dri3_major, dri3_minor;
68 int present_major, present_minor;
Chia-I Wu1db76e02014-09-15 14:21:14 +080069
70 xcb_present_event_t present_special_event_id;
71 xcb_special_event_t *present_special_event;
72
Chia-I Wu5b66aa52015-04-16 22:02:10 +080073 struct intel_img **persistent_images;
74 uint32_t persistent_image_count;
75
Chia-I Wu1db76e02014-09-15 14:21:14 +080076 struct {
77 uint32_t serial;
78 } local;
79
80 struct {
81 uint32_t serial;
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -060082 uint64_t msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +080083 } remote;
84};
85
Chia-I Wu41858c82015-04-04 16:39:25 +080086struct intel_x11_img_data {
Chia-I Wu5b66aa52015-04-16 22:02:10 +080087 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +080088 struct intel_mem *mem;
89 int prime_fd;
90 uint32_t pixmap;
91};
92
93struct intel_x11_fence_data {
Chia-I Wu6532d1d2015-04-04 22:16:45 +080094 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +080095 uint32_t serial;
96};
97
Chia-I Wu5b66aa52015-04-16 22:02:10 +080098/* these are what DDX expects */
99static const VkFormat x11_presentable_formats[] = {
100 VK_FORMAT_B5G6R5_UNORM,
101 VK_FORMAT_B8G8R8A8_UNORM,
102 VK_FORMAT_B8G8R8A8_SRGB,
103};
104
105static inline struct intel_x11_display *x11_display(VkDisplayWSI dpy)
106{
107 return (struct intel_x11_display *) dpy;
108}
109
110static inline struct intel_x11_swap_chain *x11_swap_chain(VkSwapChainWSI sc)
111{
112 return (struct intel_x11_swap_chain *) sc;
113}
114
Chia-I Wufcbc5252015-04-08 11:44:26 +0800115static bool x11_is_format_presentable(const struct intel_dev *dev,
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600116 VkFormat format)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800117{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800118 uint32_t i;
119
120 for (i = 0; i < ARRAY_SIZE(x11_presentable_formats); i++) {
121 if (x11_presentable_formats[i] == format)
122 return true;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800123 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800124
125 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800126}
127
Chia-I Wu030b2db2015-04-08 13:46:29 +0800128static int x11_export_prime_fd(struct intel_dev *dev,
129 struct intel_bo *bo,
130 const struct intel_layout *layout)
131{
132 struct intel_winsys_handle export;
133 enum intel_tiling_mode tiling;
134
135 export.type = INTEL_WINSYS_HANDLE_FD;
136
137 switch (layout->tiling) {
138 case GEN6_TILING_X:
139 tiling = INTEL_TILING_X;
140 break;
141 case GEN6_TILING_Y:
142 tiling = INTEL_TILING_Y;
143 break;
144 default:
145 assert(layout->tiling == GEN6_TILING_NONE);
146 tiling = INTEL_TILING_NONE;
147 break;
148 }
149
150 if (intel_bo_set_tiling(bo, tiling, layout->bo_stride))
151 return -1;
152
153 if (intel_winsys_export_handle(dev->winsys, bo, tiling,
154 layout->bo_stride, layout->bo_height, &export))
155 return -1;
156
157 return (int) export.handle;
158}
159
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800160/**
Chia-I Wufcbc5252015-04-08 11:44:26 +0800161 * Return true if fd points to the primary or render node of the GPU.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800162 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800163static bool x11_gpu_match_fd(const struct intel_gpu *gpu, int fd)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800164{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800165 struct stat fd_stat, gpu_stat;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800166
Chia-I Wufcbc5252015-04-08 11:44:26 +0800167 if (fstat(fd, &fd_stat))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800168 return false;
169
170 /* is it the primary node? */
171 if (!stat(gpu->primary_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800172 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800173 return true;
174
175 /* is it the render node? */
176 if (gpu->render_node && !stat(gpu->render_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800177 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800178 return true;
179
180 return false;
181}
182
Chia-I Wufcbc5252015-04-08 11:44:26 +0800183/*
184 * Return the depth of \p drawable.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800185 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800186static int x11_get_drawable_depth(xcb_connection_t *c,
187 xcb_drawable_t drawable)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800188{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800189 xcb_get_geometry_cookie_t cookie;
190 xcb_get_geometry_reply_t *reply;
191 uint8_t depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800192
Chia-I Wufcbc5252015-04-08 11:44:26 +0800193 cookie = xcb_get_geometry(c, drawable);
194 reply = xcb_get_geometry_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800195
Chia-I Wufcbc5252015-04-08 11:44:26 +0800196 if (reply) {
197 depth = reply->depth;
198 free(reply);
199 } else {
200 depth = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800201 }
202
Chia-I Wufcbc5252015-04-08 11:44:26 +0800203 return depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800204}
205
Chia-I Wu1db76e02014-09-15 14:21:14 +0800206/**
207 * Return true if DRI3 and Present are supported by the server.
208 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800209static bool x11_is_dri3_and_present_supported(xcb_connection_t *c)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800210{
211 const xcb_query_extension_reply_t *ext;
212
Chia-I Wufcbc5252015-04-08 11:44:26 +0800213 xcb_prefetch_extension_data(c, &xcb_dri3_id);
214 xcb_prefetch_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800215
Chia-I Wufcbc5252015-04-08 11:44:26 +0800216 ext = xcb_get_extension_data(c, &xcb_dri3_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800217 if (!ext || !ext->present)
218 return false;
219
Chia-I Wufcbc5252015-04-08 11:44:26 +0800220 ext = xcb_get_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800221 if (!ext || !ext->present)
222 return false;
223
224 return true;
225}
226
227/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800228 * Send a DRI3Open to get the server GPU fd.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800229 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800230static int x11_dri3_open(xcb_connection_t *c,
231 xcb_drawable_t drawable,
232 xcb_randr_provider_t provider)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800233{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800234 xcb_dri3_open_cookie_t cookie;
235 xcb_dri3_open_reply_t *reply;
236 int fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800237
Chia-I Wufcbc5252015-04-08 11:44:26 +0800238 cookie = xcb_dri3_open(c, drawable, provider);
239 reply = xcb_dri3_open_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800240 if (!reply)
Chia-I Wufcbc5252015-04-08 11:44:26 +0800241 return -1;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800242
Chia-I Wufcbc5252015-04-08 11:44:26 +0800243 fd = (reply->nfd == 1) ? xcb_dri3_open_reply_fds(c, reply)[0] : -1;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800244 free(reply);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800245
Chia-I Wufcbc5252015-04-08 11:44:26 +0800246 return fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800247}
248
249/**
Chia-I Wu030b2db2015-04-08 13:46:29 +0800250 * Send a DRI3PixmapFromBuffer to create a pixmap from \p prime_fd.
251 */
252static xcb_pixmap_t x11_dri3_pixmap_from_buffer(xcb_connection_t *c,
253 xcb_drawable_t drawable,
254 uint8_t depth, int prime_fd,
255 const struct intel_layout *layout)
256{
257 xcb_pixmap_t pixmap;
258
259 pixmap = xcb_generate_id(c);
260
261 xcb_dri3_pixmap_from_buffer(c, pixmap, drawable,
262 layout->bo_stride * layout->bo_height,
263 layout->width0, layout->height0,
264 layout->bo_stride, depth,
265 layout->block_size * 8, prime_fd);
266
267 return pixmap;
268}
269
270/**
Chia-I Wu41858c82015-04-04 16:39:25 +0800271 * Send DRI3QueryVersion and PresentQueryVersion to query extension versions.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800272 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800273static bool x11_swap_chain_dri3_and_present_query_version(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800274{
275 xcb_dri3_query_version_cookie_t dri3_cookie;
276 xcb_dri3_query_version_reply_t *dri3_reply;
277 xcb_present_query_version_cookie_t present_cookie;
278 xcb_present_query_version_reply_t *present_reply;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800279
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800280 dri3_cookie = xcb_dri3_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800281 XCB_DRI3_MAJOR_VERSION, XCB_DRI3_MINOR_VERSION);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800282 present_cookie = xcb_present_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800283 XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION);
284
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800285 dri3_reply = xcb_dri3_query_version_reply(sc->c, dri3_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800286 if (!dri3_reply)
287 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800288
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800289 sc->dri3_major = dri3_reply->major_version;
290 sc->dri3_minor = dri3_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800291 free(dri3_reply);
292
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800293 present_reply = xcb_present_query_version_reply(sc->c, present_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800294 if (!present_reply)
295 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800296
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800297 sc->present_major = present_reply->major_version;
298 sc->present_minor = present_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800299 free(present_reply);
300
Chia-I Wu41858c82015-04-04 16:39:25 +0800301 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800302}
303
304/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800305 * Send a PresentSelectInput to select interested events.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800306 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800307static bool x11_swap_chain_present_select_input(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800308{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800309 xcb_void_cookie_t cookie;
310 xcb_generic_error_t *error;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800311
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800312 /* create the event queue */
313 sc->present_special_event_id = xcb_generate_id(sc->c);
314 sc->present_special_event = xcb_register_for_special_xge(sc->c,
315 &xcb_present_id, sc->present_special_event_id, NULL);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800316
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800317 cookie = xcb_present_select_input_checked(sc->c,
318 sc->present_special_event_id, sc->window,
319 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800320
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800321 error = xcb_request_check(sc->c, cookie);
322 if (error) {
323 free(error);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800324 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800325 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800326
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800327 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800328}
329
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800330static struct intel_img *x11_swap_chain_create_persistent_image(struct intel_x11_swap_chain *sc,
331 struct intel_dev *dev,
332 const VkImageCreateInfo *img_info)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800333{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800334 struct intel_img *img;
335 struct intel_mem *mem;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800336 struct intel_x11_img_data *data;
337 VkMemoryAllocInfo mem_info;
338 int prime_fd;
339 xcb_pixmap_t pixmap;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600340 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800341
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800342 ret = intel_img_create(dev, img_info, true, &img);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600343 if (ret != VK_SUCCESS)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800344 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800345
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800346 memset(&mem_info, 0, sizeof(mem_info));
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600347 mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800348 mem_info.allocationSize = img->total_size;
349 mem_info.memProps = 0;
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600350 mem_info.memPriority = VK_MEMORY_PRIORITY_HIGH;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800351
352 ret = intel_mem_alloc(dev, &mem_info, &mem);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600353 if (ret != VK_SUCCESS) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800354 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800355 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800356 }
357
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800358 prime_fd = x11_export_prime_fd(dev, mem->bo, &img->layout);
359 if (prime_fd < 0) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800360 intel_mem_free(mem);
361 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800362 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800363 }
364
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800365 pixmap = x11_dri3_pixmap_from_buffer(sc->c, sc->window,
366 x11_get_drawable_depth(sc->c, sc->window),
367 prime_fd, &img->layout);
368
369 data = (struct intel_x11_img_data *) img->wsi_data;
370 data->swap_chain = sc;
371 data->mem = mem;
372 data->prime_fd = prime_fd;
373 data->pixmap = pixmap;
374
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800375 intel_obj_bind_mem(&img->obj, mem, 0);
376
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800377 return img;
378}
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800379
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800380static bool x11_swap_chain_create_persistent_images(struct intel_x11_swap_chain *sc,
381 struct intel_dev *dev,
382 const VkSwapChainCreateInfoWSI *info)
383{
384 struct intel_img **images;
385 VkImageCreateInfo img_info;
386 uint32_t i;
387
388 images = intel_alloc(sc, sizeof(*images) * info->imageCount,
389 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
390 if (!images)
391 return false;
392
393 memset(&img_info, 0, sizeof(img_info));
394 img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
395 img_info.imageType = VK_IMAGE_TYPE_2D;
396 img_info.format = info->imageFormat;
397 img_info.extent.width = info->imageExtent.width;
398 img_info.extent.height = info->imageExtent.height;
399 img_info.extent.depth = 1;
400 img_info.mipLevels = 1;
401 img_info.arraySize = info->imageArraySize;
402 img_info.samples = 1;
403 img_info.tiling = VK_IMAGE_TILING_OPTIMAL;
404 img_info.usage = info->imageUsageFlags;
405 img_info.flags = 0;
406
407 for (i = 0; i < info->imageCount; i++) {
408 images[i] = x11_swap_chain_create_persistent_image(sc,
409 dev, &img_info);
410 if (!images[i])
411 break;
412 }
413
414 if (i < info->imageCount) {
415 uint32_t j;
416 for (j = 0; j < i; j++)
417 intel_img_destroy(images[i]);
418
419 intel_free(sc, images);
420
421 return false;
422 }
423
424 sc->persistent_images = images;
425 sc->persistent_image_count = info->imageCount;
426
427 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800428}
429
430/**
431 * Send a PresentPixmap.
432 */
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600433static VkResult x11_swap_chain_present_pixmap(struct intel_x11_swap_chain *sc,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800434 const VkPresentInfoWSI *info)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800435{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800436 struct intel_img *img = intel_img(info->image);
Chia-I Wu41858c82015-04-04 16:39:25 +0800437 struct intel_x11_img_data *data =
438 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800439 uint32_t options = XCB_PRESENT_OPTION_NONE;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800440 uint32_t target_msc, divisor, remainder;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800441 xcb_void_cookie_t cookie;
442 xcb_generic_error_t *err;
443
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800444 target_msc = 0;
445 divisor = info->flipInterval;
446 remainder = 0;
447 if (!info->flipInterval)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800448 options |= XCB_PRESENT_OPTION_ASYNC;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800449
450 if (sc->force_copy)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800451 options |= XCB_PRESENT_OPTION_COPY;
452
Chia-I Wuf689c602015-04-28 10:55:52 +0800453 cookie = xcb_present_pixmap_checked(sc->c,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800454 sc->window,
Chia-I Wu41858c82015-04-04 16:39:25 +0800455 data->pixmap,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800456 ++sc->local.serial,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800457 0, /* valid-area */
458 0, /* update-area */
459 0, /* x-off */
460 0, /* y-off */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800461 0, /* crtc */
Chia-I Wu1db76e02014-09-15 14:21:14 +0800462 0, /* wait-fence */
463 0, /* idle-fence */
464 options,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800465 target_msc,
466 divisor,
467 remainder,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800468 0, NULL);
469
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800470 err = xcb_request_check(sc->c, cookie);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800471 if (err) {
472 free(err);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600473 return VK_ERROR_UNKNOWN;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800474 }
475
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600476 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800477}
478
479/**
Chia-I Wu1db76e02014-09-15 14:21:14 +0800480 * Handle a Present event.
481 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800482static void x11_swap_chain_present_event(struct intel_x11_swap_chain *sc,
483 const xcb_present_generic_event_t *ev)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800484{
485 union {
486 const xcb_present_generic_event_t *ev;
487 const xcb_present_complete_notify_event_t *complete;
488 } u = { .ev = ev };
489
490 switch (u.ev->evtype) {
491 case XCB_PRESENT_COMPLETE_NOTIFY:
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800492 sc->remote.serial = u.complete->serial;
493 sc->remote.msc = u.complete->msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800494 break;
495 default:
496 break;
497 }
498}
499
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600500static VkResult x11_swap_chain_wait(struct intel_x11_swap_chain *sc,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800501 uint32_t serial, int64_t timeout)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800502{
503 const bool wait = (timeout != 0);
504
505 while (sc->remote.serial < serial) {
506 xcb_present_generic_event_t *ev;
Mike Stroyan4a387162015-04-27 15:42:41 -0600507 xcb_intern_atom_reply_t *reply;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800508
509 if (wait) {
510 ev = (xcb_present_generic_event_t *)
511 xcb_wait_for_special_event(sc->c, sc->present_special_event);
Mike Stroyan4a387162015-04-27 15:42:41 -0600512 /* use xcb_intern_atom_reply just to wake other threads waiting on sc->c */
513 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
514 if (reply) {
515 free(reply);
516 }
517
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800518 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600519 return VK_ERROR_UNKNOWN;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800520 } else {
Mike Stroyan4a387162015-04-27 15:42:41 -0600521 /* use xcb_intern_atom_reply just to check socket for special event */
522 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
523 if (reply) {
524 free(reply);
525 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800526 ev = (xcb_present_generic_event_t *)
527 xcb_poll_for_special_event(sc->c, sc->present_special_event);
528 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600529 return VK_NOT_READY;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800530 }
531
532 x11_swap_chain_present_event(sc, ev);
533
534 free(ev);
535 }
536
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600537 return VK_SUCCESS;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800538}
539
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800540static void x11_swap_chain_destroy(struct intel_x11_swap_chain *sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800541{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800542 if (sc->persistent_images) {
543 uint32_t i;
544
545 for (i = 0; i < sc->persistent_image_count; i++)
546 intel_img_destroy(sc->persistent_images[i]);
547 intel_free(sc, sc->persistent_images);
548 }
549
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800550 if (sc->present_special_event)
551 xcb_unregister_for_special_event(sc->c, sc->present_special_event);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800552
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800553 intel_free(sc, sc);
554}
555
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800556static VkResult x11_swap_chain_create(struct intel_dev *dev,
557 const VkSwapChainCreateInfoWSI *info,
558 struct intel_x11_swap_chain **sc_ret)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800559{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800560 const xcb_randr_provider_t provider = 0;
561 xcb_connection_t *c = (xcb_connection_t *)
562 info->pNativeWindowSystemHandle;
563 xcb_window_t window = (xcb_window_t)
564 ((intptr_t) info->pNativeWindowHandle);
565 struct intel_x11_swap_chain *sc;
566 int fd;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800567
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800568 if (!x11_is_format_presentable(dev, info->imageFormat)) {
569 intel_dev_log(dev, VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0,
570 VK_NULL_HANDLE, 0, 0, "invalid presentable image format");
571 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800572 }
573
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800574 if (!x11_is_dri3_and_present_supported(c))
575 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800576
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800577 fd = x11_dri3_open(c, window, provider);
578 if (fd < 0 || !x11_gpu_match_fd(dev->gpu, fd)) {
Chia-I Wufcbc5252015-04-08 11:44:26 +0800579 if (fd >= 0)
580 close(fd);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800581 return VK_ERROR_INVALID_VALUE;
Chia-I Wufcbc5252015-04-08 11:44:26 +0800582 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800583
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800584 close(fd);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800585
Tony Barbour8205d902015-04-16 15:59:00 -0600586 sc = intel_alloc(dev, sizeof(*sc), 0, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800587 if (!sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800588 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800589
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800590 memset(sc, 0, sizeof(*sc));
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800591 intel_handle_init(&sc->handle, VK_DBG_OBJECT_SWAP_CHAIN_WSI, dev->base.handle.icd);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800592
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800593 sc->c = c;
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800594 sc->window = window;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800595
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800596 /* always copy unless flip bit is set */
597 sc->force_copy = !(info->swapModeFlags & VK_SWAP_MODE_FLIP_BIT_WSI);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800598
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800599 if (!x11_swap_chain_dri3_and_present_query_version(sc) ||
600 !x11_swap_chain_present_select_input(sc) ||
601 !x11_swap_chain_create_persistent_images(sc, dev, info)) {
602 x11_swap_chain_destroy(sc);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600603 return VK_ERROR_UNKNOWN;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800604 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800605
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800606 *sc_ret = sc;
Chia-I Wu41858c82015-04-04 16:39:25 +0800607
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600608 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800609}
610
Chia-I Wu8635e912015-04-09 14:13:57 +0800611static void x11_display_init_modes(struct intel_x11_display *dpy,
612 const drmModeConnectorPtr conn)
613{
614 int i;
615
616 if (!conn->count_modes)
617 return;
618
619 dpy->modes = intel_alloc(dpy, sizeof(dpy->modes[0]) * conn->count_modes,
Tony Barbour8205d902015-04-16 15:59:00 -0600620 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu8635e912015-04-09 14:13:57 +0800621 if (!dpy->modes)
622 return;
623
624 for (i = 0; i < conn->count_modes; i++) {
625 dpy->modes[i] = conn->modes[i];
626
627 if (dpy->physical_resolution.width < conn->modes[i].hdisplay &&
628 dpy->physical_resolution.height < conn->modes[i].vdisplay) {
629 dpy->physical_resolution.width = conn->modes[i].hdisplay;
630 dpy->physical_resolution.height = conn->modes[i].vdisplay;
631 }
632 }
633
634 dpy->mode_count = conn->count_modes;
635
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800636#if 0 // Remove this until we support an upstream version of WSI that has this:
Chia-I Wu8635e912015-04-09 14:13:57 +0800637 dpy->physical_dimension.width = conn->mmWidth;
638 dpy->physical_dimension.height = conn->mmHeight;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800639#endif
Chia-I Wu8635e912015-04-09 14:13:57 +0800640}
641
642static void x11_display_init_name(struct intel_x11_display *dpy,
643 const drmModeConnectorPtr conn)
644{
645 static const char *connector_names[] = {
646 [DRM_MODE_CONNECTOR_Unknown] = "Unknown",
647 [DRM_MODE_CONNECTOR_VGA] = "VGA",
648 [DRM_MODE_CONNECTOR_DVII] = "DVII",
649 [DRM_MODE_CONNECTOR_DVID] = "DVID",
650 [DRM_MODE_CONNECTOR_DVIA] = "DVIA",
651 [DRM_MODE_CONNECTOR_Composite] = "Composite",
652 [DRM_MODE_CONNECTOR_SVIDEO] = "SVIDEO",
653 [DRM_MODE_CONNECTOR_LVDS] = "LVDS",
654 [DRM_MODE_CONNECTOR_Component] = "COMPONENT",
655 [DRM_MODE_CONNECTOR_9PinDIN] = "9PinDIN",
656 [DRM_MODE_CONNECTOR_DisplayPort] = "DisplayPort",
657 [DRM_MODE_CONNECTOR_HDMIA] = "HDMIA",
658 [DRM_MODE_CONNECTOR_HDMIB] = "HDMIB",
659 [DRM_MODE_CONNECTOR_TV] = "TV",
660 [DRM_MODE_CONNECTOR_eDP] = "eDP",
661 [DRM_MODE_CONNECTOR_VIRTUAL] = "VIRTUAL",
662 [DRM_MODE_CONNECTOR_DSI] = "DSI",
663 };
664 const char *name;
665
666 name = (conn->connector_type < ARRAY_SIZE(connector_names)) ?
667 connector_names[conn->connector_type] : NULL;
668 if (!name)
669 name = connector_names[DRM_MODE_CONNECTOR_Unknown];
670
671 snprintf(dpy->name, sizeof(dpy->name),
672 "%s%d", name, conn->connector_type_id);
673}
674
675static void x11_display_destroy(struct intel_x11_display *dpy)
676{
677 intel_free(dpy, dpy->modes);
678 intel_free(dpy, dpy);
679}
680
681static struct intel_x11_display *x11_display_create(struct intel_gpu *gpu,
682 int fd,
683 uint32_t connector_id)
684{
685 struct intel_x11_display *dpy;
686 drmModeConnectorPtr conn;
687
Tony Barbour8205d902015-04-16 15:59:00 -0600688 dpy = intel_alloc(gpu, sizeof(*dpy), 0, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
Chia-I Wu8635e912015-04-09 14:13:57 +0800689 if (!dpy)
690 return NULL;
691
692 memset(dpy, 0, sizeof(*dpy));
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800693 intel_handle_init(&dpy->handle, VK_DBG_OBJECT_DISPLAY_WSI, gpu->handle.icd);
Chia-I Wu8635e912015-04-09 14:13:57 +0800694
695 dpy->fd = fd;
696 dpy->connector_id = connector_id;
697
698 conn = drmModeGetConnector(fd, connector_id);
699 if (!conn) {
700 x11_display_destroy(dpy);
701 return NULL;
702 }
703
704 x11_display_init_name(dpy, conn);
705 x11_display_init_modes(dpy, conn);
706
707 drmModeFreeConnector(conn);
708
709 return dpy;
710}
711
712static void x11_display_scan(struct intel_gpu *gpu)
713{
714 struct intel_x11_display **displays;
715 drmModeResPtr res;
716 int fd, i;
717
718 fd = intel_gpu_get_primary_fd(gpu);
719 if (fd < 0)
720 return;
721
722 res = drmModeGetResources(fd);
723 if (!res)
724 return;
725
726 displays = intel_alloc(gpu, sizeof(*displays) * res->count_connectors,
Tony Barbour8205d902015-04-16 15:59:00 -0600727 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu8635e912015-04-09 14:13:57 +0800728 if (!displays) {
729 drmModeFreeResources(res);
730 return;
731 }
732
733 for (i = 0; i < res->count_connectors; i++) {
734 displays[i] = x11_display_create(gpu, fd, res->connectors[i]);
735 if (!displays[i])
736 break;
737 }
738
739 drmModeFreeResources(res);
740
741 gpu->displays = (struct intel_wsi_display **) displays;
742 gpu->display_count = i;
743}
744
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600745VkResult intel_wsi_gpu_get_info(struct intel_gpu *gpu,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800746 VkPhysicalDeviceInfoType type,
747 size_t *size, void *data)
Chia-I Wu41858c82015-04-04 16:39:25 +0800748{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800749 VkResult ret = VK_SUCCESS;
Chia-I Wu8635e912015-04-09 14:13:57 +0800750
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800751 if (!size)
752 return VK_ERROR_INVALID_POINTER;
753
754 switch ((int) type) {
755 case VK_PHYSICAL_DEVICE_INFO_TYPE_DISPLAY_PROPERTIES_WSI:
756 {
757 VkDisplayPropertiesWSI *dst = data;
758 size_t size_ret;
759 uint32_t i;
760
761 if (!gpu->display_count)
762 x11_display_scan(gpu);
763
764 size_ret = sizeof(*dst) * gpu->display_count;
765
766 if (dst && *size < size_ret)
767 return VK_ERROR_INVALID_VALUE;
768
769 *size = size_ret;
770 if (!dst)
771 return VK_SUCCESS;
772
773 for (i = 0; i < gpu->display_count; i++) {
774 struct intel_x11_display *dpy =
775 (struct intel_x11_display *) gpu->displays[i];
776
777 dst[i].display = (VkDisplayWSI) dpy;
778#if 0 // Remove this until we support an upstream version of WSI that has this:
779 dst[i].displayName = dpy->name;
780#endif
781 }
782 }
783 break;
784 case VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PRESENT_PROPERTIES_WSI:
785 {
786 VkPhysicalDeviceQueuePresentPropertiesWSI *dst = data;
787 size_t size_ret;
788 uint32_t i;
789
790 size_ret = sizeof(*dst) * INTEL_GPU_ENGINE_COUNT;
791
792 if (dst && *size < size_ret)
793 return VK_ERROR_INVALID_VALUE;
794
795 *size = size_ret;
796 if (!dst)
797 return VK_SUCCESS;
798
799 for (i = 0; i < INTEL_GPU_ENGINE_COUNT; i++)
800 dst[i].supportsPresent = true;
801 }
802 break;
803 default:
804 ret = VK_ERROR_INVALID_VALUE;
805 break;
806 }
807
808 return ret;
Chia-I Wu41858c82015-04-04 16:39:25 +0800809}
810
811void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
812{
Chia-I Wu8635e912015-04-09 14:13:57 +0800813 if (gpu->displays) {
814 uint32_t i;
Chia-I Wu41858c82015-04-04 16:39:25 +0800815
Chia-I Wu8635e912015-04-09 14:13:57 +0800816 for (i = 0; i < gpu->display_count; i++) {
817 struct intel_x11_display *dpy =
818 (struct intel_x11_display *) gpu->displays[i];
819 x11_display_destroy(dpy);
820 }
821 intel_free(gpu, gpu->displays);
822 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800823}
824
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600825VkResult intel_wsi_img_init(struct intel_img *img)
Chia-I Wu41858c82015-04-04 16:39:25 +0800826{
827 struct intel_x11_img_data *data;
828
Tony Barbour8205d902015-04-16 15:59:00 -0600829 data = intel_alloc(img, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800830 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600831 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800832
833 memset(data, 0, sizeof(*data));
834
835 assert(!img->wsi_data);
836 img->wsi_data = data;
837
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600838 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800839}
840
841void intel_wsi_img_cleanup(struct intel_img *img)
842{
843 struct intel_x11_img_data *data =
844 (struct intel_x11_img_data *) img->wsi_data;
845
846 if (data->mem) {
847 close(data->prime_fd);
848 intel_mem_free(data->mem);
849 }
850
851 intel_free(img, img->wsi_data);
852}
853
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600854VkResult intel_wsi_fence_init(struct intel_fence *fence)
Chia-I Wu41858c82015-04-04 16:39:25 +0800855{
856 struct intel_x11_fence_data *data;
857
Tony Barbour8205d902015-04-16 15:59:00 -0600858 data = intel_alloc(fence, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800859 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600860 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800861
862 memset(data, 0, sizeof(*data));
863
864 assert(!fence->wsi_data);
865 fence->wsi_data = data;
866
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600867 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800868}
869
870void intel_wsi_fence_cleanup(struct intel_fence *fence)
871{
872 intel_free(fence, fence->wsi_data);
873}
874
875void intel_wsi_fence_copy(struct intel_fence *fence,
876 const struct intel_fence *src)
877{
878 memcpy(fence->wsi_data, src->wsi_data,
879 sizeof(struct intel_x11_fence_data));
880}
881
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600882VkResult intel_wsi_fence_wait(struct intel_fence *fence,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800883 int64_t timeout_ns)
Chia-I Wu41858c82015-04-04 16:39:25 +0800884{
885 struct intel_x11_fence_data *data =
886 (struct intel_x11_fence_data *) fence->wsi_data;
887
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800888 if (!data->swap_chain)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600889 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800890
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800891 return x11_swap_chain_wait(data->swap_chain, data->serial, timeout_ns);
Chia-I Wu41858c82015-04-04 16:39:25 +0800892}
893
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800894ICD_EXPORT VkResult VKAPI vkGetDisplayInfoWSI(
895 VkDisplayWSI display,
896 VkDisplayInfoTypeWSI infoType,
897 size_t* pDataSize,
898 void* pData)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800899{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800900 VkResult ret = VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800901
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800902 if (!pDataSize)
903 return VK_ERROR_INVALID_POINTER;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800904
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800905 switch (infoType) {
906 case VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI:
907 {
908 VkDisplayFormatPropertiesWSI *dst = pData;
909 size_t size_ret;
910 uint32_t i;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800911
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800912 size_ret = sizeof(*dst) * ARRAY_SIZE(x11_presentable_formats);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800913
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800914 if (dst && *pDataSize < size_ret)
915 return VK_ERROR_INVALID_VALUE;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800916
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800917 *pDataSize = size_ret;
918 if (!dst)
919 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800920
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800921 for (i = 0; i < ARRAY_SIZE(x11_presentable_formats); i++)
922 dst[i].swapChainFormat = x11_presentable_formats[i];
923 }
924 break;
925 default:
926 ret = VK_ERROR_INVALID_VALUE;
927 break;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800928 }
929
930 return ret;
931}
932
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800933ICD_EXPORT VkResult VKAPI vkCreateSwapChainWSI(
934 VkDevice device,
935 const VkSwapChainCreateInfoWSI* pCreateInfo,
936 VkSwapChainWSI* pSwapChain)
937{
938 struct intel_dev *dev = intel_dev(device);
939
940 return x11_swap_chain_create(dev, pCreateInfo,
941 (struct intel_x11_swap_chain **) pSwapChain);
942}
943
944ICD_EXPORT VkResult VKAPI vkDestroySwapChainWSI(
945 VkSwapChainWSI swapChain)
946{
947 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
948
949 x11_swap_chain_destroy(sc);
950
951 return VK_SUCCESS;
952}
953
954ICD_EXPORT VkResult VKAPI vkGetSwapChainInfoWSI(
955 VkSwapChainWSI swapChain,
956 VkSwapChainInfoTypeWSI infoType,
957 size_t* pDataSize,
958 void* pData)
959{
960 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
961 VkResult ret = VK_SUCCESS;
962
963 if (!pDataSize)
964 return VK_ERROR_INVALID_POINTER;
965
966 switch (infoType) {
967 case VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI:
968 {
969 VkSwapChainImageInfoWSI *images;
970 const size_t size = sizeof(*images) * sc->persistent_image_count;
971 uint32_t i;
972
973 if (pData && *pDataSize < size)
974 return VK_ERROR_INVALID_VALUE;
975
976 *pDataSize = size;
977 if (!pData)
978 return VK_SUCCESS;
979
980 images = (VkSwapChainImageInfoWSI *) pData;
981 for (i = 0; i < sc->persistent_image_count; i++) {
982 images[i].image = (VkImage) sc->persistent_images[i];
983 images[i].memory =
984 (VkDeviceMemory) sc->persistent_images[i]->obj.mem;
985 }
986 }
987 break;
988 default:
989 ret = VK_ERROR_INVALID_VALUE;
990 break;
991 }
992
993 return ret;
994}
995
996ICD_EXPORT VkResult VKAPI vkQueuePresentWSI(
997 VkQueue queue_,
998 const VkPresentInfoWSI* pPresentInfo)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800999{
1000 struct intel_queue *queue = intel_queue(queue_);
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001001 struct intel_img *img = intel_img(pPresentInfo->image);
1002 struct intel_x11_swap_chain *sc =
1003 ((struct intel_x11_img_data *) img->wsi_data)->swap_chain;
Chia-I Wub56f5df2015-04-04 20:21:10 +08001004 struct intel_x11_fence_data *data =
1005 (struct intel_x11_fence_data *) queue->fence->wsi_data;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06001006 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001007
Chia-I Wu6532d1d2015-04-04 22:16:45 +08001008 ret = x11_swap_chain_present_pixmap(sc, pPresentInfo);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001009 if (ret != VK_SUCCESS)
Chia-I Wu1db76e02014-09-15 14:21:14 +08001010 return ret;
1011
Chia-I Wu6532d1d2015-04-04 22:16:45 +08001012 data->swap_chain = sc;
1013 data->serial = sc->local.serial;
Chia-I Wub56f5df2015-04-04 20:21:10 +08001014 intel_fence_set_seqno(queue->fence, img->obj.mem->bo);
Chia-I Wubda4f622015-02-25 15:06:15 -07001015
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001016 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001017}