blob: 52bf36006cc5286402adc63c85ff05ec07e6d72c [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 =
257 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
258
259 return VK_SUCCESS;
260}
261
Chia-I Wu1db76e02014-09-15 14:21:14 +0800262/**
263 * Return true if DRI3 and Present are supported by the server.
264 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800265static bool x11_is_dri3_and_present_supported(xcb_connection_t *c)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800266{
267 const xcb_query_extension_reply_t *ext;
268
Chia-I Wufcbc5252015-04-08 11:44:26 +0800269 xcb_prefetch_extension_data(c, &xcb_dri3_id);
270 xcb_prefetch_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800271
Chia-I Wufcbc5252015-04-08 11:44:26 +0800272 ext = xcb_get_extension_data(c, &xcb_dri3_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800273 if (!ext || !ext->present)
274 return false;
275
Chia-I Wufcbc5252015-04-08 11:44:26 +0800276 ext = xcb_get_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800277 if (!ext || !ext->present)
278 return false;
279
280 return true;
281}
282
283/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800284 * Send a DRI3Open to get the server GPU fd.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800285 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800286static int x11_dri3_open(xcb_connection_t *c,
287 xcb_drawable_t drawable,
288 xcb_randr_provider_t provider)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800289{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800290 xcb_dri3_open_cookie_t cookie;
291 xcb_dri3_open_reply_t *reply;
292 int fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800293
Chia-I Wufcbc5252015-04-08 11:44:26 +0800294 cookie = xcb_dri3_open(c, drawable, provider);
295 reply = xcb_dri3_open_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800296 if (!reply)
Chia-I Wufcbc5252015-04-08 11:44:26 +0800297 return -1;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800298
Chia-I Wufcbc5252015-04-08 11:44:26 +0800299 fd = (reply->nfd == 1) ? xcb_dri3_open_reply_fds(c, reply)[0] : -1;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800300 free(reply);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800301
Chia-I Wufcbc5252015-04-08 11:44:26 +0800302 return fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800303}
304
305/**
Chia-I Wu030b2db2015-04-08 13:46:29 +0800306 * Send a DRI3PixmapFromBuffer to create a pixmap from \p prime_fd.
307 */
308static xcb_pixmap_t x11_dri3_pixmap_from_buffer(xcb_connection_t *c,
309 xcb_drawable_t drawable,
310 uint8_t depth, int prime_fd,
311 const struct intel_layout *layout)
312{
313 xcb_pixmap_t pixmap;
314
315 pixmap = xcb_generate_id(c);
316
317 xcb_dri3_pixmap_from_buffer(c, pixmap, drawable,
318 layout->bo_stride * layout->bo_height,
319 layout->width0, layout->height0,
320 layout->bo_stride, depth,
321 layout->block_size * 8, prime_fd);
322
323 return pixmap;
324}
325
326/**
Chia-I Wu41858c82015-04-04 16:39:25 +0800327 * Send DRI3QueryVersion and PresentQueryVersion to query extension versions.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800328 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800329static bool x11_swap_chain_dri3_and_present_query_version(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800330{
331 xcb_dri3_query_version_cookie_t dri3_cookie;
332 xcb_dri3_query_version_reply_t *dri3_reply;
333 xcb_present_query_version_cookie_t present_cookie;
334 xcb_present_query_version_reply_t *present_reply;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800335
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800336 dri3_cookie = xcb_dri3_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800337 XCB_DRI3_MAJOR_VERSION, XCB_DRI3_MINOR_VERSION);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800338 present_cookie = xcb_present_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800339 XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION);
340
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800341 dri3_reply = xcb_dri3_query_version_reply(sc->c, dri3_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800342 if (!dri3_reply)
343 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800344
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800345 sc->dri3_major = dri3_reply->major_version;
346 sc->dri3_minor = dri3_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800347 free(dri3_reply);
348
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800349 present_reply = xcb_present_query_version_reply(sc->c, present_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800350 if (!present_reply)
351 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800352
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800353 sc->present_major = present_reply->major_version;
354 sc->present_minor = present_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800355 free(present_reply);
356
Chia-I Wu41858c82015-04-04 16:39:25 +0800357 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800358}
359
360/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800361 * Send a PresentSelectInput to select interested events.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800362 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800363static bool x11_swap_chain_present_select_input(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800364{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800365 xcb_void_cookie_t cookie;
366 xcb_generic_error_t *error;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800367
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800368 /* create the event queue */
369 sc->present_special_event_id = xcb_generate_id(sc->c);
370 sc->present_special_event = xcb_register_for_special_xge(sc->c,
371 &xcb_present_id, sc->present_special_event_id, NULL);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800372
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800373 cookie = xcb_present_select_input_checked(sc->c,
374 sc->present_special_event_id, sc->window,
375 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800376
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800377 error = xcb_request_check(sc->c, cookie);
378 if (error) {
379 free(error);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800380 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800381 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800382
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800383 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800384}
385
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800386static struct intel_img *x11_swap_chain_create_persistent_image(struct intel_x11_swap_chain *sc,
387 struct intel_dev *dev,
388 const VkImageCreateInfo *img_info)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800389{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800390 struct intel_img *img;
391 struct intel_mem *mem;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800392 struct intel_x11_img_data *data;
393 VkMemoryAllocInfo mem_info;
394 int prime_fd;
395 xcb_pixmap_t pixmap;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600396 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800397
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800398 ret = intel_img_create(dev, img_info, true, &img);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600399 if (ret != VK_SUCCESS)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800400 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800401
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800402 memset(&mem_info, 0, sizeof(mem_info));
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600403 mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800404 mem_info.allocationSize = img->total_size;
Mark Lobodzinski72346292015-07-02 16:49:40 -0600405 mem_info.memoryTypeIndex = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800406
407 ret = intel_mem_alloc(dev, &mem_info, &mem);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600408 if (ret != VK_SUCCESS) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800409 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800410 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800411 }
412
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800413 prime_fd = x11_export_prime_fd(dev, mem->bo, &img->layout);
414 if (prime_fd < 0) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800415 intel_mem_free(mem);
416 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800417 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800418 }
419
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800420 pixmap = x11_dri3_pixmap_from_buffer(sc->c, sc->window,
421 x11_get_drawable_depth(sc->c, sc->window),
422 prime_fd, &img->layout);
423
424 data = (struct intel_x11_img_data *) img->wsi_data;
425 data->swap_chain = sc;
426 data->mem = mem;
427 data->prime_fd = prime_fd;
428 data->pixmap = pixmap;
429
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800430 intel_obj_bind_mem(&img->obj, mem, 0);
431
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800432 return img;
433}
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800434
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800435static bool x11_swap_chain_create_persistent_images(struct intel_x11_swap_chain *sc,
436 struct intel_dev *dev,
437 const VkSwapChainCreateInfoWSI *info)
438{
439 struct intel_img **images;
Ian Elliott4f299362015-07-06 14:45:11 -0600440 intel_x11_swap_chain_image_state *image_state;
441 uint32_t *present_queue;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800442 VkImageCreateInfo img_info;
443 uint32_t i;
444
Ian Elliott4f299362015-07-06 14:45:11 -0600445 images = intel_alloc(sc, sizeof(*images) * info->minImageCount,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800446 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
447 if (!images)
448 return false;
Ian Elliott4f299362015-07-06 14:45:11 -0600449 image_state = intel_alloc(
450 sc, sizeof(intel_x11_swap_chain_image_state) * info->minImageCount,
451 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
452 if (!image_state) {
453 for (i = 0; i < info->minImageCount; i++) {
454 intel_img_destroy(images[i]);
455 }
456 intel_free(sc, images);
457 return false;
458 }
459 present_queue = intel_alloc(
460 sc, sizeof(uint32_t) * info->minImageCount,
461 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
462 if (!present_queue) {
463 for (i = 0; i < info->minImageCount; i++) {
464 intel_img_destroy(images[i]);
465 }
466 intel_free(sc, images);
467 intel_free(sc, image_state);
468 return false;
469 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800470
471 memset(&img_info, 0, sizeof(img_info));
472 img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
473 img_info.imageType = VK_IMAGE_TYPE_2D;
474 img_info.format = info->imageFormat;
475 img_info.extent.width = info->imageExtent.width;
476 img_info.extent.height = info->imageExtent.height;
477 img_info.extent.depth = 1;
478 img_info.mipLevels = 1;
479 img_info.arraySize = info->imageArraySize;
480 img_info.samples = 1;
481 img_info.tiling = VK_IMAGE_TILING_OPTIMAL;
482 img_info.usage = info->imageUsageFlags;
483 img_info.flags = 0;
484
Ian Elliott4f299362015-07-06 14:45:11 -0600485 for (i = 0; i < info->minImageCount; i++) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800486 images[i] = x11_swap_chain_create_persistent_image(sc,
487 dev, &img_info);
488 if (!images[i])
489 break;
Ian Elliott4f299362015-07-06 14:45:11 -0600490 image_state[i] = INTEL_SC_STATE_UNUSED;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800491 }
492
Ian Elliott4f299362015-07-06 14:45:11 -0600493 if (i < info->minImageCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800494 uint32_t j;
495 for (j = 0; j < i; j++)
Ian Elliott4f299362015-07-06 14:45:11 -0600496 intel_img_destroy(images[j]);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800497
498 intel_free(sc, images);
499
Ian Elliott4f299362015-07-06 14:45:11 -0600500 if (image_state) {
501 intel_free(sc, image_state);
502 }
503
504 if (present_queue) {
505 intel_free(sc, present_queue);
506 }
507
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800508 return false;
509 }
510
511 sc->persistent_images = images;
Ian Elliott4f299362015-07-06 14:45:11 -0600512 sc->persistent_image_count = info->minImageCount;
513 sc->image_state = image_state;
514 sc->present_queue = present_queue;
515 sc->present_queue_length = 0;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800516
517 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800518}
519
520/**
521 * Send a PresentPixmap.
522 */
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600523static VkResult x11_swap_chain_present_pixmap(struct intel_x11_swap_chain *sc,
Ian Elliott4f299362015-07-06 14:45:11 -0600524 struct intel_img *img)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800525{
Chia-I Wu41858c82015-04-04 16:39:25 +0800526 struct intel_x11_img_data *data =
527 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800528 uint32_t options = XCB_PRESENT_OPTION_NONE;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800529 uint32_t target_msc, divisor, remainder;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800530 xcb_void_cookie_t cookie;
531 xcb_generic_error_t *err;
532
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800533 target_msc = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600534 divisor = 1;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800535 remainder = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600536 if (sc->present_mode == VK_PRESENT_MODE_IMMEDIATE_WSI) {
Chia-I Wu1db76e02014-09-15 14:21:14 +0800537 options |= XCB_PRESENT_OPTION_ASYNC;
Ian Elliott4f299362015-07-06 14:45:11 -0600538 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800539
540 if (sc->force_copy)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800541 options |= XCB_PRESENT_OPTION_COPY;
542
Chia-I Wuf689c602015-04-28 10:55:52 +0800543 cookie = xcb_present_pixmap_checked(sc->c,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800544 sc->window,
Chia-I Wu41858c82015-04-04 16:39:25 +0800545 data->pixmap,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800546 ++sc->local.serial,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800547 0, /* valid-area */
548 0, /* update-area */
549 0, /* x-off */
550 0, /* y-off */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800551 0, /* crtc */
Chia-I Wu1db76e02014-09-15 14:21:14 +0800552 0, /* wait-fence */
553 0, /* idle-fence */
554 options,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800555 target_msc,
556 divisor,
557 remainder,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800558 0, NULL);
559
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800560 err = xcb_request_check(sc->c, cookie);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800561 if (err) {
562 free(err);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600563 return VK_ERROR_UNKNOWN;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800564 }
565
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600566 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800567}
568
569/**
Chia-I Wu1db76e02014-09-15 14:21:14 +0800570 * Handle a Present event.
571 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800572static void x11_swap_chain_present_event(struct intel_x11_swap_chain *sc,
573 const xcb_present_generic_event_t *ev)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800574{
575 union {
576 const xcb_present_generic_event_t *ev;
577 const xcb_present_complete_notify_event_t *complete;
578 } u = { .ev = ev };
579
580 switch (u.ev->evtype) {
581 case XCB_PRESENT_COMPLETE_NOTIFY:
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800582 sc->remote.serial = u.complete->serial;
583 sc->remote.msc = u.complete->msc;
Ian Elliott4f299362015-07-06 14:45:11 -0600584 assert(sc->present_queue_length > 0);
585 if (sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_DISPLAYED) {
586 // Remove the previously-displayed image from the present queue:
587 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_UNUSED;
588 sc->present_queue_length--;
589 for (int j = 0; j < sc->present_queue_length; j++) {
590 sc->present_queue[j] = sc->present_queue[j+1];
591 }
592 }
593 assert(sc->present_queue_length > 0);
594 assert(sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_QUEUED_FOR_PRESENT);
595 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_DISPLAYED;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800596 break;
597 default:
598 break;
599 }
600}
601
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600602static VkResult x11_swap_chain_wait(struct intel_x11_swap_chain *sc,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800603 uint32_t serial, int64_t timeout)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800604{
605 const bool wait = (timeout != 0);
606
607 while (sc->remote.serial < serial) {
608 xcb_present_generic_event_t *ev;
Mike Stroyan4a387162015-04-27 15:42:41 -0600609 xcb_intern_atom_reply_t *reply;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800610
611 if (wait) {
612 ev = (xcb_present_generic_event_t *)
613 xcb_wait_for_special_event(sc->c, sc->present_special_event);
Mike Stroyan4a387162015-04-27 15:42:41 -0600614 /* use xcb_intern_atom_reply just to wake other threads waiting on sc->c */
615 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
616 if (reply) {
617 free(reply);
618 }
619
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800620 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600621 return VK_ERROR_UNKNOWN;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800622 } else {
Mike Stroyan4a387162015-04-27 15:42:41 -0600623 /* use xcb_intern_atom_reply just to check socket for special event */
624 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
625 if (reply) {
626 free(reply);
627 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800628 ev = (xcb_present_generic_event_t *)
629 xcb_poll_for_special_event(sc->c, sc->present_special_event);
630 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600631 return VK_NOT_READY;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800632 }
633
634 x11_swap_chain_present_event(sc, ev);
635
636 free(ev);
637 }
638
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600639 return VK_SUCCESS;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800640}
641
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800642static void x11_swap_chain_destroy(struct intel_x11_swap_chain *sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800643{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800644 if (sc->persistent_images) {
645 uint32_t i;
646
647 for (i = 0; i < sc->persistent_image_count; i++)
648 intel_img_destroy(sc->persistent_images[i]);
649 intel_free(sc, sc->persistent_images);
650 }
651
Ian Elliott4f299362015-07-06 14:45:11 -0600652 if (sc->image_state) {
653 intel_free(sc, sc->image_state);
654 }
655
656 if (sc->present_queue) {
657 intel_free(sc, sc->present_queue);
658 }
659
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800660 if (sc->present_special_event)
661 xcb_unregister_for_special_event(sc->c, sc->present_special_event);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800662
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800663 intel_free(sc, sc);
664}
665
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800666static VkResult x11_swap_chain_create(struct intel_dev *dev,
667 const VkSwapChainCreateInfoWSI *info,
668 struct intel_x11_swap_chain **sc_ret)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800669{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800670 const xcb_randr_provider_t provider = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600671 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
672 (VkSurfaceDescriptionWindowWSI*) info->pSurfaceDescription;
673 VkPlatformHandleXcbWSI *pPlatformHandleXcb = (VkPlatformHandleXcbWSI *)
674 pSurfaceDescriptionWindow->pPlatformHandle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800675 xcb_connection_t *c = (xcb_connection_t *)
Ian Elliott4f299362015-07-06 14:45:11 -0600676 pPlatformHandleXcb->connection;
677 xcb_window_t window = *((xcb_window_t *)
678 pSurfaceDescriptionWindow->pPlatformWindow);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800679 struct intel_x11_swap_chain *sc;
680 int fd;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800681
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800682 if (!x11_is_format_presentable(dev, info->imageFormat)) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600683 intel_dev_log(dev, VK_DBG_REPORT_ERROR_BIT,
684 VK_NULL_HANDLE, 0, 0, "invalid presentable image format");
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800685 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800686 }
687
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800688 if (!x11_is_dri3_and_present_supported(c))
689 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800690
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800691 fd = x11_dri3_open(c, window, provider);
692 if (fd < 0 || !x11_gpu_match_fd(dev->gpu, fd)) {
Chia-I Wufcbc5252015-04-08 11:44:26 +0800693 if (fd >= 0)
694 close(fd);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800695 return VK_ERROR_INVALID_VALUE;
Chia-I Wufcbc5252015-04-08 11:44:26 +0800696 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800697
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800698 close(fd);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800699
Tony Barbour8205d902015-04-16 15:59:00 -0600700 sc = intel_alloc(dev, sizeof(*sc), 0, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800701 if (!sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800702 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800703
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800704 memset(sc, 0, sizeof(*sc));
Courtney Goeltzenleuchter9ecf6852015-06-09 08:22:48 -0600705 intel_handle_init(&sc->handle, VK_OBJECT_TYPE_SWAP_CHAIN_WSI, dev->base.handle.instance);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800706
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800707 sc->c = c;
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800708 sc->window = window;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800709
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800710 /* always copy unless flip bit is set */
Ian Elliott4f299362015-07-06 14:45:11 -0600711 sc->present_mode = info->presentMode;
712 sc->force_copy = true;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800713
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800714 if (!x11_swap_chain_dri3_and_present_query_version(sc) ||
715 !x11_swap_chain_present_select_input(sc) ||
716 !x11_swap_chain_create_persistent_images(sc, dev, info)) {
717 x11_swap_chain_destroy(sc);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600718 return VK_ERROR_UNKNOWN;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800719 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800720
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800721 *sc_ret = sc;
Chia-I Wu41858c82015-04-04 16:39:25 +0800722
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600723 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800724}
725
Chia-I Wu8635e912015-04-09 14:13:57 +0800726static void x11_display_destroy(struct intel_x11_display *dpy)
727{
728 intel_free(dpy, dpy->modes);
729 intel_free(dpy, dpy);
730}
731
Chia-I Wu41858c82015-04-04 16:39:25 +0800732void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
733{
Chia-I Wu8635e912015-04-09 14:13:57 +0800734 if (gpu->displays) {
735 uint32_t i;
Chia-I Wu41858c82015-04-04 16:39:25 +0800736
Chia-I Wu8635e912015-04-09 14:13:57 +0800737 for (i = 0; i < gpu->display_count; i++) {
738 struct intel_x11_display *dpy =
739 (struct intel_x11_display *) gpu->displays[i];
740 x11_display_destroy(dpy);
741 }
742 intel_free(gpu, gpu->displays);
743 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800744}
745
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600746VkResult intel_wsi_img_init(struct intel_img *img)
Chia-I Wu41858c82015-04-04 16:39:25 +0800747{
748 struct intel_x11_img_data *data;
749
Tony Barbour8205d902015-04-16 15:59:00 -0600750 data = intel_alloc(img, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800751 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600752 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800753
754 memset(data, 0, sizeof(*data));
755
756 assert(!img->wsi_data);
757 img->wsi_data = data;
758
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600759 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800760}
761
762void intel_wsi_img_cleanup(struct intel_img *img)
763{
764 struct intel_x11_img_data *data =
765 (struct intel_x11_img_data *) img->wsi_data;
766
767 if (data->mem) {
768 close(data->prime_fd);
769 intel_mem_free(data->mem);
770 }
771
772 intel_free(img, img->wsi_data);
773}
774
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600775VkResult intel_wsi_fence_init(struct intel_fence *fence)
Chia-I Wu41858c82015-04-04 16:39:25 +0800776{
777 struct intel_x11_fence_data *data;
778
Tony Barbour8205d902015-04-16 15:59:00 -0600779 data = intel_alloc(fence, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800780 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600781 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800782
783 memset(data, 0, sizeof(*data));
784
785 assert(!fence->wsi_data);
786 fence->wsi_data = data;
787
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600788 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800789}
790
791void intel_wsi_fence_cleanup(struct intel_fence *fence)
792{
793 intel_free(fence, fence->wsi_data);
794}
795
796void intel_wsi_fence_copy(struct intel_fence *fence,
797 const struct intel_fence *src)
798{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600799 if (!fence->wsi_data) {
800 return;
801 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800802 memcpy(fence->wsi_data, src->wsi_data,
803 sizeof(struct intel_x11_fence_data));
804}
805
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600806VkResult intel_wsi_fence_wait(struct intel_fence *fence,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800807 int64_t timeout_ns)
Chia-I Wu41858c82015-04-04 16:39:25 +0800808{
809 struct intel_x11_fence_data *data =
810 (struct intel_x11_fence_data *) fence->wsi_data;
811
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600812 if (!data)
813 return VK_SUCCESS;
814
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800815 if (!data->swap_chain)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600816 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800817
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800818 return x11_swap_chain_wait(data->swap_chain, data->serial, timeout_ns);
Chia-I Wu41858c82015-04-04 16:39:25 +0800819}
820
Ian Elliott4f299362015-07-06 14:45:11 -0600821ICD_EXPORT VkResult VKAPI vkGetPhysicalDeviceSurfaceSupportWSI(
822 VkPhysicalDevice physicalDevice,
823 uint32_t queueNodeIndex,
824 const VkSurfaceDescriptionWSI* pSurfaceDescription,
825 VkBool32* pSupported)
826{
827 VkResult ret = VK_SUCCESS;
828 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
829 (VkSurfaceDescriptionWindowWSI*) pSurfaceDescription;
830
831 *pSupported = false;
832
833 // TODO: Move this check to a validation layer (i.e. the driver should
834 // assume the correct data type, and not check):
835 if (pSurfaceDescriptionWindow->sType != VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI) {
836 return VK_ERROR_INVALID_VALUE;
837 }
838
839 // TODO: NEED TO ALSO CHECK:
840 // - queueNodeIndex
841 // - pSurfaceDescriptionWindow->pPlatformHandle (can try to use it)
842 // - pSurfaceDescriptionWindow->pPlatformWindow (can try to use it)
843 if (pSurfaceDescriptionWindow->platform == VK_PLATFORM_XCB_WSI) {
844 *pSupported = true;
845 }
846
847 return ret;
848}
849
Ian Elliottebda9892015-08-06 17:35:06 -0600850VkResult VKAPI vkGetSurfacePropertiesWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600851 VkDevice device,
852 const VkSurfaceDescriptionWSI* pSurfaceDescription,
Ian Elliottebda9892015-08-06 17:35:06 -0600853 VkSurfacePropertiesWSI* pSurfaceProperties)
854{
855 // TODO: Move this check to a validation layer (i.e. the driver should
856 // assume the correct data type, and not check):
857 assert(pSurfaceProperties);
858
859 return x11_get_surface_properties(pSurfaceDescription, pSurfaceProperties);
860}
861
862VkResult VKAPI vkGetSurfaceFormatsWSI(
863 VkDevice device,
864 const VkSurfaceDescriptionWSI* pSurfaceDescription,
865 uint32_t* pCount,
866 VkSurfaceFormatWSI* pSurfaceFormats)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800867{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800868 VkResult ret = VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800869
Ian Elliott4f299362015-07-06 14:45:11 -0600870 // TODO: Move this check to a validation layer (i.e. the driver should
871 // assume the correct data type, and not check):
Ian Elliottebda9892015-08-06 17:35:06 -0600872 if (!pCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800873 return VK_ERROR_INVALID_POINTER;
Ian Elliott4f299362015-07-06 14:45:11 -0600874 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800875
Ian Elliottebda9892015-08-06 17:35:06 -0600876 *pCount = ARRAY_SIZE(x11_presentable_formats);
877 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 Elliottebda9892015-08-06 17:35:06 -0600883 }
884
885 return ret;
886}
887
888VkResult VKAPI vkGetSurfacePresentModesWSI(
889 VkDevice device,
890 const VkSurfaceDescriptionWSI* pSurfaceDescription,
891 uint32_t* pCount,
892 VkPresentModeWSI* pPresentModes)
893{
894 VkResult ret = VK_SUCCESS;
895
896 // TODO: Move this check to a validation layer (i.e. the driver should
897 // assume the correct data type, and not check):
898 if (!pCount) {
899 return VK_ERROR_INVALID_POINTER;
900 }
901
902 *pCount = 2;
903 if (pPresentModes) {
904 pPresentModes[0] = VK_PRESENT_MODE_IMMEDIATE_WSI;
905 pPresentModes[1] = VK_PRESENT_MODE_FIFO_WSI;
906 // TODO: Consider adding VK_PRESENT_MODE_MAILBOX_WSI sometime
Chia-I Wu1db76e02014-09-15 14:21:14 +0800907 }
908
909 return ret;
910}
911
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800912ICD_EXPORT VkResult VKAPI vkCreateSwapChainWSI(
913 VkDevice device,
914 const VkSwapChainCreateInfoWSI* pCreateInfo,
915 VkSwapChainWSI* pSwapChain)
916{
917 struct intel_dev *dev = intel_dev(device);
918
Ian Elliott4f299362015-07-06 14:45:11 -0600919 if (pCreateInfo->oldSwapChain.handle) {
920 // TODO: Eventually, do more than simply up-front destroy the
921 // oldSwapChain (but just do that for now):
922 struct intel_x11_swap_chain *sc =
923 x11_swap_chain(pCreateInfo->oldSwapChain);
924
925 x11_swap_chain_destroy(sc);
926 }
927
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800928 return x11_swap_chain_create(dev, pCreateInfo,
929 (struct intel_x11_swap_chain **) pSwapChain);
930}
931
932ICD_EXPORT VkResult VKAPI vkDestroySwapChainWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600933 VkDevice device,
934 VkSwapChainWSI swapChain)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800935{
936 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
937
938 x11_swap_chain_destroy(sc);
939
940 return VK_SUCCESS;
941}
942
Ian Elliottebda9892015-08-06 17:35:06 -0600943ICD_EXPORT VkResult VKAPI vkGetSwapChainImagesWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600944 VkDevice device,
945 VkSwapChainWSI swapChain,
Ian Elliottebda9892015-08-06 17:35:06 -0600946 uint32_t* pCount,
947 VkImage* pSwapChainImages)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800948{
949 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
950 VkResult ret = VK_SUCCESS;
951
Ian Elliott4f299362015-07-06 14:45:11 -0600952 // TODO: Move this check to a validation layer (i.e. the driver should
953 // assume the correct data type, and not check):
Ian Elliottebda9892015-08-06 17:35:06 -0600954 if (!pCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800955 return VK_ERROR_INVALID_POINTER;
Ian Elliott4f299362015-07-06 14:45:11 -0600956 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800957
Ian Elliottebda9892015-08-06 17:35:06 -0600958 *pCount = sc->persistent_image_count;
959 if (pSwapChainImages) {
960 uint32_t i;
961 for (i = 0; i < sc->persistent_image_count; i++) {
962 pSwapChainImages[i].handle = (uint64_t) sc->persistent_images[i];
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800963 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800964 }
965
966 return ret;
967}
968
Ian Elliott4f299362015-07-06 14:45:11 -0600969ICD_EXPORT VkResult VKAPI vkAcquireNextImageWSI(
970 VkDevice device,
971 VkSwapChainWSI swapChain,
972 uint64_t timeout,
973 VkSemaphore semaphore,
974 uint32_t* pImageIndex)
975{
976 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
977 VkResult ret = VK_SUCCESS;
978
Ian Elliott4f299362015-07-06 14:45:11 -0600979 // Find an unused image to return:
980 for (int i = 0; i < sc->persistent_image_count; i++) {
981 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
982 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
983 *pImageIndex = i;
984 return ret;
985 }
986 }
987
Mike Stroyanf9f6dd72015-07-28 11:00:50 -0600988 // If no image is ready, wait for a present to finish
989 ret = x11_swap_chain_wait(sc, sc->present_serial, timeout);
990 if (ret != VK_SUCCESS) {
991 return ret;
992 }
Ian Elliott4f299362015-07-06 14:45:11 -0600993
Mike Stroyanf9f6dd72015-07-28 11:00:50 -0600994 // Find an unused image to return:
995 for (int i = 0; i < sc->persistent_image_count; i++) {
996 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
997 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
998 *pImageIndex = i;
999 return ret;
1000 }
1001 }
1002 // NOTE: Should never get here, but in case we do, do something:
1003 assert(0);
1004 return VK_ERROR_UNKNOWN;
Ian Elliott4f299362015-07-06 14:45:11 -06001005}
1006
1007
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001008ICD_EXPORT VkResult VKAPI vkQueuePresentWSI(
Ian Elliott4f299362015-07-06 14:45:11 -06001009 VkQueue queue_,
1010 VkPresentInfoWSI* pPresentInfo)
Chia-I Wu1db76e02014-09-15 14:21:14 +08001011{
1012 struct intel_queue *queue = intel_queue(queue_);
Ian Elliott4f299362015-07-06 14:45:11 -06001013 uint32_t i;
1014 uint32_t num_swapchains = pPresentInfo->swapChainCount;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001015
Ian Elliott4f299362015-07-06 14:45:11 -06001016 for (i = 0; i < num_swapchains; i++) {
1017 struct intel_x11_swap_chain *sc =
1018 x11_swap_chain(pPresentInfo->swapChains[i]);
1019 struct intel_img *img =
1020 sc->persistent_images[pPresentInfo->imageIndices[i]];
1021 struct intel_x11_fence_data *data =
1022 (struct intel_x11_fence_data *) queue->fence->wsi_data;
1023 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001024
Ian Elliott4f299362015-07-06 14:45:11 -06001025 ret = x11_swap_chain_present_pixmap(sc, img);
1026 if (ret != VK_SUCCESS) {
1027 return ret;
1028 }
1029
1030 // Record the state change for this image, and add this image to the
1031 // present queue for the swap chain:
1032 sc->image_state[pPresentInfo->imageIndices[i]] =
1033 INTEL_SC_STATE_QUEUED_FOR_PRESENT;
1034 sc->present_queue[sc->present_queue_length++] =
1035 pPresentInfo->imageIndices[i];
1036
1037 data->swap_chain = sc;
1038 data->serial = sc->local.serial;
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001039 sc->present_serial = sc->local.serial;
Ian Elliott4f299362015-07-06 14:45:11 -06001040 intel_fence_set_seqno(queue->fence, img->obj.mem->bo);
1041 }
Chia-I Wubda4f622015-02-25 15:06:15 -07001042
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001043 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001044}