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