blob: 0c9162471458af24e8616f1be576829cb0962b60 [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 Wu7fbe2ab2014-11-07 13:26:45 +080045struct intel_wsi_x11_window {
46 xcb_window_t window_id;
Chia-I Wu1db76e02014-09-15 14:21:14 +080047
48 xcb_present_event_t present_special_event_id;
49 xcb_special_event_t *present_special_event;
50
51 struct {
52 uint32_t serial;
53 } local;
54
55 struct {
56 uint32_t serial;
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -060057 uint64_t msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +080058 } remote;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +080059
60 struct intel_wsi_x11_window *next;
61};
62
63struct intel_wsi_x11 {
Chia-I Wu41858c82015-04-04 16:39:25 +080064 struct intel_handle handle;
65
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +080066 xcb_connection_t *c;
67 xcb_window_t root;
68 xcb_randr_provider_t provider;
69 int root_depth;
70
71 int dri3_major, dri3_minor;
72 int present_major, present_minor;
73
74 int fd;
75
76 struct intel_wsi_x11_window *windows;
Chia-I Wu1db76e02014-09-15 14:21:14 +080077};
78
Chia-I Wu41858c82015-04-04 16:39:25 +080079struct intel_x11_img_data {
80 struct intel_mem *mem;
81 int prime_fd;
82 uint32_t pixmap;
83};
84
85struct intel_x11_fence_data {
86 struct intel_wsi_x11 *x11;
87 struct intel_wsi_x11_window *win;
88 uint32_t serial;
89};
90
Chia-I Wu1db76e02014-09-15 14:21:14 +080091/**
92 * Return true if DRI3 and Present are supported by the server.
93 */
Chia-I Wu41858c82015-04-04 16:39:25 +080094static bool wsi_x11_has_dri3_and_present(struct intel_wsi_x11 *x11)
Chia-I Wu1db76e02014-09-15 14:21:14 +080095{
96 const xcb_query_extension_reply_t *ext;
97
Chia-I Wu41858c82015-04-04 16:39:25 +080098 xcb_prefetch_extension_data(x11->c, &xcb_dri3_id);
99 xcb_prefetch_extension_data(x11->c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800100
Chia-I Wu41858c82015-04-04 16:39:25 +0800101 ext = xcb_get_extension_data(x11->c, &xcb_dri3_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800102 if (!ext || !ext->present)
103 return false;
104
Chia-I Wu41858c82015-04-04 16:39:25 +0800105 ext = xcb_get_extension_data(x11->c, &xcb_present_id);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800106 if (!ext || !ext->present)
107 return false;
108
109 return true;
110}
111
112/**
113 * Return the depth of the root window.
114 */
115static int wsi_x11_get_root_depth(struct intel_wsi_x11 *x11)
116{
117 const xcb_setup_t *setup;
118 xcb_screen_iterator_t iter;
119
120 setup = xcb_get_setup(x11->c);
121
122 iter = xcb_setup_roots_iterator(setup);
123 for (; iter.rem; xcb_screen_next(&iter)) {
124 if (iter.data->root == x11->root)
125 return iter.data->root_depth;
126 }
127
128 return 0;
129}
130
131/**
Chia-I Wu41858c82015-04-04 16:39:25 +0800132 * Send DRI3QueryVersion and PresentQueryVersion to query extension versions.
Chia-I Wu1db76e02014-09-15 14:21:14 +0800133 */
Chia-I Wu41858c82015-04-04 16:39:25 +0800134static bool wsi_x11_dri3_and_present_query_version(struct intel_wsi_x11 *x11)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800135{
136 xcb_dri3_query_version_cookie_t dri3_cookie;
137 xcb_dri3_query_version_reply_t *dri3_reply;
138 xcb_present_query_version_cookie_t present_cookie;
139 xcb_present_query_version_reply_t *present_reply;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800140
Chia-I Wu41858c82015-04-04 16:39:25 +0800141 dri3_cookie = xcb_dri3_query_version(x11->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800142 XCB_DRI3_MAJOR_VERSION, XCB_DRI3_MINOR_VERSION);
Chia-I Wu41858c82015-04-04 16:39:25 +0800143 present_cookie = xcb_present_query_version(x11->c,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800144 XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION);
145
Chia-I Wu41858c82015-04-04 16:39:25 +0800146 dri3_reply = xcb_dri3_query_version_reply(x11->c, dri3_cookie, NULL);
147 if (!dri3_reply)
148 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800149
150 x11->dri3_major = dri3_reply->major_version;
151 x11->dri3_minor = dri3_reply->minor_version;
152 free(dri3_reply);
153
Chia-I Wu41858c82015-04-04 16:39:25 +0800154 present_reply = xcb_present_query_version_reply(x11->c, present_cookie, NULL);
155 if (!present_reply)
156 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800157
158 x11->present_major = present_reply->major_version;
159 x11->present_minor = present_reply->minor_version;
160 free(present_reply);
161
Chia-I Wu41858c82015-04-04 16:39:25 +0800162 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800163}
164
165/**
166 * Return true if x11->fd points to the primary or render node of the GPU.
167 */
168static bool wsi_x11_uses_gpu(const struct intel_wsi_x11 *x11,
169 const struct intel_gpu *gpu)
170{
171 struct stat x11_stat, gpu_stat;
172
173 if (fstat(x11->fd, &x11_stat))
174 return false;
175
176 /* is it the primary node? */
177 if (!stat(gpu->primary_node, &gpu_stat) &&
178 !memcmp(&x11_stat, &gpu_stat, sizeof(x11_stat)))
179 return true;
180
181 /* is it the render node? */
182 if (gpu->render_node && !stat(gpu->render_node, &gpu_stat) &&
183 !memcmp(&x11_stat, &gpu_stat, sizeof(x11_stat)))
184 return true;
185
186 return false;
187}
188
189/**
190 * Send a DRI3Open to get the server GPU fd.
191 */
Chia-I Wu41858c82015-04-04 16:39:25 +0800192static bool wsi_x11_dri3_open(struct intel_wsi_x11 *x11)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800193{
194 xcb_dri3_open_cookie_t cookie;
195 xcb_dri3_open_reply_t *reply;
196 int fd;
197
198 cookie = xcb_dri3_open(x11->c, x11->root, x11->provider);
199 reply = xcb_dri3_open_reply(x11->c, cookie, NULL);
200 if (!reply)
Chia-I Wu41858c82015-04-04 16:39:25 +0800201 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800202
203 fd = (reply->nfd == 1) ? xcb_dri3_open_reply_fds(x11->c, reply)[0] : -1;
204 free(reply);
205
206 if (fd < 0)
Chia-I Wu41858c82015-04-04 16:39:25 +0800207 return false;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800208
209 fcntl(fd, F_SETFD, FD_CLOEXEC);
210 x11->fd = fd;
211
Chia-I Wu41858c82015-04-04 16:39:25 +0800212 return true;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800213}
214
215/**
216 * Send a DRI3PixmapFromBuffer to create a Pixmap from \p mem for \p img.
217 */
218static XGL_RESULT wsi_x11_dri3_pixmap_from_buffer(struct intel_wsi_x11 *x11,
219 struct intel_dev *dev,
220 struct intel_img *img,
221 struct intel_mem *mem)
222{
Chia-I Wu41858c82015-04-04 16:39:25 +0800223 struct intel_x11_img_data *data =
224 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800225 struct intel_winsys_handle export;
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800226 enum intel_tiling_mode tiling;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800227 xcb_pixmap_t pixmap;
228
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800229 switch (img->layout.tiling) {
230 case GEN6_TILING_X:
231 tiling = INTEL_TILING_X;
232 break;
233 case GEN6_TILING_Y:
234 tiling = INTEL_TILING_Y;
235 break;
236 default:
237 assert(img->layout.tiling == GEN6_TILING_NONE);
238 tiling = INTEL_TILING_NONE;
239 break;
240 }
241
Chia-I Wu1db76e02014-09-15 14:21:14 +0800242 /* get prime fd of the bo first */
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800243 if (intel_bo_set_tiling(mem->bo, tiling, img->layout.bo_stride))
Chia-I Wu3d0f59c2015-03-07 06:00:46 +0800244 return XGL_ERROR_UNKNOWN;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800245 export.type = INTEL_WINSYS_HANDLE_FD;
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800246 if (intel_winsys_export_handle(dev->winsys, mem->bo, tiling,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800247 img->layout.bo_stride, img->layout.bo_height, &export))
248 return XGL_ERROR_UNKNOWN;
249
250 pixmap = xcb_generate_id(x11->c);
251
252 /* create a pixmap from the prime fd */
253 xcb_dri3_pixmap_from_buffer(x11->c, pixmap,
254 x11->root, img->total_size,
255 img->layout.width0, img->layout.height0,
256 img->layout.bo_stride, x11->root_depth,
257 img->layout.block_size * 8, export.handle);
258
Chia-I Wu41858c82015-04-04 16:39:25 +0800259 data->mem = mem;
260 data->prime_fd = export.handle;
261 data->pixmap = pixmap;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800262
263 return XGL_SUCCESS;
264}
265
266/**
267 * Send a PresentSelectInput to select interested events.
268 */
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800269static XGL_RESULT wsi_x11_present_select_input(struct intel_wsi_x11 *x11,
270 struct intel_wsi_x11_window *win)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800271{
272 xcb_void_cookie_t cookie;
273 xcb_generic_error_t *error;
274
275 /* create the event queue */
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800276 win->present_special_event_id = xcb_generate_id(x11->c);
277 win->present_special_event = xcb_register_for_special_xge(x11->c,
278 &xcb_present_id, win->present_special_event_id, NULL);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800279
280 cookie = xcb_present_select_input_checked(x11->c,
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800281 win->present_special_event_id, win->window_id,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800282 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
283
284 error = xcb_request_check(x11->c, cookie);
285 if (error) {
286 free(error);
287 return XGL_ERROR_UNKNOWN;
288 }
289
290 return XGL_SUCCESS;
291}
292
293/**
294 * Send a PresentPixmap.
295 */
296static XGL_RESULT wsi_x11_present_pixmap(struct intel_wsi_x11 *x11,
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800297 struct intel_wsi_x11_window *win,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800298 const XGL_WSI_X11_PRESENT_INFO *info)
299{
300 struct intel_img *img = intel_img(info->srcImage);
Chia-I Wu41858c82015-04-04 16:39:25 +0800301 struct intel_x11_img_data *data =
302 (struct intel_x11_img_data *) img->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800303 uint32_t options = XCB_PRESENT_OPTION_NONE;
304 xcb_void_cookie_t cookie;
305 xcb_generic_error_t *err;
306
307 if (info->async)
308 options |= XCB_PRESENT_OPTION_ASYNC;
309 if (!info->flip)
310 options |= XCB_PRESENT_OPTION_COPY;
311
312 cookie = xcb_present_pixmap(x11->c,
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800313 win->window_id,
Chia-I Wu41858c82015-04-04 16:39:25 +0800314 data->pixmap,
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800315 ++win->local.serial,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800316 0, /* valid-area */
317 0, /* update-area */
318 0, /* x-off */
319 0, /* y-off */
320 info->crtc,
321 0, /* wait-fence */
322 0, /* idle-fence */
323 options,
324 info->target_msc,
325 info->divisor,
326 info->remainder,
327 0, NULL);
328
329 err = xcb_request_check(x11->c, cookie);
330 if (err) {
331 free(err);
332 return XGL_ERROR_UNKNOWN;
333 }
334
335 return XGL_SUCCESS;
336}
337
338/**
339 * Send a PresentNotifyMSC for the current MSC.
340 */
341static void wsi_x11_present_notify_msc(struct intel_wsi_x11 *x11,
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800342 struct intel_wsi_x11_window *win)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800343{
344 /* cannot specify CRTC? */
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800345 xcb_present_notify_msc(x11->c, win->window_id, ++win->local.serial,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800346 0, 0, 0);
347
348 xcb_flush(x11->c);
349}
350
351/**
352 * Handle a Present event.
353 */
354static void wsi_x11_present_event(struct intel_wsi_x11 *x11,
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800355 struct intel_wsi_x11_window *win,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800356 const xcb_present_generic_event_t *ev)
357{
358 union {
359 const xcb_present_generic_event_t *ev;
360 const xcb_present_complete_notify_event_t *complete;
361 } u = { .ev = ev };
362
363 switch (u.ev->evtype) {
364 case XCB_PRESENT_COMPLETE_NOTIFY:
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800365 win->remote.serial = u.complete->serial;
366 win->remote.msc = u.complete->msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800367 break;
368 default:
369 break;
370 }
371}
372
Chia-I Wu41858c82015-04-04 16:39:25 +0800373static struct intel_wsi_x11_window *wsi_x11_create_window(struct intel_wsi_x11 *x11,
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800374 xcb_window_t win_id)
375{
376 struct intel_wsi_x11_window *win;
377
Chia-I Wu41858c82015-04-04 16:39:25 +0800378 win = intel_alloc(x11, sizeof(*win), 0, XGL_SYSTEM_ALLOC_INTERNAL);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800379 if (!win)
380 return NULL;
381
382 memset(win, 0, sizeof(*win));
383
384 win->window_id = win_id;
385
386 if (wsi_x11_present_select_input(x11, win) != XGL_SUCCESS) {
Chia-I Wu41858c82015-04-04 16:39:25 +0800387 intel_free(x11, win);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800388 return NULL;
389 }
390
391 return win;
392}
393
Chia-I Wu41858c82015-04-04 16:39:25 +0800394static void wsi_x11_destroy_window(struct intel_wsi_x11 *x11,
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800395 struct intel_wsi_x11_window *win)
396{
397 if (win->present_special_event)
398 xcb_unregister_for_special_event(x11->c, win->present_special_event);
399
Chia-I Wu41858c82015-04-04 16:39:25 +0800400 intel_free(x11, win);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800401}
402
Chia-I Wu41858c82015-04-04 16:39:25 +0800403static struct intel_wsi_x11_window *wsi_x11_lookup_window(struct intel_wsi_x11 *x11,
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800404 xcb_window_t win_id)
405{
406 struct intel_wsi_x11_window *win = x11->windows;
407
408 while (win) {
409 if (win->window_id == win_id)
410 break;
411 win = win->next;
412 }
413
414 /* lookup failed */
415 if (!win) {
Chia-I Wu41858c82015-04-04 16:39:25 +0800416 win = wsi_x11_create_window(x11, win_id);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800417 if (win) {
418 win->next = x11->windows;
419 x11->windows = win;
420 }
421 }
422
423 return win;
424}
425
Chia-I Wu41858c82015-04-04 16:39:25 +0800426static XGL_RESULT wsi_x11_wait_window(struct intel_wsi_x11 *x11,
427 struct intel_wsi_x11_window *win,
428 uint32_t serial, int64_t timeout)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800429{
Chia-I Wu41858c82015-04-04 16:39:25 +0800430 const bool wait = (timeout != 0);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800431
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800432 while (win->remote.serial < serial) {
Chia-I Wu1db76e02014-09-15 14:21:14 +0800433 xcb_present_generic_event_t *ev;
434
435 if (wait) {
436 ev = (xcb_present_generic_event_t *)
437 xcb_wait_for_special_event(x11->c,
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800438 win->present_special_event);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800439 if (!ev)
440 return XGL_ERROR_UNKNOWN;
441 } else {
442 ev = (xcb_present_generic_event_t *)
443 xcb_poll_for_special_event(x11->c,
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800444 win->present_special_event);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800445 if (!ev)
446 return XGL_NOT_READY;
447 }
448
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800449 wsi_x11_present_event(x11, win, ev);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800450
451 free(ev);
452 }
453
454 return XGL_SUCCESS;
455}
456
Chia-I Wuc505a6f2014-11-13 00:04:01 +0800457static bool wsi_x11_is_format_presentable(struct intel_wsi_x11 *x11,
458 struct intel_dev *dev,
459 XGL_FORMAT format)
460{
461 /* this is what DDX expects */
Jeremy Hayes2b7e88a2015-01-23 08:51:43 -0700462 switch (format) {
463 case XGL_FMT_B5G6R5_UNORM:
464 case XGL_FMT_B8G8R8A8_UNORM:
465 case XGL_FMT_B8G8R8A8_SRGB:
466 return true;
Chia-I Wuc505a6f2014-11-13 00:04:01 +0800467 default:
Jeremy Hayes2b7e88a2015-01-23 08:51:43 -0700468 return false;
Chia-I Wuc505a6f2014-11-13 00:04:01 +0800469 }
Chia-I Wuc505a6f2014-11-13 00:04:01 +0800470}
471
Chia-I Wu1db76e02014-09-15 14:21:14 +0800472/**
473 * Create a presentable image.
474 */
475static XGL_RESULT wsi_x11_img_create(struct intel_wsi_x11 *x11,
476 struct intel_dev *dev,
477 const XGL_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO *info,
478 struct intel_img **img_ret)
479{
480 XGL_IMAGE_CREATE_INFO img_info;
481 XGL_MEMORY_ALLOC_INFO mem_info;
482 struct intel_img *img;
483 struct intel_mem *mem;
484 XGL_RESULT ret;
485
Chia-I Wuc505a6f2014-11-13 00:04:01 +0800486 if (!wsi_x11_is_format_presentable(x11, dev, info->format)) {
487 intel_dev_log(dev, XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0,
488 XGL_NULL_HANDLE, 0, 0, "invalid presentable image format");
489 return XGL_ERROR_INVALID_VALUE;
490 }
491
Chia-I Wu1db76e02014-09-15 14:21:14 +0800492 /* create image */
493 memset(&img_info, 0, sizeof(img_info));
494 img_info.sType = XGL_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
495 img_info.imageType = XGL_IMAGE_2D;
496 img_info.format = info->format;
497 img_info.extent.width = info->extent.width;
498 img_info.extent.height = info->extent.height;
499 img_info.extent.depth = 1;
500 img_info.mipLevels = 1;
501 img_info.arraySize = 1;
502 img_info.samples = 1;
503 img_info.tiling = XGL_OPTIMAL_TILING;
504 img_info.usage = info->usage;
505 img_info.flags = 0;
506
507 ret = intel_img_create(dev, &img_info, true, &img);
508 if (ret != XGL_SUCCESS)
509 return ret;
510
511 /* allocate memory */
512 memset(&mem_info, 0, sizeof(mem_info));
513 mem_info.sType = XGL_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
514 mem_info.allocationSize = img->total_size;
Jon Ashburn542cd092015-01-20 13:55:32 -0700515 mem_info.memProps = 0;
Jon Ashburn32769172015-01-20 15:06:59 -0700516 mem_info.memType = XGL_MEMORY_TYPE_IMAGE;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800517 mem_info.memPriority = XGL_MEMORY_PRIORITY_HIGH;
518
519 ret = intel_mem_alloc(dev, &mem_info, &mem);
520 if (ret != XGL_SUCCESS) {
521 intel_img_destroy(img);
522 return ret;
523 }
524
525 ret = wsi_x11_dri3_pixmap_from_buffer(x11, dev, img, mem);
526 if (ret != XGL_SUCCESS) {
527 intel_mem_free(mem);
528 intel_img_destroy(img);
529 return ret;
530 }
531
532 intel_obj_bind_mem(&img->obj, mem, 0);
533
534 *img_ret = img;
535
536 return XGL_SUCCESS;
537}
538
Chia-I Wu41858c82015-04-04 16:39:25 +0800539static void wsi_x11_destroy(struct intel_wsi_x11 *x11)
540{
541 struct intel_wsi_x11_window *win = x11->windows;
542
543 while (win) {
544 struct intel_wsi_x11_window *next = win->next;
545 wsi_x11_destroy_window(x11, win);
546 win = next;
547 }
548
549 if (x11->fd >= 0)
550 close(x11->fd);
551
552 intel_free(x11, x11);
553}
554
555static struct intel_wsi_x11 *wsi_x11_create(struct intel_gpu *gpu,
556 const XGL_WSI_X11_CONNECTION_INFO *info)
557{
558 struct intel_wsi_x11 *x11;
559
560 x11 = intel_alloc(gpu, sizeof(*x11), 0, XGL_SYSTEM_ALLOC_API_OBJECT);
561 if (!x11)
562 return NULL;
563
564 memset(x11, 0, sizeof(*x11));
565 /* there is no XGL_DBG_OBJECT_WSI_DISPLAY */
566 intel_handle_init(&x11->handle, XGL_DBG_OBJECT_UNKNOWN, gpu->handle.icd);
567 x11->fd = -1;
568
569 x11->c = info->pConnection;
570 x11->root = info->root;
571 x11->provider = info->provider;
572
573 x11->root_depth = wsi_x11_get_root_depth(x11);
574
575 if (!wsi_x11_has_dri3_and_present(x11) ||
576 !wsi_x11_dri3_and_present_query_version(x11) ||
577 !wsi_x11_dri3_open(x11) ||
578 !wsi_x11_uses_gpu(x11, gpu)) {
579 wsi_x11_destroy(x11);
580 return NULL;
581 }
582
583 return x11;
584}
585
586static XGL_RESULT intel_wsi_gpu_init(struct intel_gpu *gpu,
587 const XGL_WSI_X11_CONNECTION_INFO *info)
588{
589 struct intel_wsi_x11 *x11;
590
591 x11 = wsi_x11_create(gpu, info);
592 if (!x11)
593 return XGL_ERROR_UNKNOWN;
594
595 gpu->wsi_data = x11;
596
597 return XGL_SUCCESS;
598}
599
600XGL_RESULT intel_wsi_gpu_get_info(struct intel_gpu *gpu,
601 XGL_PHYSICAL_GPU_INFO_TYPE type,
602 size_t *size, void *data)
603{
604 return XGL_ERROR_INVALID_VALUE;
605}
606
607void intel_wsi_gpu_cleanup(struct intel_gpu *gpu)
608{
609 struct intel_wsi_x11 *x11 = (struct intel_wsi_x11 *) gpu->wsi_data;
610
611 wsi_x11_destroy(x11);
612}
613
614XGL_RESULT intel_wsi_img_init(struct intel_img *img)
615{
616 struct intel_x11_img_data *data;
617
618 data = intel_alloc(img, sizeof(*data), 0, XGL_SYSTEM_ALLOC_INTERNAL);
619 if (!data)
620 return XGL_ERROR_OUT_OF_MEMORY;
621
622 memset(data, 0, sizeof(*data));
623
624 assert(!img->wsi_data);
625 img->wsi_data = data;
626
627 return XGL_SUCCESS;
628}
629
630void intel_wsi_img_cleanup(struct intel_img *img)
631{
632 struct intel_x11_img_data *data =
633 (struct intel_x11_img_data *) img->wsi_data;
634
635 if (data->mem) {
636 close(data->prime_fd);
637 intel_mem_free(data->mem);
638 }
639
640 intel_free(img, img->wsi_data);
641}
642
643XGL_RESULT intel_wsi_fence_init(struct intel_fence *fence)
644{
645 struct intel_x11_fence_data *data;
646
647 data = intel_alloc(fence, sizeof(*data), 0, XGL_SYSTEM_ALLOC_INTERNAL);
648 if (!data)
649 return XGL_ERROR_OUT_OF_MEMORY;
650
651 memset(data, 0, sizeof(*data));
652
653 assert(!fence->wsi_data);
654 fence->wsi_data = data;
655
656 return XGL_SUCCESS;
657}
658
659void intel_wsi_fence_cleanup(struct intel_fence *fence)
660{
661 intel_free(fence, fence->wsi_data);
662}
663
664void intel_wsi_fence_copy(struct intel_fence *fence,
665 const struct intel_fence *src)
666{
667 memcpy(fence->wsi_data, src->wsi_data,
668 sizeof(struct intel_x11_fence_data));
669}
670
671XGL_RESULT intel_wsi_fence_wait(struct intel_fence *fence,
672 int64_t timeout_ns)
673{
674 struct intel_x11_fence_data *data =
675 (struct intel_x11_fence_data *) fence->wsi_data;
676
677 if (!data->win)
678 return XGL_SUCCESS;
679
680 return wsi_x11_wait_window(data->x11,
681 data->win, data->serial, timeout_ns);
682}
683
Chia-I Wu96177272015-01-03 15:27:41 +0800684ICD_EXPORT XGL_RESULT XGLAPI xglWsiX11AssociateConnection(
Chia-I Wu1db76e02014-09-15 14:21:14 +0800685 XGL_PHYSICAL_GPU gpu_,
686 const XGL_WSI_X11_CONNECTION_INFO* pConnectionInfo)
687{
688 struct intel_gpu *gpu = intel_gpu(gpu_);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800689
Chia-I Wu41858c82015-04-04 16:39:25 +0800690 return intel_wsi_gpu_init(gpu, pConnectionInfo);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800691}
692
Chia-I Wu96177272015-01-03 15:27:41 +0800693ICD_EXPORT XGL_RESULT XGLAPI xglWsiX11GetMSC(
Chia-I Wu1db76e02014-09-15 14:21:14 +0800694 XGL_DEVICE device,
Chia-I Wu6204f342014-11-07 13:33:45 +0800695 xcb_window_t window,
Chia-I Wu1db76e02014-09-15 14:21:14 +0800696 xcb_randr_crtc_t crtc,
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600697 uint64_t * pMsc)
Chia-I Wu1db76e02014-09-15 14:21:14 +0800698{
699 struct intel_dev *dev = intel_dev(device);
Chia-I Wu41858c82015-04-04 16:39:25 +0800700 struct intel_wsi_x11 *x11 = (struct intel_wsi_x11 *) dev->gpu->wsi_data;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800701 struct intel_wsi_x11_window *win;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800702 XGL_RESULT ret;
703
Chia-I Wu41858c82015-04-04 16:39:25 +0800704 win = wsi_x11_lookup_window(x11, window);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800705 if (!win)
706 return XGL_ERROR_UNKNOWN;
707
708 wsi_x11_present_notify_msc(x11, win);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800709
710 /* wait for the event */
Chia-I Wu41858c82015-04-04 16:39:25 +0800711 ret = wsi_x11_wait_window(x11, win, win->local.serial, -1);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800712 if (ret != XGL_SUCCESS)
713 return ret;
714
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800715 *pMsc = win->remote.msc;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800716
717 return XGL_SUCCESS;
718}
719
Chia-I Wu96177272015-01-03 15:27:41 +0800720ICD_EXPORT XGL_RESULT XGLAPI xglWsiX11CreatePresentableImage(
Chia-I Wu1db76e02014-09-15 14:21:14 +0800721 XGL_DEVICE device,
722 const XGL_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO* pCreateInfo,
723 XGL_IMAGE* pImage,
724 XGL_GPU_MEMORY* pMem)
725{
726 struct intel_dev *dev = intel_dev(device);
Chia-I Wu41858c82015-04-04 16:39:25 +0800727 struct intel_wsi_x11 *x11 = (struct intel_wsi_x11 *) dev->gpu->wsi_data;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800728 struct intel_img *img;
729 XGL_RESULT ret;
730
731 ret = wsi_x11_img_create(x11, dev, pCreateInfo, &img);
732 if (ret == XGL_SUCCESS) {
733 *pImage = (XGL_IMAGE) img;
734 *pMem = (XGL_GPU_MEMORY) img->obj.mem;
735 }
736
737 return ret;
738}
739
Chia-I Wu96177272015-01-03 15:27:41 +0800740ICD_EXPORT XGL_RESULT XGLAPI xglWsiX11QueuePresent(
Chia-I Wu1db76e02014-09-15 14:21:14 +0800741 XGL_QUEUE queue_,
742 const XGL_WSI_X11_PRESENT_INFO* pPresentInfo,
743 XGL_FENCE fence_)
744{
745 struct intel_queue *queue = intel_queue(queue_);
746 struct intel_fence *fence = intel_fence(fence_);
Chia-I Wu41858c82015-04-04 16:39:25 +0800747 struct intel_wsi_x11 *x11 =
748 (struct intel_wsi_x11 *) queue->dev->gpu->wsi_data;
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800749 struct intel_wsi_x11_window *win;
Chia-I Wu1db76e02014-09-15 14:21:14 +0800750 XGL_RESULT ret;
751
Chia-I Wu41858c82015-04-04 16:39:25 +0800752 win = wsi_x11_lookup_window(x11, pPresentInfo->destWindow);
Chia-I Wu7fbe2ab2014-11-07 13:26:45 +0800753 if (!win)
754 return XGL_ERROR_UNKNOWN;
755
756 ret = wsi_x11_present_pixmap(x11, win, pPresentInfo);
Chia-I Wu1db76e02014-09-15 14:21:14 +0800757 if (ret != XGL_SUCCESS)
758 return ret;
759
Chia-I Wubda4f622015-02-25 15:06:15 -0700760 if (fence) {
761 struct intel_img *img = intel_img(pPresentInfo->srcImage);
Chia-I Wu41858c82015-04-04 16:39:25 +0800762 struct intel_x11_fence_data *data =
763 (struct intel_x11_fence_data *) fence->wsi_data;
Chia-I Wubda4f622015-02-25 15:06:15 -0700764
Chia-I Wu41858c82015-04-04 16:39:25 +0800765 data->x11 = x11;
766 data->win = win;
767 data->serial = win->local.serial;
768
769 intel_fence_set_seqno(fence, img->obj.mem->bo);
Chia-I Wubda4f622015-02-25 15:06:15 -0700770 }
Chia-I Wu1db76e02014-09-15 14:21:14 +0800771
772 return XGL_SUCCESS;
773}