blob: a1345cb98df9d2e823c427f884de1fc803fca0ea [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
Mike Stroyan2bf17bd2015-09-03 10:20:16 -060029#define _GNU_SOURCE 1
30#include <time.h>
Chia-I Wu1db76e02014-09-15 14:21:14 +080031#include <sys/types.h>
32#include <sys/stat.h>
33#include <unistd.h>
34#include <fcntl.h>
35#include <xcb/xcb.h>
36#include <xcb/dri3.h>
37#include <xcb/present.h>
38
39#include "kmd/winsys.h"
Chia-I Wu8635e912015-04-09 14:13:57 +080040#include "kmd/libdrm/xf86drmMode.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080041#include "dev.h"
42#include "fence.h"
43#include "gpu.h"
44#include "img.h"
45#include "mem.h"
46#include "queue.h"
Chia-I Wu41858c82015-04-04 16:39:25 +080047#include "wsi.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080048
Chia-I Wu8635e912015-04-09 14:13:57 +080049struct intel_x11_display {
50 struct intel_handle handle;
51
52 int fd;
53 uint32_t connector_id;
54
55 char name[32];
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -060056 VkExtent2D physical_dimension;
57 VkExtent2D physical_resolution;
Chia-I Wu8635e912015-04-09 14:13:57 +080058
59 drmModeModeInfoPtr modes;
60 uint32_t mode_count;
61};
62
Ian Elliott4f299362015-07-06 14:45:11 -060063typedef enum intel_x11_swap_chain_image_state_
64{
65 INTEL_SC_STATE_UNUSED = 0,
66 INTEL_SC_STATE_APP_OWNED = 1,
67 INTEL_SC_STATE_QUEUED_FOR_PRESENT = 2,
68 INTEL_SC_STATE_DISPLAYED = 3,
69} intel_x11_swap_chain_image_state;
70
Chia-I Wu6532d1d2015-04-04 22:16:45 +080071struct intel_x11_swap_chain {
72 struct intel_handle handle;
73
74 xcb_connection_t *c;
75 xcb_window_t window;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080076 bool force_copy;
Ian Elliott4f299362015-07-06 14:45:11 -060077 VkPresentModeWSI present_mode;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080078
79 int dri3_major, dri3_minor;
80 int present_major, present_minor;
Chia-I Wu1db76e02014-09-15 14:21:14 +080081
82 xcb_present_event_t present_special_event_id;
83 xcb_special_event_t *present_special_event;
84
Chia-I Wu5b66aa52015-04-16 22:02:10 +080085 struct intel_img **persistent_images;
86 uint32_t persistent_image_count;
Ian Elliott4f299362015-07-06 14:45:11 -060087 intel_x11_swap_chain_image_state *image_state;
88 uint32_t *present_queue;
89 uint32_t present_queue_length;
Mike Stroyanf9f6dd72015-07-28 11:00:50 -060090 uint32_t present_serial;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080091
Chia-I Wu1db76e02014-09-15 14:21:14 +080092 struct {
93 uint32_t serial;
94 } local;
95
96 struct {
97 uint32_t serial;
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -060098 uint64_t msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +080099 } remote;
100};
101
Chia-I Wu41858c82015-04-04 16:39:25 +0800102struct intel_x11_img_data {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800103 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +0800104 struct intel_mem *mem;
105 int prime_fd;
106 uint32_t pixmap;
107};
108
109struct intel_x11_fence_data {
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800110 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +0800111 uint32_t serial;
112};
113
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800114/* these are what DDX expects */
115static const VkFormat x11_presentable_formats[] = {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800116 VK_FORMAT_B8G8R8A8_UNORM,
117 VK_FORMAT_B8G8R8A8_SRGB,
Ian Elliott32536f92015-04-21 16:41:02 -0600118 VK_FORMAT_B5G6R5_UNORM,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800119};
120
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800121static inline struct intel_x11_swap_chain *x11_swap_chain(VkSwapChainWSI sc)
122{
Ian Elliott4f299362015-07-06 14:45:11 -0600123 return (struct intel_x11_swap_chain *) sc.handle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800124}
125
Chia-I Wufcbc5252015-04-08 11:44:26 +0800126static bool x11_is_format_presentable(const struct intel_dev *dev,
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600127 VkFormat format)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800128{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800129 uint32_t i;
130
131 for (i = 0; i < ARRAY_SIZE(x11_presentable_formats); i++) {
132 if (x11_presentable_formats[i] == format)
133 return true;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800134 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800135
136 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800137}
138
Chia-I Wu030b2db2015-04-08 13:46:29 +0800139static int x11_export_prime_fd(struct intel_dev *dev,
140 struct intel_bo *bo,
141 const struct intel_layout *layout)
142{
143 struct intel_winsys_handle export;
144 enum intel_tiling_mode tiling;
145
146 export.type = INTEL_WINSYS_HANDLE_FD;
147
148 switch (layout->tiling) {
149 case GEN6_TILING_X:
150 tiling = INTEL_TILING_X;
151 break;
152 case GEN6_TILING_Y:
153 tiling = INTEL_TILING_Y;
154 break;
155 default:
156 assert(layout->tiling == GEN6_TILING_NONE);
157 tiling = INTEL_TILING_NONE;
158 break;
159 }
160
161 if (intel_bo_set_tiling(bo, tiling, layout->bo_stride))
162 return -1;
163
164 if (intel_winsys_export_handle(dev->winsys, bo, tiling,
165 layout->bo_stride, layout->bo_height, &export))
166 return -1;
167
168 return (int) export.handle;
169}
170
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800171/**
Chia-I Wufcbc5252015-04-08 11:44:26 +0800172 * Return true if fd points to the primary or render node of the GPU.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800173 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800174static bool x11_gpu_match_fd(const struct intel_gpu *gpu, int fd)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800175{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800176 struct stat fd_stat, gpu_stat;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800177
Chia-I Wufcbc5252015-04-08 11:44:26 +0800178 if (fstat(fd, &fd_stat))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800179 return false;
180
181 /* is it the primary node? */
182 if (!stat(gpu->primary_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800183 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800184 return true;
185
186 /* is it the render node? */
187 if (gpu->render_node && !stat(gpu->render_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800188 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800189 return true;
190
191 return false;
192}
193
Chia-I Wufcbc5252015-04-08 11:44:26 +0800194/*
195 * Return the depth of \p drawable.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800196 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800197static int x11_get_drawable_depth(xcb_connection_t *c,
198 xcb_drawable_t drawable)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800199{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800200 xcb_get_geometry_cookie_t cookie;
201 xcb_get_geometry_reply_t *reply;
202 uint8_t depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800203
Chia-I Wufcbc5252015-04-08 11:44:26 +0800204 cookie = xcb_get_geometry(c, drawable);
205 reply = xcb_get_geometry_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800206
Chia-I Wufcbc5252015-04-08 11:44:26 +0800207 if (reply) {
208 depth = reply->depth;
209 free(reply);
210 } else {
211 depth = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800212 }
213
Chia-I Wufcbc5252015-04-08 11:44:26 +0800214 return depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800215}
216
Ian Elliott4f299362015-07-06 14:45:11 -0600217static VkResult x11_get_surface_properties(
218 const VkSurfaceDescriptionWSI *pSurfaceDescription,
219 VkSurfacePropertiesWSI *pSurfaceProperties)
220{
221 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
222 (VkSurfaceDescriptionWindowWSI*) pSurfaceDescription;
223 VkPlatformHandleXcbWSI *pPlatformHandleXcb = (VkPlatformHandleXcbWSI *)
224 pSurfaceDescriptionWindow->pPlatformHandle;
225 xcb_connection_t *c = (xcb_connection_t *)
226 pPlatformHandleXcb->connection;
227 xcb_window_t window = *((xcb_window_t *)
228 pSurfaceDescriptionWindow->pPlatformWindow);
229 xcb_get_geometry_cookie_t cookie;
230 xcb_get_geometry_reply_t *reply;
231
232 cookie = xcb_get_geometry(c, window);
233 reply = xcb_get_geometry_reply(c, cookie, NULL);
234
235 if (reply) {
236 pSurfaceProperties->currentExtent.width = reply->width;
237 pSurfaceProperties->currentExtent.height = reply->height;
238 free(reply);
239 } else {
240 pSurfaceProperties->currentExtent.width = 0;
241 pSurfaceProperties->currentExtent.height = 0;
242 }
243
244 pSurfaceProperties->minImageCount = 2;
245 pSurfaceProperties->maxImageCount = 0;
246
247 pSurfaceProperties->minImageExtent.width =
248 pSurfaceProperties->currentExtent.width;
249 pSurfaceProperties->minImageExtent.height =
250 pSurfaceProperties->currentExtent.height;
251 pSurfaceProperties->maxImageExtent.width =
252 pSurfaceProperties->currentExtent.width;
253 pSurfaceProperties->maxImageExtent.height =
254 pSurfaceProperties->currentExtent.height;
255 pSurfaceProperties->supportedTransforms = VK_SURFACE_TRANSFORM_NONE_BIT_WSI;
256 pSurfaceProperties->currentTransform = VK_SURFACE_TRANSFORM_NONE_WSI;
257 pSurfaceProperties->maxImageArraySize = 0;
258 pSurfaceProperties->supportedUsageFlags =
Cody Northrop3440c2d2015-08-28 16:40:45 -0600259 VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
Ian Elliott4f299362015-07-06 14:45:11 -0600260 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
261
262 return VK_SUCCESS;
263}
264
Chia-I Wu1db76e02014-09-15 14:21:14 +0800265/**
266 * Return true if DRI3 and Present are supported by the server.
267 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800268static bool x11_is_dri3_and_present_supported(xcb_connection_t *c)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800269{
270 const xcb_query_extension_reply_t *ext;
271
Chia-I Wufcbc5252015-04-08 11:44:26 +0800272 xcb_prefetch_extension_data(c, &xcb_dri3_id);
273 xcb_prefetch_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800274
Chia-I Wufcbc5252015-04-08 11:44:26 +0800275 ext = xcb_get_extension_data(c, &xcb_dri3_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800276 if (!ext || !ext->present)
277 return false;
278
Chia-I Wufcbc5252015-04-08 11:44:26 +0800279 ext = xcb_get_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800280 if (!ext || !ext->present)
281 return false;
282
283 return true;
284}
285
286/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800287 * Send a DRI3Open to get the server GPU fd.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800288 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800289static int x11_dri3_open(xcb_connection_t *c,
290 xcb_drawable_t drawable,
291 xcb_randr_provider_t provider)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800292{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800293 xcb_dri3_open_cookie_t cookie;
294 xcb_dri3_open_reply_t *reply;
295 int fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800296
Chia-I Wufcbc5252015-04-08 11:44:26 +0800297 cookie = xcb_dri3_open(c, drawable, provider);
298 reply = xcb_dri3_open_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800299 if (!reply)
Chia-I Wufcbc5252015-04-08 11:44:26 +0800300 return -1;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800301
Chia-I Wufcbc5252015-04-08 11:44:26 +0800302 fd = (reply->nfd == 1) ? xcb_dri3_open_reply_fds(c, reply)[0] : -1;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800303 free(reply);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800304
Chia-I Wufcbc5252015-04-08 11:44:26 +0800305 return fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800306}
307
308/**
Chia-I Wu030b2db2015-04-08 13:46:29 +0800309 * Send a DRI3PixmapFromBuffer to create a pixmap from \p prime_fd.
310 */
311static xcb_pixmap_t x11_dri3_pixmap_from_buffer(xcb_connection_t *c,
312 xcb_drawable_t drawable,
313 uint8_t depth, int prime_fd,
314 const struct intel_layout *layout)
315{
316 xcb_pixmap_t pixmap;
317
318 pixmap = xcb_generate_id(c);
319
320 xcb_dri3_pixmap_from_buffer(c, pixmap, drawable,
321 layout->bo_stride * layout->bo_height,
322 layout->width0, layout->height0,
323 layout->bo_stride, depth,
324 layout->block_size * 8, prime_fd);
325
326 return pixmap;
327}
328
329/**
Chia-I Wu41858c82015-04-04 16:39:25 +0800330 * Send DRI3QueryVersion and PresentQueryVersion to query extension versions.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800331 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800332static bool x11_swap_chain_dri3_and_present_query_version(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800333{
334 xcb_dri3_query_version_cookie_t dri3_cookie;
335 xcb_dri3_query_version_reply_t *dri3_reply;
336 xcb_present_query_version_cookie_t present_cookie;
337 xcb_present_query_version_reply_t *present_reply;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800338
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800339 dri3_cookie = xcb_dri3_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800340 XCB_DRI3_MAJOR_VERSION, XCB_DRI3_MINOR_VERSION);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800341 present_cookie = xcb_present_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800342 XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION);
343
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800344 dri3_reply = xcb_dri3_query_version_reply(sc->c, dri3_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800345 if (!dri3_reply)
346 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800347
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800348 sc->dri3_major = dri3_reply->major_version;
349 sc->dri3_minor = dri3_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800350 free(dri3_reply);
351
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800352 present_reply = xcb_present_query_version_reply(sc->c, present_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800353 if (!present_reply)
354 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800355
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800356 sc->present_major = present_reply->major_version;
357 sc->present_minor = present_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800358 free(present_reply);
359
Chia-I Wu41858c82015-04-04 16:39:25 +0800360 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800361}
362
363/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800364 * Send a PresentSelectInput to select interested events.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800365 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800366static bool x11_swap_chain_present_select_input(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800367{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800368 xcb_void_cookie_t cookie;
369 xcb_generic_error_t *error;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800370
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800371 /* create the event queue */
372 sc->present_special_event_id = xcb_generate_id(sc->c);
373 sc->present_special_event = xcb_register_for_special_xge(sc->c,
374 &xcb_present_id, sc->present_special_event_id, NULL);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800375
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800376 cookie = xcb_present_select_input_checked(sc->c,
377 sc->present_special_event_id, sc->window,
378 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800379
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800380 error = xcb_request_check(sc->c, cookie);
381 if (error) {
382 free(error);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800383 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800384 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800385
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800386 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800387}
388
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800389static struct intel_img *x11_swap_chain_create_persistent_image(struct intel_x11_swap_chain *sc,
390 struct intel_dev *dev,
391 const VkImageCreateInfo *img_info)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800392{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800393 struct intel_img *img;
394 struct intel_mem *mem;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800395 struct intel_x11_img_data *data;
396 VkMemoryAllocInfo mem_info;
397 int prime_fd;
398 xcb_pixmap_t pixmap;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600399 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800400
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800401 ret = intel_img_create(dev, img_info, true, &img);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600402 if (ret != VK_SUCCESS)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800403 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800404
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800405 memset(&mem_info, 0, sizeof(mem_info));
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600406 mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800407 mem_info.allocationSize = img->total_size;
Mark Lobodzinski72346292015-07-02 16:49:40 -0600408 mem_info.memoryTypeIndex = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800409
410 ret = intel_mem_alloc(dev, &mem_info, &mem);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600411 if (ret != VK_SUCCESS) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800412 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800413 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800414 }
415
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800416 prime_fd = x11_export_prime_fd(dev, mem->bo, &img->layout);
417 if (prime_fd < 0) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800418 intel_mem_free(mem);
419 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800420 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800421 }
422
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800423 pixmap = x11_dri3_pixmap_from_buffer(sc->c, sc->window,
424 x11_get_drawable_depth(sc->c, sc->window),
425 prime_fd, &img->layout);
426
427 data = (struct intel_x11_img_data *) img->wsi_data;
428 data->swap_chain = sc;
429 data->mem = mem;
430 data->prime_fd = prime_fd;
431 data->pixmap = pixmap;
432
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800433 intel_obj_bind_mem(&img->obj, mem, 0);
434
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800435 return img;
436}
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800437
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800438static bool x11_swap_chain_create_persistent_images(struct intel_x11_swap_chain *sc,
439 struct intel_dev *dev,
440 const VkSwapChainCreateInfoWSI *info)
441{
442 struct intel_img **images;
Ian Elliott4f299362015-07-06 14:45:11 -0600443 intel_x11_swap_chain_image_state *image_state;
444 uint32_t *present_queue;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800445 VkImageCreateInfo img_info;
446 uint32_t i;
447
Ian Elliott4f299362015-07-06 14:45:11 -0600448 images = intel_alloc(sc, sizeof(*images) * info->minImageCount,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800449 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
450 if (!images)
451 return false;
Ian Elliott4f299362015-07-06 14:45:11 -0600452 image_state = intel_alloc(
453 sc, sizeof(intel_x11_swap_chain_image_state) * info->minImageCount,
454 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
455 if (!image_state) {
456 for (i = 0; i < info->minImageCount; i++) {
457 intel_img_destroy(images[i]);
458 }
459 intel_free(sc, images);
460 return false;
461 }
462 present_queue = intel_alloc(
463 sc, sizeof(uint32_t) * info->minImageCount,
464 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
465 if (!present_queue) {
466 for (i = 0; i < info->minImageCount; i++) {
467 intel_img_destroy(images[i]);
468 }
469 intel_free(sc, images);
470 intel_free(sc, image_state);
471 return false;
472 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800473
474 memset(&img_info, 0, sizeof(img_info));
475 img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
476 img_info.imageType = VK_IMAGE_TYPE_2D;
477 img_info.format = info->imageFormat;
478 img_info.extent.width = info->imageExtent.width;
479 img_info.extent.height = info->imageExtent.height;
480 img_info.extent.depth = 1;
481 img_info.mipLevels = 1;
482 img_info.arraySize = info->imageArraySize;
483 img_info.samples = 1;
484 img_info.tiling = VK_IMAGE_TILING_OPTIMAL;
485 img_info.usage = info->imageUsageFlags;
486 img_info.flags = 0;
487
Ian Elliott4f299362015-07-06 14:45:11 -0600488 for (i = 0; i < info->minImageCount; i++) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800489 images[i] = x11_swap_chain_create_persistent_image(sc,
490 dev, &img_info);
491 if (!images[i])
492 break;
Ian Elliott4f299362015-07-06 14:45:11 -0600493 image_state[i] = INTEL_SC_STATE_UNUSED;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800494 }
495
Ian Elliott4f299362015-07-06 14:45:11 -0600496 if (i < info->minImageCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800497 uint32_t j;
498 for (j = 0; j < i; j++)
Ian Elliott4f299362015-07-06 14:45:11 -0600499 intel_img_destroy(images[j]);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800500
501 intel_free(sc, images);
502
Ian Elliott4f299362015-07-06 14:45:11 -0600503 if (image_state) {
504 intel_free(sc, image_state);
505 }
506
507 if (present_queue) {
508 intel_free(sc, present_queue);
509 }
510
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800511 return false;
512 }
513
514 sc->persistent_images = images;
Ian Elliott4f299362015-07-06 14:45:11 -0600515 sc->persistent_image_count = info->minImageCount;
516 sc->image_state = image_state;
517 sc->present_queue = present_queue;
518 sc->present_queue_length = 0;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800519
520 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800521}
522
523/**
524 * Send a PresentPixmap.
525 */
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600526static VkResult x11_swap_chain_present_pixmap(struct intel_x11_swap_chain *sc,
Ian Elliott4f299362015-07-06 14:45:11 -0600527 struct intel_img *img)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800528{
Chia-I Wu41858c82015-04-04 16:39:25 +0800529 struct intel_x11_img_data *data =
530 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800531 uint32_t options = XCB_PRESENT_OPTION_NONE;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800532 uint32_t target_msc, divisor, remainder;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800533 xcb_void_cookie_t cookie;
534 xcb_generic_error_t *err;
535
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800536 target_msc = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600537 divisor = 1;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800538 remainder = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600539 if (sc->present_mode == VK_PRESENT_MODE_IMMEDIATE_WSI) {
Chia-I Wu1db76e02014-09-15 14:21:14 +0800540 options |= XCB_PRESENT_OPTION_ASYNC;
Ian Elliott4f299362015-07-06 14:45:11 -0600541 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800542
543 if (sc->force_copy)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800544 options |= XCB_PRESENT_OPTION_COPY;
545
Chia-I Wuf689c602015-04-28 10:55:52 +0800546 cookie = xcb_present_pixmap_checked(sc->c,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800547 sc->window,
Chia-I Wu41858c82015-04-04 16:39:25 +0800548 data->pixmap,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800549 ++sc->local.serial,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800550 0, /* valid-area */
551 0, /* update-area */
552 0, /* x-off */
553 0, /* y-off */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800554 0, /* crtc */
Chia-I Wu1db76e02014-09-15 14:21:14 +0800555 0, /* wait-fence */
556 0, /* idle-fence */
557 options,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800558 target_msc,
559 divisor,
560 remainder,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800561 0, NULL);
562
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800563 err = xcb_request_check(sc->c, cookie);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800564 if (err) {
565 free(err);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600566 return VK_ERROR_UNKNOWN;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800567 }
568
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600569 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800570}
571
572/**
Chia-I Wu1db76e02014-09-15 14:21:14 +0800573 * Handle a Present event.
574 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800575static void x11_swap_chain_present_event(struct intel_x11_swap_chain *sc,
576 const xcb_present_generic_event_t *ev)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800577{
578 union {
579 const xcb_present_generic_event_t *ev;
580 const xcb_present_complete_notify_event_t *complete;
581 } u = { .ev = ev };
582
583 switch (u.ev->evtype) {
584 case XCB_PRESENT_COMPLETE_NOTIFY:
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800585 sc->remote.serial = u.complete->serial;
586 sc->remote.msc = u.complete->msc;
Ian Elliott4f299362015-07-06 14:45:11 -0600587 assert(sc->present_queue_length > 0);
588 if (sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_DISPLAYED) {
589 // Remove the previously-displayed image from the present queue:
590 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_UNUSED;
591 sc->present_queue_length--;
592 for (int j = 0; j < sc->present_queue_length; j++) {
593 sc->present_queue[j] = sc->present_queue[j+1];
594 }
595 }
596 assert(sc->present_queue_length > 0);
597 assert(sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_QUEUED_FOR_PRESENT);
598 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_DISPLAYED;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800599 break;
600 default:
601 break;
602 }
603}
604
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600605/*
606 * Wait for an event on a swap chain.
607 * Uses polling because xcb_wait_for_special_event won't time out.
608 */
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600609static VkResult x11_swap_chain_wait(struct intel_x11_swap_chain *sc,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800610 uint32_t serial, int64_t timeout)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800611{
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600612 struct timespec start_time; // time at start of call
613 struct timespec stop_time; // time when timeout will elapse
614 struct timespec sleep_time; // time for next poll of events
615 bool wait;
616 if (timeout == 0){
617 wait = false;
618 } else {
619 wait = true;
620 clock_gettime(CLOCK_MONOTONIC, &start_time);
621 if (timeout == -1) {
622 // wait approximately forever
623 stop_time.tv_nsec = start_time.tv_nsec;
624 stop_time.tv_sec = start_time.tv_sec + 10*365*24*60*60;
625 } else {
626 stop_time.tv_nsec = start_time.tv_nsec + (timeout % 1000000000);
627 stop_time.tv_sec = start_time.tv_sec + (timeout / 1000000000);
628 // Carry overflow from tv_nsec to tv_sec
629 while (stop_time.tv_nsec > 1000000000) {
630 stop_time.tv_sec += 1;
631 stop_time.tv_nsec -= 1000000000;
632 }
633 }
634 sleep_time = start_time;
635 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800636
637 while (sc->remote.serial < serial) {
638 xcb_present_generic_event_t *ev;
Mike Stroyan4a387162015-04-27 15:42:41 -0600639 xcb_intern_atom_reply_t *reply;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800640
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600641 ev = (xcb_present_generic_event_t *)
642 xcb_poll_for_special_event(sc->c, sc->present_special_event);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800643 if (wait) {
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600644 while (!ev) {
645 if (sleep_time.tv_sec > stop_time.tv_sec ||
646 (sleep_time.tv_sec == stop_time.tv_sec && sleep_time.tv_nsec > stop_time.tv_nsec)) {
647 // Time has run out
648 return VK_TIMEOUT;
649 }
650 sleep_time.tv_nsec += 100000000; // add 0.1 seconds
651 // Carry overflow from tv_nsec to tv_sec
652 while (sleep_time.tv_nsec > 1000000000) {
653 sleep_time.tv_sec += 1;
654 sleep_time.tv_nsec -= 1000000000;
655 }
656 if (sleep_time.tv_sec > stop_time.tv_sec ||
657 (sleep_time.tv_sec == stop_time.tv_sec && sleep_time.tv_nsec > stop_time.tv_nsec)) {
658 // Cap sleep time at original stop time
659 sleep_time = stop_time;
660 }
661 clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &sleep_time, NULL);
Mike Stroyan4a387162015-04-27 15:42:41 -0600662
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600663 // Use xcb_intern_atom_reply just to make xcb really read events from socket.
664 // Calling xcb_poll_for_special_event fails to actually look for new packets.
665 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
666 if (reply) {
667 free(reply);
668 }
669
670 ev = (xcb_present_generic_event_t *)
671 xcb_poll_for_special_event(sc->c, sc->present_special_event);
Mike Stroyan4a387162015-04-27 15:42:41 -0600672 }
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600673 } else {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800674 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600675 return VK_NOT_READY;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800676 }
677
678 x11_swap_chain_present_event(sc, ev);
679
680 free(ev);
681 }
682
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600683 return VK_SUCCESS;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800684}
685
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800686static void x11_swap_chain_destroy(struct intel_x11_swap_chain *sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800687{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800688 if (sc->persistent_images) {
689 uint32_t i;
690
691 for (i = 0; i < sc->persistent_image_count; i++)
692 intel_img_destroy(sc->persistent_images[i]);
693 intel_free(sc, sc->persistent_images);
694 }
695
Ian Elliott4f299362015-07-06 14:45:11 -0600696 if (sc->image_state) {
697 intel_free(sc, sc->image_state);
698 }
699
700 if (sc->present_queue) {
701 intel_free(sc, sc->present_queue);
702 }
703
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800704 if (sc->present_special_event)
705 xcb_unregister_for_special_event(sc->c, sc->present_special_event);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800706
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800707 intel_free(sc, sc);
708}
709
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800710static VkResult x11_swap_chain_create(struct intel_dev *dev,
711 const VkSwapChainCreateInfoWSI *info,
712 struct intel_x11_swap_chain **sc_ret)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800713{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800714 const xcb_randr_provider_t provider = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600715 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
716 (VkSurfaceDescriptionWindowWSI*) info->pSurfaceDescription;
717 VkPlatformHandleXcbWSI *pPlatformHandleXcb = (VkPlatformHandleXcbWSI *)
718 pSurfaceDescriptionWindow->pPlatformHandle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800719 xcb_connection_t *c = (xcb_connection_t *)
Ian Elliott4f299362015-07-06 14:45:11 -0600720 pPlatformHandleXcb->connection;
721 xcb_window_t window = *((xcb_window_t *)
722 pSurfaceDescriptionWindow->pPlatformWindow);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800723 struct intel_x11_swap_chain *sc;
724 int fd;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800725
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800726 if (!x11_is_format_presentable(dev, info->imageFormat)) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600727 intel_dev_log(dev, VK_DBG_REPORT_ERROR_BIT,
728 VK_NULL_HANDLE, 0, 0, "invalid presentable image format");
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800729 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800730 }
731
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800732 if (!x11_is_dri3_and_present_supported(c))
733 return VK_ERROR_INVALID_VALUE;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800734
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800735 fd = x11_dri3_open(c, window, provider);
736 if (fd < 0 || !x11_gpu_match_fd(dev->gpu, fd)) {
Chia-I Wufcbc5252015-04-08 11:44:26 +0800737 if (fd >= 0)
738 close(fd);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800739 return VK_ERROR_INVALID_VALUE;
Chia-I Wufcbc5252015-04-08 11:44:26 +0800740 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800741
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800742 close(fd);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800743
Tony Barbour8205d902015-04-16 15:59:00 -0600744 sc = intel_alloc(dev, sizeof(*sc), 0, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800745 if (!sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800746 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800747
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800748 memset(sc, 0, sizeof(*sc));
Courtney Goeltzenleuchter9ecf6852015-06-09 08:22:48 -0600749 intel_handle_init(&sc->handle, VK_OBJECT_TYPE_SWAP_CHAIN_WSI, dev->base.handle.instance);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800750
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800751 sc->c = c;
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800752 sc->window = window;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800753
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800754 /* always copy unless flip bit is set */
Ian Elliott4f299362015-07-06 14:45:11 -0600755 sc->present_mode = info->presentMode;
756 sc->force_copy = true;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800757
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800758 if (!x11_swap_chain_dri3_and_present_query_version(sc) ||
759 !x11_swap_chain_present_select_input(sc) ||
760 !x11_swap_chain_create_persistent_images(sc, dev, info)) {
761 x11_swap_chain_destroy(sc);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600762 return VK_ERROR_UNKNOWN;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800763 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800764
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800765 *sc_ret = sc;
Chia-I Wu41858c82015-04-04 16:39:25 +0800766
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600767 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800768}
769
Chia-I Wu8635e912015-04-09 14:13:57 +0800770static void x11_display_destroy(struct intel_x11_display *dpy)
771{
772 intel_free(dpy, dpy->modes);
773 intel_free(dpy, dpy);
774}
775
Chia-I Wu41858c82015-04-04 16:39:25 +0800776void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
777{
Chia-I Wu8635e912015-04-09 14:13:57 +0800778 if (gpu->displays) {
779 uint32_t i;
Chia-I Wu41858c82015-04-04 16:39:25 +0800780
Chia-I Wu8635e912015-04-09 14:13:57 +0800781 for (i = 0; i < gpu->display_count; i++) {
782 struct intel_x11_display *dpy =
783 (struct intel_x11_display *) gpu->displays[i];
784 x11_display_destroy(dpy);
785 }
786 intel_free(gpu, gpu->displays);
787 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800788}
789
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600790VkResult intel_wsi_img_init(struct intel_img *img)
Chia-I Wu41858c82015-04-04 16:39:25 +0800791{
792 struct intel_x11_img_data *data;
793
Tony Barbour8205d902015-04-16 15:59:00 -0600794 data = intel_alloc(img, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800795 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600796 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800797
798 memset(data, 0, sizeof(*data));
799
800 assert(!img->wsi_data);
801 img->wsi_data = data;
802
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600803 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800804}
805
806void intel_wsi_img_cleanup(struct intel_img *img)
807{
808 struct intel_x11_img_data *data =
809 (struct intel_x11_img_data *) img->wsi_data;
810
811 if (data->mem) {
812 close(data->prime_fd);
813 intel_mem_free(data->mem);
814 }
815
816 intel_free(img, img->wsi_data);
817}
818
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600819VkResult intel_wsi_fence_init(struct intel_fence *fence)
Chia-I Wu41858c82015-04-04 16:39:25 +0800820{
821 struct intel_x11_fence_data *data;
822
Tony Barbour8205d902015-04-16 15:59:00 -0600823 data = intel_alloc(fence, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800824 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600825 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800826
827 memset(data, 0, sizeof(*data));
828
829 assert(!fence->wsi_data);
830 fence->wsi_data = data;
831
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600832 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800833}
834
835void intel_wsi_fence_cleanup(struct intel_fence *fence)
836{
837 intel_free(fence, fence->wsi_data);
838}
839
840void intel_wsi_fence_copy(struct intel_fence *fence,
841 const struct intel_fence *src)
842{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600843 if (!fence->wsi_data) {
844 return;
845 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800846 memcpy(fence->wsi_data, src->wsi_data,
847 sizeof(struct intel_x11_fence_data));
848}
849
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600850VkResult intel_wsi_fence_wait(struct intel_fence *fence,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800851 int64_t timeout_ns)
Chia-I Wu41858c82015-04-04 16:39:25 +0800852{
853 struct intel_x11_fence_data *data =
854 (struct intel_x11_fence_data *) fence->wsi_data;
855
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600856 if (!data)
857 return VK_SUCCESS;
858
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800859 if (!data->swap_chain)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600860 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800861
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800862 return x11_swap_chain_wait(data->swap_chain, data->serial, timeout_ns);
Chia-I Wu41858c82015-04-04 16:39:25 +0800863}
864
Ian Elliott4f299362015-07-06 14:45:11 -0600865ICD_EXPORT VkResult VKAPI vkGetPhysicalDeviceSurfaceSupportWSI(
866 VkPhysicalDevice physicalDevice,
867 uint32_t queueNodeIndex,
868 const VkSurfaceDescriptionWSI* pSurfaceDescription,
869 VkBool32* pSupported)
870{
871 VkResult ret = VK_SUCCESS;
872 const VkSurfaceDescriptionWindowWSI* pSurfaceDescriptionWindow =
873 (VkSurfaceDescriptionWindowWSI*) pSurfaceDescription;
874
875 *pSupported = false;
876
877 // TODO: Move this check to a validation layer (i.e. the driver should
878 // assume the correct data type, and not check):
879 if (pSurfaceDescriptionWindow->sType != VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI) {
880 return VK_ERROR_INVALID_VALUE;
881 }
882
883 // TODO: NEED TO ALSO CHECK:
884 // - queueNodeIndex
885 // - pSurfaceDescriptionWindow->pPlatformHandle (can try to use it)
886 // - pSurfaceDescriptionWindow->pPlatformWindow (can try to use it)
887 if (pSurfaceDescriptionWindow->platform == VK_PLATFORM_XCB_WSI) {
888 *pSupported = true;
889 }
890
891 return ret;
892}
893
Ian Elliottebda9892015-08-06 17:35:06 -0600894VkResult VKAPI vkGetSurfacePropertiesWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600895 VkDevice device,
896 const VkSurfaceDescriptionWSI* pSurfaceDescription,
Ian Elliottebda9892015-08-06 17:35:06 -0600897 VkSurfacePropertiesWSI* pSurfaceProperties)
898{
899 // TODO: Move this check to a validation layer (i.e. the driver should
900 // assume the correct data type, and not check):
901 assert(pSurfaceProperties);
902
903 return x11_get_surface_properties(pSurfaceDescription, pSurfaceProperties);
904}
905
906VkResult VKAPI vkGetSurfaceFormatsWSI(
907 VkDevice device,
908 const VkSurfaceDescriptionWSI* pSurfaceDescription,
909 uint32_t* pCount,
910 VkSurfaceFormatWSI* pSurfaceFormats)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800911{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800912 VkResult ret = VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800913
Ian Elliott4f299362015-07-06 14:45:11 -0600914 // TODO: Move this check to a validation layer (i.e. the driver should
915 // assume the correct data type, and not check):
Ian Elliottebda9892015-08-06 17:35:06 -0600916 if (!pCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800917 return VK_ERROR_INVALID_POINTER;
Ian Elliott4f299362015-07-06 14:45:11 -0600918 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800919
Ian Elliottebda9892015-08-06 17:35:06 -0600920 if (pSurfaceFormats) {
921 uint32_t i;
922 for (i = 0; i < *pCount; i++) {
923 pSurfaceFormats[i].format = x11_presentable_formats[i];
924 pSurfaceFormats[i].colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_WSI;
Ian Elliott4f299362015-07-06 14:45:11 -0600925 }
Ian Elliotte1ea6712015-08-19 16:49:46 -0600926 } else {
927 *pCount = ARRAY_SIZE(x11_presentable_formats);
Ian Elliottebda9892015-08-06 17:35:06 -0600928 }
929
930 return ret;
931}
932
933VkResult VKAPI vkGetSurfacePresentModesWSI(
934 VkDevice device,
935 const VkSurfaceDescriptionWSI* pSurfaceDescription,
936 uint32_t* pCount,
937 VkPresentModeWSI* pPresentModes)
938{
939 VkResult ret = VK_SUCCESS;
940
941 // TODO: Move this check to a validation layer (i.e. the driver should
942 // assume the correct data type, and not check):
943 if (!pCount) {
944 return VK_ERROR_INVALID_POINTER;
945 }
946
Ian Elliottebda9892015-08-06 17:35:06 -0600947 if (pPresentModes) {
948 pPresentModes[0] = VK_PRESENT_MODE_IMMEDIATE_WSI;
949 pPresentModes[1] = VK_PRESENT_MODE_FIFO_WSI;
950 // TODO: Consider adding VK_PRESENT_MODE_MAILBOX_WSI sometime
Ian Elliotte1ea6712015-08-19 16:49:46 -0600951 } else {
952 *pCount = 2;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800953 }
954
955 return ret;
956}
957
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800958ICD_EXPORT VkResult VKAPI vkCreateSwapChainWSI(
959 VkDevice device,
960 const VkSwapChainCreateInfoWSI* pCreateInfo,
961 VkSwapChainWSI* pSwapChain)
962{
963 struct intel_dev *dev = intel_dev(device);
964
Ian Elliott4f299362015-07-06 14:45:11 -0600965 if (pCreateInfo->oldSwapChain.handle) {
966 // TODO: Eventually, do more than simply up-front destroy the
967 // oldSwapChain (but just do that for now):
968 struct intel_x11_swap_chain *sc =
969 x11_swap_chain(pCreateInfo->oldSwapChain);
970
971 x11_swap_chain_destroy(sc);
972 }
973
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800974 return x11_swap_chain_create(dev, pCreateInfo,
975 (struct intel_x11_swap_chain **) pSwapChain);
976}
977
978ICD_EXPORT VkResult VKAPI vkDestroySwapChainWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600979 VkDevice device,
980 VkSwapChainWSI swapChain)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800981{
982 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
983
984 x11_swap_chain_destroy(sc);
985
986 return VK_SUCCESS;
987}
988
Ian Elliottebda9892015-08-06 17:35:06 -0600989ICD_EXPORT VkResult VKAPI vkGetSwapChainImagesWSI(
Ian Elliott4f299362015-07-06 14:45:11 -0600990 VkDevice device,
991 VkSwapChainWSI swapChain,
Ian Elliottebda9892015-08-06 17:35:06 -0600992 uint32_t* pCount,
993 VkImage* pSwapChainImages)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800994{
995 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
996 VkResult ret = VK_SUCCESS;
997
Ian Elliott4f299362015-07-06 14:45:11 -0600998 // TODO: Move this check to a validation layer (i.e. the driver should
999 // assume the correct data type, and not check):
Ian Elliottebda9892015-08-06 17:35:06 -06001000 if (!pCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001001 return VK_ERROR_INVALID_POINTER;
Ian Elliott4f299362015-07-06 14:45:11 -06001002 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001003
Ian Elliottebda9892015-08-06 17:35:06 -06001004 if (pSwapChainImages) {
1005 uint32_t i;
Ian Elliotte1ea6712015-08-19 16:49:46 -06001006 for (i = 0; i < *pCount; i++) {
Ian Elliottebda9892015-08-06 17:35:06 -06001007 pSwapChainImages[i].handle = (uint64_t) sc->persistent_images[i];
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001008 }
Ian Elliotte1ea6712015-08-19 16:49:46 -06001009 } else {
1010 *pCount = sc->persistent_image_count;
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001011 }
1012
1013 return ret;
1014}
1015
Ian Elliott4f299362015-07-06 14:45:11 -06001016ICD_EXPORT VkResult VKAPI vkAcquireNextImageWSI(
1017 VkDevice device,
1018 VkSwapChainWSI swapChain,
1019 uint64_t timeout,
1020 VkSemaphore semaphore,
1021 uint32_t* pImageIndex)
1022{
1023 struct intel_x11_swap_chain *sc = x11_swap_chain(swapChain);
1024 VkResult ret = VK_SUCCESS;
1025
Ian Elliott4f299362015-07-06 14:45:11 -06001026 // Find an unused image to return:
1027 for (int i = 0; i < sc->persistent_image_count; i++) {
1028 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
1029 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
1030 *pImageIndex = i;
1031 return ret;
1032 }
1033 }
1034
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001035 // If no image is ready, wait for a present to finish
1036 ret = x11_swap_chain_wait(sc, sc->present_serial, timeout);
1037 if (ret != VK_SUCCESS) {
1038 return ret;
1039 }
Ian Elliott4f299362015-07-06 14:45:11 -06001040
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001041 // Find an unused image to return:
1042 for (int i = 0; i < sc->persistent_image_count; i++) {
1043 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
1044 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
1045 *pImageIndex = i;
1046 return ret;
1047 }
1048 }
1049 // NOTE: Should never get here, but in case we do, do something:
1050 assert(0);
1051 return VK_ERROR_UNKNOWN;
Ian Elliott4f299362015-07-06 14:45:11 -06001052}
1053
1054
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001055ICD_EXPORT VkResult VKAPI vkQueuePresentWSI(
Ian Elliott4f299362015-07-06 14:45:11 -06001056 VkQueue queue_,
1057 VkPresentInfoWSI* pPresentInfo)
Chia-I Wu1db76e02014-09-15 14:21:14 +08001058{
1059 struct intel_queue *queue = intel_queue(queue_);
Ian Elliott4f299362015-07-06 14:45:11 -06001060 uint32_t i;
1061 uint32_t num_swapchains = pPresentInfo->swapChainCount;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001062
Ian Elliott4f299362015-07-06 14:45:11 -06001063 for (i = 0; i < num_swapchains; i++) {
1064 struct intel_x11_swap_chain *sc =
1065 x11_swap_chain(pPresentInfo->swapChains[i]);
1066 struct intel_img *img =
1067 sc->persistent_images[pPresentInfo->imageIndices[i]];
1068 struct intel_x11_fence_data *data =
1069 (struct intel_x11_fence_data *) queue->fence->wsi_data;
1070 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001071
Ian Elliott4f299362015-07-06 14:45:11 -06001072 ret = x11_swap_chain_present_pixmap(sc, img);
1073 if (ret != VK_SUCCESS) {
1074 return ret;
1075 }
1076
1077 // Record the state change for this image, and add this image to the
1078 // present queue for the swap chain:
1079 sc->image_state[pPresentInfo->imageIndices[i]] =
1080 INTEL_SC_STATE_QUEUED_FOR_PRESENT;
1081 sc->present_queue[sc->present_queue_length++] =
1082 pPresentInfo->imageIndices[i];
1083
1084 data->swap_chain = sc;
1085 data->serial = sc->local.serial;
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001086 sc->present_serial = sc->local.serial;
Ian Elliott4f299362015-07-06 14:45:11 -06001087 intel_fence_set_seqno(queue->fence, img->obj.mem->bo);
1088 }
Chia-I Wubda4f622015-02-25 15:06:15 -07001089
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001090 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001091}