blob: a90ebd32d1d79d41e42876635f875b90a5d336dc [file] [log] [blame]
Chia-I Wu1db76e02014-09-15 14:21:14 +08001/*
2 * XGL
3 *
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>
26 */
27
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <xcb/xcb.h>
33#include <xcb/dri3.h>
34#include <xcb/present.h>
35
36#include "kmd/winsys.h"
37#include "dev.h"
38#include "fence.h"
39#include "gpu.h"
40#include "img.h"
41#include "mem.h"
42#include "queue.h"
Chia-I Wu41858c82015-04-04 16:39:25 +080043#include "wsi.h"
Chia-I Wu1db76e02014-09-15 14:21:14 +080044
Chia-I Wu6532d1d2015-04-04 22:16:45 +080045struct intel_x11_swap_chain {
46 struct intel_handle handle;
47
48 xcb_connection_t *c;
49 xcb_window_t window;
Chia-I Wu1db76e02014-09-15 14:21:14 +080050
51 xcb_present_event_t present_special_event_id;
52 xcb_special_event_t *present_special_event;
53
54 struct {
55 uint32_t serial;
56 } local;
57
58 struct {
59 uint32_t serial;
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -060060 uint64_t msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +080061 } remote;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +080062
Chia-I Wu6532d1d2015-04-04 22:16:45 +080063 struct intel_x11_swap_chain *next;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +080064};
65
66struct intel_wsi_x11 {
Chia-I Wu41858c82015-04-04 16:39:25 +080067 struct intel_handle handle;
68
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +080069 xcb_connection_t *c;
70 xcb_window_t root;
71 xcb_randr_provider_t provider;
72 int root_depth;
73
74 int dri3_major, dri3_minor;
75 int present_major, present_minor;
76
77 int fd;
78
Chia-I Wu6532d1d2015-04-04 22:16:45 +080079 struct intel_x11_swap_chain *swap_chains;
Chia-I Wu1db76e02014-09-15 14:21:14 +080080};
81
Chia-I Wu41858c82015-04-04 16:39:25 +080082struct intel_x11_img_data {
83 struct intel_mem *mem;
84 int prime_fd;
85 uint32_t pixmap;
86};
87
88struct intel_x11_fence_data {
Chia-I Wu6532d1d2015-04-04 22:16:45 +080089 struct intel_x11_swap_chain *swap_chain;
Chia-I Wu41858c82015-04-04 16:39:25 +080090 uint32_t serial;
91};
92
Chia-I Wudbbe6ea2015-04-08 10:30:57 +080093static bool wsi_x11_is_format_presentable(struct intel_wsi_x11 *x11,
94 struct intel_dev *dev,
95 XGL_FORMAT format)
96{
97 /* this is what DDX expects */
98 switch (format) {
99 case XGL_FMT_B5G6R5_UNORM:
100 case XGL_FMT_B8G8R8A8_UNORM:
101 case XGL_FMT_B8G8R8A8_SRGB:
102 return true;
103 default:
104 return false;
105 }
106}
107
Chia-I Wu030b2db2015-04-08 13:46:29 +0800108static int x11_export_prime_fd(struct intel_dev *dev,
109 struct intel_bo *bo,
110 const struct intel_layout *layout)
111{
112 struct intel_winsys_handle export;
113 enum intel_tiling_mode tiling;
114
115 export.type = INTEL_WINSYS_HANDLE_FD;
116
117 switch (layout->tiling) {
118 case GEN6_TILING_X:
119 tiling = INTEL_TILING_X;
120 break;
121 case GEN6_TILING_Y:
122 tiling = INTEL_TILING_Y;
123 break;
124 default:
125 assert(layout->tiling == GEN6_TILING_NONE);
126 tiling = INTEL_TILING_NONE;
127 break;
128 }
129
130 if (intel_bo_set_tiling(bo, tiling, layout->bo_stride))
131 return -1;
132
133 if (intel_winsys_export_handle(dev->winsys, bo, tiling,
134 layout->bo_stride, layout->bo_height, &export))
135 return -1;
136
137 return (int) export.handle;
138}
139
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800140/**
141 * Return true if x11->fd points to the primary or render node of the GPU.
142 */
143static bool wsi_x11_uses_gpu(const struct intel_wsi_x11 *x11,
144 const struct intel_gpu *gpu)
145{
146 struct stat x11_stat, gpu_stat;
147
148 if (fstat(x11->fd, &x11_stat))
149 return false;
150
151 /* is it the primary node? */
152 if (!stat(gpu->primary_node, &gpu_stat) &&
153 !memcmp(&x11_stat, &gpu_stat, sizeof(x11_stat)))
154 return true;
155
156 /* is it the render node? */
157 if (gpu->render_node && !stat(gpu->render_node, &gpu_stat) &&
158 !memcmp(&x11_stat, &gpu_stat, sizeof(x11_stat)))
159 return true;
160
161 return false;
162}
163
164/**
165 * Return the depth of the root window.
166 */
167static int wsi_x11_get_root_depth(struct intel_wsi_x11 *x11)
168{
169 const xcb_setup_t *setup;
170 xcb_screen_iterator_t iter;
171
172 setup = xcb_get_setup(x11->c);
173
174 iter = xcb_setup_roots_iterator(setup);
175 for (; iter.rem; xcb_screen_next(&iter)) {
176 if (iter.data->root == x11->root)
177 return iter.data->root_depth;
178 }
179
180 return 0;
181}
182
Chia-I Wu1db76e02014-09-15 14:21:14 +0800183/**
184 * Return true if DRI3 and Present are supported by the server.
185 */
Chia-I Wu41858c82015-04-04 16:39:25 +0800186static bool wsi_x11_has_dri3_and_present(struct intel_wsi_x11 *x11)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800187{
188 const xcb_query_extension_reply_t *ext;
189
Chia-I Wu41858c82015-04-04 16:39:25 +0800190 xcb_prefetch_extension_data(x11->c, &xcb_dri3_id);
191 xcb_prefetch_extension_data(x11->c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800192
Chia-I Wu41858c82015-04-04 16:39:25 +0800193 ext = xcb_get_extension_data(x11->c, &xcb_dri3_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800194 if (!ext || !ext->present)
195 return false;
196
Chia-I Wu41858c82015-04-04 16:39:25 +0800197 ext = xcb_get_extension_data(x11->c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800198 if (!ext || !ext->present)
199 return false;
200
201 return true;
202}
203
204/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800205 * Send a DRI3Open to get the server GPU fd.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800206 */
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800207static bool wsi_x11_dri3_open(struct intel_wsi_x11 *x11)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800208{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800209 xcb_dri3_open_cookie_t cookie;
210 xcb_dri3_open_reply_t *reply;
211 int fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800212
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800213 cookie = xcb_dri3_open(x11->c, x11->root, x11->provider);
214 reply = xcb_dri3_open_reply(x11->c, cookie, NULL);
215 if (!reply)
216 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800217
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800218 fd = (reply->nfd == 1) ? xcb_dri3_open_reply_fds(x11->c, reply)[0] : -1;
219 free(reply);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800220
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800221 if (fd < 0)
222 return false;
223
224 fcntl(fd, F_SETFD, FD_CLOEXEC);
225 x11->fd = fd;
226
227 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800228}
229
230/**
Chia-I Wu030b2db2015-04-08 13:46:29 +0800231 * Send a DRI3PixmapFromBuffer to create a pixmap from \p prime_fd.
232 */
233static xcb_pixmap_t x11_dri3_pixmap_from_buffer(xcb_connection_t *c,
234 xcb_drawable_t drawable,
235 uint8_t depth, int prime_fd,
236 const struct intel_layout *layout)
237{
238 xcb_pixmap_t pixmap;
239
240 pixmap = xcb_generate_id(c);
241
242 xcb_dri3_pixmap_from_buffer(c, pixmap, drawable,
243 layout->bo_stride * layout->bo_height,
244 layout->width0, layout->height0,
245 layout->bo_stride, depth,
246 layout->block_size * 8, prime_fd);
247
248 return pixmap;
249}
250
251/**
Chia-I Wu41858c82015-04-04 16:39:25 +0800252 * Send DRI3QueryVersion and PresentQueryVersion to query extension versions.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800253 */
Chia-I Wu41858c82015-04-04 16:39:25 +0800254static bool wsi_x11_dri3_and_present_query_version(struct intel_wsi_x11 *x11)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800255{
256 xcb_dri3_query_version_cookie_t dri3_cookie;
257 xcb_dri3_query_version_reply_t *dri3_reply;
258 xcb_present_query_version_cookie_t present_cookie;
259 xcb_present_query_version_reply_t *present_reply;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800260
Chia-I Wu41858c82015-04-04 16:39:25 +0800261 dri3_cookie = xcb_dri3_query_version(x11->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800262 XCB_DRI3_MAJOR_VERSION, XCB_DRI3_MINOR_VERSION);
Chia-I Wu41858c82015-04-04 16:39:25 +0800263 present_cookie = xcb_present_query_version(x11->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800264 XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION);
265
Chia-I Wu41858c82015-04-04 16:39:25 +0800266 dri3_reply = xcb_dri3_query_version_reply(x11->c, dri3_cookie, NULL);
267 if (!dri3_reply)
268 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800269
270 x11->dri3_major = dri3_reply->major_version;
271 x11->dri3_minor = dri3_reply->minor_version;
272 free(dri3_reply);
273
Chia-I Wu41858c82015-04-04 16:39:25 +0800274 present_reply = xcb_present_query_version_reply(x11->c, present_cookie, NULL);
275 if (!present_reply)
276 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800277
278 x11->present_major = present_reply->major_version;
279 x11->present_minor = present_reply->minor_version;
280 free(present_reply);
281
Chia-I Wu41858c82015-04-04 16:39:25 +0800282 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800283}
284
285/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800286 * Send a PresentSelectInput to select interested events.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800287 */
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800288static XGL_RESULT x11_swap_chain_present_select_input(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800289{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800290 xcb_void_cookie_t cookie;
291 xcb_generic_error_t *error;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800292
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800293 /* create the event queue */
294 sc->present_special_event_id = xcb_generate_id(sc->c);
295 sc->present_special_event = xcb_register_for_special_xge(sc->c,
296 &xcb_present_id, sc->present_special_event_id, NULL);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800297
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800298 cookie = xcb_present_select_input_checked(sc->c,
299 sc->present_special_event_id, sc->window,
300 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800301
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800302 error = xcb_request_check(sc->c, cookie);
303 if (error) {
304 free(error);
305 return XGL_ERROR_UNKNOWN;
306 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800307
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800308 return XGL_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800309}
310
Chia-I Wu1db76e02014-09-15 14:21:14 +0800311static XGL_RESULT wsi_x11_dri3_pixmap_from_buffer(struct intel_wsi_x11 *x11,
312 struct intel_dev *dev,
313 struct intel_img *img,
314 struct intel_mem *mem)
315{
Chia-I Wu41858c82015-04-04 16:39:25 +0800316 struct intel_x11_img_data *data =
317 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800318
Chia-I Wu030b2db2015-04-08 13:46:29 +0800319 data->prime_fd = x11_export_prime_fd(dev, mem->bo, &img->layout);
320 if (data->prime_fd < 0)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800321 return XGL_ERROR_UNKNOWN;
322
Chia-I Wu030b2db2015-04-08 13:46:29 +0800323 data->pixmap = x11_dri3_pixmap_from_buffer(x11->c, x11->root,
324 x11->root_depth, data->prime_fd, &img->layout);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800325
Chia-I Wu41858c82015-04-04 16:39:25 +0800326 data->mem = mem;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800327
328 return XGL_SUCCESS;
329}
330
331/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800332 * Create a presentable image.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800333 */
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800334static XGL_RESULT wsi_x11_img_create(struct intel_wsi_x11 *x11,
335 struct intel_dev *dev,
336 const XGL_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO *info,
337 struct intel_img **img_ret)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800338{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800339 XGL_IMAGE_CREATE_INFO img_info;
340 XGL_MEMORY_ALLOC_INFO mem_info;
341 struct intel_img *img;
342 struct intel_mem *mem;
343 XGL_RESULT ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800344
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800345 if (!wsi_x11_is_format_presentable(x11, dev, info->format)) {
346 intel_dev_log(dev, XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0,
347 XGL_NULL_HANDLE, 0, 0, "invalid presentable image format");
348 return XGL_ERROR_INVALID_VALUE;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800349 }
350
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800351 /* create image */
352 memset(&img_info, 0, sizeof(img_info));
353 img_info.sType = XGL_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
354 img_info.imageType = XGL_IMAGE_2D;
355 img_info.format = info->format;
356 img_info.extent.width = info->extent.width;
357 img_info.extent.height = info->extent.height;
358 img_info.extent.depth = 1;
359 img_info.mipLevels = 1;
360 img_info.arraySize = 1;
361 img_info.samples = 1;
362 img_info.tiling = XGL_OPTIMAL_TILING;
363 img_info.usage = info->usage;
364 img_info.flags = 0;
365
366 ret = intel_img_create(dev, &img_info, true, &img);
367 if (ret != XGL_SUCCESS)
368 return ret;
369
370 /* allocate memory */
371 memset(&mem_info, 0, sizeof(mem_info));
372 mem_info.sType = XGL_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
373 mem_info.allocationSize = img->total_size;
374 mem_info.memProps = 0;
375 mem_info.memType = XGL_MEMORY_TYPE_IMAGE;
376 mem_info.memPriority = XGL_MEMORY_PRIORITY_HIGH;
377
378 ret = intel_mem_alloc(dev, &mem_info, &mem);
379 if (ret != XGL_SUCCESS) {
380 intel_img_destroy(img);
381 return ret;
382 }
383
384 ret = wsi_x11_dri3_pixmap_from_buffer(x11, dev, img, mem);
385 if (ret != XGL_SUCCESS) {
386 intel_mem_free(mem);
387 intel_img_destroy(img);
388 return ret;
389 }
390
391 intel_obj_bind_mem(&img->obj, mem, 0);
392
393 *img_ret = img;
394
Chia-I Wu1db76e02014-09-15 14:21:14 +0800395 return XGL_SUCCESS;
396}
397
398/**
399 * Send a PresentPixmap.
400 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800401static XGL_RESULT x11_swap_chain_present_pixmap(struct intel_x11_swap_chain *sc,
402 const XGL_WSI_X11_PRESENT_INFO *info)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800403{
404 struct intel_img *img = intel_img(info->srcImage);
Chia-I Wu41858c82015-04-04 16:39:25 +0800405 struct intel_x11_img_data *data =
406 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800407 uint32_t options = XCB_PRESENT_OPTION_NONE;
408 xcb_void_cookie_t cookie;
409 xcb_generic_error_t *err;
410
411 if (info->async)
412 options |= XCB_PRESENT_OPTION_ASYNC;
413 if (!info->flip)
414 options |= XCB_PRESENT_OPTION_COPY;
415
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800416 cookie = xcb_present_pixmap(sc->c,
417 sc->window,
Chia-I Wu41858c82015-04-04 16:39:25 +0800418 data->pixmap,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800419 ++sc->local.serial,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800420 0, /* valid-area */
421 0, /* update-area */
422 0, /* x-off */
423 0, /* y-off */
424 info->crtc,
425 0, /* wait-fence */
426 0, /* idle-fence */
427 options,
428 info->target_msc,
429 info->divisor,
430 info->remainder,
431 0, NULL);
432
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800433 err = xcb_request_check(sc->c, cookie);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800434 if (err) {
435 free(err);
436 return XGL_ERROR_UNKNOWN;
437 }
438
439 return XGL_SUCCESS;
440}
441
442/**
443 * Send a PresentNotifyMSC for the current MSC.
444 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800445static void x11_swap_chain_present_notify_msc(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800446{
447 /* cannot specify CRTC? */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800448 xcb_present_notify_msc(sc->c, sc->window, ++sc->local.serial, 0, 0, 0);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800449
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800450 xcb_flush(sc->c);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800451}
452
453/**
454 * Handle a Present event.
455 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800456static void x11_swap_chain_present_event(struct intel_x11_swap_chain *sc,
457 const xcb_present_generic_event_t *ev)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800458{
459 union {
460 const xcb_present_generic_event_t *ev;
461 const xcb_present_complete_notify_event_t *complete;
462 } u = { .ev = ev };
463
464 switch (u.ev->evtype) {
465 case XCB_PRESENT_COMPLETE_NOTIFY:
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800466 sc->remote.serial = u.complete->serial;
467 sc->remote.msc = u.complete->msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800468 break;
469 default:
470 break;
471 }
472}
473
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800474static XGL_RESULT x11_swap_chain_wait(struct intel_x11_swap_chain *sc,
475 uint32_t serial, int64_t timeout)
476{
477 const bool wait = (timeout != 0);
478
479 while (sc->remote.serial < serial) {
480 xcb_present_generic_event_t *ev;
481
482 if (wait) {
483 ev = (xcb_present_generic_event_t *)
484 xcb_wait_for_special_event(sc->c, sc->present_special_event);
485 if (!ev)
486 return XGL_ERROR_UNKNOWN;
487 } else {
488 ev = (xcb_present_generic_event_t *)
489 xcb_poll_for_special_event(sc->c, sc->present_special_event);
490 if (!ev)
491 return XGL_NOT_READY;
492 }
493
494 x11_swap_chain_present_event(sc, ev);
495
496 free(ev);
497 }
498
499 return XGL_SUCCESS;
500}
501
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800502static void x11_swap_chain_destroy(struct intel_x11_swap_chain *sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800503{
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800504 if (sc->present_special_event)
505 xcb_unregister_for_special_event(sc->c, sc->present_special_event);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800506
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800507 intel_free(sc, sc);
508}
509
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800510static void wsi_x11_destroy(struct intel_wsi_x11 *x11)
511{
512 struct intel_x11_swap_chain *sc = x11->swap_chains;
513
514 while (sc) {
515 struct intel_x11_swap_chain *next = sc->next;
516 x11_swap_chain_destroy(sc);
517 sc = next;
518 }
519
520 if (x11->fd >= 0)
521 close(x11->fd);
522
523 intel_free(x11, x11);
524}
525
526static struct intel_wsi_x11 *wsi_x11_create(struct intel_gpu *gpu,
527 const XGL_WSI_X11_CONNECTION_INFO *info)
528{
529 struct intel_wsi_x11 *x11;
530
531 x11 = intel_alloc(gpu, sizeof(*x11), 0, XGL_SYSTEM_ALLOC_API_OBJECT);
532 if (!x11)
533 return NULL;
534
535 memset(x11, 0, sizeof(*x11));
536 /* there is no XGL_DBG_OBJECT_WSI_DISPLAY */
537 intel_handle_init(&x11->handle, XGL_DBG_OBJECT_UNKNOWN, gpu->handle.icd);
538 x11->fd = -1;
539
540 x11->c = info->pConnection;
541 x11->root = info->root;
542 x11->provider = info->provider;
543
544 x11->root_depth = wsi_x11_get_root_depth(x11);
545
546 if (!wsi_x11_has_dri3_and_present(x11) ||
547 !wsi_x11_dri3_and_present_query_version(x11) ||
548 !wsi_x11_dri3_open(x11) ||
549 !wsi_x11_uses_gpu(x11, gpu)) {
550 wsi_x11_destroy(x11);
551 return NULL;
552 }
553
554 return x11;
555}
556
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800557static struct intel_x11_swap_chain *x11_swap_chain_create(struct intel_dev *dev,
558 xcb_window_t window)
559{
560 struct intel_wsi_x11 *x11 = (struct intel_wsi_x11 *) dev->gpu->wsi_data;
561 struct intel_x11_swap_chain *sc;
562
563 sc = intel_alloc(dev, sizeof(*sc), 0, XGL_SYSTEM_ALLOC_API_OBJECT);
564 if (!sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800565 return NULL;
566
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800567 memset(sc, 0, sizeof(*sc));
568 /* there is no XGL_DBG_OBJECT_WSI_SWAP_CHAIN */
569 intel_handle_init(&sc->handle, XGL_DBG_OBJECT_UNKNOWN,
570 dev->base.handle.icd);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800571
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800572 sc->c = x11->c;
573 sc->window = window;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800574
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800575 if (x11_swap_chain_present_select_input(sc) != XGL_SUCCESS) {
576 intel_free(dev, sc);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800577 return NULL;
578 }
579
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800580 return sc;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800581}
582
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800583static struct intel_x11_swap_chain *x11_swap_chain_lookup(struct intel_dev *dev,
584 xcb_window_t window)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800585{
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800586 struct intel_wsi_x11 *x11 = (struct intel_wsi_x11 *) dev->gpu->wsi_data;
587 struct intel_x11_swap_chain *sc = x11->swap_chains;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800588
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800589 while (sc) {
590 if (sc->window == window)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800591 break;
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800592 sc = sc->next;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800593 }
594
595 /* lookup failed */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800596 if (!sc) {
597 sc = x11_swap_chain_create(dev, window);
598 if (sc) {
599 sc->next = x11->swap_chains;
600 x11->swap_chains = sc;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800601 }
602 }
603
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800604 return sc;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800605}
606
Chia-I Wu41858c82015-04-04 16:39:25 +0800607static XGL_RESULT intel_wsi_gpu_init(struct intel_gpu *gpu,
608 const XGL_WSI_X11_CONNECTION_INFO *info)
609{
610 struct intel_wsi_x11 *x11;
611
612 x11 = wsi_x11_create(gpu, info);
613 if (!x11)
614 return XGL_ERROR_UNKNOWN;
615
616 gpu->wsi_data = x11;
617
618 return XGL_SUCCESS;
619}
620
621XGL_RESULT intel_wsi_gpu_get_info(struct intel_gpu *gpu,
622 XGL_PHYSICAL_GPU_INFO_TYPE type,
623 size_t *size, void *data)
624{
625 return XGL_ERROR_INVALID_VALUE;
626}
627
628void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
629{
630 struct intel_wsi_x11 *x11 = (struct intel_wsi_x11 *) gpu->wsi_data;
631
632 wsi_x11_destroy(x11);
633}
634
635XGL_RESULT intel_wsi_img_init(struct intel_img *img)
636{
637 struct intel_x11_img_data *data;
638
639 data = intel_alloc(img, sizeof(*data), 0, XGL_SYSTEM_ALLOC_INTERNAL);
640 if (!data)
641 return XGL_ERROR_OUT_OF_MEMORY;
642
643 memset(data, 0, sizeof(*data));
644
645 assert(!img->wsi_data);
646 img->wsi_data = data;
647
648 return XGL_SUCCESS;
649}
650
651void intel_wsi_img_cleanup(struct intel_img *img)
652{
653 struct intel_x11_img_data *data =
654 (struct intel_x11_img_data *) img->wsi_data;
655
656 if (data->mem) {
657 close(data->prime_fd);
658 intel_mem_free(data->mem);
659 }
660
661 intel_free(img, img->wsi_data);
662}
663
664XGL_RESULT intel_wsi_fence_init(struct intel_fence *fence)
665{
666 struct intel_x11_fence_data *data;
667
668 data = intel_alloc(fence, sizeof(*data), 0, XGL_SYSTEM_ALLOC_INTERNAL);
669 if (!data)
670 return XGL_ERROR_OUT_OF_MEMORY;
671
672 memset(data, 0, sizeof(*data));
673
674 assert(!fence->wsi_data);
675 fence->wsi_data = data;
676
677 return XGL_SUCCESS;
678}
679
680void intel_wsi_fence_cleanup(struct intel_fence *fence)
681{
682 intel_free(fence, fence->wsi_data);
683}
684
685void intel_wsi_fence_copy(struct intel_fence *fence,
686 const struct intel_fence *src)
687{
688 memcpy(fence->wsi_data, src->wsi_data,
689 sizeof(struct intel_x11_fence_data));
690}
691
692XGL_RESULT intel_wsi_fence_wait(struct intel_fence *fence,
693 int64_t timeout_ns)
694{
695 struct intel_x11_fence_data *data =
696 (struct intel_x11_fence_data *) fence->wsi_data;
697
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800698 if (!data->swap_chain)
Chia-I Wu41858c82015-04-04 16:39:25 +0800699 return XGL_SUCCESS;
700
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800701 return x11_swap_chain_wait(data->swap_chain, data->serial, timeout_ns);
Chia-I Wu41858c82015-04-04 16:39:25 +0800702}
703
Chia-I Wu96177272015-01-03 15:27:41 +0800704ICD_EXPORT XGL_RESULT XGLAPI xglWsiX11AssociateConnection(
Chia-I Wu1db76e02014-09-15 14:21:14 +0800705 XGL_PHYSICAL_GPU gpu_,
706 const XGL_WSI_X11_CONNECTION_INFO* pConnectionInfo)
707{
708 struct intel_gpu *gpu = intel_gpu(gpu_);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800709
Chia-I Wu41858c82015-04-04 16:39:25 +0800710 return intel_wsi_gpu_init(gpu, pConnectionInfo);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800711}
712
Chia-I Wu96177272015-01-03 15:27:41 +0800713ICD_EXPORT XGL_RESULT XGLAPI xglWsiX11GetMSC(
Chia-I Wu1db76e02014-09-15 14:21:14 +0800714 XGL_DEVICE device,
Chia-I Wu6204f342014-11-07 13:33:45 +0800715 xcb_window_t window,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800716 xcb_randr_crtc_t crtc,
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600717 uint64_t * pMsc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800718{
719 struct intel_dev *dev = intel_dev(device);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800720 struct intel_x11_swap_chain *sc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800721 XGL_RESULT ret;
722
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800723 sc = x11_swap_chain_lookup(dev, window);
724 if (!sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800725 return XGL_ERROR_UNKNOWN;
726
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800727 x11_swap_chain_present_notify_msc(sc);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800728
729 /* wait for the event */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800730 ret = x11_swap_chain_wait(sc, sc->local.serial, -1);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800731 if (ret != XGL_SUCCESS)
732 return ret;
733
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800734 *pMsc = sc->remote.msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800735
736 return XGL_SUCCESS;
737}
738
Chia-I Wu96177272015-01-03 15:27:41 +0800739ICD_EXPORT XGL_RESULT XGLAPI xglWsiX11CreatePresentableImage(
Chia-I Wu1db76e02014-09-15 14:21:14 +0800740 XGL_DEVICE device,
741 const XGL_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO* pCreateInfo,
742 XGL_IMAGE* pImage,
743 XGL_GPU_MEMORY* pMem)
744{
745 struct intel_dev *dev = intel_dev(device);
Chia-I Wu41858c82015-04-04 16:39:25 +0800746 struct intel_wsi_x11 *x11 = (struct intel_wsi_x11 *) dev->gpu->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800747 struct intel_img *img;
748 XGL_RESULT ret;
749
750 ret = wsi_x11_img_create(x11, dev, pCreateInfo, &img);
751 if (ret == XGL_SUCCESS) {
752 *pImage = (XGL_IMAGE) img;
753 *pMem = (XGL_GPU_MEMORY) img->obj.mem;
754 }
755
756 return ret;
757}
758
Chia-I Wu96177272015-01-03 15:27:41 +0800759ICD_EXPORT XGL_RESULT XGLAPI xglWsiX11QueuePresent(
Chia-I Wu1db76e02014-09-15 14:21:14 +0800760 XGL_QUEUE queue_,
761 const XGL_WSI_X11_PRESENT_INFO* pPresentInfo,
762 XGL_FENCE fence_)
763{
764 struct intel_queue *queue = intel_queue(queue_);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800765 struct intel_dev *dev = queue->dev;
Chia-I Wub56f5df2015-04-04 20:21:10 +0800766 struct intel_x11_fence_data *data =
767 (struct intel_x11_fence_data *) queue->fence->wsi_data;
768 struct intel_img *img = intel_img(pPresentInfo->srcImage);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800769 struct intel_x11_swap_chain *sc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800770 XGL_RESULT ret;
771
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800772 sc = x11_swap_chain_lookup(dev, pPresentInfo->destWindow);
773 if (!sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800774 return XGL_ERROR_UNKNOWN;
775
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800776 ret = x11_swap_chain_present_pixmap(sc, pPresentInfo);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800777 if (ret != XGL_SUCCESS)
778 return ret;
779
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800780 data->swap_chain = sc;
781 data->serial = sc->local.serial;
Chia-I Wub56f5df2015-04-04 20:21:10 +0800782 intel_fence_set_seqno(queue->fence, img->obj.mem->bo);
Chia-I Wubda4f622015-02-25 15:06:15 -0700783
Chia-I Wub56f5df2015-04-04 20:21:10 +0800784 if (fence_ != XGL_NULL_HANDLE) {
785 struct intel_fence *fence = intel_fence(fence_);
786 intel_fence_copy(fence, queue->fence);
Chia-I Wubda4f622015-02-25 15:06:15 -0700787 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800788
789 return XGL_SUCCESS;
790}