blob: bec4cde089374fb30ca2a8410e51f611021235ac [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;
507
508 if (wait) {
509 ev = (xcb_present_generic_event_t *)
510 xcb_wait_for_special_event(sc->c, sc->present_special_event);
511 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600512 return VK_ERROR_UNKNOWN;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800513 } else {
514 ev = (xcb_present_generic_event_t *)
515 xcb_poll_for_special_event(sc->c, sc->present_special_event);
516 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600517 return VK_NOT_READY;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800518 }
519
520 x11_swap_chain_present_event(sc, ev);
521
522 free(ev);
523 }
524
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600525 return VK_SUCCESS;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800526}
527
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800528static void x11_swap_chain_destroy(struct intel_x11_swap_chain *sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800529{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800530 if (sc->persistent_images) {
531 uint32_t i;
532
533 for (i = 0; i < sc->persistent_image_count; i++)
534 intel_img_destroy(sc->persistent_images[i]);
535 intel_free(sc, sc->persistent_images);
536 }
537
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800538 if (sc->present_special_event)
539 xcb_unregister_for_special_event(sc->c, sc->present_special_event);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800540
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800541 intel_free(sc, sc);
542}
543
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800544static VkResult x11_swap_chain_create(struct intel_dev *dev,
545 const VkSwapChainCreateInfoWSI *info,
546 struct intel_x11_swap_chain **sc_ret)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800547{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800548 const xcb_randr_provider_t provider = 0;
549 xcb_connection_t *c = (xcb_connection_t *)
550 info->pNativeWindowSystemHandle;
551 xcb_window_t window = (xcb_window_t)
552 ((intptr_t) info->pNativeWindowHandle);
553 struct intel_x11_swap_chain *sc;
554 int fd;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800555
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800556 if (!x11_is_format_presentable(dev, info->imageFormat)) {
557 intel_dev_log(dev, VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0,
558 VK_NULL_HANDLE, 0, 0, "invalid presentable image format");
559 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800560 }
561
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800562 if (!x11_is_dri3_and_present_supported(c))
563 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800564
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800565 fd = x11_dri3_open(c, window, provider);
566 if (fd < 0 || !x11_gpu_match_fd(dev->gpu, fd)) {
Chia-I Wufcbc5252015-04-08 11:44:26 +0800567 if (fd >= 0)
568 close(fd);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800569 return VK_ERROR_INVALID_VALUE;
Chia-I Wufcbc5252015-04-08 11:44:26 +0800570 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800571
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800572 close(fd);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800573
Tony Barbour8205d902015-04-16 15:59:00 -0600574 sc = intel_alloc(dev, sizeof(*sc), 0, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800575 if (!sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800576 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800577
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800578 memset(sc, 0, sizeof(*sc));
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800579 intel_handle_init(&sc->handle, VK_DBG_OBJECT_SWAP_CHAIN_WSI, dev->base.handle.icd);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800580
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800581 sc->c = c;
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800582 sc->window = window;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800583
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800584 /* always copy unless flip bit is set */
585 sc->force_copy = !(info->swapModeFlags & VK_SWAP_MODE_FLIP_BIT_WSI);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800586
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800587 if (!x11_swap_chain_dri3_and_present_query_version(sc) ||
588 !x11_swap_chain_present_select_input(sc) ||
589 !x11_swap_chain_create_persistent_images(sc, dev, info)) {
590 x11_swap_chain_destroy(sc);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600591 return VK_ERROR_UNKNOWN;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800592 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800593
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800594 *sc_ret = sc;
Chia-I Wu41858c82015-04-04 16:39:25 +0800595
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600596 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800597}
598
Chia-I Wu8635e912015-04-09 14:13:57 +0800599static void x11_display_init_modes(struct intel_x11_display *dpy,
600 const drmModeConnectorPtr conn)
601{
602 int i;
603
604 if (!conn->count_modes)
605 return;
606
607 dpy->modes = intel_alloc(dpy, sizeof(dpy->modes[0]) * conn->count_modes,
Tony Barbour8205d902015-04-16 15:59:00 -0600608 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu8635e912015-04-09 14:13:57 +0800609 if (!dpy->modes)
610 return;
611
612 for (i = 0; i < conn->count_modes; i++) {
613 dpy->modes[i] = conn->modes[i];
614
615 if (dpy->physical_resolution.width < conn->modes[i].hdisplay &&
616 dpy->physical_resolution.height < conn->modes[i].vdisplay) {
617 dpy->physical_resolution.width = conn->modes[i].hdisplay;
618 dpy->physical_resolution.height = conn->modes[i].vdisplay;
619 }
620 }
621
622 dpy->mode_count = conn->count_modes;
623
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800624#if 0 // Remove this until we support an upstream version of WSI that has this:
Chia-I Wu8635e912015-04-09 14:13:57 +0800625 dpy->physical_dimension.width = conn->mmWidth;
626 dpy->physical_dimension.height = conn->mmHeight;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800627#endif
Chia-I Wu8635e912015-04-09 14:13:57 +0800628}
629
630static void x11_display_init_name(struct intel_x11_display *dpy,
631 const drmModeConnectorPtr conn)
632{
633 static const char *connector_names[] = {
634 [DRM_MODE_CONNECTOR_Unknown] = "Unknown",
635 [DRM_MODE_CONNECTOR_VGA] = "VGA",
636 [DRM_MODE_CONNECTOR_DVII] = "DVII",
637 [DRM_MODE_CONNECTOR_DVID] = "DVID",
638 [DRM_MODE_CONNECTOR_DVIA] = "DVIA",
639 [DRM_MODE_CONNECTOR_Composite] = "Composite",
640 [DRM_MODE_CONNECTOR_SVIDEO] = "SVIDEO",
641 [DRM_MODE_CONNECTOR_LVDS] = "LVDS",
642 [DRM_MODE_CONNECTOR_Component] = "COMPONENT",
643 [DRM_MODE_CONNECTOR_9PinDIN] = "9PinDIN",
644 [DRM_MODE_CONNECTOR_DisplayPort] = "DisplayPort",
645 [DRM_MODE_CONNECTOR_HDMIA] = "HDMIA",
646 [DRM_MODE_CONNECTOR_HDMIB] = "HDMIB",
647 [DRM_MODE_CONNECTOR_TV] = "TV",
648 [DRM_MODE_CONNECTOR_eDP] = "eDP",
649 [DRM_MODE_CONNECTOR_VIRTUAL] = "VIRTUAL",
650 [DRM_MODE_CONNECTOR_DSI] = "DSI",
651 };
652 const char *name;
653
654 name = (conn->connector_type < ARRAY_SIZE(connector_names)) ?
655 connector_names[conn->connector_type] : NULL;
656 if (!name)
657 name = connector_names[DRM_MODE_CONNECTOR_Unknown];
658
659 snprintf(dpy->name, sizeof(dpy->name),
660 "%s%d", name, conn->connector_type_id);
661}
662
663static void x11_display_destroy(struct intel_x11_display *dpy)
664{
665 intel_free(dpy, dpy->modes);
666 intel_free(dpy, dpy);
667}
668
669static struct intel_x11_display *x11_display_create(struct intel_gpu *gpu,
670 int fd,
671 uint32_t connector_id)
672{
673 struct intel_x11_display *dpy;
674 drmModeConnectorPtr conn;
675
Tony Barbour8205d902015-04-16 15:59:00 -0600676 dpy = intel_alloc(gpu, sizeof(*dpy), 0, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
Chia-I Wu8635e912015-04-09 14:13:57 +0800677 if (!dpy)
678 return NULL;
679
680 memset(dpy, 0, sizeof(*dpy));
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800681 intel_handle_init(&dpy->handle, VK_DBG_OBJECT_DISPLAY_WSI, gpu->handle.icd);
Chia-I Wu8635e912015-04-09 14:13:57 +0800682
683 dpy->fd = fd;
684 dpy->connector_id = connector_id;
685
686 conn = drmModeGetConnector(fd, connector_id);
687 if (!conn) {
688 x11_display_destroy(dpy);
689 return NULL;
690 }
691
692 x11_display_init_name(dpy, conn);
693 x11_display_init_modes(dpy, conn);
694
695 drmModeFreeConnector(conn);
696
697 return dpy;
698}
699
700static void x11_display_scan(struct intel_gpu *gpu)
701{
702 struct intel_x11_display **displays;
703 drmModeResPtr res;
704 int fd, i;
705
706 fd = intel_gpu_get_primary_fd(gpu);
707 if (fd < 0)
708 return;
709
710 res = drmModeGetResources(fd);
711 if (!res)
712 return;
713
714 displays = intel_alloc(gpu, sizeof(*displays) * res->count_connectors,
Tony Barbour8205d902015-04-16 15:59:00 -0600715 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu8635e912015-04-09 14:13:57 +0800716 if (!displays) {
717 drmModeFreeResources(res);
718 return;
719 }
720
721 for (i = 0; i < res->count_connectors; i++) {
722 displays[i] = x11_display_create(gpu, fd, res->connectors[i]);
723 if (!displays[i])
724 break;
725 }
726
727 drmModeFreeResources(res);
728
729 gpu->displays = (struct intel_wsi_display **) displays;
730 gpu->display_count = i;
731}
732
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600733VkResult intel_wsi_gpu_get_info(struct intel_gpu *gpu,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800734 VkPhysicalDeviceInfoType type,
735 size_t *size, void *data)
Chia-I Wu41858c82015-04-04 16:39:25 +0800736{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800737 VkResult ret = VK_SUCCESS;
Chia-I Wu8635e912015-04-09 14:13:57 +0800738
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800739 if (!size)
740 return VK_ERROR_INVALID_POINTER;
741
742 switch ((int) type) {
743 case VK_PHYSICAL_DEVICE_INFO_TYPE_DISPLAY_PROPERTIES_WSI:
744 {
745 VkDisplayPropertiesWSI *dst = data;
746 size_t size_ret;
747 uint32_t i;
748
749 if (!gpu->display_count)
750 x11_display_scan(gpu);
751
752 size_ret = sizeof(*dst) * gpu->display_count;
753
754 if (dst && *size < size_ret)
755 return VK_ERROR_INVALID_VALUE;
756
757 *size = size_ret;
758 if (!dst)
759 return VK_SUCCESS;
760
761 for (i = 0; i < gpu->display_count; i++) {
762 struct intel_x11_display *dpy =
763 (struct intel_x11_display *) gpu->displays[i];
764
765 dst[i].display = (VkDisplayWSI) dpy;
766#if 0 // Remove this until we support an upstream version of WSI that has this:
767 dst[i].displayName = dpy->name;
768#endif
769 }
770 }
771 break;
772 case VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PRESENT_PROPERTIES_WSI:
773 {
774 VkPhysicalDeviceQueuePresentPropertiesWSI *dst = data;
775 size_t size_ret;
776 uint32_t i;
777
778 size_ret = sizeof(*dst) * INTEL_GPU_ENGINE_COUNT;
779
780 if (dst && *size < size_ret)
781 return VK_ERROR_INVALID_VALUE;
782
783 *size = size_ret;
784 if (!dst)
785 return VK_SUCCESS;
786
787 for (i = 0; i < INTEL_GPU_ENGINE_COUNT; i++)
788 dst[i].supportsPresent = true;
789 }
790 break;
791 default:
792 ret = VK_ERROR_INVALID_VALUE;
793 break;
794 }
795
796 return ret;
Chia-I Wu41858c82015-04-04 16:39:25 +0800797}
798
799void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
800{
Chia-I Wu8635e912015-04-09 14:13:57 +0800801 if (gpu->displays) {
802 uint32_t i;
Chia-I Wu41858c82015-04-04 16:39:25 +0800803
Chia-I Wu8635e912015-04-09 14:13:57 +0800804 for (i = 0; i < gpu->display_count; i++) {
805 struct intel_x11_display *dpy =
806 (struct intel_x11_display *) gpu->displays[i];
807 x11_display_destroy(dpy);
808 }
809 intel_free(gpu, gpu->displays);
810 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800811}
812
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600813VkResult intel_wsi_img_init(struct intel_img *img)
Chia-I Wu41858c82015-04-04 16:39:25 +0800814{
815 struct intel_x11_img_data *data;
816
Tony Barbour8205d902015-04-16 15:59:00 -0600817 data = intel_alloc(img, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800818 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600819 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800820
821 memset(data, 0, sizeof(*data));
822
823 assert(!img->wsi_data);
824 img->wsi_data = data;
825
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600826 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800827}
828
829void intel_wsi_img_cleanup(struct intel_img *img)
830{
831 struct intel_x11_img_data *data =
832 (struct intel_x11_img_data *) img->wsi_data;
833
834 if (data->mem) {
835 close(data->prime_fd);
836 intel_mem_free(data->mem);
837 }
838
839 intel_free(img, img->wsi_data);
840}
841
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600842VkResult intel_wsi_fence_init(struct intel_fence *fence)
Chia-I Wu41858c82015-04-04 16:39:25 +0800843{
844 struct intel_x11_fence_data *data;
845
Tony Barbour8205d902015-04-16 15:59:00 -0600846 data = intel_alloc(fence, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800847 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600848 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800849
850 memset(data, 0, sizeof(*data));
851
852 assert(!fence->wsi_data);
853 fence->wsi_data = data;
854
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600855 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800856}
857
858void intel_wsi_fence_cleanup(struct intel_fence *fence)
859{
860 intel_free(fence, fence->wsi_data);
861}
862
863void intel_wsi_fence_copy(struct intel_fence *fence,
864 const struct intel_fence *src)
865{
866 memcpy(fence->wsi_data, src->wsi_data,
867 sizeof(struct intel_x11_fence_data));
868}
869
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600870VkResult intel_wsi_fence_wait(struct intel_fence *fence,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800871 int64_t timeout_ns)
Chia-I Wu41858c82015-04-04 16:39:25 +0800872{
873 struct intel_x11_fence_data *data =
874 (struct intel_x11_fence_data *) fence->wsi_data;
875
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800876 if (!data->swap_chain)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600877 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800878
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800879 return x11_swap_chain_wait(data->swap_chain, data->serial, timeout_ns);
Chia-I Wu41858c82015-04-04 16:39:25 +0800880}
881
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800882ICD_EXPORT VkResult VKAPI vkGetDisplayInfoWSI(
883 VkDisplayWSI display,
884 VkDisplayInfoTypeWSI infoType,
885 size_t* pDataSize,
886 void* pData)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800887{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800888 VkResult ret = VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800889
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800890 if (!pDataSize)
891 return VK_ERROR_INVALID_POINTER;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800892
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800893 switch (infoType) {
894 case VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI:
895 {
896 VkDisplayFormatPropertiesWSI *dst = pData;
897 size_t size_ret;
898 uint32_t i;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800899
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800900 size_ret = sizeof(*dst) * ARRAY_SIZE(x11_presentable_formats);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800901
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800902 if (dst && *pDataSize < size_ret)
903 return VK_ERROR_INVALID_VALUE;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800904
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800905 *pDataSize = size_ret;
906 if (!dst)
907 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800908
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800909 for (i = 0; i < ARRAY_SIZE(x11_presentable_formats); i++)
910 dst[i].swapChainFormat = x11_presentable_formats[i];
911 }
912 break;
913 default:
914 ret = VK_ERROR_INVALID_VALUE;
915 break;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800916 }
917
918 return ret;
919}
920
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800921ICD_EXPORT VkResult VKAPI vkCreateSwapChainWSI(
922 VkDevice device,
923 const VkSwapChainCreateInfoWSI* pCreateInfo,
924 VkSwapChainWSI* pSwapChain)
925{
926 struct intel_dev *dev = intel_dev(device);
927
928 return x11_swap_chain_create(dev, pCreateInfo,
929 (struct intel_x11_swap_chain **) pSwapChain);
930}
931
932ICD_EXPORT VkResult VKAPI vkDestroySwapChainWSI(
933 VkSwapChainWSI swapChain)
934{
935 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
936
937 x11_swap_chain_destroy(sc);
938
939 return VK_SUCCESS;
940}
941
942ICD_EXPORT VkResult VKAPI vkGetSwapChainInfoWSI(
943 VkSwapChainWSI swapChain,
944 VkSwapChainInfoTypeWSI infoType,
945 size_t* pDataSize,
946 void* pData)
947{
948 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
949 VkResult ret = VK_SUCCESS;
950
951 if (!pDataSize)
952 return VK_ERROR_INVALID_POINTER;
953
954 switch (infoType) {
955 case VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI:
956 {
957 VkSwapChainImageInfoWSI *images;
958 const size_t size = sizeof(*images) * sc->persistent_image_count;
959 uint32_t i;
960
961 if (pData && *pDataSize < size)
962 return VK_ERROR_INVALID_VALUE;
963
964 *pDataSize = size;
965 if (!pData)
966 return VK_SUCCESS;
967
968 images = (VkSwapChainImageInfoWSI *) pData;
969 for (i = 0; i < sc->persistent_image_count; i++) {
970 images[i].image = (VkImage) sc->persistent_images[i];
971 images[i].memory =
972 (VkDeviceMemory) sc->persistent_images[i]->obj.mem;
973 }
974 }
975 break;
976 default:
977 ret = VK_ERROR_INVALID_VALUE;
978 break;
979 }
980
981 return ret;
982}
983
984ICD_EXPORT VkResult VKAPI vkQueuePresentWSI(
985 VkQueue queue_,
986 const VkPresentInfoWSI* pPresentInfo)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800987{
988 struct intel_queue *queue = intel_queue(queue_);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800989 struct intel_img *img = intel_img(pPresentInfo->image);
990 struct intel_x11_swap_chain *sc =
991 ((struct intel_x11_img_data *) img->wsi_data)->swap_chain;
Chia-I Wub56f5df2015-04-04 20:21:10 +0800992 struct intel_x11_fence_data *data =
993 (struct intel_x11_fence_data *) queue->fence->wsi_data;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600994 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800995
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800996 ret = x11_swap_chain_present_pixmap(sc, pPresentInfo);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600997 if (ret != VK_SUCCESS)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800998 return ret;
999
Chia-I Wu6532d1d2015-04-04 22:16:45 +08001000 data->swap_chain = sc;
1001 data->serial = sc->local.serial;
Chia-I Wub56f5df2015-04-04 20:21:10 +08001002 intel_fence_set_seqno(queue->fence, img->obj.mem->bo);
Chia-I Wubda4f622015-02-25 15:06:15 -07001003
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001004 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001005}