egl/x11: Handle both depth 30 formats for eglCreateImage(). (v4)
[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 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(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
109 {
110 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
111
112 (void) drv;
113
114 loader_dri3_drawable_fini(&dri3_surf->loader_drawable);
115
116 dri2_fini_surface(surf);
117 free(surf);
118
119 return EGL_TRUE;
120 }
121
122 static EGLBoolean
123 dri3_set_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
124 EGLint interval)
125 {
126 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
127
128 dri3_surf->surf.base.SwapInterval = interval;
129 loader_dri3_set_swap_interval(&dri3_surf->loader_drawable, interval);
130
131 return EGL_TRUE;
132 }
133
134 static _EGLSurface *
135 dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
136 _EGLConfig *conf, void *native_surface,
137 const EGLint *attrib_list)
138 {
139 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
140 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
141 struct dri3_egl_surface *dri3_surf;
142 const __DRIconfig *dri_config;
143 xcb_drawable_t drawable;
144
145 (void) drv;
146
147 dri3_surf = calloc(1, sizeof *dri3_surf);
148 if (!dri3_surf) {
149 _eglError(EGL_BAD_ALLOC, "dri3_create_surface");
150 return NULL;
151 }
152
153 if (!dri2_init_surface(&dri3_surf->surf.base, disp, type, conf, attrib_list, false))
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->API.CreateWindowSurface().
218 */
219 static _EGLSurface *
220 dri3_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
221 _EGLConfig *conf, void *native_window,
222 const EGLint *attrib_list)
223 {
224 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
225 _EGLSurface *surf;
226
227 surf = dri3_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
228 native_window, attrib_list);
229 if (surf != NULL)
230 dri3_set_swap_interval(drv, disp, surf, dri2_dpy->default_swap_interval);
231
232 return surf;
233 }
234
235 static _EGLSurface *
236 dri3_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
237 _EGLConfig *conf, void *native_pixmap,
238 const EGLint *attrib_list)
239 {
240 return dri3_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
241 native_pixmap, attrib_list);
242 }
243
244 static _EGLSurface *
245 dri3_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
246 _EGLConfig *conf, const EGLint *attrib_list)
247 {
248 return dri3_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
249 NULL, attrib_list);
250 }
251
252 static EGLBoolean
253 dri3_get_sync_values(_EGLDisplay *display, _EGLSurface *surface,
254 EGLuint64KHR *ust, EGLuint64KHR *msc,
255 EGLuint64KHR *sbc)
256 {
257 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surface);
258
259 return loader_dri3_wait_for_msc(&dri3_surf->loader_drawable, 0, 0, 0,
260 (int64_t *) ust, (int64_t *) msc,
261 (int64_t *) sbc) ? EGL_TRUE : EGL_FALSE;
262 }
263
264 static _EGLImage *
265 dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
266 EGLClientBuffer buffer, const EGLint *attr_list)
267 {
268 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
269 struct dri2_egl_image *dri2_img;
270 xcb_drawable_t drawable;
271 xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
272 xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
273 unsigned int format;
274
275 drawable = (xcb_drawable_t) (uintptr_t) buffer;
276 bp_cookie = xcb_dri3_buffer_from_pixmap(dri2_dpy->conn, drawable);
277 bp_reply = xcb_dri3_buffer_from_pixmap_reply(dri2_dpy->conn,
278 bp_cookie, NULL);
279 if (!bp_reply) {
280 _eglError(EGL_BAD_ALLOC, "xcb_dri3_buffer_from_pixmap");
281 return NULL;
282 }
283
284 format = dri2_format_for_depth(dri2_dpy, bp_reply->depth);
285 if (format == __DRI_IMAGE_FORMAT_NONE) {
286 _eglError(EGL_BAD_PARAMETER,
287 "dri3_create_image_khr: unsupported pixmap depth");
288 free(bp_reply);
289 return EGL_NO_IMAGE_KHR;
290 }
291
292 dri2_img = malloc(sizeof *dri2_img);
293 if (!dri2_img) {
294 _eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
295 free(bp_reply);
296 return EGL_NO_IMAGE_KHR;
297 }
298
299 _eglInitImage(&dri2_img->base, disp);
300
301 dri2_img->dri_image = loader_dri3_create_image(dri2_dpy->conn,
302 bp_reply,
303 format,
304 dri2_dpy->dri_screen,
305 dri2_dpy->image,
306 dri2_img);
307
308 free(bp_reply);
309
310 return &dri2_img->base;
311 }
312
313 #ifdef HAVE_DRI3_MODIFIERS
314 static _EGLImage *
315 dri3_create_image_khr_pixmap_from_buffers(_EGLDisplay *disp, _EGLContext *ctx,
316 EGLClientBuffer buffer,
317 const EGLint *attr_list)
318 {
319 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
320 struct dri2_egl_image *dri2_img;
321 xcb_dri3_buffers_from_pixmap_cookie_t bp_cookie;
322 xcb_dri3_buffers_from_pixmap_reply_t *bp_reply;
323 xcb_drawable_t drawable;
324 unsigned int format;
325
326 drawable = (xcb_drawable_t) (uintptr_t) buffer;
327 bp_cookie = xcb_dri3_buffers_from_pixmap(dri2_dpy->conn, drawable);
328 bp_reply = xcb_dri3_buffers_from_pixmap_reply(dri2_dpy->conn,
329 bp_cookie, NULL);
330
331 if (!bp_reply) {
332 _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
333 return EGL_NO_IMAGE_KHR;
334 }
335
336 format = dri2_format_for_depth(dri2_dpy, bp_reply->depth);
337 if (format == __DRI_IMAGE_FORMAT_NONE) {
338 _eglError(EGL_BAD_PARAMETER,
339 "dri3_create_image_khr: unsupported pixmap depth");
340 free(bp_reply);
341 return EGL_NO_IMAGE_KHR;
342 }
343
344 dri2_img = malloc(sizeof *dri2_img);
345 if (!dri2_img) {
346 _eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
347 free(bp_reply);
348 return EGL_NO_IMAGE_KHR;
349 }
350
351 _eglInitImage(&dri2_img->base, disp);
352
353 dri2_img->dri_image = loader_dri3_create_image_from_buffers(dri2_dpy->conn,
354 bp_reply,
355 format,
356 dri2_dpy->dri_screen,
357 dri2_dpy->image,
358 dri2_img);
359 free(bp_reply);
360
361 if (!dri2_img->dri_image) {
362 _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
363 free(dri2_img);
364 return EGL_NO_IMAGE_KHR;
365 }
366
367 return &dri2_img->base;
368 }
369 #endif
370
371 static _EGLImage *
372 dri3_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
373 _EGLContext *ctx, EGLenum target,
374 EGLClientBuffer buffer, const EGLint *attr_list)
375 {
376 #ifdef HAVE_DRI3_MODIFIERS
377 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
378 #endif
379
380 switch (target) {
381 case EGL_NATIVE_PIXMAP_KHR:
382 #ifdef HAVE_DRI3_MODIFIERS
383 if (dri2_dpy->multibuffers_available)
384 return dri3_create_image_khr_pixmap_from_buffers(disp, ctx, buffer,
385 attr_list);
386 #endif
387 return dri3_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
388 default:
389 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
390 }
391 }
392
393 /**
394 * Called by the driver when it needs to update the real front buffer with the
395 * contents of its fake front buffer.
396 */
397 static void
398 dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
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 _eglLog(_EGL_WARNING, "FIXME: egl/x11 doesn't support front buffer rendering.");
405 (void) driDrawable;
406 (void) loaderPrivate;
407 }
408
409 const __DRIimageLoaderExtension dri3_image_loader_extension = {
410 .base = { __DRI_IMAGE_LOADER, 1 },
411
412 .getBuffers = loader_dri3_get_buffers,
413 .flushFrontBuffer = dri3_flush_front_buffer,
414 };
415
416 static EGLBoolean
417 dri3_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
418 {
419 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(draw);
420
421 /* No-op for a pixmap or pbuffer surface */
422 if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
423 return EGL_FALSE;
424
425 return loader_dri3_swap_buffers_msc(&dri3_surf->loader_drawable,
426 0, 0, 0, 0,
427 draw->SwapBehavior == EGL_BUFFER_PRESERVED) != -1;
428 }
429
430 static EGLBoolean
431 dri3_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
432 void *native_pixmap_target)
433 {
434 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
435 xcb_pixmap_t target;
436
437 STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_pixmap_target));
438 target = (uintptr_t) native_pixmap_target;
439
440 loader_dri3_copy_drawable(&dri3_surf->loader_drawable, target,
441 dri3_surf->loader_drawable.drawable);
442
443 return EGL_TRUE;
444 }
445
446 static int
447 dri3_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
448 {
449 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
450
451 return loader_dri3_query_buffer_age(&dri3_surf->loader_drawable);
452 }
453
454 static EGLBoolean
455 dri3_query_surface(_EGLDriver *drv, _EGLDisplay *dpy,
456 _EGLSurface *surf, EGLint attribute,
457 EGLint *value)
458 {
459 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
460
461 switch (attribute) {
462 case EGL_WIDTH:
463 case EGL_HEIGHT:
464 loader_dri3_update_drawable_geometry(&dri3_surf->loader_drawable);
465 break;
466 default:
467 break;
468 }
469
470 return _eglQuerySurface(drv, dpy, surf, attribute, value);
471 }
472
473 static __DRIdrawable *
474 dri3_get_dri_drawable(_EGLSurface *surf)
475 {
476 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
477
478 return dri3_surf->loader_drawable.dri_drawable;
479 }
480
481 static void
482 dri3_close_screen_notify(_EGLDisplay *dpy)
483 {
484 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
485
486 loader_dri3_close_screen(dri2_dpy->dri_screen);
487 }
488
489 struct dri2_egl_display_vtbl dri3_x11_display_vtbl = {
490 .authenticate = dri3_authenticate,
491 .create_window_surface = dri3_create_window_surface,
492 .create_pixmap_surface = dri3_create_pixmap_surface,
493 .create_pbuffer_surface = dri3_create_pbuffer_surface,
494 .destroy_surface = dri3_destroy_surface,
495 .create_image = dri3_create_image_khr,
496 .swap_interval = dri3_set_swap_interval,
497 .swap_buffers = dri3_swap_buffers,
498 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
499 .swap_buffers_region = dri2_fallback_swap_buffers_region,
500 .set_damage_region = dri2_fallback_set_damage_region,
501 .post_sub_buffer = dri2_fallback_post_sub_buffer,
502 .copy_buffers = dri3_copy_buffers,
503 .query_buffer_age = dri3_query_buffer_age,
504 .query_surface = dri3_query_surface,
505 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
506 .get_sync_values = dri3_get_sync_values,
507 .get_dri_drawable = dri3_get_dri_drawable,
508 .close_screen_notify = dri3_close_screen_notify,
509 };
510
511 /* Only request versions of these protocols which we actually support. */
512 #define DRI3_SUPPORTED_MAJOR 1
513 #define PRESENT_SUPPORTED_MAJOR 1
514
515 #ifdef HAVE_DRI3_MODIFIERS
516 #define DRI3_SUPPORTED_MINOR 2
517 #define PRESENT_SUPPORTED_MINOR 2
518 #else
519 #define PRESENT_SUPPORTED_MINOR 0
520 #define DRI3_SUPPORTED_MINOR 0
521 #endif
522
523 EGLBoolean
524 dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
525 {
526 xcb_dri3_query_version_reply_t *dri3_query;
527 xcb_dri3_query_version_cookie_t dri3_query_cookie;
528 xcb_present_query_version_reply_t *present_query;
529 xcb_present_query_version_cookie_t present_query_cookie;
530 xcb_generic_error_t *error;
531 const xcb_query_extension_reply_t *extension;
532
533 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri3_id);
534 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_present_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 dri3_query_cookie = xcb_dri3_query_version(dri2_dpy->conn,
545 DRI3_SUPPORTED_MAJOR,
546 DRI3_SUPPORTED_MINOR);
547
548 present_query_cookie = xcb_present_query_version(dri2_dpy->conn,
549 PRESENT_SUPPORTED_MAJOR,
550 PRESENT_SUPPORTED_MINOR);
551
552 dri3_query =
553 xcb_dri3_query_version_reply(dri2_dpy->conn, dri3_query_cookie, &error);
554 if (dri3_query == NULL || error != NULL) {
555 _eglLog(_EGL_WARNING, "DRI3: failed to query the version");
556 free(dri3_query);
557 free(error);
558 return EGL_FALSE;
559 }
560
561 dri2_dpy->dri3_major_version = dri3_query->major_version;
562 dri2_dpy->dri3_minor_version = dri3_query->minor_version;
563 free(dri3_query);
564
565 present_query =
566 xcb_present_query_version_reply(dri2_dpy->conn,
567 present_query_cookie, &error);
568 if (present_query == NULL || error != NULL) {
569 _eglLog(_EGL_WARNING, "DRI3: failed to query Present version");
570 free(present_query);
571 free(error);
572 return EGL_FALSE;
573 }
574
575 dri2_dpy->present_major_version = present_query->major_version;
576 dri2_dpy->present_minor_version = present_query->minor_version;
577 free(present_query);
578
579 dri2_dpy->fd = loader_dri3_open(dri2_dpy->conn, dri2_dpy->screen->root, 0);
580 if (dri2_dpy->fd < 0) {
581 int conn_error = xcb_connection_has_error(dri2_dpy->conn);
582 _eglLog(_EGL_WARNING, "DRI3: Screen seems not DRI3 capable");
583
584 if (conn_error)
585 _eglLog(_EGL_WARNING, "DRI3: Failed to initialize");
586
587 return EGL_FALSE;
588 }
589
590 dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd, &dri2_dpy->is_different_gpu);
591
592 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
593 if (!dri2_dpy->driver_name) {
594 _eglLog(_EGL_WARNING, "DRI3: No driver found");
595 close(dri2_dpy->fd);
596 return EGL_FALSE;
597 }
598
599 #ifdef HAVE_WAYLAND_PLATFORM
600 /* Only try to get a render device name since dri3 doesn't provide a
601 * mechanism for authenticating client opened device node fds. If this
602 * fails then don't advertise the extension. */
603 dri2_dpy->device_name = drmGetRenderDeviceNameFromFd(dri2_dpy->fd);
604 #endif
605
606 return EGL_TRUE;
607 }