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