blob: 7484900070c8a71947743992ee885884435e9dac [file] [log] [blame]
Chia-I Wu1db76e02014-09-15 14:21:14 +08001/*
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002 * Vulkan
Chia-I Wu1db76e02014-09-15 14:21:14 +08003 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Ian Elliott4f299362015-07-06 14:45:11 -060026 * Ian Elliott <ian@lunarg.com>
Chia-I Wu1db76e02014-09-15 14:21:14 +080027 */
28
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <unistd.h>
32#include <fcntl.h>
33#include <xcb/xcb.h>
34#include <xcb/dri3.h>
35#include <xcb/present.h>
36
37#include "kmd/winsys.h"
Chia-I Wu8635e912015-04-09 14:13:57 +080038#include "kmd/libdrm/xf86drmMode.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080039#include "dev.h"
40#include "fence.h"
41#include "gpu.h"
42#include "img.h"
43#include "mem.h"
44#include "queue.h"
Chia-I Wu41858c82015-04-04 16:39:25 +080045#include "wsi.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080046
Chia-I Wu8635e912015-04-09 14:13:57 +080047struct intel_x11_display {
48 struct intel_handle handle;
49
50 int fd;
51 uint32_t connector_id;
52
53 char name[32];
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -060054 VkExtent2D physical_dimension;
55 VkExtent2D physical_resolution;
Chia-I Wu8635e912015-04-09 14:13:57 +080056
57 drmModeModeInfoPtr modes;
58 uint32_t mode_count;
59};
60
Ian Elliott4f299362015-07-06 14:45:11 -060061typedef enum intel_x11_swap_chain_image_state_
62{
63 INTEL_SC_STATE_UNUSED = 0,
64 INTEL_SC_STATE_APP_OWNED = 1,
65 INTEL_SC_STATE_QUEUED_FOR_PRESENT = 2,
66 INTEL_SC_STATE_DISPLAYED = 3,
67} intel_x11_swap_chain_image_state;
68
Chia-I Wu6532d1d2015-04-04 22:16:45 +080069struct intel_x11_swap_chain {
70 struct intel_handle handle;
71
72 xcb_connection_t *c;
73 xcb_window_t window;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080074 bool force_copy;
Ian Elliott4f299362015-07-06 14:45:11 -060075 VkPresentModeWSI present_mode;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080076
77 int dri3_major, dri3_minor;
78 int present_major, present_minor;
Chia-I Wu1db76e02014-09-15 14:21:14 +080079
80 xcb_present_event_t present_special_event_id;
81 xcb_special_event_t *present_special_event;
82
Chia-I Wu5b66aa52015-04-16 22:02:10 +080083 struct intel_img **persistent_images;
84 uint32_t persistent_image_count;
Ian Elliott4f299362015-07-06 14:45:11 -060085 intel_x11_swap_chain_image_state *image_state;
86 uint32_t *present_queue;
87 uint32_t present_queue_length;
Mike Stroyanf9f6dd72015-07-28 11:00:50 -060088 uint32_t present_serial;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080089
Chia-I Wu1db76e02014-09-15 14:21:14 +080090 struct {
91 uint32_t serial;
92 } local;
93
94 struct {
95 uint32_t serial;
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -060096 uint64_t msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +080097 } remote;
98};
99
Chia-I Wu41858c82015-04-04 16:39:25 +0800100struct intel_x11_img_data {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800101 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +0800102 struct intel_mem *mem;
103 int prime_fd;
104 uint32_t pixmap;
105};
106
107struct intel_x11_fence_data {
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800108 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +0800109 uint32_t serial;
110};
111
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800112/* these are what DDX expects */
113static const VkFormat x11_presentable_formats[] = {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800114 VK_FORMAT_B8G8R8A8_UNORM,
115 VK_FORMAT_B8G8R8A8_SRGB,
Ian Elliott32536f92015-04-21 16:41:02 -0600116 VK_FORMAT_B5G6R5_UNORM,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800117};
118
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800119static inline struct intel_x11_swap_chain *x11_swap_chain(VkSwapChainWSI sc)
120{
Ian Elliott4f299362015-07-06 14:45:11 -0600121 return (struct intel_x11_swap_chain *) sc.handle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800122}
123
Chia-I Wufcbc5252015-04-08 11:44:26 +0800124static bool x11_is_format_presentable(const struct intel_dev *dev,
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600125 VkFormat format)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800126{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800127 uint32_t i;
128
129 for (i = 0; i < ARRAY_SIZE(x11_presentable_formats); i++) {
130 if (x11_presentable_formats[i] == format)
131 return true;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800132 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800133
134 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800135}
136
Chia-I Wu030b2db2015-04-08 13:46:29 +0800137static int x11_export_prime_fd(struct intel_dev *dev,
138 struct intel_bo *bo,
139 const struct intel_layout *layout)
140{
141 struct intel_winsys_handle export;
142 enum intel_tiling_mode tiling;
143
144 export.type = INTEL_WINSYS_HANDLE_FD;
145
146 switch (layout->tiling) {
147 case GEN6_TILING_X:
148 tiling = INTEL_TILING_X;
149 break;
150 case GEN6_TILING_Y:
151 tiling = INTEL_TILING_Y;
152 break;
153 default:
154 assert(layout->tiling == GEN6_TILING_NONE);
155 tiling = INTEL_TILING_NONE;
156 break;
157 }
158
159 if (intel_bo_set_tiling(bo, tiling, layout->bo_stride))
160 return -1;
161
162 if (intel_winsys_export_handle(dev->winsys, bo, tiling,
163 layout->bo_stride, layout->bo_height, &export))
164 return -1;
165
166 return (int) export.handle;
167}
168
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800169/**
Chia-I Wufcbc5252015-04-08 11:44:26 +0800170 * Return true if fd points to the primary or render node of the GPU.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800171 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800172static bool x11_gpu_match_fd(const struct intel_gpu *gpu, int fd)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800173{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800174 struct stat fd_stat, gpu_stat;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800175
Chia-I Wufcbc5252015-04-08 11:44:26 +0800176 if (fstat(fd, &fd_stat))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800177 return false;
178
179 /* is it the primary node? */
180 if (!stat(gpu->primary_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800181 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800182 return true;
183
184 /* is it the render node? */
185 if (gpu->render_node && !stat(gpu->render_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800186 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800187 return true;
188
189 return false;
190}
191
Chia-I Wufcbc5252015-04-08 11:44:26 +0800192/*
193 * Return the depth of \p drawable.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800194 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800195static int x11_get_drawable_depth(xcb_connection_t *c,
196 xcb_drawable_t drawable)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800197{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800198 xcb_get_geometry_cookie_t cookie;
199 xcb_get_geometry_reply_t *reply;
200 uint8_t depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800201
Chia-I Wufcbc5252015-04-08 11:44:26 +0800202 cookie = xcb_get_geometry(c, drawable);
203 reply = xcb_get_geometry_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800204
Chia-I Wufcbc5252015-04-08 11:44:26 +0800205 if (reply) {
206 depth = reply->depth;
207 free(reply);
208 } else {
209 depth = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800210 }
211
Chia-I Wufcbc5252015-04-08 11:44:26 +0800212 return depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800213}
214
Ian Elliott4f299362015-07-06 14:45:11 -0600215static VkResult x11_get_surface_properties(
216 const VkSurfaceDescriptionWSI *pSurfaceDescription,
217 VkSurfacePropertiesWSI *pSurfaceProperties)
218{
219 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
220 (VkSurfaceDescriptionWindowWSI*) pSurfaceDescription;
221 VkPlatformHandleXcbWSI *pPlatformHandleXcb = (VkPlatformHandleXcbWSI *)
222 pSurfaceDescriptionWindow->pPlatformHandle;
223 xcb_connection_t *c = (xcb_connection_t *)
224 pPlatformHandleXcb->connection;
225 xcb_window_t window = *((xcb_window_t *)
226 pSurfaceDescriptionWindow->pPlatformWindow);
227 xcb_get_geometry_cookie_t cookie;
228 xcb_get_geometry_reply_t *reply;
229
230 cookie = xcb_get_geometry(c, window);
231 reply = xcb_get_geometry_reply(c, cookie, NULL);
232
233 if (reply) {
234 pSurfaceProperties->currentExtent.width = reply->width;
235 pSurfaceProperties->currentExtent.height = reply->height;
236 free(reply);
237 } else {
238 pSurfaceProperties->currentExtent.width = 0;
239 pSurfaceProperties->currentExtent.height = 0;
240 }
241
242 pSurfaceProperties->minImageCount = 2;
243 pSurfaceProperties->maxImageCount = 0;
244
245 pSurfaceProperties->minImageExtent.width =
246 pSurfaceProperties->currentExtent.width;
247 pSurfaceProperties->minImageExtent.height =
248 pSurfaceProperties->currentExtent.height;
249 pSurfaceProperties->maxImageExtent.width =
250 pSurfaceProperties->currentExtent.width;
251 pSurfaceProperties->maxImageExtent.height =
252 pSurfaceProperties->currentExtent.height;
253 pSurfaceProperties->supportedTransforms = VK_SURFACE_TRANSFORM_NONE_BIT_WSI;
254 pSurfaceProperties->currentTransform = VK_SURFACE_TRANSFORM_NONE_WSI;
255 pSurfaceProperties->maxImageArraySize = 0;
256 pSurfaceProperties->supportedUsageFlags =
Cody Northrop3440c2d2015-08-28 16:40:45 -0600257 VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
Ian Elliott4f299362015-07-06 14:45:11 -0600258 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
259
260 return VK_SUCCESS;
261}
262
Chia-I Wu1db76e02014-09-15 14:21:14 +0800263/**
264 * Return true if DRI3 and Present are supported by the server.
265 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800266static bool x11_is_dri3_and_present_supported(xcb_connection_t *c)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800267{
268 const xcb_query_extension_reply_t *ext;
269
Chia-I Wufcbc5252015-04-08 11:44:26 +0800270 xcb_prefetch_extension_data(c, &xcb_dri3_id);
271 xcb_prefetch_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800272
Chia-I Wufcbc5252015-04-08 11:44:26 +0800273 ext = xcb_get_extension_data(c, &xcb_dri3_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800274 if (!ext || !ext->present)
275 return false;
276
Chia-I Wufcbc5252015-04-08 11:44:26 +0800277 ext = xcb_get_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800278 if (!ext || !ext->present)
279 return false;
280
281 return true;
282}
283
284/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800285 * Send a DRI3Open to get the server GPU fd.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800286 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800287static int x11_dri3_open(xcb_connection_t *c,
288 xcb_drawable_t drawable,
289 xcb_randr_provider_t provider)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800290{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800291 xcb_dri3_open_cookie_t cookie;
292 xcb_dri3_open_reply_t *reply;
293 int fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800294
Chia-I Wufcbc5252015-04-08 11:44:26 +0800295 cookie = xcb_dri3_open(c, drawable, provider);
296 reply = xcb_dri3_open_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800297 if (!reply)
Chia-I Wufcbc5252015-04-08 11:44:26 +0800298 return -1;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800299
Chia-I Wufcbc5252015-04-08 11:44:26 +0800300 fd = (reply->nfd == 1) ? xcb_dri3_open_reply_fds(c, reply)[0] : -1;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800301 free(reply);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800302
Chia-I Wufcbc5252015-04-08 11:44:26 +0800303 return fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800304}
305
306/**
Chia-I Wu030b2db2015-04-08 13:46:29 +0800307 * Send a DRI3PixmapFromBuffer to create a pixmap from \p prime_fd.
308 */
309static xcb_pixmap_t x11_dri3_pixmap_from_buffer(xcb_connection_t *c,
310 xcb_drawable_t drawable,
311 uint8_t depth, int prime_fd,
312 const struct intel_layout *layout)
313{
314 xcb_pixmap_t pixmap;
315
316 pixmap = xcb_generate_id(c);
317
318 xcb_dri3_pixmap_from_buffer(c, pixmap, drawable,
319 layout->bo_stride * layout->bo_height,
320 layout->width0, layout->height0,
321 layout->bo_stride, depth,
322 layout->block_size * 8, prime_fd);
323
324 return pixmap;
325}
326
327/**
Chia-I Wu41858c82015-04-04 16:39:25 +0800328 * Send DRI3QueryVersion and PresentQueryVersion to query extension versions.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800329 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800330static bool x11_swap_chain_dri3_and_present_query_version(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800331{
332 xcb_dri3_query_version_cookie_t dri3_cookie;
333 xcb_dri3_query_version_reply_t *dri3_reply;
334 xcb_present_query_version_cookie_t present_cookie;
335 xcb_present_query_version_reply_t *present_reply;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800336
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800337 dri3_cookie = xcb_dri3_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800338 XCB_DRI3_MAJOR_VERSION, XCB_DRI3_MINOR_VERSION);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800339 present_cookie = xcb_present_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800340 XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION);
341
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800342 dri3_reply = xcb_dri3_query_version_reply(sc->c, dri3_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800343 if (!dri3_reply)
344 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800345
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800346 sc->dri3_major = dri3_reply->major_version;
347 sc->dri3_minor = dri3_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800348 free(dri3_reply);
349
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800350 present_reply = xcb_present_query_version_reply(sc->c, present_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800351 if (!present_reply)
352 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800353
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800354 sc->present_major = present_reply->major_version;
355 sc->present_minor = present_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800356 free(present_reply);
357
Chia-I Wu41858c82015-04-04 16:39:25 +0800358 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800359}
360
361/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800362 * Send a PresentSelectInput to select interested events.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800363 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800364static bool x11_swap_chain_present_select_input(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800365{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800366 xcb_void_cookie_t cookie;
367 xcb_generic_error_t *error;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800368
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800369 /* create the event queue */
370 sc->present_special_event_id = xcb_generate_id(sc->c);
371 sc->present_special_event = xcb_register_for_special_xge(sc->c,
372 &xcb_present_id, sc->present_special_event_id, NULL);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800373
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800374 cookie = xcb_present_select_input_checked(sc->c,
375 sc->present_special_event_id, sc->window,
376 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800377
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800378 error = xcb_request_check(sc->c, cookie);
379 if (error) {
380 free(error);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800381 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800382 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800383
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800384 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800385}
386
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800387static struct intel_img *x11_swap_chain_create_persistent_image(struct intel_x11_swap_chain *sc,
388 struct intel_dev *dev,
389 const VkImageCreateInfo *img_info)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800390{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800391 struct intel_img *img;
392 struct intel_mem *mem;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800393 struct intel_x11_img_data *data;
394 VkMemoryAllocInfo mem_info;
395 int prime_fd;
396 xcb_pixmap_t pixmap;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600397 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800398
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800399 ret = intel_img_create(dev, img_info, true, &img);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600400 if (ret != VK_SUCCESS)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800401 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800402
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800403 memset(&mem_info, 0, sizeof(mem_info));
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600404 mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800405 mem_info.allocationSize = img->total_size;
Mark Lobodzinski72346292015-07-02 16:49:40 -0600406 mem_info.memoryTypeIndex = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800407
408 ret = intel_mem_alloc(dev, &mem_info, &mem);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600409 if (ret != VK_SUCCESS) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800410 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800411 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800412 }
413
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800414 prime_fd = x11_export_prime_fd(dev, mem->bo, &img->layout);
415 if (prime_fd < 0) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800416 intel_mem_free(mem);
417 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800418 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800419 }
420
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800421 pixmap = x11_dri3_pixmap_from_buffer(sc->c, sc->window,
422 x11_get_drawable_depth(sc->c, sc->window),
423 prime_fd, &img->layout);
424
425 data = (struct intel_x11_img_data *) img->wsi_data;
426 data->swap_chain = sc;
427 data->mem = mem;
428 data->prime_fd = prime_fd;
429 data->pixmap = pixmap;
430
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800431 intel_obj_bind_mem(&img->obj, mem, 0);
432
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800433 return img;
434}
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800435
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800436static bool x11_swap_chain_create_persistent_images(struct intel_x11_swap_chain *sc,
437 struct intel_dev *dev,
438 const VkSwapChainCreateInfoWSI *info)
439{
440 struct intel_img **images;
Ian Elliott4f299362015-07-06 14:45:11 -0600441 intel_x11_swap_chain_image_state *image_state;
442 uint32_t *present_queue;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800443 VkImageCreateInfo img_info;
444 uint32_t i;
445
Ian Elliott4f299362015-07-06 14:45:11 -0600446 images = intel_alloc(sc, sizeof(*images) * info->minImageCount,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800447 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
448 if (!images)
449 return false;
Ian Elliott4f299362015-07-06 14:45:11 -0600450 image_state = intel_alloc(
451 sc, sizeof(intel_x11_swap_chain_image_state) * info->minImageCount,
452 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
453 if (!image_state) {
454 for (i = 0; i < info->minImageCount; i++) {
455 intel_img_destroy(images[i]);
456 }
457 intel_free(sc, images);
458 return false;
459 }
460 present_queue = intel_alloc(
461 sc, sizeof(uint32_t) * info->minImageCount,
462 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
463 if (!present_queue) {
464 for (i = 0; i < info->minImageCount; i++) {
465 intel_img_destroy(images[i]);
466 }
467 intel_free(sc, images);
468 intel_free(sc, image_state);
469 return false;
470 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800471
472 memset(&img_info, 0, sizeof(img_info));
473 img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
474 img_info.imageType = VK_IMAGE_TYPE_2D;
475 img_info.format = info->imageFormat;
476 img_info.extent.width = info->imageExtent.width;
477 img_info.extent.height = info->imageExtent.height;
478 img_info.extent.depth = 1;
479 img_info.mipLevels = 1;
480 img_info.arraySize = info->imageArraySize;
481 img_info.samples = 1;
482 img_info.tiling = VK_IMAGE_TILING_OPTIMAL;
483 img_info.usage = info->imageUsageFlags;
484 img_info.flags = 0;
485
Ian Elliott4f299362015-07-06 14:45:11 -0600486 for (i = 0; i < info->minImageCount; i++) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800487 images[i] = x11_swap_chain_create_persistent_image(sc,
488 dev, &img_info);
489 if (!images[i])
490 break;
Ian Elliott4f299362015-07-06 14:45:11 -0600491 image_state[i] = INTEL_SC_STATE_UNUSED;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800492 }
493
Ian Elliott4f299362015-07-06 14:45:11 -0600494 if (i < info->minImageCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800495 uint32_t j;
496 for (j = 0; j < i; j++)
Ian Elliott4f299362015-07-06 14:45:11 -0600497 intel_img_destroy(images[j]);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800498
499 intel_free(sc, images);
500
Ian Elliott4f299362015-07-06 14:45:11 -0600501 if (image_state) {
502 intel_free(sc, image_state);
503 }
504
505 if (present_queue) {
506 intel_free(sc, present_queue);
507 }
508
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800509 return false;
510 }
511
512 sc->persistent_images = images;
Ian Elliott4f299362015-07-06 14:45:11 -0600513 sc->persistent_image_count = info->minImageCount;
514 sc->image_state = image_state;
515 sc->present_queue = present_queue;
516 sc->present_queue_length = 0;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800517
518 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800519}
520
521/**
522 * Send a PresentPixmap.
523 */
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600524static VkResult x11_swap_chain_present_pixmap(struct intel_x11_swap_chain *sc,
Ian Elliott4f299362015-07-06 14:45:11 -0600525 struct intel_img *img)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800526{
Chia-I Wu41858c82015-04-04 16:39:25 +0800527 struct intel_x11_img_data *data =
528 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800529 uint32_t options = XCB_PRESENT_OPTION_NONE;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800530 uint32_t target_msc, divisor, remainder;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800531 xcb_void_cookie_t cookie;
532 xcb_generic_error_t *err;
533
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800534 target_msc = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600535 divisor = 1;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800536 remainder = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600537 if (sc->present_mode == VK_PRESENT_MODE_IMMEDIATE_WSI) {
Chia-I Wu1db76e02014-09-15 14:21:14 +0800538 options |= XCB_PRESENT_OPTION_ASYNC;
Ian Elliott4f299362015-07-06 14:45:11 -0600539 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800540
541 if (sc->force_copy)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800542 options |= XCB_PRESENT_OPTION_COPY;
543
Chia-I Wuf689c602015-04-28 10:55:52 +0800544 cookie = xcb_present_pixmap_checked(sc->c,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800545 sc->window,
Chia-I Wu41858c82015-04-04 16:39:25 +0800546 data->pixmap,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800547 ++sc->local.serial,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800548 0, /* valid-area */
549 0, /* update-area */
550 0, /* x-off */
551 0, /* y-off */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800552 0, /* crtc */
Chia-I Wu1db76e02014-09-15 14:21:14 +0800553 0, /* wait-fence */
554 0, /* idle-fence */
555 options,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800556 target_msc,
557 divisor,
558 remainder,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800559 0, NULL);
560
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800561 err = xcb_request_check(sc->c, cookie);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800562 if (err) {
563 free(err);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600564 return VK_ERROR_UNKNOWN;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800565 }
566
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600567 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800568}
569
570/**
Chia-I Wu1db76e02014-09-15 14:21:14 +0800571 * Handle a Present event.
572 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800573static void x11_swap_chain_present_event(struct intel_x11_swap_chain *sc,
574 const xcb_present_generic_event_t *ev)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800575{
576 union {
577 const xcb_present_generic_event_t *ev;
578 const xcb_present_complete_notify_event_t *complete;
579 } u = { .ev = ev };
580
581 switch (u.ev->evtype) {
582 case XCB_PRESENT_COMPLETE_NOTIFY:
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800583 sc->remote.serial = u.complete->serial;
584 sc->remote.msc = u.complete->msc;
Ian Elliott4f299362015-07-06 14:45:11 -0600585 assert(sc->present_queue_length > 0);
586 if (sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_DISPLAYED) {
587 // Remove the previously-displayed image from the present queue:
588 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_UNUSED;
589 sc->present_queue_length--;
590 for (int j = 0; j < sc->present_queue_length; j++) {
591 sc->present_queue[j] = sc->present_queue[j+1];
592 }
593 }
594 assert(sc->present_queue_length > 0);
595 assert(sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_QUEUED_FOR_PRESENT);
596 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_DISPLAYED;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800597 break;
598 default:
599 break;
600 }
601}
602
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600603static VkResult x11_swap_chain_wait(struct intel_x11_swap_chain *sc,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800604 uint32_t serial, int64_t timeout)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800605{
606 const bool wait = (timeout != 0);
607
608 while (sc->remote.serial < serial) {
609 xcb_present_generic_event_t *ev;
Mike Stroyan4a387162015-04-27 15:42:41 -0600610 xcb_intern_atom_reply_t *reply;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800611
612 if (wait) {
613 ev = (xcb_present_generic_event_t *)
614 xcb_wait_for_special_event(sc->c, sc->present_special_event);
Mike Stroyan4a387162015-04-27 15:42:41 -0600615 /* use xcb_intern_atom_reply just to wake other threads waiting on sc->c */
616 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
617 if (reply) {
618 free(reply);
619 }
620
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800621 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600622 return VK_ERROR_UNKNOWN;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800623 } else {
Mike Stroyan4a387162015-04-27 15:42:41 -0600624 /* use xcb_intern_atom_reply just to check socket for special event */
625 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
626 if (reply) {
627 free(reply);
628 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800629 ev = (xcb_present_generic_event_t *)
630 xcb_poll_for_special_event(sc->c, sc->present_special_event);
631 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600632 return VK_NOT_READY;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800633 }
634
635 x11_swap_chain_present_event(sc, ev);
636
637 free(ev);
638 }
639
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600640 return VK_SUCCESS;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800641}
642
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800643static void x11_swap_chain_destroy(struct intel_x11_swap_chain *sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800644{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800645 if (sc->persistent_images) {
646 uint32_t i;
647
648 for (i = 0; i < sc->persistent_image_count; i++)
649 intel_img_destroy(sc->persistent_images[i]);
650 intel_free(sc, sc->persistent_images);
651 }
652
Ian Elliott4f299362015-07-06 14:45:11 -0600653 if (sc->image_state) {
654 intel_free(sc, sc->image_state);
655 }
656
657 if (sc->present_queue) {
658 intel_free(sc, sc->present_queue);
659 }
660
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800661 if (sc->present_special_event)
662 xcb_unregister_for_special_event(sc->c, sc->present_special_event);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800663
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800664 intel_free(sc, sc);
665}
666
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800667static VkResult x11_swap_chain_create(struct intel_dev *dev,
668 const VkSwapChainCreateInfoWSI *info,
669 struct intel_x11_swap_chain **sc_ret)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800670{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800671 const xcb_randr_provider_t provider = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600672 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
673 (VkSurfaceDescriptionWindowWSI*) info->pSurfaceDescription;
674 VkPlatformHandleXcbWSI *pPlatformHandleXcb = (VkPlatformHandleXcbWSI *)
675 pSurfaceDescriptionWindow->pPlatformHandle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800676 xcb_connection_t *c = (xcb_connection_t *)
Ian Elliott4f299362015-07-06 14:45:11 -0600677 pPlatformHandleXcb->connection;
678 xcb_window_t window = *((xcb_window_t *)
679 pSurfaceDescriptionWindow->pPlatformWindow);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800680 struct intel_x11_swap_chain *sc;
681 int fd;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800682
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800683 if (!x11_is_format_presentable(dev, info->imageFormat)) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600684 intel_dev_log(dev, VK_DBG_REPORT_ERROR_BIT,
685 VK_NULL_HANDLE, 0, 0, "invalid presentable image format");
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800686 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800687 }
688
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800689 if (!x11_is_dri3_and_present_supported(c))
690 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800691
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800692 fd = x11_dri3_open(c, window, provider);
693 if (fd < 0 || !x11_gpu_match_fd(dev->gpu, fd)) {
Chia-I Wufcbc5252015-04-08 11:44:26 +0800694 if (fd >= 0)
695 close(fd);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800696 return VK_ERROR_INVALID_VALUE;
Chia-I Wufcbc5252015-04-08 11:44:26 +0800697 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800698
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800699 close(fd);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800700
Tony Barbour8205d902015-04-16 15:59:00 -0600701 sc = intel_alloc(dev, sizeof(*sc), 0, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800702 if (!sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800703 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800704
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800705 memset(sc, 0, sizeof(*sc));
Courtney Goeltzenleuchter9ecf6852015-06-09 08:22:48 -0600706 intel_handle_init(&sc->handle, VK_OBJECT_TYPE_SWAP_CHAIN_WSI, dev->base.handle.instance);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800707
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800708 sc->c = c;
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800709 sc->window = window;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800710
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800711 /* always copy unless flip bit is set */
Ian Elliott4f299362015-07-06 14:45:11 -0600712 sc->present_mode = info->presentMode;
713 sc->force_copy = true;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800714
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800715 if (!x11_swap_chain_dri3_and_present_query_version(sc) ||
716 !x11_swap_chain_present_select_input(sc) ||
717 !x11_swap_chain_create_persistent_images(sc, dev, info)) {
718 x11_swap_chain_destroy(sc);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600719 return VK_ERROR_UNKNOWN;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800720 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800721
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800722 *sc_ret = sc;
Chia-I Wu41858c82015-04-04 16:39:25 +0800723
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600724 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800725}
726
Chia-I Wu8635e912015-04-09 14:13:57 +0800727static void x11_display_destroy(struct intel_x11_display *dpy)
728{
729 intel_free(dpy, dpy->modes);
730 intel_free(dpy, dpy);
731}
732
Chia-I Wu41858c82015-04-04 16:39:25 +0800733void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
734{
Chia-I Wu8635e912015-04-09 14:13:57 +0800735 if (gpu->displays) {
736 uint32_t i;
Chia-I Wu41858c82015-04-04 16:39:25 +0800737
Chia-I Wu8635e912015-04-09 14:13:57 +0800738 for (i = 0; i < gpu->display_count; i++) {
739 struct intel_x11_display *dpy =
740 (struct intel_x11_display *) gpu->displays[i];
741 x11_display_destroy(dpy);
742 }
743 intel_free(gpu, gpu->displays);
744 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800745}
746
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600747VkResult intel_wsi_img_init(struct intel_img *img)
Chia-I Wu41858c82015-04-04 16:39:25 +0800748{
749 struct intel_x11_img_data *data;
750
Tony Barbour8205d902015-04-16 15:59:00 -0600751 data = intel_alloc(img, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800752 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600753 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800754
755 memset(data, 0, sizeof(*data));
756
757 assert(!img->wsi_data);
758 img->wsi_data = data;
759
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600760 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800761}
762
763void intel_wsi_img_cleanup(struct intel_img *img)
764{
765 struct intel_x11_img_data *data =
766 (struct intel_x11_img_data *) img->wsi_data;
767
768 if (data->mem) {
769 close(data->prime_fd);
770 intel_mem_free(data->mem);
771 }
772
773 intel_free(img, img->wsi_data);
774}
775
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600776VkResult intel_wsi_fence_init(struct intel_fence *fence)
Chia-I Wu41858c82015-04-04 16:39:25 +0800777{
778 struct intel_x11_fence_data *data;
779
Tony Barbour8205d902015-04-16 15:59:00 -0600780 data = intel_alloc(fence, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800781 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600782 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800783
784 memset(data, 0, sizeof(*data));
785
786 assert(!fence->wsi_data);
787 fence->wsi_data = data;
788
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600789 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800790}
791
792void intel_wsi_fence_cleanup(struct intel_fence *fence)
793{
794 intel_free(fence, fence->wsi_data);
795}
796
797void intel_wsi_fence_copy(struct intel_fence *fence,
798 const struct intel_fence *src)
799{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600800 if (!fence->wsi_data) {
801 return;
802 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800803 memcpy(fence->wsi_data, src->wsi_data,
804 sizeof(struct intel_x11_fence_data));
805}
806
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600807VkResult intel_wsi_fence_wait(struct intel_fence *fence,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800808 int64_t timeout_ns)
Chia-I Wu41858c82015-04-04 16:39:25 +0800809{
810 struct intel_x11_fence_data *data =
811 (struct intel_x11_fence_data *) fence->wsi_data;
812
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600813 if (!data)
814 return VK_SUCCESS;
815
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800816 if (!data->swap_chain)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600817 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800818
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800819 return x11_swap_chain_wait(data->swap_chain, data->serial, timeout_ns);
Chia-I Wu41858c82015-04-04 16:39:25 +0800820}
821
Ian Elliott4f299362015-07-06 14:45:11 -0600822ICD_EXPORT VkResult VKAPI vkGetPhysicalDeviceSurfaceSupportWSI(
823 VkPhysicalDevice physicalDevice,
824 uint32_t queueNodeIndex,
825 const VkSurfaceDescriptionWSI* pSurfaceDescription,
826 VkBool32* pSupported)
827{
828 VkResult ret = VK_SUCCESS;
829 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
830 (VkSurfaceDescriptionWindowWSI*) pSurfaceDescription;
831
832 *pSupported = false;
833
834 // TODO: Move this check to a validation layer (i.e. the driver should
835 // assume the correct data type, and not check):
836 if (pSurfaceDescriptionWindow->sType != VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI) {
837 return VK_ERROR_INVALID_VALUE;
838 }
839
840 // TODO: NEED TO ALSO CHECK:
841 // - queueNodeIndex
842 // - pSurfaceDescriptionWindow->pPlatformHandle (can try to use it)
843 // - pSurfaceDescriptionWindow->pPlatformWindow (can try to use it)
844 if (pSurfaceDescriptionWindow->platform == VK_PLATFORM_XCB_WSI) {
845 *pSupported = true;
846 }
847
848 return ret;
849}
850
Ian Elliottebda9892015-08-06 17:35:06 -0600851VkResult VKAPI vkGetSurfacePropertiesWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600852 VkDevice device,
853 const VkSurfaceDescriptionWSI* pSurfaceDescription,
Ian Elliottebda9892015-08-06 17:35:06 -0600854 VkSurfacePropertiesWSI* pSurfaceProperties)
855{
856 // TODO: Move this check to a validation layer (i.e. the driver should
857 // assume the correct data type, and not check):
858 assert(pSurfaceProperties);
859
860 return x11_get_surface_properties(pSurfaceDescription, pSurfaceProperties);
861}
862
863VkResult VKAPI vkGetSurfaceFormatsWSI(
864 VkDevice device,
865 const VkSurfaceDescriptionWSI* pSurfaceDescription,
866 uint32_t* pCount,
867 VkSurfaceFormatWSI* pSurfaceFormats)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800868{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800869 VkResult ret = VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800870
Ian Elliott4f299362015-07-06 14:45:11 -0600871 // TODO: Move this check to a validation layer (i.e. the driver should
872 // assume the correct data type, and not check):
Ian Elliottebda9892015-08-06 17:35:06 -0600873 if (!pCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800874 return VK_ERROR_INVALID_POINTER;
Ian Elliott4f299362015-07-06 14:45:11 -0600875 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800876
Ian Elliottebda9892015-08-06 17:35:06 -0600877 if (pSurfaceFormats) {
878 uint32_t i;
879 for (i = 0; i < *pCount; i++) {
880 pSurfaceFormats[i].format = x11_presentable_formats[i];
881 pSurfaceFormats[i].colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_WSI;
Ian Elliott4f299362015-07-06 14:45:11 -0600882 }
Ian Elliotte1ea6712015-08-19 16:49:46 -0600883 } else {
884 *pCount = ARRAY_SIZE(x11_presentable_formats);
Ian Elliottebda9892015-08-06 17:35:06 -0600885 }
886
887 return ret;
888}
889
890VkResult VKAPI vkGetSurfacePresentModesWSI(
891 VkDevice device,
892 const VkSurfaceDescriptionWSI* pSurfaceDescription,
893 uint32_t* pCount,
894 VkPresentModeWSI* pPresentModes)
895{
896 VkResult ret = VK_SUCCESS;
897
898 // TODO: Move this check to a validation layer (i.e. the driver should
899 // assume the correct data type, and not check):
900 if (!pCount) {
901 return VK_ERROR_INVALID_POINTER;
902 }
903
Ian Elliottebda9892015-08-06 17:35:06 -0600904 if (pPresentModes) {
905 pPresentModes[0] = VK_PRESENT_MODE_IMMEDIATE_WSI;
906 pPresentModes[1] = VK_PRESENT_MODE_FIFO_WSI;
907 // TODO: Consider adding VK_PRESENT_MODE_MAILBOX_WSI sometime
Ian Elliotte1ea6712015-08-19 16:49:46 -0600908 } else {
909 *pCount = 2;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800910 }
911
912 return ret;
913}
914
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800915ICD_EXPORT VkResult VKAPI vkCreateSwapChainWSI(
916 VkDevice device,
917 const VkSwapChainCreateInfoWSI* pCreateInfo,
918 VkSwapChainWSI* pSwapChain)
919{
920 struct intel_dev *dev = intel_dev(device);
921
Ian Elliott4f299362015-07-06 14:45:11 -0600922 if (pCreateInfo->oldSwapChain.handle) {
923 // TODO: Eventually, do more than simply up-front destroy the
924 // oldSwapChain (but just do that for now):
925 struct intel_x11_swap_chain *sc =
926 x11_swap_chain(pCreateInfo->oldSwapChain);
927
928 x11_swap_chain_destroy(sc);
929 }
930
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800931 return x11_swap_chain_create(dev, pCreateInfo,
932 (struct intel_x11_swap_chain **) pSwapChain);
933}
934
935ICD_EXPORT VkResult VKAPI vkDestroySwapChainWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600936 VkDevice device,
937 VkSwapChainWSI swapChain)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800938{
939 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
940
941 x11_swap_chain_destroy(sc);
942
943 return VK_SUCCESS;
944}
945
Ian Elliottebda9892015-08-06 17:35:06 -0600946ICD_EXPORT VkResult VKAPI vkGetSwapChainImagesWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600947 VkDevice device,
948 VkSwapChainWSI swapChain,
Ian Elliottebda9892015-08-06 17:35:06 -0600949 uint32_t* pCount,
950 VkImage* pSwapChainImages)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800951{
952 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
953 VkResult ret = VK_SUCCESS;
954
Ian Elliott4f299362015-07-06 14:45:11 -0600955 // TODO: Move this check to a validation layer (i.e. the driver should
956 // assume the correct data type, and not check):
Ian Elliottebda9892015-08-06 17:35:06 -0600957 if (!pCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800958 return VK_ERROR_INVALID_POINTER;
Ian Elliott4f299362015-07-06 14:45:11 -0600959 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800960
Ian Elliottebda9892015-08-06 17:35:06 -0600961 if (pSwapChainImages) {
962 uint32_t i;
Ian Elliotte1ea6712015-08-19 16:49:46 -0600963 for (i = 0; i < *pCount; i++) {
Ian Elliottebda9892015-08-06 17:35:06 -0600964 pSwapChainImages[i].handle = (uint64_t) sc->persistent_images[i];
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800965 }
Ian Elliotte1ea6712015-08-19 16:49:46 -0600966 } else {
967 *pCount = sc->persistent_image_count;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800968 }
969
970 return ret;
971}
972
Ian Elliott4f299362015-07-06 14:45:11 -0600973ICD_EXPORT VkResult VKAPI vkAcquireNextImageWSI(
974 VkDevice device,
975 VkSwapChainWSI swapChain,
976 uint64_t timeout,
977 VkSemaphore semaphore,
978 uint32_t* pImageIndex)
979{
980 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
981 VkResult ret = VK_SUCCESS;
982
Ian Elliott4f299362015-07-06 14:45:11 -0600983 // Find an unused image to return:
984 for (int i = 0; i < sc->persistent_image_count; i++) {
985 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
986 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
987 *pImageIndex = i;
988 return ret;
989 }
990 }
991
Mike Stroyanf9f6dd72015-07-28 11:00:50 -0600992 // If no image is ready, wait for a present to finish
993 ret = x11_swap_chain_wait(sc, sc->present_serial, timeout);
994 if (ret != VK_SUCCESS) {
995 return ret;
996 }
Ian Elliott4f299362015-07-06 14:45:11 -0600997
Mike Stroyanf9f6dd72015-07-28 11:00:50 -0600998 // Find an unused image to return:
999 for (int i = 0; i < sc->persistent_image_count; i++) {
1000 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
1001 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
1002 *pImageIndex = i;
1003 return ret;
1004 }
1005 }
1006 // NOTE: Should never get here, but in case we do, do something:
1007 assert(0);
1008 return VK_ERROR_UNKNOWN;
Ian Elliott4f299362015-07-06 14:45:11 -06001009}
1010
1011
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001012ICD_EXPORT VkResult VKAPI vkQueuePresentWSI(
Ian Elliott4f299362015-07-06 14:45:11 -06001013 VkQueue queue_,
1014 VkPresentInfoWSI* pPresentInfo)
Chia-I Wu1db76e02014-09-15 14:21:14 +08001015{
1016 struct intel_queue *queue = intel_queue(queue_);
Ian Elliott4f299362015-07-06 14:45:11 -06001017 uint32_t i;
1018 uint32_t num_swapchains = pPresentInfo->swapChainCount;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001019
Ian Elliott4f299362015-07-06 14:45:11 -06001020 for (i = 0; i < num_swapchains; i++) {
1021 struct intel_x11_swap_chain *sc =
1022 x11_swap_chain(pPresentInfo->swapChains[i]);
1023 struct intel_img *img =
1024 sc->persistent_images[pPresentInfo->imageIndices[i]];
1025 struct intel_x11_fence_data *data =
1026 (struct intel_x11_fence_data *) queue->fence->wsi_data;
1027 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001028
Ian Elliott4f299362015-07-06 14:45:11 -06001029 ret = x11_swap_chain_present_pixmap(sc, img);
1030 if (ret != VK_SUCCESS) {
1031 return ret;
1032 }
1033
1034 // Record the state change for this image, and add this image to the
1035 // present queue for the swap chain:
1036 sc->image_state[pPresentInfo->imageIndices[i]] =
1037 INTEL_SC_STATE_QUEUED_FOR_PRESENT;
1038 sc->present_queue[sc->present_queue_length++] =
1039 pPresentInfo->imageIndices[i];
1040
1041 data->swap_chain = sc;
1042 data->serial = sc->local.serial;
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001043 sc->present_serial = sc->local.serial;
Ian Elliott4f299362015-07-06 14:45:11 -06001044 intel_fence_set_seqno(queue->fence, img->obj.mem->bo);
1045 }
Chia-I Wubda4f622015-02-25 15:06:15 -07001046
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001047 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001048}