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