egl/dri2: Dispatch eglCreateImageKHR by display, not driver
[mesa.git] / src / egl / drivers / dri2 / platform_x11.c
1 /*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Kristian Høgsberg <krh@bitplanet.net>
26 */
27
28 #include <stdbool.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <limits.h>
33 #include <dlfcn.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 #include <unistd.h>
37 #ifdef HAVE_LIBDRM
38 #include <xf86drm.h>
39 #endif
40 #include <sys/types.h>
41 #include <sys/stat.h>
42
43 #include "egl_dri2.h"
44 #include "egl_dri2_fallbacks.h"
45
46 static EGLBoolean
47 dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
48 EGLint interval);
49
50 static void
51 swrastCreateDrawable(struct dri2_egl_display * dri2_dpy,
52 struct dri2_egl_surface * dri2_surf,
53 int depth)
54 {
55 uint32_t mask;
56 const uint32_t function = GXcopy;
57 uint32_t valgc[2];
58
59 /* create GC's */
60 dri2_surf->gc = xcb_generate_id(dri2_dpy->conn);
61 mask = XCB_GC_FUNCTION;
62 xcb_create_gc(dri2_dpy->conn, dri2_surf->gc, dri2_surf->drawable, mask, &function);
63
64 dri2_surf->swapgc = xcb_generate_id(dri2_dpy->conn);
65 mask = XCB_GC_FUNCTION | XCB_GC_GRAPHICS_EXPOSURES;
66 valgc[0] = function;
67 valgc[1] = False;
68 xcb_create_gc(dri2_dpy->conn, dri2_surf->swapgc, dri2_surf->drawable, mask, valgc);
69 dri2_surf->depth = depth;
70 switch (depth) {
71 case 32:
72 case 24:
73 dri2_surf->bytes_per_pixel = 4;
74 break;
75 case 16:
76 dri2_surf->bytes_per_pixel = 2;
77 break;
78 case 8:
79 dri2_surf->bytes_per_pixel = 1;
80 break;
81 case 0:
82 dri2_surf->bytes_per_pixel = 0;
83 break;
84 default:
85 _eglLog(_EGL_WARNING, "unsupported depth %d", depth);
86 }
87 }
88
89 static void
90 swrastDestroyDrawable(struct dri2_egl_display * dri2_dpy,
91 struct dri2_egl_surface * dri2_surf)
92 {
93 xcb_free_gc(dri2_dpy->conn, dri2_surf->gc);
94 xcb_free_gc(dri2_dpy->conn, dri2_surf->swapgc);
95 }
96
97 static void
98 swrastGetDrawableInfo(__DRIdrawable * draw,
99 int *x, int *y, int *w, int *h,
100 void *loaderPrivate)
101 {
102 struct dri2_egl_surface *dri2_surf = loaderPrivate;
103 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
104
105 xcb_get_geometry_cookie_t cookie;
106 xcb_get_geometry_reply_t *reply;
107 xcb_generic_error_t *error;
108
109 *w = *h = 0;
110 cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
111 reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
112 if (reply == NULL)
113 return;
114
115 if (error != NULL) {
116 _eglLog(_EGL_WARNING, "error in xcb_get_geometry");
117 free(error);
118 } else {
119 *w = reply->width;
120 *h = reply->height;
121 }
122 free(reply);
123 }
124
125 static void
126 swrastPutImage(__DRIdrawable * draw, int op,
127 int x, int y, int w, int h,
128 char *data, void *loaderPrivate)
129 {
130 struct dri2_egl_surface *dri2_surf = loaderPrivate;
131 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
132
133 xcb_gcontext_t gc;
134
135 switch (op) {
136 case __DRI_SWRAST_IMAGE_OP_DRAW:
137 gc = dri2_surf->gc;
138 break;
139 case __DRI_SWRAST_IMAGE_OP_SWAP:
140 gc = dri2_surf->swapgc;
141 break;
142 default:
143 return;
144 }
145
146 xcb_put_image(dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, dri2_surf->drawable,
147 gc, w, h, x, y, 0, dri2_surf->depth,
148 w*h*dri2_surf->bytes_per_pixel, (const uint8_t *)data);
149 }
150
151 static void
152 swrastGetImage(__DRIdrawable * read,
153 int x, int y, int w, int h,
154 char *data, void *loaderPrivate)
155 {
156 struct dri2_egl_surface *dri2_surf = loaderPrivate;
157 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
158
159 xcb_get_image_cookie_t cookie;
160 xcb_get_image_reply_t *reply;
161 xcb_generic_error_t *error;
162
163 cookie = xcb_get_image (dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
164 dri2_surf->drawable, x, y, w, h, ~0);
165 reply = xcb_get_image_reply (dri2_dpy->conn, cookie, &error);
166 if (reply == NULL)
167 return;
168
169 if (error != NULL) {
170 _eglLog(_EGL_WARNING, "error in xcb_get_image");
171 free(error);
172 } else {
173 uint32_t bytes = xcb_get_image_data_length(reply);
174 uint8_t *idata = xcb_get_image_data(reply);
175 memcpy(data, idata, bytes);
176 }
177 free(reply);
178 }
179
180
181 /**
182 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
183 */
184 static _EGLSurface *
185 dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
186 _EGLConfig *conf, EGLNativeWindowType native_window,
187 const EGLint *attrib_list)
188 {
189 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
190 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
191 struct dri2_egl_surface *dri2_surf;
192 xcb_get_geometry_cookie_t cookie;
193 xcb_get_geometry_reply_t *reply;
194 xcb_screen_iterator_t s;
195 xcb_generic_error_t *error;
196 xcb_drawable_t window = (uintptr_t )native_window;
197
198 (void) drv;
199
200 dri2_surf = malloc(sizeof *dri2_surf);
201 if (!dri2_surf) {
202 _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
203 return NULL;
204 }
205
206 if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
207 goto cleanup_surf;
208
209 dri2_surf->region = XCB_NONE;
210 if (type == EGL_PBUFFER_BIT) {
211 dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn);
212 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
213 xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
214 dri2_surf->drawable, s.data->root,
215 dri2_surf->base.Width, dri2_surf->base.Height);
216 } else {
217 dri2_surf->drawable = window;
218 }
219
220 if (dri2_dpy->dri2) {
221 dri2_surf->dri_drawable =
222 (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
223 type == EGL_WINDOW_BIT ?
224 dri2_conf->dri_double_config :
225 dri2_conf->dri_single_config,
226 dri2_surf);
227 } else {
228 assert(dri2_dpy->swrast);
229 dri2_surf->dri_drawable =
230 (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen,
231 dri2_conf->dri_double_config,
232 dri2_surf);
233 }
234
235 if (dri2_surf->dri_drawable == NULL) {
236 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
237 goto cleanup_pixmap;
238 }
239
240 if (dri2_dpy->dri2) {
241 xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable);
242 } else {
243 swrastCreateDrawable(dri2_dpy, dri2_surf, _eglGetConfigKey(conf, EGL_BUFFER_SIZE));
244 }
245
246 if (type != EGL_PBUFFER_BIT) {
247 cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
248 reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
249 if (reply == NULL || error != NULL) {
250 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
251 free(error);
252 goto cleanup_dri_drawable;
253 }
254
255 dri2_surf->base.Width = reply->width;
256 dri2_surf->base.Height = reply->height;
257 free(reply);
258 }
259
260 /* we always copy the back buffer to front */
261 dri2_surf->base.PostSubBufferSupportedNV = EGL_TRUE;
262
263 return &dri2_surf->base;
264
265 cleanup_dri_drawable:
266 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
267 cleanup_pixmap:
268 if (type == EGL_PBUFFER_BIT)
269 xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable);
270 cleanup_surf:
271 free(dri2_surf);
272
273 return NULL;
274 }
275
276 /**
277 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
278 */
279 static _EGLSurface *
280 dri2_x11_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
281 _EGLConfig *conf, EGLNativeWindowType window,
282 const EGLint *attrib_list)
283 {
284 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
285 _EGLSurface *surf;
286
287 surf = dri2_x11_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
288 window, attrib_list);
289 if (surf != NULL) {
290 /* When we first create the DRI2 drawable, its swap interval on the
291 * server side is 1.
292 */
293 surf->SwapInterval = 1;
294
295 /* Override that with a driconf-set value. */
296 dri2_x11_swap_interval(drv, disp, surf, dri2_dpy->default_swap_interval);
297 }
298
299 return surf;
300 }
301
302 static _EGLSurface *
303 dri2_x11_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
304 _EGLConfig *conf, EGLNativePixmapType pixmap,
305 const EGLint *attrib_list)
306 {
307 return dri2_x11_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
308 pixmap, attrib_list);
309 }
310
311 static _EGLSurface *
312 dri2_x11_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
313 _EGLConfig *conf, const EGLint *attrib_list)
314 {
315 return dri2_x11_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
316 XCB_WINDOW_NONE, attrib_list);
317 }
318
319 static EGLBoolean
320 dri2_x11_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
321 {
322 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
323 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
324
325 (void) drv;
326
327 if (!_eglPutSurface(surf))
328 return EGL_TRUE;
329
330 (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
331
332 if (dri2_dpy->dri2) {
333 xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable);
334 } else {
335 assert(dri2_dpy->swrast);
336 swrastDestroyDrawable(dri2_dpy, dri2_surf);
337 }
338
339 if (surf->Type == EGL_PBUFFER_BIT)
340 xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable);
341
342 free(surf);
343
344 return EGL_TRUE;
345 }
346
347 /**
348 * Process list of buffer received from the server
349 *
350 * Processes the list of buffers received in a reply from the server to either
351 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
352 */
353 static void
354 dri2_x11_process_buffers(struct dri2_egl_surface *dri2_surf,
355 xcb_dri2_dri2_buffer_t *buffers, unsigned count)
356 {
357 struct dri2_egl_display *dri2_dpy =
358 dri2_egl_display(dri2_surf->base.Resource.Display);
359 xcb_rectangle_t rectangle;
360 unsigned i;
361
362 dri2_surf->buffer_count = count;
363 dri2_surf->have_fake_front = 0;
364
365 /* This assumes the DRI2 buffer attachment tokens matches the
366 * __DRIbuffer tokens. */
367 for (i = 0; i < count; i++) {
368 dri2_surf->buffers[i].attachment = buffers[i].attachment;
369 dri2_surf->buffers[i].name = buffers[i].name;
370 dri2_surf->buffers[i].pitch = buffers[i].pitch;
371 dri2_surf->buffers[i].cpp = buffers[i].cpp;
372 dri2_surf->buffers[i].flags = buffers[i].flags;
373
374 /* We only use the DRI drivers single buffer configs. This
375 * means that if we try to render to a window, DRI2 will give us
376 * the fake front buffer, which we'll use as a back buffer.
377 * Note that EGL doesn't require that several clients rendering
378 * to the same window must see the same aux buffers. */
379 if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
380 dri2_surf->have_fake_front = 1;
381 }
382
383 if (dri2_surf->region != XCB_NONE)
384 xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region);
385
386 rectangle.x = 0;
387 rectangle.y = 0;
388 rectangle.width = dri2_surf->base.Width;
389 rectangle.height = dri2_surf->base.Height;
390 dri2_surf->region = xcb_generate_id(dri2_dpy->conn);
391 xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle);
392 }
393
394 static __DRIbuffer *
395 dri2_x11_get_buffers(__DRIdrawable * driDrawable,
396 int *width, int *height,
397 unsigned int *attachments, int count,
398 int *out_count, void *loaderPrivate)
399 {
400 struct dri2_egl_surface *dri2_surf = loaderPrivate;
401 struct dri2_egl_display *dri2_dpy =
402 dri2_egl_display(dri2_surf->base.Resource.Display);
403 xcb_dri2_dri2_buffer_t *buffers;
404 xcb_dri2_get_buffers_reply_t *reply;
405 xcb_dri2_get_buffers_cookie_t cookie;
406
407 (void) driDrawable;
408
409 cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
410 dri2_surf->drawable,
411 count, count, attachments);
412 reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, cookie, NULL);
413 buffers = xcb_dri2_get_buffers_buffers (reply);
414 if (buffers == NULL)
415 return NULL;
416
417 *out_count = reply->count;
418 dri2_surf->base.Width = *width = reply->width;
419 dri2_surf->base.Height = *height = reply->height;
420 dri2_x11_process_buffers(dri2_surf, buffers, *out_count);
421
422 free(reply);
423
424 return dri2_surf->buffers;
425 }
426
427 static __DRIbuffer *
428 dri2_x11_get_buffers_with_format(__DRIdrawable * driDrawable,
429 int *width, int *height,
430 unsigned int *attachments, int count,
431 int *out_count, void *loaderPrivate)
432 {
433 struct dri2_egl_surface *dri2_surf = loaderPrivate;
434 struct dri2_egl_display *dri2_dpy =
435 dri2_egl_display(dri2_surf->base.Resource.Display);
436 xcb_dri2_dri2_buffer_t *buffers;
437 xcb_dri2_get_buffers_with_format_reply_t *reply;
438 xcb_dri2_get_buffers_with_format_cookie_t cookie;
439 xcb_dri2_attach_format_t *format_attachments;
440
441 (void) driDrawable;
442
443 format_attachments = (xcb_dri2_attach_format_t *) attachments;
444 cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn,
445 dri2_surf->drawable,
446 count, count,
447 format_attachments);
448
449 reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->conn,
450 cookie, NULL);
451 if (reply == NULL)
452 return NULL;
453
454 buffers = xcb_dri2_get_buffers_with_format_buffers (reply);
455 dri2_surf->base.Width = *width = reply->width;
456 dri2_surf->base.Height = *height = reply->height;
457 *out_count = reply->count;
458 dri2_x11_process_buffers(dri2_surf, buffers, *out_count);
459
460 free(reply);
461
462 return dri2_surf->buffers;
463 }
464
465 static void
466 dri2_x11_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
467 {
468 (void) driDrawable;
469
470 /* FIXME: Does EGL support front buffer rendering at all? */
471
472 #if 0
473 struct dri2_egl_surface *dri2_surf = loaderPrivate;
474
475 dri2WaitGL(dri2_surf);
476 #else
477 (void) loaderPrivate;
478 #endif
479 }
480
481 static char *
482 dri2_x11_strndup(const char *s, int length)
483 {
484 char *d;
485
486 d = malloc(length + 1);
487 if (d == NULL)
488 return NULL;
489
490 memcpy(d, s, length);
491 d[length] = '\0';
492
493 return d;
494 }
495
496 static EGLBoolean
497 dri2_x11_connect(struct dri2_egl_display *dri2_dpy)
498 {
499 xcb_xfixes_query_version_reply_t *xfixes_query;
500 xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
501 xcb_dri2_query_version_reply_t *dri2_query;
502 xcb_dri2_query_version_cookie_t dri2_query_cookie;
503 xcb_dri2_connect_reply_t *connect;
504 xcb_dri2_connect_cookie_t connect_cookie;
505 xcb_generic_error_t *error;
506 xcb_screen_iterator_t s;
507 char *driver_name, *device_name;
508 const xcb_query_extension_reply_t *extension;
509
510 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id);
511 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id);
512
513 extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id);
514 if (!(extension && extension->present))
515 return EGL_FALSE;
516
517 extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri2_id);
518 if (!(extension && extension->present))
519 return EGL_FALSE;
520
521 xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
522 XCB_XFIXES_MAJOR_VERSION,
523 XCB_XFIXES_MINOR_VERSION);
524
525 dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn,
526 XCB_DRI2_MAJOR_VERSION,
527 XCB_DRI2_MINOR_VERSION);
528
529 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
530 connect_cookie = xcb_dri2_connect_unchecked (dri2_dpy->conn,
531 s.data->root,
532 XCB_DRI2_DRIVER_TYPE_DRI);
533
534 xfixes_query =
535 xcb_xfixes_query_version_reply (dri2_dpy->conn,
536 xfixes_query_cookie, &error);
537 if (xfixes_query == NULL ||
538 error != NULL || xfixes_query->major_version < 2) {
539 _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version");
540 free(error);
541 return EGL_FALSE;
542 }
543 free(xfixes_query);
544
545 dri2_query =
546 xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error);
547 if (dri2_query == NULL || error != NULL) {
548 _eglLog(_EGL_WARNING, "DRI2: failed to query version");
549 free(error);
550 return EGL_FALSE;
551 }
552 dri2_dpy->dri2_major = dri2_query->major_version;
553 dri2_dpy->dri2_minor = dri2_query->minor_version;
554 free(dri2_query);
555
556 connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL);
557 if (connect == NULL ||
558 connect->driver_name_length + connect->device_name_length == 0) {
559 _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
560 return EGL_FALSE;
561 }
562
563 driver_name = xcb_dri2_connect_driver_name (connect);
564 dri2_dpy->driver_name =
565 dri2_x11_strndup(driver_name,
566 xcb_dri2_connect_driver_name_length(connect));
567
568 device_name = xcb_dri2_connect_device_name (connect);
569
570 dri2_dpy->device_name =
571 dri2_x11_strndup(device_name,
572 xcb_dri2_connect_device_name_length(connect));
573
574 if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) {
575 free(dri2_dpy->device_name);
576 free(dri2_dpy->driver_name);
577 free(connect);
578 return EGL_FALSE;
579 }
580 free(connect);
581
582 return EGL_TRUE;
583 }
584
585 static int
586 dri2_x11_authenticate(_EGLDisplay *disp, uint32_t id)
587 {
588 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
589 xcb_dri2_authenticate_reply_t *authenticate;
590 xcb_dri2_authenticate_cookie_t authenticate_cookie;
591 xcb_screen_iterator_t s;
592 int ret = 0;
593
594 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
595 authenticate_cookie =
596 xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, id);
597 authenticate =
598 xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL);
599
600 if (authenticate == NULL || !authenticate->authenticated)
601 ret = -1;
602
603 free(authenticate);
604
605 return ret;
606 }
607
608 static EGLBoolean
609 dri2_x11_local_authenticate(_EGLDisplay *disp)
610 {
611 #ifdef HAVE_LIBDRM
612 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
613 drm_magic_t magic;
614
615 if (drmGetMagic(dri2_dpy->fd, &magic)) {
616 _eglLog(_EGL_WARNING, "DRI2: failed to get drm magic");
617 return EGL_FALSE;
618 }
619
620 if (dri2_x11_authenticate(disp, magic) < 0) {
621 _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
622 return EGL_FALSE;
623 }
624 #endif
625 return EGL_TRUE;
626 }
627
628 static EGLBoolean
629 dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
630 _EGLDisplay *disp)
631 {
632 xcb_screen_iterator_t s;
633 xcb_depth_iterator_t d;
634 xcb_visualtype_t *visuals;
635 int i, j, id;
636 unsigned int rgba_masks[4];
637 EGLint surface_type;
638 EGLint config_attrs[] = {
639 EGL_NATIVE_VISUAL_ID, 0,
640 EGL_NATIVE_VISUAL_TYPE, 0,
641 EGL_NONE
642 };
643
644 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
645 d = xcb_screen_allowed_depths_iterator(s.data);
646 id = 1;
647
648 surface_type =
649 EGL_WINDOW_BIT |
650 EGL_PIXMAP_BIT |
651 EGL_PBUFFER_BIT |
652 EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
653
654 while (d.rem > 0) {
655 EGLBoolean class_added[6] = { 0, };
656
657 visuals = xcb_depth_visuals(d.data);
658 for (i = 0; i < xcb_depth_visuals_length(d.data); i++) {
659 if (class_added[visuals[i]._class])
660 continue;
661
662 class_added[visuals[i]._class] = EGL_TRUE;
663 for (j = 0; dri2_dpy->driver_configs[j]; j++) {
664 config_attrs[1] = visuals[i].visual_id;
665 config_attrs[3] = visuals[i]._class;
666
667 rgba_masks[0] = visuals[i].red_mask;
668 rgba_masks[1] = visuals[i].green_mask;
669 rgba_masks[2] = visuals[i].blue_mask;
670 rgba_masks[3] = 0;
671 dri2_add_config(disp, dri2_dpy->driver_configs[j], id++,
672 surface_type, config_attrs, rgba_masks);
673
674 /* Allow a 24-bit RGB visual to match a 32-bit RGBA EGLConfig.
675 * Otherwise it will only match a 32-bit RGBA visual. On a
676 * composited window manager on X11, this will make all of the
677 * EGLConfigs with destination alpha get blended by the
678 * compositor. This is probably not what the application
679 * wants... especially on drivers that only have 32-bit RGBA
680 * EGLConfigs! */
681 if (d.data->depth == 24) {
682 rgba_masks[3] =
683 ~(rgba_masks[0] | rgba_masks[1] | rgba_masks[2]);
684 dri2_add_config(disp, dri2_dpy->driver_configs[j], id++,
685 surface_type, config_attrs, rgba_masks);
686 }
687 }
688 }
689
690 xcb_depth_next(&d);
691 }
692
693 if (!_eglGetArraySize(disp->Configs)) {
694 _eglLog(_EGL_WARNING, "DRI2: failed to create any config");
695 return EGL_FALSE;
696 }
697
698 return EGL_TRUE;
699 }
700
701 static EGLBoolean
702 dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp,
703 _EGLSurface *draw, xcb_xfixes_region_t region)
704 {
705 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
706 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
707 enum xcb_dri2_attachment_t render_attachment;
708 xcb_dri2_copy_region_cookie_t cookie;
709
710 /* No-op for a pixmap or pbuffer surface */
711 if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
712 return EGL_TRUE;
713
714 if (dri2_dpy->flush)
715 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
716
717 if (dri2_surf->have_fake_front)
718 render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT;
719 else
720 render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT;
721
722 cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn,
723 dri2_surf->drawable,
724 region,
725 XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
726 render_attachment);
727 free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL));
728
729 return EGL_TRUE;
730 }
731
732 static int64_t
733 dri2_x11_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
734 int64_t msc, int64_t divisor, int64_t remainder)
735 {
736 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
737 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
738 uint32_t msc_hi = msc >> 32;
739 uint32_t msc_lo = msc & 0xffffffff;
740 uint32_t divisor_hi = divisor >> 32;
741 uint32_t divisor_lo = divisor & 0xffffffff;
742 uint32_t remainder_hi = remainder >> 32;
743 uint32_t remainder_lo = remainder & 0xffffffff;
744 xcb_dri2_swap_buffers_cookie_t cookie;
745 xcb_dri2_swap_buffers_reply_t *reply;
746 int64_t swap_count = -1;
747
748 /* No-op for a pixmap or pbuffer surface */
749 if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
750 return 0;
751
752 if (draw->SwapBehavior == EGL_BUFFER_PRESERVED || !dri2_dpy->swap_available)
753 return dri2_copy_region(drv, disp, draw, dri2_surf->region) ? 0 : -1;
754
755 if (dri2_dpy->flush)
756 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
757
758 cookie = xcb_dri2_swap_buffers_unchecked(dri2_dpy->conn, dri2_surf->drawable,
759 msc_hi, msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo);
760
761 reply = xcb_dri2_swap_buffers_reply(dri2_dpy->conn, cookie, NULL);
762
763 if (reply) {
764 swap_count = (((int64_t)reply->swap_hi) << 32) | reply->swap_lo;
765 free(reply);
766 }
767
768 /* Since we aren't watching for the server's invalidate events like we're
769 * supposed to (due to XCB providing no mechanism for filtering the events
770 * the way xlib does), and SwapBuffers is a common cause of invalidate
771 * events, just shove one down to the driver, even though we haven't told
772 * the driver that we're the kind of loader that provides reliable
773 * invalidate events. This causes the driver to request buffers again at
774 * its next draw, so that we get the correct buffers if a pageflip
775 * happened. The driver should still be using the viewport hack to catch
776 * window resizes.
777 */
778 if (dri2_dpy->flush &&
779 dri2_dpy->flush->base.version >= 3 && dri2_dpy->flush->invalidate)
780 (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
781
782 return swap_count;
783 }
784
785 static EGLBoolean
786 dri2_x11_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
787 {
788 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
789 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
790
791 if (dri2_dpy->dri2) {
792 return dri2_x11_swap_buffers_msc(drv, disp, draw, 0, 0, 0) != -1;
793 } else {
794 assert(dri2_dpy->swrast);
795
796 dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
797 return EGL_TRUE;
798 }
799 }
800
801 static EGLBoolean
802 dri2_x11_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp,
803 _EGLSurface *draw,
804 EGLint numRects, const EGLint *rects)
805 {
806 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
807 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
808 EGLBoolean ret;
809 xcb_xfixes_region_t region;
810 xcb_rectangle_t rectangles[16];
811 int i;
812
813 if (numRects > (int)ARRAY_SIZE(rectangles))
814 return dri2_copy_region(drv, disp, draw, dri2_surf->region);
815
816 for (i = 0; i < numRects; i++) {
817 rectangles[i].x = rects[i * 4];
818 rectangles[i].y = dri2_surf->base.Height - rects[i * 4 + 1] - rects[i * 4 + 3];
819 rectangles[i].width = rects[i * 4 + 2];
820 rectangles[i].height = rects[i * 4 + 3];
821 }
822
823 region = xcb_generate_id(dri2_dpy->conn);
824 xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles);
825 ret = dri2_copy_region(drv, disp, draw, region);
826 xcb_xfixes_destroy_region(dri2_dpy->conn, region);
827
828 return ret;
829 }
830
831 static EGLBoolean
832 dri2_x11_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
833 EGLint x, EGLint y, EGLint width, EGLint height)
834 {
835 const EGLint rect[4] = { x, y, width, height };
836
837 if (x < 0 || y < 0 || width < 0 || height < 0)
838 _eglError(EGL_BAD_PARAMETER, "eglPostSubBufferNV");
839
840 return dri2_x11_swap_buffers_region(drv, disp, draw, 1, rect);
841 }
842
843 static EGLBoolean
844 dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
845 EGLint interval)
846 {
847 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
848 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
849
850 if (interval > surf->Config->MaxSwapInterval)
851 interval = surf->Config->MaxSwapInterval;
852 else if (interval < surf->Config->MinSwapInterval)
853 interval = surf->Config->MinSwapInterval;
854
855 if (interval != surf->SwapInterval && dri2_dpy->swap_available)
856 xcb_dri2_swap_interval(dri2_dpy->conn, dri2_surf->drawable, interval);
857
858 surf->SwapInterval = interval;
859
860 return EGL_TRUE;
861 }
862
863 static EGLBoolean
864 dri2_x11_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
865 EGLNativePixmapType native_target)
866 {
867 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
868 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
869 xcb_gcontext_t gc;
870 xcb_pixmap_t target = (uintptr_t )native_target;
871
872 (void) drv;
873
874 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
875
876 gc = xcb_generate_id(dri2_dpy->conn);
877 xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL);
878 xcb_copy_area(dri2_dpy->conn,
879 dri2_surf->drawable,
880 target,
881 gc,
882 0, 0,
883 0, 0,
884 dri2_surf->base.Width,
885 dri2_surf->base.Height);
886 xcb_free_gc(dri2_dpy->conn, gc);
887
888 return EGL_TRUE;
889 }
890
891 static _EGLImage *
892 dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
893 EGLClientBuffer buffer, const EGLint *attr_list)
894 {
895 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
896 struct dri2_egl_image *dri2_img;
897 unsigned int attachments[1];
898 xcb_drawable_t drawable;
899 xcb_dri2_get_buffers_cookie_t buffers_cookie;
900 xcb_dri2_get_buffers_reply_t *buffers_reply;
901 xcb_dri2_dri2_buffer_t *buffers;
902 xcb_get_geometry_cookie_t geometry_cookie;
903 xcb_get_geometry_reply_t *geometry_reply;
904 xcb_generic_error_t *error;
905 int stride, format;
906
907 (void) ctx;
908
909 drawable = (xcb_drawable_t) (uintptr_t) buffer;
910 xcb_dri2_create_drawable (dri2_dpy->conn, drawable);
911 attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT;
912 buffers_cookie =
913 xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
914 drawable, 1, 1, attachments);
915 geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable);
916 buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn,
917 buffers_cookie, NULL);
918 buffers = xcb_dri2_get_buffers_buffers (buffers_reply);
919 if (buffers == NULL) {
920 return NULL;
921 }
922
923 geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn,
924 geometry_cookie, &error);
925 if (geometry_reply == NULL || error != NULL) {
926 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
927 free(error);
928 free(buffers_reply);
929 return NULL;
930 }
931
932 switch (geometry_reply->depth) {
933 case 16:
934 format = __DRI_IMAGE_FORMAT_RGB565;
935 break;
936 case 24:
937 format = __DRI_IMAGE_FORMAT_XRGB8888;
938 break;
939 case 32:
940 format = __DRI_IMAGE_FORMAT_ARGB8888;
941 break;
942 default:
943 _eglError(EGL_BAD_PARAMETER,
944 "dri2_create_image_khr: unsupported pixmap depth");
945 free(buffers_reply);
946 free(geometry_reply);
947 return NULL;
948 }
949
950 dri2_img = malloc(sizeof *dri2_img);
951 if (!dri2_img) {
952 free(buffers_reply);
953 free(geometry_reply);
954 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
955 return EGL_NO_IMAGE_KHR;
956 }
957
958 if (!_eglInitImage(&dri2_img->base, disp)) {
959 free(buffers_reply);
960 free(geometry_reply);
961 free(dri2_img);
962 return EGL_NO_IMAGE_KHR;
963 }
964
965 stride = buffers[0].pitch / buffers[0].cpp;
966 dri2_img->dri_image =
967 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
968 buffers_reply->width,
969 buffers_reply->height,
970 format,
971 buffers[0].name,
972 stride,
973 dri2_img);
974
975 free(buffers_reply);
976 free(geometry_reply);
977
978 return &dri2_img->base;
979 }
980
981 static _EGLImage *
982 dri2_x11_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
983 _EGLContext *ctx, EGLenum target,
984 EGLClientBuffer buffer, const EGLint *attr_list)
985 {
986 (void) drv;
987
988 switch (target) {
989 case EGL_NATIVE_PIXMAP_KHR:
990 return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
991 default:
992 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
993 }
994 }
995
996 static _EGLImage*
997 dri2_x11_swrast_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
998 _EGLContext *ctx, EGLenum target,
999 EGLClientBuffer buffer,
1000 const EGLint *attr_list)
1001 {
1002 return NULL;
1003 }
1004
1005 static struct dri2_egl_display_vtbl dri2_x11_swrast_display_vtbl = {
1006 .authenticate = NULL,
1007 .create_window_surface = dri2_x11_create_window_surface,
1008 .create_pixmap_surface = dri2_x11_create_pixmap_surface,
1009 .create_pbuffer_surface = dri2_x11_create_pbuffer_surface,
1010 .destroy_surface = dri2_x11_destroy_surface,
1011 .create_image = dri2_x11_swrast_create_image_khr,
1012 .swap_interval = dri2_fallback_swap_interval,
1013 .swap_buffers = dri2_x11_swap_buffers,
1014 .swap_buffers_region = dri2_fallback_swap_buffers_region,
1015 .post_sub_buffer = dri2_fallback_post_sub_buffer,
1016 .copy_buffers = dri2_x11_copy_buffers,
1017 .query_buffer_age = dri2_fallback_query_buffer_age,
1018 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
1019 };
1020
1021 static struct dri2_egl_display_vtbl dri2_x11_display_vtbl = {
1022 .authenticate = dri2_x11_authenticate,
1023 .create_window_surface = dri2_x11_create_window_surface,
1024 .create_pixmap_surface = dri2_x11_create_pixmap_surface,
1025 .create_pbuffer_surface = dri2_x11_create_pbuffer_surface,
1026 .destroy_surface = dri2_x11_destroy_surface,
1027 .create_image = dri2_x11_create_image_khr,
1028 .swap_interval = dri2_x11_swap_interval,
1029 .swap_buffers = dri2_x11_swap_buffers,
1030 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
1031 .swap_buffers_region = dri2_x11_swap_buffers_region,
1032 .post_sub_buffer = dri2_x11_post_sub_buffer,
1033 .copy_buffers = dri2_x11_copy_buffers,
1034 .query_buffer_age = dri2_fallback_query_buffer_age,
1035 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
1036 };
1037
1038 static EGLBoolean
1039 dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp)
1040 {
1041 struct dri2_egl_display *dri2_dpy;
1042
1043 dri2_dpy = calloc(1, sizeof *dri2_dpy);
1044 if (!dri2_dpy)
1045 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1046
1047 disp->DriverData = (void *) dri2_dpy;
1048 if (disp->PlatformDisplay == NULL) {
1049 dri2_dpy->conn = xcb_connect(0, 0);
1050 dri2_dpy->own_device = true;
1051 } else {
1052 dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
1053 }
1054
1055 if (xcb_connection_has_error(dri2_dpy->conn)) {
1056 _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
1057 goto cleanup_dpy;
1058 }
1059
1060 if (!dri2_load_driver_swrast(disp))
1061 goto cleanup_conn;
1062
1063 dri2_dpy->swrast_loader_extension.base.name = __DRI_SWRAST_LOADER;
1064 dri2_dpy->swrast_loader_extension.base.version = __DRI_SWRAST_LOADER_VERSION;
1065 dri2_dpy->swrast_loader_extension.getDrawableInfo = swrastGetDrawableInfo;
1066 dri2_dpy->swrast_loader_extension.putImage = swrastPutImage;
1067 dri2_dpy->swrast_loader_extension.getImage = swrastGetImage;
1068
1069 dri2_dpy->extensions[0] = &dri2_dpy->swrast_loader_extension.base;
1070 dri2_dpy->extensions[1] = NULL;
1071 dri2_dpy->extensions[2] = NULL;
1072
1073 if (!dri2_create_screen(disp))
1074 goto cleanup_driver;
1075
1076 if (dri2_dpy->conn) {
1077 if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp))
1078 goto cleanup_configs;
1079 }
1080
1081 /* we're supporting EGL 1.4 */
1082 disp->VersionMajor = 1;
1083 disp->VersionMinor = 4;
1084
1085 /* Fill vtbl last to prevent accidentally calling virtual function during
1086 * initialization.
1087 */
1088 dri2_dpy->vtbl = &dri2_x11_swrast_display_vtbl;
1089
1090 return EGL_TRUE;
1091
1092 cleanup_configs:
1093 _eglCleanupDisplay(disp);
1094 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1095 cleanup_driver:
1096 dlclose(dri2_dpy->driver);
1097 cleanup_conn:
1098 if (disp->PlatformDisplay == NULL)
1099 xcb_disconnect(dri2_dpy->conn);
1100 cleanup_dpy:
1101 free(dri2_dpy);
1102
1103 return EGL_FALSE;
1104 }
1105
1106 static void
1107 dri2_x11_setup_swap_interval(struct dri2_egl_display *dri2_dpy)
1108 {
1109 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
1110 int arbitrary_max_interval = 1000;
1111
1112 /* default behavior for no SwapBuffers support: no vblank syncing
1113 * either.
1114 */
1115 dri2_dpy->min_swap_interval = 0;
1116 dri2_dpy->max_swap_interval = 0;
1117
1118 if (!dri2_dpy->swap_available)
1119 return;
1120
1121 /* If we do have swapbuffers, then we can support pretty much any swap
1122 * interval, but we allow driconf to override applications.
1123 */
1124 if (dri2_dpy->config)
1125 dri2_dpy->config->configQueryi(dri2_dpy->dri_screen,
1126 "vblank_mode", &vblank_mode);
1127 switch (vblank_mode) {
1128 case DRI_CONF_VBLANK_NEVER:
1129 dri2_dpy->min_swap_interval = 0;
1130 dri2_dpy->max_swap_interval = 0;
1131 dri2_dpy->default_swap_interval = 0;
1132 break;
1133 case DRI_CONF_VBLANK_ALWAYS_SYNC:
1134 dri2_dpy->min_swap_interval = 1;
1135 dri2_dpy->max_swap_interval = arbitrary_max_interval;
1136 dri2_dpy->default_swap_interval = 1;
1137 break;
1138 case DRI_CONF_VBLANK_DEF_INTERVAL_0:
1139 dri2_dpy->min_swap_interval = 0;
1140 dri2_dpy->max_swap_interval = arbitrary_max_interval;
1141 dri2_dpy->default_swap_interval = 0;
1142 break;
1143 default:
1144 case DRI_CONF_VBLANK_DEF_INTERVAL_1:
1145 dri2_dpy->min_swap_interval = 0;
1146 dri2_dpy->max_swap_interval = arbitrary_max_interval;
1147 dri2_dpy->default_swap_interval = 1;
1148 break;
1149 }
1150 }
1151
1152 static EGLBoolean
1153 dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
1154 {
1155 struct dri2_egl_display *dri2_dpy;
1156
1157 dri2_dpy = calloc(1, sizeof *dri2_dpy);
1158 if (!dri2_dpy)
1159 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1160
1161 disp->DriverData = (void *) dri2_dpy;
1162 if (disp->PlatformDisplay == NULL) {
1163 dri2_dpy->conn = xcb_connect(0, 0);
1164 dri2_dpy->own_device = true;
1165 } else {
1166 dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
1167 }
1168
1169 if (xcb_connection_has_error(dri2_dpy->conn)) {
1170 _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
1171 goto cleanup_dpy;
1172 }
1173
1174 if (dri2_dpy->conn) {
1175 if (!dri2_x11_connect(dri2_dpy))
1176 goto cleanup_conn;
1177 }
1178
1179 if (!dri2_load_driver(disp))
1180 goto cleanup_conn;
1181
1182 #ifdef O_CLOEXEC
1183 dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR | O_CLOEXEC);
1184 if (dri2_dpy->fd == -1 && errno == EINVAL)
1185 #endif
1186 {
1187 dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
1188 if (dri2_dpy->fd != -1)
1189 fcntl(dri2_dpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) |
1190 FD_CLOEXEC);
1191 }
1192 if (dri2_dpy->fd == -1) {
1193 _eglLog(_EGL_WARNING,
1194 "DRI2: could not open %s (%s)", dri2_dpy->device_name,
1195 strerror(errno));
1196 goto cleanup_driver;
1197 }
1198
1199 if (dri2_dpy->conn) {
1200 if (!dri2_x11_local_authenticate(disp))
1201 goto cleanup_fd;
1202 }
1203
1204 if (dri2_dpy->dri2_minor >= 1) {
1205 dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
1206 dri2_dpy->dri2_loader_extension.base.version = 3;
1207 dri2_dpy->dri2_loader_extension.getBuffers = dri2_x11_get_buffers;
1208 dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_x11_flush_front_buffer;
1209 dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
1210 dri2_x11_get_buffers_with_format;
1211 } else {
1212 dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
1213 dri2_dpy->dri2_loader_extension.base.version = 2;
1214 dri2_dpy->dri2_loader_extension.getBuffers = dri2_x11_get_buffers;
1215 dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_x11_flush_front_buffer;
1216 dri2_dpy->dri2_loader_extension.getBuffersWithFormat = NULL;
1217 }
1218
1219 dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base;
1220 dri2_dpy->extensions[1] = &image_lookup_extension.base;
1221 dri2_dpy->extensions[2] = NULL;
1222
1223 dri2_dpy->swap_available = (dri2_dpy->dri2_minor >= 2);
1224 dri2_dpy->invalidate_available = (dri2_dpy->dri2_minor >= 3);
1225
1226 if (!dri2_create_screen(disp))
1227 goto cleanup_fd;
1228
1229 dri2_x11_setup_swap_interval(dri2_dpy);
1230
1231 if (dri2_dpy->conn) {
1232 if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp))
1233 goto cleanup_configs;
1234 }
1235
1236 disp->Extensions.KHR_image_pixmap = EGL_TRUE;
1237 disp->Extensions.NOK_swap_region = EGL_TRUE;
1238 disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
1239 disp->Extensions.NV_post_sub_buffer = EGL_TRUE;
1240
1241 #ifdef HAVE_WAYLAND_PLATFORM
1242 disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
1243 #endif
1244
1245 if (dri2_dpy->conn) {
1246 if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp))
1247 goto cleanup_configs;
1248 }
1249
1250 /* we're supporting EGL 1.4 */
1251 disp->VersionMajor = 1;
1252 disp->VersionMinor = 4;
1253
1254 /* Fill vtbl last to prevent accidentally calling virtual function during
1255 * initialization.
1256 */
1257 dri2_dpy->vtbl = &dri2_x11_display_vtbl;
1258
1259 return EGL_TRUE;
1260
1261 cleanup_configs:
1262 _eglCleanupDisplay(disp);
1263 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1264 cleanup_fd:
1265 close(dri2_dpy->fd);
1266 cleanup_driver:
1267 dlclose(dri2_dpy->driver);
1268 cleanup_conn:
1269 if (disp->PlatformDisplay == NULL)
1270 xcb_disconnect(dri2_dpy->conn);
1271 cleanup_dpy:
1272 free(dri2_dpy);
1273
1274 return EGL_FALSE;
1275 }
1276
1277 EGLBoolean
1278 dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp)
1279 {
1280 EGLBoolean initialized = EGL_TRUE;
1281
1282 int x11_dri2_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
1283
1284 if (x11_dri2_accel) {
1285 if (!dri2_initialize_x11_dri2(drv, disp)) {
1286 initialized = dri2_initialize_x11_swrast(drv, disp);
1287 }
1288 } else {
1289 initialized = dri2_initialize_x11_swrast(drv, disp);
1290 }
1291
1292 return initialized;
1293 }
1294