blob: b0fd7d8e6e1e2a7a343bf06b055d40b5a9969cf4 [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
108/**
109 * Return true if x11->fd points to the primary or render node of the GPU.
110 */
111static bool wsi_x11_uses_gpu(const struct intel_wsi_x11 *x11,
112 const struct intel_gpu *gpu)
113{
114 struct stat x11_stat, gpu_stat;
115
116 if (fstat(x11->fd, &x11_stat))
117 return false;
118
119 /* is it the primary node? */
120 if (!stat(gpu->primary_node, &gpu_stat) &&
121 !memcmp(&x11_stat, &gpu_stat, sizeof(x11_stat)))
122 return true;
123
124 /* is it the render node? */
125 if (gpu->render_node && !stat(gpu->render_node, &gpu_stat) &&
126 !memcmp(&x11_stat, &gpu_stat, sizeof(x11_stat)))
127 return true;
128
129 return false;
130}
131
132/**
133 * Return the depth of the root window.
134 */
135static int wsi_x11_get_root_depth(struct intel_wsi_x11 *x11)
136{
137 const xcb_setup_t *setup;
138 xcb_screen_iterator_t iter;
139
140 setup = xcb_get_setup(x11->c);
141
142 iter = xcb_setup_roots_iterator(setup);
143 for (; iter.rem; xcb_screen_next(&iter)) {
144 if (iter.data->root == x11->root)
145 return iter.data->root_depth;
146 }
147
148 return 0;
149}
150
Chia-I Wu1db76e02014-09-15 14:21:14 +0800151/**
152 * Return true if DRI3 and Present are supported by the server.
153 */
Chia-I Wu41858c82015-04-04 16:39:25 +0800154static bool wsi_x11_has_dri3_and_present(struct intel_wsi_x11 *x11)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800155{
156 const xcb_query_extension_reply_t *ext;
157
Chia-I Wu41858c82015-04-04 16:39:25 +0800158 xcb_prefetch_extension_data(x11->c, &xcb_dri3_id);
159 xcb_prefetch_extension_data(x11->c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800160
Chia-I Wu41858c82015-04-04 16:39:25 +0800161 ext = xcb_get_extension_data(x11->c, &xcb_dri3_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800162 if (!ext || !ext->present)
163 return false;
164
Chia-I Wu41858c82015-04-04 16:39:25 +0800165 ext = xcb_get_extension_data(x11->c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800166 if (!ext || !ext->present)
167 return false;
168
169 return true;
170}
171
172/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800173 * Send a DRI3Open to get the server GPU fd.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800174 */
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800175static bool wsi_x11_dri3_open(struct intel_wsi_x11 *x11)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800176{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800177 xcb_dri3_open_cookie_t cookie;
178 xcb_dri3_open_reply_t *reply;
179 int fd;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800180
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800181 cookie = xcb_dri3_open(x11->c, x11->root, x11->provider);
182 reply = xcb_dri3_open_reply(x11->c, cookie, NULL);
183 if (!reply)
184 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800185
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800186 fd = (reply->nfd == 1) ? xcb_dri3_open_reply_fds(x11->c, reply)[0] : -1;
187 free(reply);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800188
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800189 if (fd < 0)
190 return false;
191
192 fcntl(fd, F_SETFD, FD_CLOEXEC);
193 x11->fd = fd;
194
195 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800196}
197
198/**
Chia-I Wu41858c82015-04-04 16:39:25 +0800199 * Send DRI3QueryVersion and PresentQueryVersion to query extension versions.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800200 */
Chia-I Wu41858c82015-04-04 16:39:25 +0800201static bool wsi_x11_dri3_and_present_query_version(struct intel_wsi_x11 *x11)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800202{
203 xcb_dri3_query_version_cookie_t dri3_cookie;
204 xcb_dri3_query_version_reply_t *dri3_reply;
205 xcb_present_query_version_cookie_t present_cookie;
206 xcb_present_query_version_reply_t *present_reply;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800207
Chia-I Wu41858c82015-04-04 16:39:25 +0800208 dri3_cookie = xcb_dri3_query_version(x11->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800209 XCB_DRI3_MAJOR_VERSION, XCB_DRI3_MINOR_VERSION);
Chia-I Wu41858c82015-04-04 16:39:25 +0800210 present_cookie = xcb_present_query_version(x11->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800211 XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION);
212
Chia-I Wu41858c82015-04-04 16:39:25 +0800213 dri3_reply = xcb_dri3_query_version_reply(x11->c, dri3_cookie, NULL);
214 if (!dri3_reply)
215 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800216
217 x11->dri3_major = dri3_reply->major_version;
218 x11->dri3_minor = dri3_reply->minor_version;
219 free(dri3_reply);
220
Chia-I Wu41858c82015-04-04 16:39:25 +0800221 present_reply = xcb_present_query_version_reply(x11->c, present_cookie, NULL);
222 if (!present_reply)
223 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800224
225 x11->present_major = present_reply->major_version;
226 x11->present_minor = present_reply->minor_version;
227 free(present_reply);
228
Chia-I Wu41858c82015-04-04 16:39:25 +0800229 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800230}
231
232/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800233 * Send a PresentSelectInput to select interested events.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800234 */
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800235static XGL_RESULT x11_swap_chain_present_select_input(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800236{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800237 xcb_void_cookie_t cookie;
238 xcb_generic_error_t *error;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800239
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800240 /* create the event queue */
241 sc->present_special_event_id = xcb_generate_id(sc->c);
242 sc->present_special_event = xcb_register_for_special_xge(sc->c,
243 &xcb_present_id, sc->present_special_event_id, NULL);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800244
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800245 cookie = xcb_present_select_input_checked(sc->c,
246 sc->present_special_event_id, sc->window,
247 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800248
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800249 error = xcb_request_check(sc->c, cookie);
250 if (error) {
251 free(error);
252 return XGL_ERROR_UNKNOWN;
253 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800254
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800255 return XGL_SUCCESS;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800256}
257
258/**
259 * Send a DRI3PixmapFromBuffer to create a Pixmap from \p mem for \p img.
260 */
261static XGL_RESULT wsi_x11_dri3_pixmap_from_buffer(struct intel_wsi_x11 *x11,
262 struct intel_dev *dev,
263 struct intel_img *img,
264 struct intel_mem *mem)
265{
Chia-I Wu41858c82015-04-04 16:39:25 +0800266 struct intel_x11_img_data *data =
267 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800268 struct intel_winsys_handle export;
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800269 enum intel_tiling_mode tiling;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800270 xcb_pixmap_t pixmap;
271
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800272 switch (img->layout.tiling) {
273 case GEN6_TILING_X:
274 tiling = INTEL_TILING_X;
275 break;
276 case GEN6_TILING_Y:
277 tiling = INTEL_TILING_Y;
278 break;
279 default:
280 assert(img->layout.tiling == GEN6_TILING_NONE);
281 tiling = INTEL_TILING_NONE;
282 break;
283 }
284
Chia-I Wu1db76e02014-09-15 14:21:14 +0800285 /* get prime fd of the bo first */
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800286 if (intel_bo_set_tiling(mem->bo, tiling, img->layout.bo_stride))
Chia-I Wu3d0f59c2015-03-07 06:00:46 +0800287 return XGL_ERROR_UNKNOWN;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800288 export.type = INTEL_WINSYS_HANDLE_FD;
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800289 if (intel_winsys_export_handle(dev->winsys, mem->bo, tiling,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800290 img->layout.bo_stride, img->layout.bo_height, &export))
291 return XGL_ERROR_UNKNOWN;
292
293 pixmap = xcb_generate_id(x11->c);
294
295 /* create a pixmap from the prime fd */
296 xcb_dri3_pixmap_from_buffer(x11->c, pixmap,
297 x11->root, img->total_size,
298 img->layout.width0, img->layout.height0,
299 img->layout.bo_stride, x11->root_depth,
300 img->layout.block_size * 8, export.handle);
301
Chia-I Wu41858c82015-04-04 16:39:25 +0800302 data->mem = mem;
303 data->prime_fd = export.handle;
304 data->pixmap = pixmap;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800305
306 return XGL_SUCCESS;
307}
308
309/**
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800310 * Create a presentable image.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800311 */
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800312static XGL_RESULT wsi_x11_img_create(struct intel_wsi_x11 *x11,
313 struct intel_dev *dev,
314 const XGL_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO *info,
315 struct intel_img **img_ret)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800316{
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800317 XGL_IMAGE_CREATE_INFO img_info;
318 XGL_MEMORY_ALLOC_INFO mem_info;
319 struct intel_img *img;
320 struct intel_mem *mem;
321 XGL_RESULT ret;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800322
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800323 if (!wsi_x11_is_format_presentable(x11, dev, info->format)) {
324 intel_dev_log(dev, XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0,
325 XGL_NULL_HANDLE, 0, 0, "invalid presentable image format");
326 return XGL_ERROR_INVALID_VALUE;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800327 }
328
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800329 /* create image */
330 memset(&img_info, 0, sizeof(img_info));
331 img_info.sType = XGL_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
332 img_info.imageType = XGL_IMAGE_2D;
333 img_info.format = info->format;
334 img_info.extent.width = info->extent.width;
335 img_info.extent.height = info->extent.height;
336 img_info.extent.depth = 1;
337 img_info.mipLevels = 1;
338 img_info.arraySize = 1;
339 img_info.samples = 1;
340 img_info.tiling = XGL_OPTIMAL_TILING;
341 img_info.usage = info->usage;
342 img_info.flags = 0;
343
344 ret = intel_img_create(dev, &img_info, true, &img);
345 if (ret != XGL_SUCCESS)
346 return ret;
347
348 /* allocate memory */
349 memset(&mem_info, 0, sizeof(mem_info));
350 mem_info.sType = XGL_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
351 mem_info.allocationSize = img->total_size;
352 mem_info.memProps = 0;
353 mem_info.memType = XGL_MEMORY_TYPE_IMAGE;
354 mem_info.memPriority = XGL_MEMORY_PRIORITY_HIGH;
355
356 ret = intel_mem_alloc(dev, &mem_info, &mem);
357 if (ret != XGL_SUCCESS) {
358 intel_img_destroy(img);
359 return ret;
360 }
361
362 ret = wsi_x11_dri3_pixmap_from_buffer(x11, dev, img, mem);
363 if (ret != XGL_SUCCESS) {
364 intel_mem_free(mem);
365 intel_img_destroy(img);
366 return ret;
367 }
368
369 intel_obj_bind_mem(&img->obj, mem, 0);
370
371 *img_ret = img;
372
Chia-I Wu1db76e02014-09-15 14:21:14 +0800373 return XGL_SUCCESS;
374}
375
376/**
377 * Send a PresentPixmap.
378 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800379static XGL_RESULT x11_swap_chain_present_pixmap(struct intel_x11_swap_chain *sc,
380 const XGL_WSI_X11_PRESENT_INFO *info)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800381{
382 struct intel_img *img = intel_img(info->srcImage);
Chia-I Wu41858c82015-04-04 16:39:25 +0800383 struct intel_x11_img_data *data =
384 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800385 uint32_t options = XCB_PRESENT_OPTION_NONE;
386 xcb_void_cookie_t cookie;
387 xcb_generic_error_t *err;
388
389 if (info->async)
390 options |= XCB_PRESENT_OPTION_ASYNC;
391 if (!info->flip)
392 options |= XCB_PRESENT_OPTION_COPY;
393
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800394 cookie = xcb_present_pixmap(sc->c,
395 sc->window,
Chia-I Wu41858c82015-04-04 16:39:25 +0800396 data->pixmap,
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800397 ++sc->local.serial,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800398 0, /* valid-area */
399 0, /* update-area */
400 0, /* x-off */
401 0, /* y-off */
402 info->crtc,
403 0, /* wait-fence */
404 0, /* idle-fence */
405 options,
406 info->target_msc,
407 info->divisor,
408 info->remainder,
409 0, NULL);
410
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800411 err = xcb_request_check(sc->c, cookie);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800412 if (err) {
413 free(err);
414 return XGL_ERROR_UNKNOWN;
415 }
416
417 return XGL_SUCCESS;
418}
419
420/**
421 * Send a PresentNotifyMSC for the current MSC.
422 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800423static void x11_swap_chain_present_notify_msc(struct intel_x11_swap_chain *sc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800424{
425 /* cannot specify CRTC? */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800426 xcb_present_notify_msc(sc->c, sc->window, ++sc->local.serial, 0, 0, 0);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800427
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800428 xcb_flush(sc->c);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800429}
430
431/**
432 * Handle a Present event.
433 */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800434static void x11_swap_chain_present_event(struct intel_x11_swap_chain *sc,
435 const xcb_present_generic_event_t *ev)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800436{
437 union {
438 const xcb_present_generic_event_t *ev;
439 const xcb_present_complete_notify_event_t *complete;
440 } u = { .ev = ev };
441
442 switch (u.ev->evtype) {
443 case XCB_PRESENT_COMPLETE_NOTIFY:
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800444 sc->remote.serial = u.complete->serial;
445 sc->remote.msc = u.complete->msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800446 break;
447 default:
448 break;
449 }
450}
451
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800452static XGL_RESULT x11_swap_chain_wait(struct intel_x11_swap_chain *sc,
453 uint32_t serial, int64_t timeout)
454{
455 const bool wait = (timeout != 0);
456
457 while (sc->remote.serial < serial) {
458 xcb_present_generic_event_t *ev;
459
460 if (wait) {
461 ev = (xcb_present_generic_event_t *)
462 xcb_wait_for_special_event(sc->c, sc->present_special_event);
463 if (!ev)
464 return XGL_ERROR_UNKNOWN;
465 } else {
466 ev = (xcb_present_generic_event_t *)
467 xcb_poll_for_special_event(sc->c, sc->present_special_event);
468 if (!ev)
469 return XGL_NOT_READY;
470 }
471
472 x11_swap_chain_present_event(sc, ev);
473
474 free(ev);
475 }
476
477 return XGL_SUCCESS;
478}
479
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800480static void x11_swap_chain_destroy(struct intel_x11_swap_chain *sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800481{
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800482 if (sc->present_special_event)
483 xcb_unregister_for_special_event(sc->c, sc->present_special_event);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800484
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800485 intel_free(sc, sc);
486}
487
Chia-I Wudbbe6ea2015-04-08 10:30:57 +0800488static void wsi_x11_destroy(struct intel_wsi_x11 *x11)
489{
490 struct intel_x11_swap_chain *sc = x11->swap_chains;
491
492 while (sc) {
493 struct intel_x11_swap_chain *next = sc->next;
494 x11_swap_chain_destroy(sc);
495 sc = next;
496 }
497
498 if (x11->fd >= 0)
499 close(x11->fd);
500
501 intel_free(x11, x11);
502}
503
504static struct intel_wsi_x11 *wsi_x11_create(struct intel_gpu *gpu,
505 const XGL_WSI_X11_CONNECTION_INFO *info)
506{
507 struct intel_wsi_x11 *x11;
508
509 x11 = intel_alloc(gpu, sizeof(*x11), 0, XGL_SYSTEM_ALLOC_API_OBJECT);
510 if (!x11)
511 return NULL;
512
513 memset(x11, 0, sizeof(*x11));
514 /* there is no XGL_DBG_OBJECT_WSI_DISPLAY */
515 intel_handle_init(&x11->handle, XGL_DBG_OBJECT_UNKNOWN, gpu->handle.icd);
516 x11->fd = -1;
517
518 x11->c = info->pConnection;
519 x11->root = info->root;
520 x11->provider = info->provider;
521
522 x11->root_depth = wsi_x11_get_root_depth(x11);
523
524 if (!wsi_x11_has_dri3_and_present(x11) ||
525 !wsi_x11_dri3_and_present_query_version(x11) ||
526 !wsi_x11_dri3_open(x11) ||
527 !wsi_x11_uses_gpu(x11, gpu)) {
528 wsi_x11_destroy(x11);
529 return NULL;
530 }
531
532 return x11;
533}
534
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800535static struct intel_x11_swap_chain *x11_swap_chain_create(struct intel_dev *dev,
536 xcb_window_t window)
537{
538 struct intel_wsi_x11 *x11 = (struct intel_wsi_x11 *) dev->gpu->wsi_data;
539 struct intel_x11_swap_chain *sc;
540
541 sc = intel_alloc(dev, sizeof(*sc), 0, XGL_SYSTEM_ALLOC_API_OBJECT);
542 if (!sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800543 return NULL;
544
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800545 memset(sc, 0, sizeof(*sc));
546 /* there is no XGL_DBG_OBJECT_WSI_SWAP_CHAIN */
547 intel_handle_init(&sc->handle, XGL_DBG_OBJECT_UNKNOWN,
548 dev->base.handle.icd);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800549
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800550 sc->c = x11->c;
551 sc->window = window;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800552
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800553 if (x11_swap_chain_present_select_input(sc) != XGL_SUCCESS) {
554 intel_free(dev, sc);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800555 return NULL;
556 }
557
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800558 return sc;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800559}
560
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800561static struct intel_x11_swap_chain *x11_swap_chain_lookup(struct intel_dev *dev,
562 xcb_window_t window)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800563{
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800564 struct intel_wsi_x11 *x11 = (struct intel_wsi_x11 *) dev->gpu->wsi_data;
565 struct intel_x11_swap_chain *sc = x11->swap_chains;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800566
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800567 while (sc) {
568 if (sc->window == window)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800569 break;
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800570 sc = sc->next;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800571 }
572
573 /* lookup failed */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800574 if (!sc) {
575 sc = x11_swap_chain_create(dev, window);
576 if (sc) {
577 sc->next = x11->swap_chains;
578 x11->swap_chains = sc;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800579 }
580 }
581
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800582 return sc;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800583}
584
Chia-I Wu41858c82015-04-04 16:39:25 +0800585static XGL_RESULT intel_wsi_gpu_init(struct intel_gpu *gpu,
586 const XGL_WSI_X11_CONNECTION_INFO *info)
587{
588 struct intel_wsi_x11 *x11;
589
590 x11 = wsi_x11_create(gpu, info);
591 if (!x11)
592 return XGL_ERROR_UNKNOWN;
593
594 gpu->wsi_data = x11;
595
596 return XGL_SUCCESS;
597}
598
599XGL_RESULT intel_wsi_gpu_get_info(struct intel_gpu *gpu,
600 XGL_PHYSICAL_GPU_INFO_TYPE type,
601 size_t *size, void *data)
602{
603 return XGL_ERROR_INVALID_VALUE;
604}
605
606void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
607{
608 struct intel_wsi_x11 *x11 = (struct intel_wsi_x11 *) gpu->wsi_data;
609
610 wsi_x11_destroy(x11);
611}
612
613XGL_RESULT intel_wsi_img_init(struct intel_img *img)
614{
615 struct intel_x11_img_data *data;
616
617 data = intel_alloc(img, sizeof(*data), 0, XGL_SYSTEM_ALLOC_INTERNAL);
618 if (!data)
619 return XGL_ERROR_OUT_OF_MEMORY;
620
621 memset(data, 0, sizeof(*data));
622
623 assert(!img->wsi_data);
624 img->wsi_data = data;
625
626 return XGL_SUCCESS;
627}
628
629void intel_wsi_img_cleanup(struct intel_img *img)
630{
631 struct intel_x11_img_data *data =
632 (struct intel_x11_img_data *) img->wsi_data;
633
634 if (data->mem) {
635 close(data->prime_fd);
636 intel_mem_free(data->mem);
637 }
638
639 intel_free(img, img->wsi_data);
640}
641
642XGL_RESULT intel_wsi_fence_init(struct intel_fence *fence)
643{
644 struct intel_x11_fence_data *data;
645
646 data = intel_alloc(fence, sizeof(*data), 0, XGL_SYSTEM_ALLOC_INTERNAL);
647 if (!data)
648 return XGL_ERROR_OUT_OF_MEMORY;
649
650 memset(data, 0, sizeof(*data));
651
652 assert(!fence->wsi_data);
653 fence->wsi_data = data;
654
655 return XGL_SUCCESS;
656}
657
658void intel_wsi_fence_cleanup(struct intel_fence *fence)
659{
660 intel_free(fence, fence->wsi_data);
661}
662
663void intel_wsi_fence_copy(struct intel_fence *fence,
664 const struct intel_fence *src)
665{
666 memcpy(fence->wsi_data, src->wsi_data,
667 sizeof(struct intel_x11_fence_data));
668}
669
670XGL_RESULT intel_wsi_fence_wait(struct intel_fence *fence,
671 int64_t timeout_ns)
672{
673 struct intel_x11_fence_data *data =
674 (struct intel_x11_fence_data *) fence->wsi_data;
675
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800676 if (!data->swap_chain)
Chia-I Wu41858c82015-04-04 16:39:25 +0800677 return XGL_SUCCESS;
678
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800679 return x11_swap_chain_wait(data->swap_chain, data->serial, timeout_ns);
Chia-I Wu41858c82015-04-04 16:39:25 +0800680}
681
Chia-I Wu96177272015-01-03 15:27:41 +0800682ICD_EXPORT XGL_RESULT XGLAPI xglWsiX11AssociateConnection(
Chia-I Wu1db76e02014-09-15 14:21:14 +0800683 XGL_PHYSICAL_GPU gpu_,
684 const XGL_WSI_X11_CONNECTION_INFO* pConnectionInfo)
685{
686 struct intel_gpu *gpu = intel_gpu(gpu_);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800687
Chia-I Wu41858c82015-04-04 16:39:25 +0800688 return intel_wsi_gpu_init(gpu, pConnectionInfo);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800689}
690
Chia-I Wu96177272015-01-03 15:27:41 +0800691ICD_EXPORT XGL_RESULT XGLAPI xglWsiX11GetMSC(
Chia-I Wu1db76e02014-09-15 14:21:14 +0800692 XGL_DEVICE device,
Chia-I Wu6204f342014-11-07 13:33:45 +0800693 xcb_window_t window,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800694 xcb_randr_crtc_t crtc,
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600695 uint64_t * pMsc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800696{
697 struct intel_dev *dev = intel_dev(device);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800698 struct intel_x11_swap_chain *sc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800699 XGL_RESULT ret;
700
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800701 sc = x11_swap_chain_lookup(dev, window);
702 if (!sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800703 return XGL_ERROR_UNKNOWN;
704
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800705 x11_swap_chain_present_notify_msc(sc);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800706
707 /* wait for the event */
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800708 ret = x11_swap_chain_wait(sc, sc->local.serial, -1);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800709 if (ret != XGL_SUCCESS)
710 return ret;
711
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800712 *pMsc = sc->remote.msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800713
714 return XGL_SUCCESS;
715}
716
Chia-I Wu96177272015-01-03 15:27:41 +0800717ICD_EXPORT XGL_RESULT XGLAPI xglWsiX11CreatePresentableImage(
Chia-I Wu1db76e02014-09-15 14:21:14 +0800718 XGL_DEVICE device,
719 const XGL_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO* pCreateInfo,
720 XGL_IMAGE* pImage,
721 XGL_GPU_MEMORY* pMem)
722{
723 struct intel_dev *dev = intel_dev(device);
Chia-I Wu41858c82015-04-04 16:39:25 +0800724 struct intel_wsi_x11 *x11 = (struct intel_wsi_x11 *) dev->gpu->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800725 struct intel_img *img;
726 XGL_RESULT ret;
727
728 ret = wsi_x11_img_create(x11, dev, pCreateInfo, &img);
729 if (ret == XGL_SUCCESS) {
730 *pImage = (XGL_IMAGE) img;
731 *pMem = (XGL_GPU_MEMORY) img->obj.mem;
732 }
733
734 return ret;
735}
736
Chia-I Wu96177272015-01-03 15:27:41 +0800737ICD_EXPORT XGL_RESULT XGLAPI xglWsiX11QueuePresent(
Chia-I Wu1db76e02014-09-15 14:21:14 +0800738 XGL_QUEUE queue_,
739 const XGL_WSI_X11_PRESENT_INFO* pPresentInfo,
740 XGL_FENCE fence_)
741{
742 struct intel_queue *queue = intel_queue(queue_);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800743 struct intel_dev *dev = queue->dev;
Chia-I Wub56f5df2015-04-04 20:21:10 +0800744 struct intel_x11_fence_data *data =
745 (struct intel_x11_fence_data *) queue->fence->wsi_data;
746 struct intel_img *img = intel_img(pPresentInfo->srcImage);
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800747 struct intel_x11_swap_chain *sc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800748 XGL_RESULT ret;
749
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800750 sc = x11_swap_chain_lookup(dev, pPresentInfo->destWindow);
751 if (!sc)
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800752 return XGL_ERROR_UNKNOWN;
753
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800754 ret = x11_swap_chain_present_pixmap(sc, pPresentInfo);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800755 if (ret != XGL_SUCCESS)
756 return ret;
757
Chia-I Wu6532d1d2015-04-04 22:16:45 +0800758 data->swap_chain = sc;
759 data->serial = sc->local.serial;
Chia-I Wub56f5df2015-04-04 20:21:10 +0800760 intel_fence_set_seqno(queue->fence, img->obj.mem->bo);
Chia-I Wubda4f622015-02-25 15:06:15 -0700761
Chia-I Wub56f5df2015-04-04 20:21:10 +0800762 if (fence_ != XGL_NULL_HANDLE) {
763 struct intel_fence *fence = intel_fence(fence_);
764 intel_fence_copy(fence, queue->fence);
Chia-I Wubda4f622015-02-25 15:06:15 -0700765 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800766
767 return XGL_SUCCESS;
768}