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