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