blob: de509628ae320c6ea80105ad2eb5ee7a97336833 [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>
Mike Stroyanc8b6f822015-09-11 13:21:05 -060031#include <poll.h>
Chia-I Wu1db76e02014-09-15 14:21:14 +080032#include <sys/types.h>
33#include <sys/stat.h>
34#include <unistd.h>
35#include <fcntl.h>
36#include <xcb/xcb.h>
37#include <xcb/dri3.h>
38#include <xcb/present.h>
39
40#include "kmd/winsys.h"
Chia-I Wu8635e912015-04-09 14:13:57 +080041#include "kmd/libdrm/xf86drmMode.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080042#include "dev.h"
43#include "fence.h"
44#include "gpu.h"
45#include "img.h"
46#include "mem.h"
47#include "queue.h"
Chia-I Wu41858c82015-04-04 16:39:25 +080048#include "wsi.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080049
Chia-I Wu8635e912015-04-09 14:13:57 +080050struct intel_x11_display {
51 struct intel_handle handle;
52
53 int fd;
54 uint32_t connector_id;
55
56 char name[32];
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -060057 VkExtent2D physical_dimension;
58 VkExtent2D physical_resolution;
Chia-I Wu8635e912015-04-09 14:13:57 +080059
60 drmModeModeInfoPtr modes;
61 uint32_t mode_count;
62};
63
Ian Elliott4f299362015-07-06 14:45:11 -060064typedef enum intel_x11_swap_chain_image_state_
65{
66 INTEL_SC_STATE_UNUSED = 0,
67 INTEL_SC_STATE_APP_OWNED = 1,
68 INTEL_SC_STATE_QUEUED_FOR_PRESENT = 2,
69 INTEL_SC_STATE_DISPLAYED = 3,
70} intel_x11_swap_chain_image_state;
71
Chia-I Wu6532d1d2015-04-04 22:16:45 +080072struct intel_x11_swap_chain {
73 struct intel_handle handle;
74
75 xcb_connection_t *c;
76 xcb_window_t window;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080077 bool force_copy;
Ian Elliott338dedb2015-08-21 15:09:33 -060078 VkPresentModeKHR present_mode;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080079
80 int dri3_major, dri3_minor;
81 int present_major, present_minor;
Chia-I Wu1db76e02014-09-15 14:21:14 +080082
83 xcb_present_event_t present_special_event_id;
84 xcb_special_event_t *present_special_event;
85
Chia-I Wu5b66aa52015-04-16 22:02:10 +080086 struct intel_img **persistent_images;
87 uint32_t persistent_image_count;
Ian Elliott4f299362015-07-06 14:45:11 -060088 intel_x11_swap_chain_image_state *image_state;
89 uint32_t *present_queue;
90 uint32_t present_queue_length;
Mike Stroyanf9f6dd72015-07-28 11:00:50 -060091 uint32_t present_serial;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080092
Chia-I Wu1db76e02014-09-15 14:21:14 +080093 struct {
94 uint32_t serial;
95 } local;
96
97 struct {
98 uint32_t serial;
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -060099 uint64_t msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800100 } remote;
101};
102
Chia-I Wu41858c82015-04-04 16:39:25 +0800103struct intel_x11_img_data {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800104 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +0800105 struct intel_mem *mem;
106 int prime_fd;
107 uint32_t pixmap;
108};
109
110struct intel_x11_fence_data {
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800111 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +0800112 uint32_t serial;
113};
114
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800115/* these are what DDX expects */
116static const VkFormat x11_presentable_formats[] = {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800117 VK_FORMAT_B8G8R8A8_UNORM,
118 VK_FORMAT_B8G8R8A8_SRGB,
Ian Elliott32536f92015-04-21 16:41:02 -0600119 VK_FORMAT_B5G6R5_UNORM,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800120};
121
Ian Elliott338dedb2015-08-21 15:09:33 -0600122static inline struct intel_x11_swap_chain *x11_swap_chain(VkSwapchainKHR sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800123{
Ian Elliott4f299362015-07-06 14:45:11 -0600124 return (struct intel_x11_swap_chain *) sc.handle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800125}
126
Chia-I Wufcbc5252015-04-08 11:44:26 +0800127static bool x11_is_format_presentable(const struct intel_dev *dev,
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600128 VkFormat format)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800129{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800130 uint32_t i;
131
132 for (i = 0; i < ARRAY_SIZE(x11_presentable_formats); i++) {
133 if (x11_presentable_formats[i] == format)
134 return true;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800135 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800136
137 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800138}
139
Chia-I Wu030b2db2015-04-08 13:46:29 +0800140static int x11_export_prime_fd(struct intel_dev *dev,
141 struct intel_bo *bo,
142 const struct intel_layout *layout)
143{
144 struct intel_winsys_handle export;
145 enum intel_tiling_mode tiling;
146
147 export.type = INTEL_WINSYS_HANDLE_FD;
148
149 switch (layout->tiling) {
150 case GEN6_TILING_X:
151 tiling = INTEL_TILING_X;
152 break;
153 case GEN6_TILING_Y:
154 tiling = INTEL_TILING_Y;
155 break;
156 default:
157 assert(layout->tiling == GEN6_TILING_NONE);
158 tiling = INTEL_TILING_NONE;
159 break;
160 }
161
162 if (intel_bo_set_tiling(bo, tiling, layout->bo_stride))
163 return -1;
164
165 if (intel_winsys_export_handle(dev->winsys, bo, tiling,
166 layout->bo_stride, layout->bo_height, &export))
167 return -1;
168
169 return (int) export.handle;
170}
171
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800172/**
Chia-I Wufcbc5252015-04-08 11:44:26 +0800173 * Return true if fd points to the primary or render node of the GPU.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800174 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800175static bool x11_gpu_match_fd(const struct intel_gpu *gpu, int fd)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800176{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800177 struct stat fd_stat, gpu_stat;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800178
Chia-I Wufcbc5252015-04-08 11:44:26 +0800179 if (fstat(fd, &fd_stat))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800180 return false;
181
182 /* is it the primary node? */
183 if (!stat(gpu->primary_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800184 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800185 return true;
186
187 /* is it the render node? */
188 if (gpu->render_node && !stat(gpu->render_node, &gpu_stat) &&
Chia-I Wufcbc5252015-04-08 11:44:26 +0800189 !memcmp(&fd_stat, &gpu_stat, sizeof(fd_stat)))
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800190 return true;
191
192 return false;
193}
194
Chia-I Wufcbc5252015-04-08 11:44:26 +0800195/*
196 * Return the depth of \p drawable.
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800197 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800198static int x11_get_drawable_depth(xcb_connection_t *c,
199 xcb_drawable_t drawable)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800200{
Chia-I Wufcbc5252015-04-08 11:44:26 +0800201 xcb_get_geometry_cookie_t cookie;
202 xcb_get_geometry_reply_t *reply;
203 uint8_t depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800204
Chia-I Wufcbc5252015-04-08 11:44:26 +0800205 cookie = xcb_get_geometry(c, drawable);
206 reply = xcb_get_geometry_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800207
Chia-I Wufcbc5252015-04-08 11:44:26 +0800208 if (reply) {
209 depth = reply->depth;
210 free(reply);
211 } else {
212 depth = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800213 }
214
Chia-I Wufcbc5252015-04-08 11:44:26 +0800215 return depth;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800216}
217
Ian Elliott4f299362015-07-06 14:45:11 -0600218static VkResult x11_get_surface_properties(
Ian Elliott338dedb2015-08-21 15:09:33 -0600219 const VkSurfaceDescriptionKHR *pSurfaceDescription,
220 VkSurfacePropertiesKHR *pSurfaceProperties)
Ian Elliott4f299362015-07-06 14:45:11 -0600221{
Ian Elliott338dedb2015-08-21 15:09:33 -0600222 const VkSurfaceDescriptionWindowKHR* pSurfaceDescriptionWindow =
223 (VkSurfaceDescriptionWindowKHR*) pSurfaceDescription;
224 VkPlatformHandleXcbKHR *pPlatformHandleXcb = (VkPlatformHandleXcbKHR *)
Ian Elliott4f299362015-07-06 14:45:11 -0600225 pSurfaceDescriptionWindow->pPlatformHandle;
226 xcb_connection_t *c = (xcb_connection_t *)
227 pPlatformHandleXcb->connection;
228 xcb_window_t window = *((xcb_window_t *)
229 pSurfaceDescriptionWindow->pPlatformWindow);
230 xcb_get_geometry_cookie_t cookie;
231 xcb_get_geometry_reply_t *reply;
232
233 cookie = xcb_get_geometry(c, window);
234 reply = xcb_get_geometry_reply(c, cookie, NULL);
235
236 if (reply) {
237 pSurfaceProperties->currentExtent.width = reply->width;
238 pSurfaceProperties->currentExtent.height = reply->height;
239 free(reply);
240 } else {
241 pSurfaceProperties->currentExtent.width = 0;
242 pSurfaceProperties->currentExtent.height = 0;
243 }
244
245 pSurfaceProperties->minImageCount = 2;
246 pSurfaceProperties->maxImageCount = 0;
247
248 pSurfaceProperties->minImageExtent.width =
249 pSurfaceProperties->currentExtent.width;
250 pSurfaceProperties->minImageExtent.height =
251 pSurfaceProperties->currentExtent.height;
252 pSurfaceProperties->maxImageExtent.width =
253 pSurfaceProperties->currentExtent.width;
254 pSurfaceProperties->maxImageExtent.height =
255 pSurfaceProperties->currentExtent.height;
Ian Elliott338dedb2015-08-21 15:09:33 -0600256 pSurfaceProperties->supportedTransforms = VK_SURFACE_TRANSFORM_NONE_BIT_KHR;
257 pSurfaceProperties->currentTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Ian Elliott4f299362015-07-06 14:45:11 -0600258 pSurfaceProperties->maxImageArraySize = 0;
259 pSurfaceProperties->supportedUsageFlags =
Cody Northrop3440c2d2015-08-28 16:40:45 -0600260 VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
Ian Elliott4f299362015-07-06 14:45:11 -0600261 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
262
263 return VK_SUCCESS;
264}
265
Chia-I Wu1db76e02014-09-15 14:21:14 +0800266/**
267 * Return true if DRI3 and Present are supported by the server.
268 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800269static bool x11_is_dri3_and_present_supported(xcb_connection_t *c)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800270{
271 const xcb_query_extension_reply_t *ext;
272
Chia-I Wufcbc5252015-04-08 11:44:26 +0800273 xcb_prefetch_extension_data(c, &xcb_dri3_id);
274 xcb_prefetch_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800275
Chia-I Wufcbc5252015-04-08 11:44:26 +0800276 ext = xcb_get_extension_data(c, &xcb_dri3_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800277 if (!ext || !ext->present)
278 return false;
279
Chia-I Wufcbc5252015-04-08 11:44:26 +0800280 ext = xcb_get_extension_data(c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800281 if (!ext || !ext->present)
282 return false;
283
284 return true;
285}
286
287/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800288 * Send a DRI3Open to get the server GPU fd.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800289 */
Chia-I Wufcbc5252015-04-08 11:44:26 +0800290static int x11_dri3_open(xcb_connection_t *c,
291 xcb_drawable_t drawable,
292 xcb_randr_provider_t provider)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800293{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800294 xcb_dri3_open_cookie_t cookie;
295 xcb_dri3_open_reply_t *reply;
296 int fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800297
Chia-I Wufcbc5252015-04-08 11:44:26 +0800298 cookie = xcb_dri3_open(c, drawable, provider);
299 reply = xcb_dri3_open_reply(c, cookie, NULL);
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800300 if (!reply)
Chia-I Wufcbc5252015-04-08 11:44:26 +0800301 return -1;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800302
Chia-I Wufcbc5252015-04-08 11:44:26 +0800303 fd = (reply->nfd == 1) ? xcb_dri3_open_reply_fds(c, reply)[0] : -1;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800304 free(reply);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800305
Chia-I Wufcbc5252015-04-08 11:44:26 +0800306 return fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800307}
308
309/**
Chia-I Wu030b2db2015-04-08 13:46:29 +0800310 * Send a DRI3PixmapFromBuffer to create a pixmap from \p prime_fd.
311 */
312static xcb_pixmap_t x11_dri3_pixmap_from_buffer(xcb_connection_t *c,
313 xcb_drawable_t drawable,
314 uint8_t depth, int prime_fd,
315 const struct intel_layout *layout)
316{
317 xcb_pixmap_t pixmap;
318
319 pixmap = xcb_generate_id(c);
320
321 xcb_dri3_pixmap_from_buffer(c, pixmap, drawable,
322 layout->bo_stride * layout->bo_height,
323 layout->width0, layout->height0,
324 layout->bo_stride, depth,
325 layout->block_size * 8, prime_fd);
326
327 return pixmap;
328}
329
330/**
Chia-I Wu41858c82015-04-04 16:39:25 +0800331 * Send DRI3QueryVersion and PresentQueryVersion to query extension versions.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800332 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800333static bool x11_swap_chain_dri3_and_present_query_version(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800334{
335 xcb_dri3_query_version_cookie_t dri3_cookie;
336 xcb_dri3_query_version_reply_t *dri3_reply;
337 xcb_present_query_version_cookie_t present_cookie;
338 xcb_present_query_version_reply_t *present_reply;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800339
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800340 dri3_cookie = xcb_dri3_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800341 XCB_DRI3_MAJOR_VERSION, XCB_DRI3_MINOR_VERSION);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800342 present_cookie = xcb_present_query_version(sc->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800343 XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION);
344
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800345 dri3_reply = xcb_dri3_query_version_reply(sc->c, dri3_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800346 if (!dri3_reply)
347 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800348
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800349 sc->dri3_major = dri3_reply->major_version;
350 sc->dri3_minor = dri3_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800351 free(dri3_reply);
352
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800353 present_reply = xcb_present_query_version_reply(sc->c, present_cookie, NULL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800354 if (!present_reply)
355 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800356
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800357 sc->present_major = present_reply->major_version;
358 sc->present_minor = present_reply->minor_version;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800359 free(present_reply);
360
Chia-I Wu41858c82015-04-04 16:39:25 +0800361 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800362}
363
364/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800365 * Send a PresentSelectInput to select interested events.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800366 */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800367static bool x11_swap_chain_present_select_input(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800368{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800369 xcb_void_cookie_t cookie;
370 xcb_generic_error_t *error;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800371
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800372 /* create the event queue */
373 sc->present_special_event_id = xcb_generate_id(sc->c);
374 sc->present_special_event = xcb_register_for_special_xge(sc->c,
375 &xcb_present_id, sc->present_special_event_id, NULL);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800376
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800377 cookie = xcb_present_select_input_checked(sc->c,
378 sc->present_special_event_id, sc->window,
379 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800380
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800381 error = xcb_request_check(sc->c, cookie);
382 if (error) {
383 free(error);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800384 return false;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800385 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800386
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800387 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800388}
389
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800390static struct intel_img *x11_swap_chain_create_persistent_image(struct intel_x11_swap_chain *sc,
391 struct intel_dev *dev,
392 const VkImageCreateInfo *img_info)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800393{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800394 struct intel_img *img;
395 struct intel_mem *mem;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800396 struct intel_x11_img_data *data;
397 VkMemoryAllocInfo mem_info;
398 int prime_fd;
399 xcb_pixmap_t pixmap;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600400 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800401
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800402 ret = intel_img_create(dev, img_info, true, &img);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600403 if (ret != VK_SUCCESS)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800404 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800405
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800406 memset(&mem_info, 0, sizeof(mem_info));
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600407 mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800408 mem_info.allocationSize = img->total_size;
Mark Lobodzinski72346292015-07-02 16:49:40 -0600409 mem_info.memoryTypeIndex = 0;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800410
411 ret = intel_mem_alloc(dev, &mem_info, &mem);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600412 if (ret != VK_SUCCESS) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800413 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800414 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800415 }
416
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800417 prime_fd = x11_export_prime_fd(dev, mem->bo, &img->layout);
418 if (prime_fd < 0) {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800419 intel_mem_free(mem);
420 intel_img_destroy(img);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800421 return NULL;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800422 }
423
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800424 pixmap = x11_dri3_pixmap_from_buffer(sc->c, sc->window,
425 x11_get_drawable_depth(sc->c, sc->window),
426 prime_fd, &img->layout);
427
428 data = (struct intel_x11_img_data *) img->wsi_data;
429 data->swap_chain = sc;
430 data->mem = mem;
431 data->prime_fd = prime_fd;
432 data->pixmap = pixmap;
433
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800434 intel_obj_bind_mem(&img->obj, mem, 0);
435
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800436 return img;
437}
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800438
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800439static bool x11_swap_chain_create_persistent_images(struct intel_x11_swap_chain *sc,
440 struct intel_dev *dev,
Ian Elliott338dedb2015-08-21 15:09:33 -0600441 const VkSwapchainCreateInfoKHR *info)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800442{
443 struct intel_img **images;
Ian Elliott4f299362015-07-06 14:45:11 -0600444 intel_x11_swap_chain_image_state *image_state;
445 uint32_t *present_queue;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800446 VkImageCreateInfo img_info;
447 uint32_t i;
448
Ian Elliott4f299362015-07-06 14:45:11 -0600449 images = intel_alloc(sc, sizeof(*images) * info->minImageCount,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800450 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
451 if (!images)
452 return false;
Ian Elliott4f299362015-07-06 14:45:11 -0600453 image_state = intel_alloc(
454 sc, sizeof(intel_x11_swap_chain_image_state) * info->minImageCount,
455 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
456 if (!image_state) {
457 for (i = 0; i < info->minImageCount; i++) {
458 intel_img_destroy(images[i]);
459 }
460 intel_free(sc, images);
461 return false;
462 }
463 present_queue = intel_alloc(
464 sc, sizeof(uint32_t) * info->minImageCount,
465 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
466 if (!present_queue) {
467 for (i = 0; i < info->minImageCount; i++) {
468 intel_img_destroy(images[i]);
469 }
470 intel_free(sc, images);
471 intel_free(sc, image_state);
472 return false;
473 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800474
475 memset(&img_info, 0, sizeof(img_info));
476 img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
477 img_info.imageType = VK_IMAGE_TYPE_2D;
478 img_info.format = info->imageFormat;
479 img_info.extent.width = info->imageExtent.width;
480 img_info.extent.height = info->imageExtent.height;
481 img_info.extent.depth = 1;
482 img_info.mipLevels = 1;
483 img_info.arraySize = info->imageArraySize;
484 img_info.samples = 1;
485 img_info.tiling = VK_IMAGE_TILING_OPTIMAL;
486 img_info.usage = info->imageUsageFlags;
487 img_info.flags = 0;
488
Ian Elliott4f299362015-07-06 14:45:11 -0600489 for (i = 0; i < info->minImageCount; i++) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800490 images[i] = x11_swap_chain_create_persistent_image(sc,
491 dev, &img_info);
492 if (!images[i])
493 break;
Ian Elliott4f299362015-07-06 14:45:11 -0600494 image_state[i] = INTEL_SC_STATE_UNUSED;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800495 }
496
Ian Elliott4f299362015-07-06 14:45:11 -0600497 if (i < info->minImageCount) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800498 uint32_t j;
499 for (j = 0; j < i; j++)
Ian Elliott4f299362015-07-06 14:45:11 -0600500 intel_img_destroy(images[j]);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800501
502 intel_free(sc, images);
503
Ian Elliott4f299362015-07-06 14:45:11 -0600504 if (image_state) {
505 intel_free(sc, image_state);
506 }
507
508 if (present_queue) {
509 intel_free(sc, present_queue);
510 }
511
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800512 return false;
513 }
514
515 sc->persistent_images = images;
Ian Elliott4f299362015-07-06 14:45:11 -0600516 sc->persistent_image_count = info->minImageCount;
517 sc->image_state = image_state;
518 sc->present_queue = present_queue;
519 sc->present_queue_length = 0;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800520
521 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800522}
523
524/**
525 * Send a PresentPixmap.
526 */
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600527static VkResult x11_swap_chain_present_pixmap(struct intel_x11_swap_chain *sc,
Ian Elliott4f299362015-07-06 14:45:11 -0600528 struct intel_img *img)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800529{
Chia-I Wu41858c82015-04-04 16:39:25 +0800530 struct intel_x11_img_data *data =
531 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800532 uint32_t options = XCB_PRESENT_OPTION_NONE;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800533 uint32_t target_msc, divisor, remainder;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800534 xcb_void_cookie_t cookie;
535 xcb_generic_error_t *err;
536
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800537 target_msc = 0;
Ian Elliott4f299362015-07-06 14:45:11 -0600538 divisor = 1;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800539 remainder = 0;
Ian Elliott338dedb2015-08-21 15:09:33 -0600540 if (sc->present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR) {
Chia-I Wu1db76e02014-09-15 14:21:14 +0800541 options |= XCB_PRESENT_OPTION_ASYNC;
Ian Elliott4f299362015-07-06 14:45:11 -0600542 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800543
544 if (sc->force_copy)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800545 options |= XCB_PRESENT_OPTION_COPY;
546
Chia-I Wuf689c602015-04-28 10:55:52 +0800547 cookie = xcb_present_pixmap_checked(sc->c,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800548 sc->window,
Chia-I Wu41858c82015-04-04 16:39:25 +0800549 data->pixmap,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800550 ++sc->local.serial,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800551 0, /* valid-area */
552 0, /* update-area */
553 0, /* x-off */
554 0, /* y-off */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800555 0, /* crtc */
Chia-I Wu1db76e02014-09-15 14:21:14 +0800556 0, /* wait-fence */
557 0, /* idle-fence */
558 options,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800559 target_msc,
560 divisor,
561 remainder,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800562 0, NULL);
563
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800564 err = xcb_request_check(sc->c, cookie);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600565 /* TODOVV: Can this be validated */
Chia-I Wu1db76e02014-09-15 14:21:14 +0800566 if (err) {
567 free(err);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600568 return VK_ERROR_INITIALIZATION_FAILED;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800569 }
570
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600571 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800572}
573
574/**
Chia-I Wu1db76e02014-09-15 14:21:14 +0800575 * Handle a Present event.
576 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800577static void x11_swap_chain_present_event(struct intel_x11_swap_chain *sc,
578 const xcb_present_generic_event_t *ev)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800579{
580 union {
581 const xcb_present_generic_event_t *ev;
582 const xcb_present_complete_notify_event_t *complete;
583 } u = { .ev = ev };
584
585 switch (u.ev->evtype) {
586 case XCB_PRESENT_COMPLETE_NOTIFY:
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800587 sc->remote.serial = u.complete->serial;
588 sc->remote.msc = u.complete->msc;
Ian Elliott4f299362015-07-06 14:45:11 -0600589 assert(sc->present_queue_length > 0);
590 if (sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_DISPLAYED) {
591 // Remove the previously-displayed image from the present queue:
592 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_UNUSED;
593 sc->present_queue_length--;
594 for (int j = 0; j < sc->present_queue_length; j++) {
595 sc->present_queue[j] = sc->present_queue[j+1];
596 }
597 }
598 assert(sc->present_queue_length > 0);
599 assert(sc->image_state[sc->present_queue[0]] == INTEL_SC_STATE_QUEUED_FOR_PRESENT);
600 sc->image_state[sc->present_queue[0]] = INTEL_SC_STATE_DISPLAYED;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800601 break;
602 default:
603 break;
604 }
605}
606
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600607/*
608 * Wait for an event on a swap chain.
609 * Uses polling because xcb_wait_for_special_event won't time out.
610 */
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600611static VkResult x11_swap_chain_wait(struct intel_x11_swap_chain *sc,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800612 uint32_t serial, int64_t timeout)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800613{
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600614 struct timespec current_time; // current time for planning wait
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600615 struct timespec stop_time; // time when timeout will elapse
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600616 bool wait;
617 if (timeout == 0){
618 wait = false;
619 } else {
620 wait = true;
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600621 clock_gettime(CLOCK_MONOTONIC, &current_time);
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600622 if (timeout == -1) {
623 // wait approximately forever
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600624 stop_time.tv_nsec = current_time.tv_nsec;
625 stop_time.tv_sec = current_time.tv_sec + 10*365*24*60*60;
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600626 } else {
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600627 stop_time.tv_nsec = current_time.tv_nsec + (timeout % 1000000000);
628 stop_time.tv_sec = current_time.tv_sec + (timeout / 1000000000);
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600629 // Carry overflow from tv_nsec to tv_sec
630 while (stop_time.tv_nsec > 1000000000) {
631 stop_time.tv_sec += 1;
632 stop_time.tv_nsec -= 1000000000;
633 }
634 }
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600635 }
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 Stroyanc8b6f822015-09-11 13:21:05 -0600644 int poll_timeout;
645 struct pollfd fds;
646
647 fds.fd = xcb_get_file_descriptor(sc->c);
648 fds.events = POLLIN;
649
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600650 while (!ev) {
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600651 clock_gettime(CLOCK_MONOTONIC, &current_time);
652 if (current_time.tv_sec > stop_time.tv_sec ||
653 (current_time.tv_sec == stop_time.tv_sec && current_time.tv_nsec > stop_time.tv_nsec)) {
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600654 // Time has run out
655 return VK_TIMEOUT;
656 }
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600657 poll_timeout = 1000/60; // milliseconds for 60 HZ
658 if (current_time.tv_sec >= stop_time.tv_sec-1) { // Remaining timeout may be under 1/60 seconds.
659 int remaining_timeout;
660 remaining_timeout = 1000 * (stop_time.tv_sec - current_time.tv_sec) + (stop_time.tv_nsec - current_time.tv_nsec) / 1000000;
661 if (poll_timeout > remaining_timeout) {
662 poll_timeout = remaining_timeout; // milliseconds for remainder of timeout
663 }
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600664 }
Mike Stroyanc8b6f822015-09-11 13:21:05 -0600665
666 // Wait for any input on the xcb connection or a timeout.
667 // Events may come in and be queued up before poll. Timing out handles that.
668 poll(&fds, 1, poll_timeout);
669
670 // Another thread may have handled events and updated sc->remote.serial
671 if (sc->remote.serial >= serial) {
672 return VK_SUCCESS;
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600673 }
Mike Stroyan4a387162015-04-27 15:42:41 -0600674
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600675 // Use xcb_intern_atom_reply just to make xcb really read events from socket.
676 // Calling xcb_poll_for_special_event fails to actually look for new packets.
677 reply = xcb_intern_atom_reply(sc->c, xcb_intern_atom(sc->c, 1, 1, "a"), NULL);
678 if (reply) {
679 free(reply);
680 }
681
682 ev = (xcb_present_generic_event_t *)
683 xcb_poll_for_special_event(sc->c, sc->present_special_event);
Mike Stroyan4a387162015-04-27 15:42:41 -0600684 }
Mike Stroyan2bf17bd2015-09-03 10:20:16 -0600685 } else {
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800686 if (!ev)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600687 return VK_NOT_READY;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800688 }
689
690 x11_swap_chain_present_event(sc, ev);
691
692 free(ev);
693 }
694
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600695 return VK_SUCCESS;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800696}
697
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800698static void x11_swap_chain_destroy(struct intel_x11_swap_chain *sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800699{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800700 if (sc->persistent_images) {
701 uint32_t i;
702
703 for (i = 0; i < sc->persistent_image_count; i++)
704 intel_img_destroy(sc->persistent_images[i]);
705 intel_free(sc, sc->persistent_images);
706 }
707
Ian Elliott4f299362015-07-06 14:45:11 -0600708 if (sc->image_state) {
709 intel_free(sc, sc->image_state);
710 }
711
712 if (sc->present_queue) {
713 intel_free(sc, sc->present_queue);
714 }
715
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800716 if (sc->present_special_event)
717 xcb_unregister_for_special_event(sc->c, sc->present_special_event);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800718
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800719 intel_free(sc, sc);
720}
721
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800722static VkResult x11_swap_chain_create(struct intel_dev *dev,
Ian Elliott338dedb2015-08-21 15:09:33 -0600723 const VkSwapchainCreateInfoKHR *info,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800724 struct intel_x11_swap_chain **sc_ret)
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800725{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800726 const xcb_randr_provider_t provider = 0;
Ian Elliott338dedb2015-08-21 15:09:33 -0600727 const VkSurfaceDescriptionWindowKHR* pSurfaceDescriptionWindow =
728 (VkSurfaceDescriptionWindowKHR*) info->pSurfaceDescription;
729 VkPlatformHandleXcbKHR *pPlatformHandleXcb = (VkPlatformHandleXcbKHR *)
Ian Elliott4f299362015-07-06 14:45:11 -0600730 pSurfaceDescriptionWindow->pPlatformHandle;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800731 xcb_connection_t *c = (xcb_connection_t *)
Ian Elliott4f299362015-07-06 14:45:11 -0600732 pPlatformHandleXcb->connection;
733 xcb_window_t window = *((xcb_window_t *)
734 pSurfaceDescriptionWindow->pPlatformWindow);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800735 struct intel_x11_swap_chain *sc;
736 int fd;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800737
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600738 /* TODOVV: Add test to validation layer */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800739 if (!x11_is_format_presentable(dev, info->imageFormat)) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600740 intel_dev_log(dev, VK_DBG_REPORT_ERROR_BIT,
741 VK_NULL_HANDLE, 0, 0, "invalid presentable image format");
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600742// return VK_ERROR_INVALID_VALUE;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600743 return VK_ERROR_VALIDATION_FAILED;
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800744 }
745
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600746 /* TODOVV: Can we add test to validation layer? */
747 if (!x11_is_dri3_and_present_supported(c)) {
748// return VK_ERROR_INVALID_VALUE;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600749 return VK_ERROR_VALIDATION_FAILED;
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600750 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800751
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600752 /* TODOVV: Can we add test to validation layer? */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800753 fd = x11_dri3_open(c, window, provider);
754 if (fd < 0 || !x11_gpu_match_fd(dev->gpu, fd)) {
Chia-I Wufcbc5252015-04-08 11:44:26 +0800755 if (fd >= 0)
756 close(fd);
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600757// return VK_ERROR_INVALID_VALUE;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600758 return VK_ERROR_VALIDATION_FAILED;
Chia-I Wufcbc5252015-04-08 11:44:26 +0800759 }
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800760
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800761 close(fd);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800762
Tony Barbour8205d902015-04-16 15:59:00 -0600763 sc = intel_alloc(dev, sizeof(*sc), 0, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800764 if (!sc)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800765 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800766
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800767 memset(sc, 0, sizeof(*sc));
Ian Elliott338dedb2015-08-21 15:09:33 -0600768 intel_handle_init(&sc->handle, VK_OBJECT_TYPE_SWAPCHAIN_KHR, dev->base.handle.instance);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800769
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800770 sc->c = c;
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800771 sc->window = window;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800772
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800773 /* always copy unless flip bit is set */
Ian Elliott4f299362015-07-06 14:45:11 -0600774 sc->present_mode = info->presentMode;
775 sc->force_copy = true;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800776
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800777 if (!x11_swap_chain_dri3_and_present_query_version(sc) ||
778 !x11_swap_chain_present_select_input(sc) ||
779 !x11_swap_chain_create_persistent_images(sc, dev, info)) {
780 x11_swap_chain_destroy(sc);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600781 return VK_ERROR_VALIDATION_FAILED;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800782 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800783
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800784 *sc_ret = sc;
Chia-I Wu41858c82015-04-04 16:39:25 +0800785
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600786 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800787}
788
Chia-I Wu8635e912015-04-09 14:13:57 +0800789static void x11_display_destroy(struct intel_x11_display *dpy)
790{
791 intel_free(dpy, dpy->modes);
792 intel_free(dpy, dpy);
793}
794
Chia-I Wu41858c82015-04-04 16:39:25 +0800795void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
796{
Chia-I Wu8635e912015-04-09 14:13:57 +0800797 if (gpu->displays) {
798 uint32_t i;
Chia-I Wu41858c82015-04-04 16:39:25 +0800799
Chia-I Wu8635e912015-04-09 14:13:57 +0800800 for (i = 0; i < gpu->display_count; i++) {
801 struct intel_x11_display *dpy =
802 (struct intel_x11_display *) gpu->displays[i];
803 x11_display_destroy(dpy);
804 }
805 intel_free(gpu, gpu->displays);
806 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800807}
808
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600809VkResult intel_wsi_img_init(struct intel_img *img)
Chia-I Wu41858c82015-04-04 16:39:25 +0800810{
811 struct intel_x11_img_data *data;
812
Tony Barbour8205d902015-04-16 15:59:00 -0600813 data = intel_alloc(img, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800814 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600815 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800816
817 memset(data, 0, sizeof(*data));
818
819 assert(!img->wsi_data);
820 img->wsi_data = data;
821
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600822 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800823}
824
825void intel_wsi_img_cleanup(struct intel_img *img)
826{
827 struct intel_x11_img_data *data =
828 (struct intel_x11_img_data *) img->wsi_data;
829
830 if (data->mem) {
831 close(data->prime_fd);
832 intel_mem_free(data->mem);
833 }
834
835 intel_free(img, img->wsi_data);
836}
837
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600838VkResult intel_wsi_fence_init(struct intel_fence *fence)
Chia-I Wu41858c82015-04-04 16:39:25 +0800839{
840 struct intel_x11_fence_data *data;
841
Tony Barbour8205d902015-04-16 15:59:00 -0600842 data = intel_alloc(fence, sizeof(*data), 0, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu41858c82015-04-04 16:39:25 +0800843 if (!data)
Tony Barbour8205d902015-04-16 15:59:00 -0600844 return VK_ERROR_OUT_OF_HOST_MEMORY;
Chia-I Wu41858c82015-04-04 16:39:25 +0800845
846 memset(data, 0, sizeof(*data));
847
848 assert(!fence->wsi_data);
849 fence->wsi_data = data;
850
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600851 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800852}
853
854void intel_wsi_fence_cleanup(struct intel_fence *fence)
855{
856 intel_free(fence, fence->wsi_data);
857}
858
859void intel_wsi_fence_copy(struct intel_fence *fence,
860 const struct intel_fence *src)
861{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600862 if (!fence->wsi_data) {
863 return;
864 }
Chia-I Wu41858c82015-04-04 16:39:25 +0800865 memcpy(fence->wsi_data, src->wsi_data,
866 sizeof(struct intel_x11_fence_data));
867}
868
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600869VkResult intel_wsi_fence_wait(struct intel_fence *fence,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800870 int64_t timeout_ns)
Chia-I Wu41858c82015-04-04 16:39:25 +0800871{
872 struct intel_x11_fence_data *data =
873 (struct intel_x11_fence_data *) fence->wsi_data;
874
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600875 if (!data)
876 return VK_SUCCESS;
877
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800878 if (!data->swap_chain)
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600879 return VK_SUCCESS;
Chia-I Wu41858c82015-04-04 16:39:25 +0800880
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800881 return x11_swap_chain_wait(data->swap_chain, data->serial, timeout_ns);
Chia-I Wu41858c82015-04-04 16:39:25 +0800882}
883
Ian Elliott338dedb2015-08-21 15:09:33 -0600884ICD_EXPORT VkResult VKAPI vkGetPhysicalDeviceSurfaceSupportKHR(
Ian Elliott4f299362015-07-06 14:45:11 -0600885 VkPhysicalDevice physicalDevice,
886 uint32_t queueNodeIndex,
Ian Elliott338dedb2015-08-21 15:09:33 -0600887 const VkSurfaceDescriptionKHR* pSurfaceDescription,
Ian Elliott4f299362015-07-06 14:45:11 -0600888 VkBool32* pSupported)
889{
890 VkResult ret = VK_SUCCESS;
Ian Elliott338dedb2015-08-21 15:09:33 -0600891 const VkSurfaceDescriptionWindowKHR* pSurfaceDescriptionWindow =
892 (VkSurfaceDescriptionWindowKHR*) pSurfaceDescription;
Ian Elliott4f299362015-07-06 14:45:11 -0600893
894 *pSupported = false;
895
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600896 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliott4f299362015-07-06 14:45:11 -0600897 // assume the correct data type, and not check):
Ian Elliott338dedb2015-08-21 15:09:33 -0600898 if (pSurfaceDescriptionWindow->sType != VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR) {
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600899 return VK_ERROR_VALIDATION_FAILED;
Ian Elliott4f299362015-07-06 14:45:11 -0600900 }
901
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600902 // TODOVV: NEED TO ALSO CHECK:
Ian Elliott4f299362015-07-06 14:45:11 -0600903 // - queueNodeIndex
904 // - pSurfaceDescriptionWindow->pPlatformHandle (can try to use it)
905 // - pSurfaceDescriptionWindow->pPlatformWindow (can try to use it)
Ian Elliott338dedb2015-08-21 15:09:33 -0600906 if (pSurfaceDescriptionWindow->platform == VK_PLATFORM_XCB_KHR) {
Ian Elliott4f299362015-07-06 14:45:11 -0600907 *pSupported = true;
908 }
909
910 return ret;
911}
912
Ian Elliott338dedb2015-08-21 15:09:33 -0600913VkResult VKAPI vkGetSurfacePropertiesKHR(
Ian Elliott4f299362015-07-06 14:45:11 -0600914 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -0600915 const VkSurfaceDescriptionKHR* pSurfaceDescription,
916 VkSurfacePropertiesKHR* pSurfaceProperties)
Ian Elliottebda9892015-08-06 17:35:06 -0600917{
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600918 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliottebda9892015-08-06 17:35:06 -0600919 // assume the correct data type, and not check):
920 assert(pSurfaceProperties);
921
922 return x11_get_surface_properties(pSurfaceDescription, pSurfaceProperties);
923}
924
Ian Elliott338dedb2015-08-21 15:09:33 -0600925VkResult VKAPI vkGetSurfaceFormatsKHR(
Ian Elliottebda9892015-08-06 17:35:06 -0600926 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -0600927 const VkSurfaceDescriptionKHR* pSurfaceDescription,
Ian Elliottebda9892015-08-06 17:35:06 -0600928 uint32_t* pCount,
Ian Elliott338dedb2015-08-21 15:09:33 -0600929 VkSurfaceFormatKHR* pSurfaceFormats)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800930{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800931 VkResult ret = VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800932
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600933 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliott4f299362015-07-06 14:45:11 -0600934 // assume the correct data type, and not check):
Ian Elliottebda9892015-08-06 17:35:06 -0600935 if (!pCount) {
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600936// return VK_ERROR_INVALID_POINTER;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600937 return VK_ERROR_VALIDATION_FAILED;
Ian Elliott4f299362015-07-06 14:45:11 -0600938 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800939
Ian Elliottebda9892015-08-06 17:35:06 -0600940 if (pSurfaceFormats) {
941 uint32_t i;
942 for (i = 0; i < *pCount; i++) {
943 pSurfaceFormats[i].format = x11_presentable_formats[i];
Ian Elliott338dedb2015-08-21 15:09:33 -0600944 pSurfaceFormats[i].colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
Ian Elliott4f299362015-07-06 14:45:11 -0600945 }
Ian Elliotte1ea6712015-08-19 16:49:46 -0600946 } else {
947 *pCount = ARRAY_SIZE(x11_presentable_formats);
Ian Elliottebda9892015-08-06 17:35:06 -0600948 }
949
950 return ret;
951}
952
Ian Elliott338dedb2015-08-21 15:09:33 -0600953VkResult VKAPI vkGetSurfacePresentModesKHR(
Ian Elliottebda9892015-08-06 17:35:06 -0600954 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -0600955 const VkSurfaceDescriptionKHR* pSurfaceDescription,
Ian Elliottebda9892015-08-06 17:35:06 -0600956 uint32_t* pCount,
Ian Elliott338dedb2015-08-21 15:09:33 -0600957 VkPresentModeKHR* pPresentModes)
Ian Elliottebda9892015-08-06 17:35:06 -0600958{
959 VkResult ret = VK_SUCCESS;
960
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600961 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliottebda9892015-08-06 17:35:06 -0600962 // assume the correct data type, and not check):
963 if (!pCount) {
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -0600964// return VK_ERROR_INVALID_POINTER;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600965 return VK_ERROR_VALIDATION_FAILED;
Ian Elliottebda9892015-08-06 17:35:06 -0600966 }
967
Ian Elliottebda9892015-08-06 17:35:06 -0600968 if (pPresentModes) {
Ian Elliott338dedb2015-08-21 15:09:33 -0600969 pPresentModes[0] = VK_PRESENT_MODE_IMMEDIATE_KHR;
970 pPresentModes[1] = VK_PRESENT_MODE_FIFO_KHR;
971 // TODO: Consider adding VK_PRESENT_MODE_MAILBOX_KHR sometime
Ian Elliotte1ea6712015-08-19 16:49:46 -0600972 } else {
973 *pCount = 2;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800974 }
975
976 return ret;
977}
978
Ian Elliott338dedb2015-08-21 15:09:33 -0600979ICD_EXPORT VkResult VKAPI vkCreateSwapchainKHR(
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800980 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -0600981 const VkSwapchainCreateInfoKHR* pCreateInfo,
982 VkSwapchainKHR* pSwapchain)
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800983{
984 struct intel_dev *dev = intel_dev(device);
985
Ian Elliott338dedb2015-08-21 15:09:33 -0600986 if (pCreateInfo->oldSwapchain.handle) {
Ian Elliott4f299362015-07-06 14:45:11 -0600987 // TODO: Eventually, do more than simply up-front destroy the
Ian Elliott338dedb2015-08-21 15:09:33 -0600988 // oldSwapchain (but just do that for now):
Ian Elliott4f299362015-07-06 14:45:11 -0600989 struct intel_x11_swap_chain *sc =
Ian Elliott338dedb2015-08-21 15:09:33 -0600990 x11_swap_chain(pCreateInfo->oldSwapchain);
Ian Elliott4f299362015-07-06 14:45:11 -0600991
992 x11_swap_chain_destroy(sc);
993 }
994
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800995 return x11_swap_chain_create(dev, pCreateInfo,
Ian Elliott338dedb2015-08-21 15:09:33 -0600996 (struct intel_x11_swap_chain **) pSwapchain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800997}
998
Ian Elliott338dedb2015-08-21 15:09:33 -0600999ICD_EXPORT VkResult VKAPI vkDestroySwapchainKHR(
Ian Elliott4f299362015-07-06 14:45:11 -06001000 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -06001001 VkSwapchainKHR swapchain)
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001002{
Ian Elliott338dedb2015-08-21 15:09:33 -06001003 struct intel_x11_swap_chain *sc = x11_swap_chain(swapchain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001004
1005 x11_swap_chain_destroy(sc);
1006
1007 return VK_SUCCESS;
1008}
1009
Ian Elliott338dedb2015-08-21 15:09:33 -06001010ICD_EXPORT VkResult VKAPI vkGetSwapchainImagesKHR(
Ian Elliott4f299362015-07-06 14:45:11 -06001011 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -06001012 VkSwapchainKHR swapchain,
Ian Elliottebda9892015-08-06 17:35:06 -06001013 uint32_t* pCount,
Ian Elliott338dedb2015-08-21 15:09:33 -06001014 VkImage* pSwapchainImages)
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001015{
Ian Elliott338dedb2015-08-21 15:09:33 -06001016 struct intel_x11_swap_chain *sc = x11_swap_chain(swapchain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001017 VkResult ret = VK_SUCCESS;
1018
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -06001019 // TODOVV: Move this check to a validation layer (i.e. the driver should
Ian Elliott4f299362015-07-06 14:45:11 -06001020 // assume the correct data type, and not check):
Ian Elliottebda9892015-08-06 17:35:06 -06001021 if (!pCount) {
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -06001022// return VK_ERROR_INVALID_POINTER;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06001023 return VK_ERROR_VALIDATION_FAILED;
Ian Elliott4f299362015-07-06 14:45:11 -06001024 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001025
Ian Elliott338dedb2015-08-21 15:09:33 -06001026 if (pSwapchainImages) {
Ian Elliottebda9892015-08-06 17:35:06 -06001027 uint32_t i;
Ian Elliotte1ea6712015-08-19 16:49:46 -06001028 for (i = 0; i < *pCount; i++) {
Ian Elliott338dedb2015-08-21 15:09:33 -06001029 pSwapchainImages[i].handle = (uint64_t) sc->persistent_images[i];
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001030 }
Ian Elliotte1ea6712015-08-19 16:49:46 -06001031 } else {
1032 *pCount = sc->persistent_image_count;
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001033 }
1034
1035 return ret;
1036}
1037
Ian Elliott338dedb2015-08-21 15:09:33 -06001038ICD_EXPORT VkResult VKAPI vkAcquireNextImageKHR(
Ian Elliott4f299362015-07-06 14:45:11 -06001039 VkDevice device,
Ian Elliott338dedb2015-08-21 15:09:33 -06001040 VkSwapchainKHR swapchain,
Ian Elliott4f299362015-07-06 14:45:11 -06001041 uint64_t timeout,
1042 VkSemaphore semaphore,
1043 uint32_t* pImageIndex)
1044{
Ian Elliott338dedb2015-08-21 15:09:33 -06001045 struct intel_x11_swap_chain *sc = x11_swap_chain(swapchain);
Ian Elliott4f299362015-07-06 14:45:11 -06001046 VkResult ret = VK_SUCCESS;
1047
Ian Elliott4f299362015-07-06 14:45:11 -06001048 // Find an unused image to return:
1049 for (int i = 0; i < sc->persistent_image_count; i++) {
1050 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
1051 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
1052 *pImageIndex = i;
1053 return ret;
1054 }
1055 }
1056
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001057 // If no image is ready, wait for a present to finish
Mike Stroyanb28dd442015-09-03 10:22:15 -06001058 ret = x11_swap_chain_wait(sc, sc->remote.serial+1, timeout);
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001059 if (ret != VK_SUCCESS) {
1060 return ret;
1061 }
Ian Elliott4f299362015-07-06 14:45:11 -06001062
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001063 // Find an unused image to return:
1064 for (int i = 0; i < sc->persistent_image_count; i++) {
1065 if (sc->image_state[i] == INTEL_SC_STATE_UNUSED) {
1066 sc->image_state[i] = INTEL_SC_STATE_APP_OWNED;
1067 *pImageIndex = i;
1068 return ret;
1069 }
1070 }
1071 // NOTE: Should never get here, but in case we do, do something:
1072 assert(0);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06001073 return VK_ERROR_VALIDATION_FAILED;
Ian Elliott4f299362015-07-06 14:45:11 -06001074}
1075
1076
Ian Elliott338dedb2015-08-21 15:09:33 -06001077ICD_EXPORT VkResult VKAPI vkQueuePresentKHR(
Ian Elliott4f299362015-07-06 14:45:11 -06001078 VkQueue queue_,
Ian Elliott338dedb2015-08-21 15:09:33 -06001079 VkPresentInfoKHR* pPresentInfo)
Chia-I Wu1db76e02014-09-15 14:21:14 +08001080{
1081 struct intel_queue *queue = intel_queue(queue_);
Ian Elliott4f299362015-07-06 14:45:11 -06001082 uint32_t i;
Ian Elliott338dedb2015-08-21 15:09:33 -06001083 uint32_t num_swapchains = pPresentInfo->swapchainCount;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001084
Mike Stroyan12915ce2015-09-03 10:25:44 -06001085 // Wait for queue to idle before out-of-band xcb present operation.
1086 const VkResult r = intel_queue_wait(queue, -1);
1087 (void) r;
1088
Ian Elliott4f299362015-07-06 14:45:11 -06001089 for (i = 0; i < num_swapchains; i++) {
1090 struct intel_x11_swap_chain *sc =
Ian Elliott338dedb2015-08-21 15:09:33 -06001091 x11_swap_chain(pPresentInfo->swapchains[i]);
Ian Elliott4f299362015-07-06 14:45:11 -06001092 struct intel_img *img =
1093 sc->persistent_images[pPresentInfo->imageIndices[i]];
1094 struct intel_x11_fence_data *data =
1095 (struct intel_x11_fence_data *) queue->fence->wsi_data;
1096 VkResult ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001097
Ian Elliott4f299362015-07-06 14:45:11 -06001098 ret = x11_swap_chain_present_pixmap(sc, img);
1099 if (ret != VK_SUCCESS) {
1100 return ret;
1101 }
1102
1103 // Record the state change for this image, and add this image to the
1104 // present queue for the swap chain:
1105 sc->image_state[pPresentInfo->imageIndices[i]] =
1106 INTEL_SC_STATE_QUEUED_FOR_PRESENT;
1107 sc->present_queue[sc->present_queue_length++] =
1108 pPresentInfo->imageIndices[i];
1109
1110 data->swap_chain = sc;
1111 data->serial = sc->local.serial;
Mike Stroyanf9f6dd72015-07-28 11:00:50 -06001112 sc->present_serial = sc->local.serial;
Ian Elliott4f299362015-07-06 14:45:11 -06001113 intel_fence_set_seqno(queue->fence, img->obj.mem->bo);
1114 }
Chia-I Wubda4f622015-02-25 15:06:15 -07001115
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001116 return VK_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +08001117}