blob: 880ece8835dcecbaa4ae2b3afe869fb4b98bef22 [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 Elliott338dedb2015-08-21 15:09:33 -060077 VkPresentModeKHR 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
Ian Elliott338dedb2015-08-21 15:09:33 -0600121static inline struct intel_x11_swap_chain *x11_swap_chain(VkSwapchainKHR sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800122{
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(
Ian Elliott338dedb2015-08-21 15:09:33 -0600218 const VkSurfaceDescriptionKHR *pSurfaceDescription,
219 VkSurfacePropertiesKHR *pSurfaceProperties)
Ian Elliott4f299362015-07-06 14:45:11 -0600220{
Ian Elliott338dedb2015-08-21 15:09:33 -0600221 const VkSurfaceDescriptionWindowKHR* pSurfaceDescriptionWindow =
222 (VkSurfaceDescriptionWindowKHR*) pSurfaceDescription;
223 VkPlatformHandleXcbKHR *pPlatformHandleXcb = (VkPlatformHandleXcbKHR *)
Ian Elliott4f299362015-07-06 14:45:11 -0600224 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;
Ian Elliott338dedb2015-08-21 15:09:33 -0600255 pSurfaceProperties->supportedTransforms = VK_SURFACE_TRANSFORM_NONE_BIT_KHR;
256 pSurfaceProperties->currentTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Ian Elliott4f299362015-07-06 14:45:11 -0600257 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,
Ian Elliott338dedb2015-08-21 15:09:33 -0600440 const VkSwapchainCreateInfoKHR *info)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800441{
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 Elliott338dedb2015-08-21 15:09:33 -0600539 if (sc->present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR) {
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,
Ian Elliott338dedb2015-08-21 15:09:33 -0600711 const VkSwapchainCreateInfoKHR *info,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800712 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 Elliott338dedb2015-08-21 15:09:33 -0600715 const VkSurfaceDescriptionWindowKHR* pSurfaceDescriptionWindow =
716 (VkSurfaceDescriptionWindowKHR*) info->pSurfaceDescription;
717 VkPlatformHandleXcbKHR *pPlatformHandleXcb = (VkPlatformHandleXcbKHR *)
Ian Elliott4f299362015-07-06 14:45:11 -0600718 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
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600726 /* TODOVV: Add test to validation layer */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800727 if (!x11_is_format_presentable(dev, info->imageFormat)) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600728 intel_dev_log(dev, VK_DBG_REPORT_ERROR_BIT,
729 VK_NULL_HANDLE, 0, 0, "invalid presentable image format");
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600730// return VK_ERROR_INVALID_VALUE;
731 return VK_ERROR_UNKNOWN;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800732 }
733
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600734 /* TODOVV: Can we add test to validation layer? */
735 if (!x11_is_dri3_and_present_supported(c)) {
736// return VK_ERROR_INVALID_VALUE;
737 return VK_ERROR_UNKNOWN;
738 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800739
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600740 /* TODOVV: Can we add test to validation layer? */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800741 fd = x11_dri3_open(c, window, provider);
742 if (fd < 0 || !x11_gpu_match_fd(dev->gpu, fd)) {
Chia-I Wufcbc5252015-04-08 11:44:26 +0800743 if (fd >= 0)
744 close(fd);
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600745// return VK_ERROR_INVALID_VALUE;
746 return VK_ERROR_UNKNOWN;
Chia-I Wufcbc5252015-04-08 11:44:26 +0800747 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800748
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800749 close(fd);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800750
Tony Barbour8205d902015-04-16 15:59:00 -0600751 sc = intel_alloc(dev, sizeof(*sc), 0, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800752 if (!sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800753 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800754
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800755 memset(sc, 0, sizeof(*sc));
Ian Elliott338dedb2015-08-21 15:09:33 -0600756 intel_handle_init(&sc->handle, VK_OBJECT_TYPE_SWAPCHAIN_KHR, dev->base.handle.instance);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800757
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800758 sc->c = c;
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800759 sc->window = window;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800760
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800761 /* always copy unless flip bit is set */
Ian Elliott4f299362015-07-06 14:45:11 -0600762 sc->present_mode = info->presentMode;
763 sc->force_copy = true;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800764
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800765 if (!x11_swap_chain_dri3_and_present_query_version(sc) ||
766 !x11_swap_chain_present_select_input(sc) ||
767 !x11_swap_chain_create_persistent_images(sc, dev, info)) {
768 x11_swap_chain_destroy(sc);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600769 return VK_ERROR_UNKNOWN;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800770 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800771
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800772 *sc_ret = sc;
Chia-I Wu41858c82015-04-04 16:39:25 +0800773
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600774 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800775}
776
Chia-I Wu8635e912015-04-09 14:13:57 +0800777static void x11_display_destroy(struct intel_x11_display *dpy)
778{
779 intel_free(dpy, dpy->modes);
780 intel_free(dpy, dpy);
781}
782
Chia-I Wu41858c82015-04-04 16:39:25 +0800783void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
784{
Chia-I Wu8635e912015-04-09 14:13:57 +0800785 if (gpu->displays) {
786 uint32_t i;
Chia-I Wu41858c82015-04-04 16:39:25 +0800787
Chia-I Wu8635e912015-04-09 14:13:57 +0800788 for (i = 0; i < gpu->display_count; i++) {
789 struct intel_x11_display *dpy =
790 (struct intel_x11_display *) gpu->displays[i];
791 x11_display_destroy(dpy);
792 }
793 intel_free(gpu, gpu->displays);
794 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800795}
796
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600797VkResult intel_wsi_img_init(struct intel_img *img)
Chia-I Wu41858c82015-04-04 16:39:25 +0800798{
799 struct intel_x11_img_data *data;
800
Tony Barbour8205d902015-04-16 15:59:00 -0600801 data = intel_alloc(img, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800802 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600803 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800804
805 memset(data, 0, sizeof(*data));
806
807 assert(!img->wsi_data);
808 img->wsi_data = data;
809
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600810 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800811}
812
813void intel_wsi_img_cleanup(struct intel_img *img)
814{
815 struct intel_x11_img_data *data =
816 (struct intel_x11_img_data *) img->wsi_data;
817
818 if (data->mem) {
819 close(data->prime_fd);
820 intel_mem_free(data->mem);
821 }
822
823 intel_free(img, img->wsi_data);
824}
825
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600826VkResult intel_wsi_fence_init(struct intel_fence *fence)
Chia-I Wu41858c82015-04-04 16:39:25 +0800827{
828 struct intel_x11_fence_data *data;
829
Tony Barbour8205d902015-04-16 15:59:00 -0600830 data = intel_alloc(fence, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800831 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600832 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800833
834 memset(data, 0, sizeof(*data));
835
836 assert(!fence->wsi_data);
837 fence->wsi_data = data;
838
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600839 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800840}
841
842void intel_wsi_fence_cleanup(struct intel_fence *fence)
843{
844 intel_free(fence, fence->wsi_data);
845}
846
847void intel_wsi_fence_copy(struct intel_fence *fence,
848 const struct intel_fence *src)
849{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600850 if (!fence->wsi_data) {
851 return;
852 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800853 memcpy(fence->wsi_data, src->wsi_data,
854 sizeof(struct intel_x11_fence_data));
855}
856
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600857VkResult intel_wsi_fence_wait(struct intel_fence *fence,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800858 int64_t timeout_ns)
Chia-I Wu41858c82015-04-04 16:39:25 +0800859{
860 struct intel_x11_fence_data *data =
861 (struct intel_x11_fence_data *) fence->wsi_data;
862
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600863 if (!data)
864 return VK_SUCCESS;
865
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800866 if (!data->swap_chain)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600867 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800868
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800869 return x11_swap_chain_wait(data->swap_chain, data->serial, timeout_ns);
Chia-I Wu41858c82015-04-04 16:39:25 +0800870}
871
Ian Elliott338dedb2015-08-21 15:09:33 -0600872ICD_EXPORT VkResult VKAPI vkGetPhysicalDeviceSurfaceSupportKHR(
Ian Elliott4f299362015-07-06 14:45:11 -0600873 VkPhysicalDevice physicalDevice,
874 uint32_t queueNodeIndex,
Ian Elliott338dedb2015-08-21 15:09:33 -0600875 const VkSurfaceDescriptionKHR* pSurfaceDescription,
Ian Elliott4f299362015-07-06 14:45:11 -0600876 VkBool32* pSupported)
877{
878 VkResult ret = VK_SUCCESS;
Ian Elliott338dedb2015-08-21 15:09:33 -0600879 const VkSurfaceDescriptionWindowKHR* pSurfaceDescriptionWindow =
880 (VkSurfaceDescriptionWindowKHR*) pSurfaceDescription;
Ian Elliott4f299362015-07-06 14:45:11 -0600881
882 *pSupported = false;
883
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600884 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliott4f299362015-07-06 14:45:11 -0600885 // assume the correct data type, and not check):
Ian Elliott338dedb2015-08-21 15:09:33 -0600886 if (pSurfaceDescriptionWindow->sType != VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR) {
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600887 return VK_ERROR_UNKNOWN;
Ian Elliott4f299362015-07-06 14:45:11 -0600888 }
889
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600890 // TODOVV: NEED TO ALSO CHECK:
Ian Elliott4f299362015-07-06 14:45:11 -0600891 // - queueNodeIndex
892 // - pSurfaceDescriptionWindow->pPlatformHandle (can try to use it)
893 // - pSurfaceDescriptionWindow->pPlatformWindow (can try to use it)
Ian Elliott338dedb2015-08-21 15:09:33 -0600894 if (pSurfaceDescriptionWindow->platform == VK_PLATFORM_XCB_KHR) {
Ian Elliott4f299362015-07-06 14:45:11 -0600895 *pSupported = true;
896 }
897
898 return ret;
899}
900
Ian Elliott338dedb2015-08-21 15:09:33 -0600901VkResult VKAPI vkGetSurfacePropertiesKHR(
Ian Elliott4f299362015-07-06 14:45:11 -0600902 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -0600903 const VkSurfaceDescriptionKHR* pSurfaceDescription,
904 VkSurfacePropertiesKHR* pSurfaceProperties)
Ian Elliottebda9892015-08-06 17:35:06 -0600905{
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600906 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliottebda9892015-08-06 17:35:06 -0600907 // assume the correct data type, and not check):
908 assert(pSurfaceProperties);
909
910 return x11_get_surface_properties(pSurfaceDescription, pSurfaceProperties);
911}
912
Ian Elliott338dedb2015-08-21 15:09:33 -0600913VkResult VKAPI vkGetSurfaceFormatsKHR(
Ian Elliottebda9892015-08-06 17:35:06 -0600914 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -0600915 const VkSurfaceDescriptionKHR* pSurfaceDescription,
Ian Elliottebda9892015-08-06 17:35:06 -0600916 uint32_t* pCount,
Ian Elliott338dedb2015-08-21 15:09:33 -0600917 VkSurfaceFormatKHR* pSurfaceFormats)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800918{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800919 VkResult ret = VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800920
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600921 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliott4f299362015-07-06 14:45:11 -0600922 // assume the correct data type, and not check):
Ian Elliottebda9892015-08-06 17:35:06 -0600923 if (!pCount) {
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600924// return VK_ERROR_INVALID_POINTER;
925 return VK_ERROR_UNKNOWN;
Ian Elliott4f299362015-07-06 14:45:11 -0600926 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800927
Ian Elliottebda9892015-08-06 17:35:06 -0600928 if (pSurfaceFormats) {
929 uint32_t i;
930 for (i = 0; i < *pCount; i++) {
931 pSurfaceFormats[i].format = x11_presentable_formats[i];
Ian Elliott338dedb2015-08-21 15:09:33 -0600932 pSurfaceFormats[i].colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
Ian Elliott4f299362015-07-06 14:45:11 -0600933 }
Ian Elliotte1ea6712015-08-19 16:49:46 -0600934 } else {
935 *pCount = ARRAY_SIZE(x11_presentable_formats);
Ian Elliottebda9892015-08-06 17:35:06 -0600936 }
937
938 return ret;
939}
940
Ian Elliott338dedb2015-08-21 15:09:33 -0600941VkResult VKAPI vkGetSurfacePresentModesKHR(
Ian Elliottebda9892015-08-06 17:35:06 -0600942 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -0600943 const VkSurfaceDescriptionKHR* pSurfaceDescription,
Ian Elliottebda9892015-08-06 17:35:06 -0600944 uint32_t* pCount,
Ian Elliott338dedb2015-08-21 15:09:33 -0600945 VkPresentModeKHR* pPresentModes)
Ian Elliottebda9892015-08-06 17:35:06 -0600946{
947 VkResult ret = VK_SUCCESS;
948
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600949 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliottebda9892015-08-06 17:35:06 -0600950 // assume the correct data type, and not check):
951 if (!pCount) {
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600952// return VK_ERROR_INVALID_POINTER;
953 return VK_ERROR_UNKNOWN;
Ian Elliottebda9892015-08-06 17:35:06 -0600954 }
955
Ian Elliottebda9892015-08-06 17:35:06 -0600956 if (pPresentModes) {
Ian Elliott338dedb2015-08-21 15:09:33 -0600957 pPresentModes[0] = VK_PRESENT_MODE_IMMEDIATE_KHR;
958 pPresentModes[1] = VK_PRESENT_MODE_FIFO_KHR;
959 // TODO: Consider adding VK_PRESENT_MODE_MAILBOX_KHR sometime
Ian Elliotte1ea6712015-08-19 16:49:46 -0600960 } else {
961 *pCount = 2;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800962 }
963
964 return ret;
965}
966
Ian Elliott338dedb2015-08-21 15:09:33 -0600967ICD_EXPORT VkResult VKAPI vkCreateSwapchainKHR(
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800968 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -0600969 const VkSwapchainCreateInfoKHR* pCreateInfo,
970 VkSwapchainKHR* pSwapchain)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800971{
972 struct intel_dev *dev = intel_dev(device);
973
Ian Elliott338dedb2015-08-21 15:09:33 -0600974 if (pCreateInfo->oldSwapchain.handle) {
Ian Elliott4f299362015-07-06 14:45:11 -0600975 // TODO: Eventually, do more than simply up-front destroy the
Ian Elliott338dedb2015-08-21 15:09:33 -0600976 // oldSwapchain (but just do that for now):
Ian Elliott4f299362015-07-06 14:45:11 -0600977 struct intel_x11_swap_chain *sc =
Ian Elliott338dedb2015-08-21 15:09:33 -0600978 x11_swap_chain(pCreateInfo->oldSwapchain);
Ian Elliott4f299362015-07-06 14:45:11 -0600979
980 x11_swap_chain_destroy(sc);
981 }
982
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800983 return x11_swap_chain_create(dev, pCreateInfo,
Ian Elliott338dedb2015-08-21 15:09:33 -0600984 (struct intel_x11_swap_chain **) pSwapchain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800985}
986
Ian Elliott338dedb2015-08-21 15:09:33 -0600987ICD_EXPORT VkResult VKAPI vkDestroySwapchainKHR(
Ian Elliott4f299362015-07-06 14:45:11 -0600988 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -0600989 VkSwapchainKHR swapchain)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800990{
Ian Elliott338dedb2015-08-21 15:09:33 -0600991 struct intel_x11_swap_chain *sc = x11_swap_chain(swapchain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800992
993 x11_swap_chain_destroy(sc);
994
995 return VK_SUCCESS;
996}
997
Ian Elliott338dedb2015-08-21 15:09:33 -0600998ICD_EXPORT VkResult VKAPI vkGetSwapchainImagesKHR(
Ian Elliott4f299362015-07-06 14:45:11 -0600999 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -06001000 VkSwapchainKHR swapchain,
Ian Elliottebda9892015-08-06 17:35:06 -06001001 uint32_t* pCount,
Ian Elliott338dedb2015-08-21 15:09:33 -06001002 VkImage* pSwapchainImages)
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001003{
Ian Elliott338dedb2015-08-21 15:09:33 -06001004 struct intel_x11_swap_chain *sc = x11_swap_chain(swapchain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001005 VkResult ret = VK_SUCCESS;
1006
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -06001007 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliott4f299362015-07-06 14:45:11 -06001008 // assume the correct data type, and not check):
Ian Elliottebda9892015-08-06 17:35:06 -06001009 if (!pCount) {
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -06001010// return VK_ERROR_INVALID_POINTER;
1011 return VK_ERROR_UNKNOWN;
Ian Elliott4f299362015-07-06 14:45:11 -06001012 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001013
Ian Elliott338dedb2015-08-21 15:09:33 -06001014 if (pSwapchainImages) {
Ian Elliottebda9892015-08-06 17:35:06 -06001015 uint32_t i;
Ian Elliotte1ea6712015-08-19 16:49:46 -06001016 for (i = 0; i < *pCount; i++) {
Ian Elliott338dedb2015-08-21 15:09:33 -06001017 pSwapchainImages[i].handle = (uint64_t) sc->persistent_images[i];
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001018 }
Ian Elliotte1ea6712015-08-19 16:49:46 -06001019 } else {
1020 *pCount = sc->persistent_image_count;
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001021 }
1022
1023 return ret;
1024}
1025
Ian Elliott338dedb2015-08-21 15:09:33 -06001026ICD_EXPORT VkResult VKAPI vkAcquireNextImageKHR(
Ian Elliott4f299362015-07-06 14:45:11 -06001027 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -06001028 VkSwapchainKHR swapchain,
Ian Elliott4f299362015-07-06 14:45:11 -06001029 uint64_t timeout,
1030 VkSemaphore semaphore,
1031 uint32_t* pImageIndex)
1032{
Ian Elliott338dedb2015-08-21 15:09:33 -06001033 struct intel_x11_swap_chain *sc = x11_swap_chain(swapchain);
Ian Elliott4f299362015-07-06 14:45:11 -06001034 VkResult ret = VK_SUCCESS;
1035
Ian Elliott4f299362015-07-06 14:45:11 -06001036 // Find an unused image to return:
1037 for (int i = 0; i < sc->persistent_image_count; i++) {
1038 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
1039 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
1040 *pImageIndex = i;
1041 return ret;
1042 }
1043 }
1044
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001045 // If no image is ready, wait for a present to finish
Mike Stroyanb28dd442015-09-03 10:22:15 -06001046 ret = x11_swap_chain_wait(sc, sc->remote.serial+1, timeout);
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001047 if (ret != VK_SUCCESS) {
1048 return ret;
1049 }
Ian Elliott4f299362015-07-06 14:45:11 -06001050
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001051 // Find an unused image to return:
1052 for (int i = 0; i < sc->persistent_image_count; i++) {
1053 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
1054 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
1055 *pImageIndex = i;
1056 return ret;
1057 }
1058 }
1059 // NOTE: Should never get here, but in case we do, do something:
1060 assert(0);
1061 return VK_ERROR_UNKNOWN;
Ian Elliott4f299362015-07-06 14:45:11 -06001062}
1063
1064
Ian Elliott338dedb2015-08-21 15:09:33 -06001065ICD_EXPORT VkResult VKAPI vkQueuePresentKHR(
Ian Elliott4f299362015-07-06 14:45:11 -06001066 VkQueue queue_,
Ian Elliott338dedb2015-08-21 15:09:33 -06001067 VkPresentInfoKHR* pPresentInfo)
Chia-I Wu1db76e02014-09-15 14:21:14 +08001068{
1069 struct intel_queue *queue = intel_queue(queue_);
Ian Elliott4f299362015-07-06 14:45:11 -06001070 uint32_t i;
Ian Elliott338dedb2015-08-21 15:09:33 -06001071 uint32_t num_swapchains = pPresentInfo->swapchainCount;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001072
Mike Stroyan12915ce2015-09-03 10:25:44 -06001073 // Wait for queue to idle before out-of-band xcb present operation.
1074 const VkResult r = intel_queue_wait(queue, -1);
1075 (void) r;
1076
Ian Elliott4f299362015-07-06 14:45:11 -06001077 for (i = 0; i < num_swapchains; i++) {
1078 struct intel_x11_swap_chain *sc =
Ian Elliott338dedb2015-08-21 15:09:33 -06001079 x11_swap_chain(pPresentInfo->swapchains[i]);
Ian Elliott4f299362015-07-06 14:45:11 -06001080 struct intel_img *img =
1081 sc->persistent_images[pPresentInfo->imageIndices[i]];
1082 struct intel_x11_fence_data *data =
1083 (struct intel_x11_fence_data *) queue->fence->wsi_data;
1084 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001085
Ian Elliott4f299362015-07-06 14:45:11 -06001086 ret = x11_swap_chain_present_pixmap(sc, img);
1087 if (ret != VK_SUCCESS) {
1088 return ret;
1089 }
1090
1091 // Record the state change for this image, and add this image to the
1092 // present queue for the swap chain:
1093 sc->image_state[pPresentInfo->imageIndices[i]] =
1094 INTEL_SC_STATE_QUEUED_FOR_PRESENT;
1095 sc->present_queue[sc->present_queue_length++] =
1096 pPresentInfo->imageIndices[i];
1097
1098 data->swap_chain = sc;
1099 data->serial = sc->local.serial;
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001100 sc->present_serial = sc->local.serial;
Ian Elliott4f299362015-07-06 14:45:11 -06001101 intel_fence_set_seqno(queue->fence, img->obj.mem->bo);
1102 }
Chia-I Wubda4f622015-02-25 15:06:15 -07001103
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001104 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001105}