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