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