egl/x11: simplify dri2_initialize_x11()
[mesa.git] / src / egl / drivers / dri2 / platform_x11_dri3.c
1 /*
2 * Copyright © 2015 Boyan Ding
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23 #include <stdbool.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include <xcb/xcb.h>
29 #include <xcb/dri3.h>
30 #include <xcb/present.h>
31 #include <xcb/xfixes.h>
32
33 #include <xf86drm.h>
34 #include "util/macros.h"
35
36 #include "egl_dri2.h"
37 #include "platform_x11_dri3.h"
38
39 #include "loader.h"
40 #include "loader_dri3_helper.h"
41
42 static struct dri3_egl_surface *
43 loader_drawable_to_egl_surface(struct loader_dri3_drawable *draw) {
44 size_t offset = offsetof(struct dri3_egl_surface, loader_drawable);
45 return (struct dri3_egl_surface *)(((void*) draw) - offset);
46 }
47
48 static void
49 egl_dri3_set_drawable_size(struct loader_dri3_drawable *draw,
50 int width, int height)
51 {
52 struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
53
54 dri3_surf->surf.base.Width = width;
55 dri3_surf->surf.base.Height = height;
56 }
57
58 static bool
59 egl_dri3_in_current_context(struct loader_dri3_drawable *draw)
60 {
61 struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
62 _EGLContext *ctx = _eglGetCurrentContext();
63
64 return ctx->Resource.Display == dri3_surf->surf.base.Resource.Display;
65 }
66
67 static __DRIcontext *
68 egl_dri3_get_dri_context(struct loader_dri3_drawable *draw)
69 {
70 _EGLContext *ctx = _eglGetCurrentContext();
71 struct dri2_egl_context *dri2_ctx;
72 if (!ctx)
73 return NULL;
74 dri2_ctx = dri2_egl_context(ctx);
75 return dri2_ctx->dri_context;
76 }
77
78 static __DRIscreen *
79 egl_dri3_get_dri_screen(void)
80 {
81 _EGLContext *ctx = _eglGetCurrentContext();
82 struct dri2_egl_context *dri2_ctx;
83 if (!ctx)
84 return NULL;
85 dri2_ctx = dri2_egl_context(ctx);
86 return dri2_egl_display(dri2_ctx->base.Resource.Display)->dri_screen;
87 }
88
89 static void
90 egl_dri3_flush_drawable(struct loader_dri3_drawable *draw, unsigned flags)
91 {
92 struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
93 _EGLDisplay *disp = dri3_surf->surf.base.Resource.Display;
94
95 dri2_flush_drawable_for_swapbuffers(disp, &dri3_surf->surf.base);
96 }
97
98 static const struct loader_dri3_vtable egl_dri3_vtable = {
99 .set_drawable_size = egl_dri3_set_drawable_size,
100 .in_current_context = egl_dri3_in_current_context,
101 .get_dri_context = egl_dri3_get_dri_context,
102 .get_dri_screen = egl_dri3_get_dri_screen,
103 .flush_drawable = egl_dri3_flush_drawable,
104 .show_fps = NULL,
105 };
106
107 static EGLBoolean
108 dri3_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
109 {
110 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
111 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
112 xcb_drawable_t drawable = dri3_surf->loader_drawable.drawable;
113
114 loader_dri3_drawable_fini(&dri3_surf->loader_drawable);
115
116 if (surf->Type == EGL_PBUFFER_BIT)
117 xcb_free_pixmap (dri2_dpy->conn, drawable);
118
119 dri2_fini_surface(surf);
120 free(surf);
121
122 return EGL_TRUE;
123 }
124
125 static EGLBoolean
126 dri3_set_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
127 {
128 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
129
130 dri3_surf->surf.base.SwapInterval = interval;
131 loader_dri3_set_swap_interval(&dri3_surf->loader_drawable, interval);
132
133 return EGL_TRUE;
134 }
135
136 static _EGLSurface *
137 dri3_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
138 void *native_surface, const EGLint *attrib_list)
139 {
140 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
141 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
142 struct dri3_egl_surface *dri3_surf;
143 const __DRIconfig *dri_config;
144 xcb_drawable_t drawable;
145
146 dri3_surf = calloc(1, sizeof *dri3_surf);
147 if (!dri3_surf) {
148 _eglError(EGL_BAD_ALLOC, "dri3_create_surface");
149 return NULL;
150 }
151
152 if (!dri2_init_surface(&dri3_surf->surf.base, disp, type, conf,
153 attrib_list, false, native_surface))
154 goto cleanup_surf;
155
156 if (type == EGL_PBUFFER_BIT) {
157 drawable = xcb_generate_id(dri2_dpy->conn);
158 xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
159 drawable, dri2_dpy->screen->root,
160 dri3_surf->surf.base.Width, dri3_surf->surf.base.Height);
161 } else {
162 STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface));
163 drawable = (uintptr_t) native_surface;
164 }
165
166 dri_config = dri2_get_dri_config(dri2_conf, type,
167 dri3_surf->surf.base.GLColorspace);
168
169 if (!dri_config) {
170 _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
171 goto cleanup_pixmap;
172 }
173
174 if (loader_dri3_drawable_init(dri2_dpy->conn, drawable,
175 dri2_dpy->dri_screen,
176 dri2_dpy->is_different_gpu,
177 dri2_dpy->multibuffers_available,
178 dri_config,
179 &dri2_dpy->loader_dri3_ext,
180 &egl_dri3_vtable,
181 &dri3_surf->loader_drawable)) {
182 _eglError(EGL_BAD_ALLOC, "dri3_surface_create");
183 goto cleanup_pixmap;
184 }
185
186 return &dri3_surf->surf.base;
187
188 cleanup_pixmap:
189 if (type == EGL_PBUFFER_BIT)
190 xcb_free_pixmap(dri2_dpy->conn, drawable);
191 cleanup_surf:
192 free(dri3_surf);
193
194 return NULL;
195 }
196
197 static int
198 dri3_authenticate(_EGLDisplay *disp, uint32_t id)
199 {
200 #ifdef HAVE_WAYLAND_PLATFORM
201 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
202
203 if (dri2_dpy->device_name) {
204 _eglLog(_EGL_WARNING,
205 "Wayland client render node authentication is unnecessary");
206 return 0;
207 }
208
209 _eglLog(_EGL_WARNING,
210 "Wayland client primary node authentication isn't supported");
211 #endif
212
213 return -1;
214 }
215
216 /**
217 * Called via eglCreateWindowSurface(), drv->CreateWindowSurface().
218 */
219 static _EGLSurface *
220 dri3_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
221 void *native_window, const EGLint *attrib_list)
222 {
223 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
224 _EGLSurface *surf;
225
226 surf = dri3_create_surface(disp, EGL_WINDOW_BIT, conf,
227 native_window, attrib_list);
228 if (surf != NULL)
229 dri3_set_swap_interval(disp, surf, dri2_dpy->default_swap_interval);
230
231 return surf;
232 }
233
234 static _EGLSurface *
235 dri3_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
236 void *native_pixmap, const EGLint *attrib_list)
237 {
238 return dri3_create_surface(disp, EGL_PIXMAP_BIT, conf,
239 native_pixmap, attrib_list);
240 }
241
242 static _EGLSurface *
243 dri3_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
244 const EGLint *attrib_list)
245 {
246 return dri3_create_surface(disp, EGL_PBUFFER_BIT, conf,
247 NULL, attrib_list);
248 }
249
250 static EGLBoolean
251 dri3_get_sync_values(_EGLDisplay *display, _EGLSurface *surface,
252 EGLuint64KHR *ust, EGLuint64KHR *msc,
253 EGLuint64KHR *sbc)
254 {
255 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surface);
256
257 return loader_dri3_wait_for_msc(&dri3_surf->loader_drawable, 0, 0, 0,
258 (int64_t *) ust, (int64_t *) msc,
259 (int64_t *) sbc) ? EGL_TRUE : EGL_FALSE;
260 }
261
262 static _EGLImage *
263 dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
264 EGLClientBuffer buffer, const EGLint *attr_list)
265 {
266 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
267 struct dri2_egl_image *dri2_img;
268 xcb_drawable_t drawable;
269 xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
270 xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
271 unsigned int format;
272
273 drawable = (xcb_drawable_t) (uintptr_t) buffer;
274 bp_cookie = xcb_dri3_buffer_from_pixmap(dri2_dpy->conn, drawable);
275 bp_reply = xcb_dri3_buffer_from_pixmap_reply(dri2_dpy->conn,
276 bp_cookie, NULL);
277 if (!bp_reply) {
278 _eglError(EGL_BAD_ALLOC, "xcb_dri3_buffer_from_pixmap");
279 return NULL;
280 }
281
282 format = dri2_format_for_depth(dri2_dpy, bp_reply->depth);
283 if (format == __DRI_IMAGE_FORMAT_NONE) {
284 _eglError(EGL_BAD_PARAMETER,
285 "dri3_create_image_khr: unsupported pixmap depth");
286 free(bp_reply);
287 return EGL_NO_IMAGE_KHR;
288 }
289
290 dri2_img = malloc(sizeof *dri2_img);
291 if (!dri2_img) {
292 _eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
293 free(bp_reply);
294 return EGL_NO_IMAGE_KHR;
295 }
296
297 _eglInitImage(&dri2_img->base, disp);
298
299 dri2_img->dri_image = loader_dri3_create_image(dri2_dpy->conn,
300 bp_reply,
301 format,
302 dri2_dpy->dri_screen,
303 dri2_dpy->image,
304 dri2_img);
305
306 free(bp_reply);
307
308 return &dri2_img->base;
309 }
310
311 #ifdef HAVE_DRI3_MODIFIERS
312 static _EGLImage *
313 dri3_create_image_khr_pixmap_from_buffers(_EGLDisplay *disp, _EGLContext *ctx,
314 EGLClientBuffer buffer,
315 const EGLint *attr_list)
316 {
317 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
318 struct dri2_egl_image *dri2_img;
319 xcb_dri3_buffers_from_pixmap_cookie_t bp_cookie;
320 xcb_dri3_buffers_from_pixmap_reply_t *bp_reply;
321 xcb_drawable_t drawable;
322 unsigned int format;
323
324 drawable = (xcb_drawable_t) (uintptr_t) buffer;
325 bp_cookie = xcb_dri3_buffers_from_pixmap(dri2_dpy->conn, drawable);
326 bp_reply = xcb_dri3_buffers_from_pixmap_reply(dri2_dpy->conn,
327 bp_cookie, NULL);
328
329 if (!bp_reply) {
330 _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
331 return EGL_NO_IMAGE_KHR;
332 }
333
334 format = dri2_format_for_depth(dri2_dpy, bp_reply->depth);
335 if (format == __DRI_IMAGE_FORMAT_NONE) {
336 _eglError(EGL_BAD_PARAMETER,
337 "dri3_create_image_khr: unsupported pixmap depth");
338 free(bp_reply);
339 return EGL_NO_IMAGE_KHR;
340 }
341
342 dri2_img = malloc(sizeof *dri2_img);
343 if (!dri2_img) {
344 _eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
345 free(bp_reply);
346 return EGL_NO_IMAGE_KHR;
347 }
348
349 _eglInitImage(&dri2_img->base, disp);
350
351 dri2_img->dri_image = loader_dri3_create_image_from_buffers(dri2_dpy->conn,
352 bp_reply,
353 format,
354 dri2_dpy->dri_screen,
355 dri2_dpy->image,
356 dri2_img);
357 free(bp_reply);
358
359 if (!dri2_img->dri_image) {
360 _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
361 free(dri2_img);
362 return EGL_NO_IMAGE_KHR;
363 }
364
365 return &dri2_img->base;
366 }
367 #endif
368
369 static _EGLImage *
370 dri3_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
371 EGLClientBuffer buffer, const EGLint *attr_list)
372 {
373 #ifdef HAVE_DRI3_MODIFIERS
374 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
375 #endif
376
377 switch (target) {
378 case EGL_NATIVE_PIXMAP_KHR:
379 #ifdef HAVE_DRI3_MODIFIERS
380 if (dri2_dpy->multibuffers_available)
381 return dri3_create_image_khr_pixmap_from_buffers(disp, ctx, buffer,
382 attr_list);
383 #endif
384 return dri3_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
385 default:
386 return dri2_create_image_khr(disp, ctx, target, buffer, attr_list);
387 }
388 }
389
390 /**
391 * Called by the driver when it needs to update the real front buffer with the
392 * contents of its fake front buffer.
393 */
394 static void
395 dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
396 {
397 struct loader_dri3_drawable *draw = loaderPrivate;
398 (void) driDrawable;
399
400 /* There does not seem to be any kind of consensus on whether we should
401 * support front-buffer rendering or not:
402 * http://lists.freedesktop.org/archives/mesa-dev/2013-June/040129.html
403 */
404 if (!draw->is_pixmap)
405 _eglLog(_EGL_WARNING, "FIXME: egl/x11 doesn't support front buffer rendering.");
406 }
407
408 const __DRIimageLoaderExtension dri3_image_loader_extension = {
409 .base = { __DRI_IMAGE_LOADER, 1 },
410
411 .getBuffers = loader_dri3_get_buffers,
412 .flushFrontBuffer = dri3_flush_front_buffer,
413 };
414
415 static EGLBoolean
416 dri3_swap_buffers_with_damage(_EGLDisplay *disp, _EGLSurface *draw,
417 const EGLint *rects, EGLint n_rects)
418 {
419 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(draw);
420
421 return loader_dri3_swap_buffers_msc(&dri3_surf->loader_drawable,
422 0, 0, 0, 0,
423 rects, n_rects,
424 draw->SwapBehavior == EGL_BUFFER_PRESERVED) != -1;
425 }
426
427 static EGLBoolean
428 dri3_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
429 {
430 return dri3_swap_buffers_with_damage(disp, draw, NULL, 0);
431 }
432
433 static EGLBoolean
434 dri3_copy_buffers(_EGLDisplay *disp, _EGLSurface *surf, void *native_pixmap_target)
435 {
436 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
437 xcb_pixmap_t target;
438
439 STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_pixmap_target));
440 target = (uintptr_t) native_pixmap_target;
441
442 loader_dri3_copy_drawable(&dri3_surf->loader_drawable, target,
443 dri3_surf->loader_drawable.drawable);
444
445 return EGL_TRUE;
446 }
447
448 static int
449 dri3_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surf)
450 {
451 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
452
453 return loader_dri3_query_buffer_age(&dri3_surf->loader_drawable);
454 }
455
456 static EGLBoolean
457 dri3_query_surface(_EGLDisplay *disp, _EGLSurface *surf,
458 EGLint attribute, EGLint *value)
459 {
460 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
461
462 switch (attribute) {
463 case EGL_WIDTH:
464 case EGL_HEIGHT:
465 loader_dri3_update_drawable_geometry(&dri3_surf->loader_drawable);
466 break;
467 default:
468 break;
469 }
470
471 return _eglQuerySurface(disp, surf, attribute, value);
472 }
473
474 static __DRIdrawable *
475 dri3_get_dri_drawable(_EGLSurface *surf)
476 {
477 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
478
479 return dri3_surf->loader_drawable.dri_drawable;
480 }
481
482 static void
483 dri3_close_screen_notify(_EGLDisplay *disp)
484 {
485 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
486
487 loader_dri3_close_screen(dri2_dpy->dri_screen);
488 }
489
490 struct dri2_egl_display_vtbl dri3_x11_display_vtbl = {
491 .authenticate = dri3_authenticate,
492 .create_window_surface = dri3_create_window_surface,
493 .create_pixmap_surface = dri3_create_pixmap_surface,
494 .create_pbuffer_surface = dri3_create_pbuffer_surface,
495 .destroy_surface = dri3_destroy_surface,
496 .create_image = dri3_create_image_khr,
497 .swap_interval = dri3_set_swap_interval,
498 .swap_buffers = dri3_swap_buffers,
499 .swap_buffers_with_damage = dri3_swap_buffers_with_damage,
500 .copy_buffers = dri3_copy_buffers,
501 .query_buffer_age = dri3_query_buffer_age,
502 .query_surface = dri3_query_surface,
503 .get_sync_values = dri3_get_sync_values,
504 .get_dri_drawable = dri3_get_dri_drawable,
505 .close_screen_notify = dri3_close_screen_notify,
506 };
507
508 /* Only request versions of these protocols which we actually support. */
509 #define DRI3_SUPPORTED_MAJOR 1
510 #define PRESENT_SUPPORTED_MAJOR 1
511
512 #ifdef HAVE_DRI3_MODIFIERS
513 #define DRI3_SUPPORTED_MINOR 2
514 #define PRESENT_SUPPORTED_MINOR 2
515 #else
516 #define PRESENT_SUPPORTED_MINOR 0
517 #define DRI3_SUPPORTED_MINOR 0
518 #endif
519
520 EGLBoolean
521 dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
522 {
523 xcb_dri3_query_version_reply_t *dri3_query;
524 xcb_dri3_query_version_cookie_t dri3_query_cookie;
525 xcb_present_query_version_reply_t *present_query;
526 xcb_present_query_version_cookie_t present_query_cookie;
527 xcb_xfixes_query_version_reply_t *xfixes_query;
528 xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
529 xcb_generic_error_t *error;
530 const xcb_query_extension_reply_t *extension;
531
532 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri3_id);
533 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_present_id);
534 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id);
535
536 extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri3_id);
537 if (!(extension && extension->present))
538 return EGL_FALSE;
539
540 extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_present_id);
541 if (!(extension && extension->present))
542 return EGL_FALSE;
543
544 extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id);
545 if (!(extension && extension->present))
546 return EGL_FALSE;
547
548 dri3_query_cookie = xcb_dri3_query_version(dri2_dpy->conn,
549 DRI3_SUPPORTED_MAJOR,
550 DRI3_SUPPORTED_MINOR);
551
552 present_query_cookie = xcb_present_query_version(dri2_dpy->conn,
553 PRESENT_SUPPORTED_MAJOR,
554 PRESENT_SUPPORTED_MINOR);
555
556 xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
557 XCB_XFIXES_MAJOR_VERSION,
558 XCB_XFIXES_MINOR_VERSION);
559
560 dri3_query =
561 xcb_dri3_query_version_reply(dri2_dpy->conn, dri3_query_cookie, &error);
562 if (dri3_query == NULL || error != NULL) {
563 _eglLog(_EGL_WARNING, "DRI3: failed to query the version");
564 free(dri3_query);
565 free(error);
566 return EGL_FALSE;
567 }
568
569 dri2_dpy->dri3_major_version = dri3_query->major_version;
570 dri2_dpy->dri3_minor_version = dri3_query->minor_version;
571 free(dri3_query);
572
573 present_query =
574 xcb_present_query_version_reply(dri2_dpy->conn,
575 present_query_cookie, &error);
576 if (present_query == NULL || error != NULL) {
577 _eglLog(_EGL_WARNING, "DRI3: failed to query Present version");
578 free(present_query);
579 free(error);
580 return EGL_FALSE;
581 }
582
583 dri2_dpy->present_major_version = present_query->major_version;
584 dri2_dpy->present_minor_version = present_query->minor_version;
585 free(present_query);
586
587 xfixes_query =
588 xcb_xfixes_query_version_reply(dri2_dpy->conn,
589 xfixes_query_cookie, &error);
590 if (xfixes_query == NULL || error != NULL ||
591 xfixes_query->major_version < 2) {
592 _eglLog(_EGL_WARNING, "DRI3: failed to query xfixes version");
593 free(error);
594 free(xfixes_query);
595 return EGL_FALSE;
596 }
597 free(xfixes_query);
598
599 dri2_dpy->fd = loader_dri3_open(dri2_dpy->conn, dri2_dpy->screen->root, 0);
600 if (dri2_dpy->fd < 0) {
601 int conn_error = xcb_connection_has_error(dri2_dpy->conn);
602 _eglLog(_EGL_WARNING, "DRI3: Screen seems not DRI3 capable");
603
604 if (conn_error)
605 _eglLog(_EGL_WARNING, "DRI3: Failed to initialize");
606
607 return EGL_FALSE;
608 }
609
610 dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd, &dri2_dpy->is_different_gpu);
611
612 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
613 if (!dri2_dpy->driver_name) {
614 _eglLog(_EGL_WARNING, "DRI3: No driver found");
615 close(dri2_dpy->fd);
616 return EGL_FALSE;
617 }
618
619 #ifdef HAVE_WAYLAND_PLATFORM
620 /* Only try to get a render device name since dri3 doesn't provide a
621 * mechanism for authenticating client opened device node fds. If this
622 * fails then don't advertise the extension. */
623 dri2_dpy->device_name = drmGetRenderDeviceNameFromFd(dri2_dpy->fd);
624 #endif
625
626 return EGL_TRUE;
627 }