1 /* 2 * Copyright 2011 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Kristian Hgsberg <krh (at) bitplanet.net> 26 */ 27 28 #include <stdbool.h> 29 #include <stdint.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <stdio.h> 33 #include <limits.h> 34 #include <dlfcn.h> 35 #include <fcntl.h> 36 #include <errno.h> 37 #include <unistd.h> 38 #ifdef HAVE_LIBDRM 39 #include <xf86drm.h> 40 #endif 41 #include <sys/types.h> 42 #include <sys/stat.h> 43 #include "util/debug.h" 44 #include "util/macros.h" 45 46 #include "egl_dri2.h" 47 #include "egl_dri2_fallbacks.h" 48 #include "loader.h" 49 50 #ifdef HAVE_DRI3 51 #include "platform_x11_dri3.h" 52 #endif 53 54 static EGLBoolean 55 dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, 56 EGLint interval); 57 58 static void 59 swrastCreateDrawable(struct dri2_egl_display * dri2_dpy, 60 struct dri2_egl_surface * dri2_surf) 61 { 62 uint32_t mask; 63 const uint32_t function = GXcopy; 64 uint32_t valgc[2]; 65 66 /* create GC's */ 67 dri2_surf->gc = xcb_generate_id(dri2_dpy->conn); 68 mask = XCB_GC_FUNCTION; 69 xcb_create_gc(dri2_dpy->conn, dri2_surf->gc, dri2_surf->drawable, mask, &function); 70 71 dri2_surf->swapgc = xcb_generate_id(dri2_dpy->conn); 72 mask = XCB_GC_FUNCTION | XCB_GC_GRAPHICS_EXPOSURES; 73 valgc[0] = function; 74 valgc[1] = False; 75 xcb_create_gc(dri2_dpy->conn, dri2_surf->swapgc, dri2_surf->drawable, mask, valgc); 76 switch (dri2_surf->depth) { 77 case 32: 78 case 30: 79 case 24: 80 dri2_surf->bytes_per_pixel = 4; 81 break; 82 case 16: 83 dri2_surf->bytes_per_pixel = 2; 84 break; 85 case 8: 86 dri2_surf->bytes_per_pixel = 1; 87 break; 88 case 0: 89 dri2_surf->bytes_per_pixel = 0; 90 break; 91 default: 92 _eglLog(_EGL_WARNING, "unsupported depth %d", dri2_surf->depth); 93 } 94 } 95 96 static void 97 swrastDestroyDrawable(struct dri2_egl_display * dri2_dpy, 98 struct dri2_egl_surface * dri2_surf) 99 { 100 xcb_free_gc(dri2_dpy->conn, dri2_surf->gc); 101 xcb_free_gc(dri2_dpy->conn, dri2_surf->swapgc); 102 } 103 104 static bool 105 x11_get_drawable_info(__DRIdrawable * draw, 106 int *x, int *y, int *w, int *h, 107 void *loaderPrivate) 108 { 109 struct dri2_egl_surface *dri2_surf = loaderPrivate; 110 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); 111 112 xcb_get_geometry_cookie_t cookie; 113 xcb_get_geometry_reply_t *reply; 114 xcb_generic_error_t *error; 115 bool ret; 116 117 cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); 118 reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error); 119 if (reply == NULL) 120 return false; 121 122 if (error != NULL) { 123 ret = false; 124 _eglLog(_EGL_WARNING, "error in xcb_get_geometry"); 125 free(error); 126 } else { 127 *x = reply->x; 128 *y = reply->y; 129 *w = reply->width; 130 *h = reply->height; 131 ret = true; 132 } 133 free(reply); 134 return ret; 135 } 136 137 static void 138 swrastGetDrawableInfo(__DRIdrawable * draw, 139 int *x, int *y, int *w, int *h, 140 void *loaderPrivate) 141 { 142 *x = *y = *w = *h = 0; 143 x11_get_drawable_info(draw, x, y, w, h, loaderPrivate); 144 } 145 146 static void 147 swrastPutImage(__DRIdrawable * draw, int op, 148 int x, int y, int w, int h, 149 char *data, void *loaderPrivate) 150 { 151 struct dri2_egl_surface *dri2_surf = loaderPrivate; 152 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); 153 154 xcb_gcontext_t gc; 155 156 switch (op) { 157 case __DRI_SWRAST_IMAGE_OP_DRAW: 158 gc = dri2_surf->gc; 159 break; 160 case __DRI_SWRAST_IMAGE_OP_SWAP: 161 gc = dri2_surf->swapgc; 162 break; 163 default: 164 return; 165 } 166 167 xcb_put_image(dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, dri2_surf->drawable, 168 gc, w, h, x, y, 0, dri2_surf->depth, 169 w*h*dri2_surf->bytes_per_pixel, (const uint8_t *)data); 170 } 171 172 static void 173 swrastGetImage(__DRIdrawable * read, 174 int x, int y, int w, int h, 175 char *data, void *loaderPrivate) 176 { 177 struct dri2_egl_surface *dri2_surf = loaderPrivate; 178 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); 179 180 xcb_get_image_cookie_t cookie; 181 xcb_get_image_reply_t *reply; 182 xcb_generic_error_t *error; 183 184 cookie = xcb_get_image (dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, 185 dri2_surf->drawable, x, y, w, h, ~0); 186 reply = xcb_get_image_reply (dri2_dpy->conn, cookie, &error); 187 if (reply == NULL) 188 return; 189 190 if (error != NULL) { 191 _eglLog(_EGL_WARNING, "error in xcb_get_image"); 192 free(error); 193 } else { 194 uint32_t bytes = xcb_get_image_data_length(reply); 195 uint8_t *idata = xcb_get_image_data(reply); 196 memcpy(data, idata, bytes); 197 } 198 free(reply); 199 } 200 201 202 static xcb_screen_t * 203 get_xcb_screen(xcb_screen_iterator_t iter, int screen) 204 { 205 for (; iter.rem; --screen, xcb_screen_next(&iter)) 206 if (screen == 0) 207 return iter.data; 208 209 return NULL; 210 } 211 212 213 /** 214 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). 215 */ 216 static _EGLSurface * 217 dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, 218 _EGLConfig *conf, void *native_surface, 219 const EGLint *attrib_list) 220 { 221 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 222 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); 223 struct dri2_egl_surface *dri2_surf; 224 xcb_get_geometry_cookie_t cookie; 225 xcb_get_geometry_reply_t *reply; 226 xcb_generic_error_t *error; 227 const __DRIconfig *config; 228 229 (void) drv; 230 231 dri2_surf = malloc(sizeof *dri2_surf); 232 if (!dri2_surf) { 233 _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); 234 return NULL; 235 } 236 237 if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, false)) 238 goto cleanup_surf; 239 240 dri2_surf->region = XCB_NONE; 241 if (type == EGL_PBUFFER_BIT) { 242 dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn); 243 xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize, 244 dri2_surf->drawable, dri2_dpy->screen->root, 245 dri2_surf->base.Width, dri2_surf->base.Height); 246 } else { 247 STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface)); 248 dri2_surf->drawable = (uintptr_t) native_surface; 249 } 250 251 config = dri2_get_dri_config(dri2_conf, type, 252 dri2_surf->base.GLColorspace); 253 254 if (dri2_dpy->dri2) { 255 dri2_surf->dri_drawable = 256 dri2_dpy->dri2->createNewDrawable(dri2_dpy->dri_screen, config, 257 dri2_surf); 258 } else { 259 assert(dri2_dpy->swrast); 260 dri2_surf->dri_drawable = 261 dri2_dpy->swrast->createNewDrawable(dri2_dpy->dri_screen, config, 262 dri2_surf); 263 } 264 265 if (dri2_surf->dri_drawable == NULL) { 266 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); 267 goto cleanup_pixmap; 268 } 269 270 if (type != EGL_PBUFFER_BIT) { 271 cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); 272 reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error); 273 if (error != NULL) { 274 if (error->error_code == BadAlloc) 275 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); 276 else if (type == EGL_WINDOW_BIT) 277 _eglError(EGL_BAD_NATIVE_WINDOW, "xcb_get_geometry"); 278 else 279 _eglError(EGL_BAD_NATIVE_PIXMAP, "xcb_get_geometry"); 280 free(error); 281 goto cleanup_dri_drawable; 282 } else if (reply == NULL) { 283 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); 284 goto cleanup_dri_drawable; 285 } 286 287 dri2_surf->base.Width = reply->width; 288 dri2_surf->base.Height = reply->height; 289 dri2_surf->depth = reply->depth; 290 free(reply); 291 } 292 293 if (dri2_dpy->dri2) { 294 xcb_void_cookie_t cookie; 295 int conn_error; 296 297 cookie = xcb_dri2_create_drawable_checked(dri2_dpy->conn, 298 dri2_surf->drawable); 299 error = xcb_request_check(dri2_dpy->conn, cookie); 300 conn_error = xcb_connection_has_error(dri2_dpy->conn); 301 if (conn_error || error != NULL) { 302 if (type == EGL_PBUFFER_BIT || conn_error || error->error_code == BadAlloc) 303 _eglError(EGL_BAD_ALLOC, "xcb_dri2_create_drawable_checked"); 304 else if (type == EGL_WINDOW_BIT) 305 _eglError(EGL_BAD_NATIVE_WINDOW, 306 "xcb_dri2_create_drawable_checked"); 307 else 308 _eglError(EGL_BAD_NATIVE_PIXMAP, 309 "xcb_dri2_create_drawable_checked"); 310 free(error); 311 goto cleanup_dri_drawable; 312 } 313 } else { 314 if (type == EGL_PBUFFER_BIT) { 315 dri2_surf->depth = _eglGetConfigKey(conf, EGL_BUFFER_SIZE); 316 } 317 swrastCreateDrawable(dri2_dpy, dri2_surf); 318 } 319 320 /* we always copy the back buffer to front */ 321 dri2_surf->base.PostSubBufferSupportedNV = EGL_TRUE; 322 323 return &dri2_surf->base; 324 325 cleanup_dri_drawable: 326 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); 327 cleanup_pixmap: 328 if (type == EGL_PBUFFER_BIT) 329 xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable); 330 cleanup_surf: 331 free(dri2_surf); 332 333 return NULL; 334 } 335 336 /** 337 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). 338 */ 339 static _EGLSurface * 340 dri2_x11_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, 341 _EGLConfig *conf, void *native_window, 342 const EGLint *attrib_list) 343 { 344 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 345 _EGLSurface *surf; 346 347 surf = dri2_x11_create_surface(drv, disp, EGL_WINDOW_BIT, conf, 348 native_window, attrib_list); 349 if (surf != NULL) { 350 /* When we first create the DRI2 drawable, its swap interval on the 351 * server side is 1. 352 */ 353 surf->SwapInterval = 1; 354 355 /* Override that with a driconf-set value. */ 356 dri2_x11_swap_interval(drv, disp, surf, dri2_dpy->default_swap_interval); 357 } 358 359 return surf; 360 } 361 362 static _EGLSurface * 363 dri2_x11_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, 364 _EGLConfig *conf, void *native_pixmap, 365 const EGLint *attrib_list) 366 { 367 return dri2_x11_create_surface(drv, disp, EGL_PIXMAP_BIT, conf, 368 native_pixmap, attrib_list); 369 } 370 371 static _EGLSurface * 372 dri2_x11_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, 373 _EGLConfig *conf, const EGLint *attrib_list) 374 { 375 return dri2_x11_create_surface(drv, disp, EGL_PBUFFER_BIT, conf, 376 NULL, attrib_list); 377 } 378 379 static EGLBoolean 380 dri2_x11_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) 381 { 382 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 383 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 384 385 (void) drv; 386 387 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); 388 389 if (dri2_dpy->dri2) { 390 xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable); 391 } else { 392 assert(dri2_dpy->swrast); 393 swrastDestroyDrawable(dri2_dpy, dri2_surf); 394 } 395 396 if (surf->Type == EGL_PBUFFER_BIT) 397 xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable); 398 399 dri2_fini_surface(surf); 400 free(surf); 401 402 return EGL_TRUE; 403 } 404 405 /** 406 * Function utilizes swrastGetDrawableInfo to get surface 407 * geometry from x server and calls default query surface 408 * implementation that returns the updated values. 409 * 410 * In case of errors we still return values that we currently 411 * have. 412 */ 413 static EGLBoolean 414 dri2_query_surface(_EGLDriver *drv, _EGLDisplay *dpy, 415 _EGLSurface *surf, EGLint attribute, 416 EGLint *value) 417 { 418 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 419 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 420 int x, y, w, h; 421 422 __DRIdrawable *drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 423 424 switch (attribute) { 425 case EGL_WIDTH: 426 case EGL_HEIGHT: 427 if (x11_get_drawable_info(drawable, &x, &y, &w, &h, dri2_surf)) { 428 surf->Width = w; 429 surf->Height = h; 430 } 431 break; 432 default: 433 break; 434 } 435 return _eglQuerySurface(drv, dpy, surf, attribute, value); 436 } 437 438 /** 439 * Process list of buffer received from the server 440 * 441 * Processes the list of buffers received in a reply from the server to either 442 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. 443 */ 444 static void 445 dri2_x11_process_buffers(struct dri2_egl_surface *dri2_surf, 446 xcb_dri2_dri2_buffer_t *buffers, unsigned count) 447 { 448 struct dri2_egl_display *dri2_dpy = 449 dri2_egl_display(dri2_surf->base.Resource.Display); 450 xcb_rectangle_t rectangle; 451 452 dri2_surf->have_fake_front = false; 453 454 /* This assumes the DRI2 buffer attachment tokens matches the 455 * __DRIbuffer tokens. */ 456 for (unsigned i = 0; i < count; i++) { 457 dri2_surf->buffers[i].attachment = buffers[i].attachment; 458 dri2_surf->buffers[i].name = buffers[i].name; 459 dri2_surf->buffers[i].pitch = buffers[i].pitch; 460 dri2_surf->buffers[i].cpp = buffers[i].cpp; 461 dri2_surf->buffers[i].flags = buffers[i].flags; 462 463 /* We only use the DRI drivers single buffer configs. This 464 * means that if we try to render to a window, DRI2 will give us 465 * the fake front buffer, which we'll use as a back buffer. 466 * Note that EGL doesn't require that several clients rendering 467 * to the same window must see the same aux buffers. */ 468 if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) 469 dri2_surf->have_fake_front = true; 470 } 471 472 if (dri2_surf->region != XCB_NONE) 473 xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region); 474 475 rectangle.x = 0; 476 rectangle.y = 0; 477 rectangle.width = dri2_surf->base.Width; 478 rectangle.height = dri2_surf->base.Height; 479 dri2_surf->region = xcb_generate_id(dri2_dpy->conn); 480 xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle); 481 } 482 483 static __DRIbuffer * 484 dri2_x11_get_buffers(__DRIdrawable * driDrawable, 485 int *width, int *height, 486 unsigned int *attachments, int count, 487 int *out_count, void *loaderPrivate) 488 { 489 struct dri2_egl_surface *dri2_surf = loaderPrivate; 490 struct dri2_egl_display *dri2_dpy = 491 dri2_egl_display(dri2_surf->base.Resource.Display); 492 xcb_dri2_dri2_buffer_t *buffers; 493 xcb_dri2_get_buffers_reply_t *reply; 494 xcb_dri2_get_buffers_cookie_t cookie; 495 496 (void) driDrawable; 497 498 cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn, 499 dri2_surf->drawable, 500 count, count, attachments); 501 reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, cookie, NULL); 502 if (reply == NULL) 503 return NULL; 504 buffers = xcb_dri2_get_buffers_buffers (reply); 505 if (buffers == NULL) 506 return NULL; 507 508 *out_count = reply->count; 509 dri2_surf->base.Width = *width = reply->width; 510 dri2_surf->base.Height = *height = reply->height; 511 dri2_x11_process_buffers(dri2_surf, buffers, *out_count); 512 513 free(reply); 514 515 return dri2_surf->buffers; 516 } 517 518 static __DRIbuffer * 519 dri2_x11_get_buffers_with_format(__DRIdrawable * driDrawable, 520 int *width, int *height, 521 unsigned int *attachments, int count, 522 int *out_count, void *loaderPrivate) 523 { 524 struct dri2_egl_surface *dri2_surf = loaderPrivate; 525 struct dri2_egl_display *dri2_dpy = 526 dri2_egl_display(dri2_surf->base.Resource.Display); 527 xcb_dri2_dri2_buffer_t *buffers; 528 xcb_dri2_get_buffers_with_format_reply_t *reply; 529 xcb_dri2_get_buffers_with_format_cookie_t cookie; 530 xcb_dri2_attach_format_t *format_attachments; 531 532 (void) driDrawable; 533 534 format_attachments = (xcb_dri2_attach_format_t *) attachments; 535 cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn, 536 dri2_surf->drawable, 537 count, count, 538 format_attachments); 539 540 reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->conn, 541 cookie, NULL); 542 if (reply == NULL) 543 return NULL; 544 545 buffers = xcb_dri2_get_buffers_with_format_buffers (reply); 546 dri2_surf->base.Width = *width = reply->width; 547 dri2_surf->base.Height = *height = reply->height; 548 *out_count = reply->count; 549 dri2_x11_process_buffers(dri2_surf, buffers, *out_count); 550 551 free(reply); 552 553 return dri2_surf->buffers; 554 } 555 556 static void 557 dri2_x11_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) 558 { 559 (void) driDrawable; 560 561 /* FIXME: Does EGL support front buffer rendering at all? */ 562 563 #if 0 564 struct dri2_egl_surface *dri2_surf = loaderPrivate; 565 566 dri2WaitGL(dri2_surf); 567 #else 568 (void) loaderPrivate; 569 #endif 570 } 571 572 static int 573 dri2_x11_do_authenticate(struct dri2_egl_display *dri2_dpy, uint32_t id) 574 { 575 xcb_dri2_authenticate_reply_t *authenticate; 576 xcb_dri2_authenticate_cookie_t authenticate_cookie; 577 int ret = 0; 578 579 authenticate_cookie = 580 xcb_dri2_authenticate_unchecked(dri2_dpy->conn, dri2_dpy->screen->root, id); 581 authenticate = 582 xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL); 583 584 if (authenticate == NULL || !authenticate->authenticated) 585 ret = -1; 586 587 free(authenticate); 588 589 return ret; 590 } 591 592 static EGLBoolean 593 dri2_x11_local_authenticate(struct dri2_egl_display *dri2_dpy) 594 { 595 #ifdef HAVE_LIBDRM 596 drm_magic_t magic; 597 598 if (drmGetMagic(dri2_dpy->fd, &magic)) { 599 _eglLog(_EGL_WARNING, "DRI2: failed to get drm magic"); 600 return EGL_FALSE; 601 } 602 603 if (dri2_x11_do_authenticate(dri2_dpy, magic) < 0) { 604 _eglLog(_EGL_WARNING, "DRI2: failed to authenticate"); 605 return EGL_FALSE; 606 } 607 #endif 608 return EGL_TRUE; 609 } 610 611 static EGLBoolean 612 dri2_x11_connect(struct dri2_egl_display *dri2_dpy) 613 { 614 xcb_xfixes_query_version_reply_t *xfixes_query; 615 xcb_xfixes_query_version_cookie_t xfixes_query_cookie; 616 xcb_dri2_query_version_reply_t *dri2_query; 617 xcb_dri2_query_version_cookie_t dri2_query_cookie; 618 xcb_dri2_connect_reply_t *connect; 619 xcb_dri2_connect_cookie_t connect_cookie; 620 xcb_generic_error_t *error; 621 char *driver_name, *loader_driver_name, *device_name; 622 const xcb_query_extension_reply_t *extension; 623 624 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id); 625 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id); 626 627 extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id); 628 if (!(extension && extension->present)) 629 return EGL_FALSE; 630 631 extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri2_id); 632 if (!(extension && extension->present)) 633 return EGL_FALSE; 634 635 xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn, 636 XCB_XFIXES_MAJOR_VERSION, 637 XCB_XFIXES_MINOR_VERSION); 638 639 dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn, 640 XCB_DRI2_MAJOR_VERSION, 641 XCB_DRI2_MINOR_VERSION); 642 643 connect_cookie = xcb_dri2_connect_unchecked(dri2_dpy->conn, dri2_dpy->screen->root, 644 XCB_DRI2_DRIVER_TYPE_DRI); 645 646 xfixes_query = 647 xcb_xfixes_query_version_reply (dri2_dpy->conn, 648 xfixes_query_cookie, &error); 649 if (xfixes_query == NULL || 650 error != NULL || xfixes_query->major_version < 2) { 651 _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version"); 652 free(error); 653 free(xfixes_query); 654 return EGL_FALSE; 655 } 656 free(xfixes_query); 657 658 dri2_query = 659 xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error); 660 if (dri2_query == NULL || error != NULL) { 661 _eglLog(_EGL_WARNING, "DRI2: failed to query version"); 662 free(error); 663 return EGL_FALSE; 664 } 665 dri2_dpy->dri2_major = dri2_query->major_version; 666 dri2_dpy->dri2_minor = dri2_query->minor_version; 667 free(dri2_query); 668 669 connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL); 670 if (connect == NULL || 671 connect->driver_name_length + connect->device_name_length == 0) { 672 _eglLog(_EGL_WARNING, "DRI2: failed to authenticate"); 673 return EGL_FALSE; 674 } 675 676 device_name = xcb_dri2_connect_device_name (connect); 677 678 dri2_dpy->fd = loader_open_device(device_name); 679 if (dri2_dpy->fd == -1) { 680 _eglLog(_EGL_WARNING, 681 "DRI2: could not open %s (%s)", device_name, strerror(errno)); 682 free(connect); 683 return EGL_FALSE; 684 } 685 686 if (!dri2_x11_local_authenticate(dri2_dpy)) { 687 close(dri2_dpy->fd); 688 free(connect); 689 return EGL_FALSE; 690 } 691 692 driver_name = xcb_dri2_connect_driver_name (connect); 693 694 /* If Mesa knows about the appropriate driver for this fd, then trust it. 695 * Otherwise, default to the server's value. 696 */ 697 loader_driver_name = loader_get_driver_for_fd(dri2_dpy->fd); 698 if (loader_driver_name) { 699 dri2_dpy->driver_name = loader_driver_name; 700 } else { 701 dri2_dpy->driver_name = 702 strndup(driver_name, 703 xcb_dri2_connect_driver_name_length(connect)); 704 } 705 706 if (dri2_dpy->driver_name == NULL) { 707 close(dri2_dpy->fd); 708 free(connect); 709 return EGL_FALSE; 710 } 711 712 #ifdef HAVE_WAYLAND_PLATFORM 713 dri2_dpy->device_name = 714 strndup(device_name, 715 xcb_dri2_connect_device_name_length(connect)); 716 #endif 717 718 free(connect); 719 720 return EGL_TRUE; 721 } 722 723 static int 724 dri2_x11_authenticate(_EGLDisplay *disp, uint32_t id) 725 { 726 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 727 728 return dri2_x11_do_authenticate(dri2_dpy, id); 729 } 730 731 static EGLBoolean 732 dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy, 733 _EGLDisplay *disp, bool supports_preserved) 734 { 735 xcb_depth_iterator_t d; 736 xcb_visualtype_t *visuals; 737 int config_count = 0; 738 EGLint surface_type; 739 740 d = xcb_screen_allowed_depths_iterator(dri2_dpy->screen); 741 742 surface_type = 743 EGL_WINDOW_BIT | 744 EGL_PIXMAP_BIT | 745 EGL_PBUFFER_BIT; 746 747 if (supports_preserved) 748 surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 749 750 while (d.rem > 0) { 751 EGLBoolean class_added[6] = { 0, }; 752 753 visuals = xcb_depth_visuals(d.data); 754 755 for (int i = 0; i < xcb_depth_visuals_length(d.data); i++) { 756 if (class_added[visuals[i]._class]) 757 continue; 758 759 class_added[visuals[i]._class] = EGL_TRUE; 760 761 for (int j = 0; dri2_dpy->driver_configs[j]; j++) { 762 struct dri2_egl_config *dri2_conf; 763 const __DRIconfig *config = dri2_dpy->driver_configs[j]; 764 765 const EGLint config_attrs[] = { 766 EGL_NATIVE_VISUAL_ID, visuals[i].visual_id, 767 EGL_NATIVE_VISUAL_TYPE, visuals[i]._class, 768 EGL_NONE 769 }; 770 771 unsigned int rgba_masks[4] = { 772 visuals[i].red_mask, 773 visuals[i].green_mask, 774 visuals[i].blue_mask, 775 0, 776 }; 777 778 dri2_conf = dri2_add_config(disp, config, config_count + 1, 779 surface_type, config_attrs, 780 rgba_masks); 781 if (dri2_conf) 782 if (dri2_conf->base.ConfigID == config_count + 1) 783 config_count++; 784 785 /* Allow a 24-bit RGB visual to match a 32-bit RGBA EGLConfig. 786 * Ditto for 30-bit RGB visuals to match a 32-bit RGBA EGLConfig. 787 * Otherwise it will only match a 32-bit RGBA visual. On a 788 * composited window manager on X11, this will make all of the 789 * EGLConfigs with destination alpha get blended by the 790 * compositor. This is probably not what the application 791 * wants... especially on drivers that only have 32-bit RGBA 792 * EGLConfigs! */ 793 if (d.data->depth == 24 || d.data->depth == 30) { 794 rgba_masks[3] = 795 ~(rgba_masks[0] | rgba_masks[1] | rgba_masks[2]); 796 dri2_conf = dri2_add_config(disp, config, config_count + 1, 797 surface_type, config_attrs, 798 rgba_masks); 799 if (dri2_conf) 800 if (dri2_conf->base.ConfigID == config_count + 1) 801 config_count++; 802 } 803 } 804 } 805 806 xcb_depth_next(&d); 807 } 808 809 if (!config_count) { 810 _eglLog(_EGL_WARNING, "DRI2: failed to create any config"); 811 return EGL_FALSE; 812 } 813 814 return EGL_TRUE; 815 } 816 817 static EGLBoolean 818 dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp, 819 _EGLSurface *draw, xcb_xfixes_region_t region) 820 { 821 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 822 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 823 enum xcb_dri2_attachment_t render_attachment; 824 xcb_dri2_copy_region_cookie_t cookie; 825 826 /* No-op for a pixmap or pbuffer surface */ 827 if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT) 828 return EGL_TRUE; 829 830 dri2_dpy->flush->flush(dri2_surf->dri_drawable); 831 832 if (dri2_surf->have_fake_front) 833 render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT; 834 else 835 render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT; 836 837 cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn, 838 dri2_surf->drawable, 839 region, 840 XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, 841 render_attachment); 842 free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL)); 843 844 return EGL_TRUE; 845 } 846 847 static int64_t 848 dri2_x11_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, 849 int64_t msc, int64_t divisor, int64_t remainder) 850 { 851 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 852 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 853 uint32_t msc_hi = msc >> 32; 854 uint32_t msc_lo = msc & 0xffffffff; 855 uint32_t divisor_hi = divisor >> 32; 856 uint32_t divisor_lo = divisor & 0xffffffff; 857 uint32_t remainder_hi = remainder >> 32; 858 uint32_t remainder_lo = remainder & 0xffffffff; 859 xcb_dri2_swap_buffers_cookie_t cookie; 860 xcb_dri2_swap_buffers_reply_t *reply; 861 int64_t swap_count = -1; 862 863 /* No-op for a pixmap or pbuffer surface */ 864 if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT) 865 return 0; 866 867 if (draw->SwapBehavior == EGL_BUFFER_PRESERVED || !dri2_dpy->swap_available) 868 return dri2_copy_region(drv, disp, draw, dri2_surf->region) ? 0 : -1; 869 870 dri2_flush_drawable_for_swapbuffers(disp, draw); 871 872 cookie = xcb_dri2_swap_buffers_unchecked(dri2_dpy->conn, dri2_surf->drawable, 873 msc_hi, msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo); 874 875 reply = xcb_dri2_swap_buffers_reply(dri2_dpy->conn, cookie, NULL); 876 877 if (reply) { 878 swap_count = (((int64_t)reply->swap_hi) << 32) | reply->swap_lo; 879 free(reply); 880 } 881 882 /* Since we aren't watching for the server's invalidate events like we're 883 * supposed to (due to XCB providing no mechanism for filtering the events 884 * the way xlib does), and SwapBuffers is a common cause of invalidate 885 * events, just shove one down to the driver, even though we haven't told 886 * the driver that we're the kind of loader that provides reliable 887 * invalidate events. This causes the driver to request buffers again at 888 * its next draw, so that we get the correct buffers if a pageflip 889 * happened. The driver should still be using the viewport hack to catch 890 * window resizes. 891 */ 892 if (dri2_dpy->flush->base.version >= 3 && dri2_dpy->flush->invalidate) 893 dri2_dpy->flush->invalidate(dri2_surf->dri_drawable); 894 895 return swap_count; 896 } 897 898 static EGLBoolean 899 dri2_x11_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) 900 { 901 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 902 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 903 904 if (!dri2_dpy->flush) { 905 dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable); 906 return EGL_TRUE; 907 } 908 909 if (dri2_x11_swap_buffers_msc(drv, disp, draw, 0, 0, 0) == -1) { 910 /* Swap failed with a window drawable. */ 911 return _eglError(EGL_BAD_NATIVE_WINDOW, __func__); 912 } 913 return EGL_TRUE; 914 } 915 916 static EGLBoolean 917 dri2_x11_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, 918 _EGLSurface *draw, 919 EGLint numRects, const EGLint *rects) 920 { 921 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 922 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 923 EGLBoolean ret; 924 xcb_xfixes_region_t region; 925 xcb_rectangle_t rectangles[16]; 926 927 if (numRects > (int)ARRAY_SIZE(rectangles)) 928 return dri2_copy_region(drv, disp, draw, dri2_surf->region); 929 930 for (int i = 0; i < numRects; i++) { 931 rectangles[i].x = rects[i * 4]; 932 rectangles[i].y = dri2_surf->base.Height - rects[i * 4 + 1] - rects[i * 4 + 3]; 933 rectangles[i].width = rects[i * 4 + 2]; 934 rectangles[i].height = rects[i * 4 + 3]; 935 } 936 937 region = xcb_generate_id(dri2_dpy->conn); 938 xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles); 939 ret = dri2_copy_region(drv, disp, draw, region); 940 xcb_xfixes_destroy_region(dri2_dpy->conn, region); 941 942 return ret; 943 } 944 945 static EGLBoolean 946 dri2_x11_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, 947 EGLint x, EGLint y, EGLint width, EGLint height) 948 { 949 const EGLint rect[4] = { x, y, width, height }; 950 951 if (x < 0 || y < 0 || width < 0 || height < 0) 952 _eglError(EGL_BAD_PARAMETER, "eglPostSubBufferNV"); 953 954 return dri2_x11_swap_buffers_region(drv, disp, draw, 1, rect); 955 } 956 957 static EGLBoolean 958 dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, 959 EGLint interval) 960 { 961 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 962 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 963 964 if (dri2_dpy->swap_available) 965 xcb_dri2_swap_interval(dri2_dpy->conn, dri2_surf->drawable, interval); 966 967 return EGL_TRUE; 968 } 969 970 static EGLBoolean 971 dri2_x11_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, 972 void *native_pixmap_target) 973 { 974 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 975 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 976 xcb_gcontext_t gc; 977 xcb_pixmap_t target; 978 979 STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_pixmap_target)); 980 target = (uintptr_t) native_pixmap_target; 981 982 (void) drv; 983 984 dri2_dpy->flush->flush(dri2_surf->dri_drawable); 985 986 gc = xcb_generate_id(dri2_dpy->conn); 987 xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL); 988 xcb_copy_area(dri2_dpy->conn, 989 dri2_surf->drawable, 990 target, 991 gc, 992 0, 0, 993 0, 0, 994 dri2_surf->base.Width, 995 dri2_surf->base.Height); 996 xcb_free_gc(dri2_dpy->conn, gc); 997 998 return EGL_TRUE; 999 } 1000 1001 static _EGLImage * 1002 dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, 1003 EGLClientBuffer buffer, const EGLint *attr_list) 1004 { 1005 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1006 struct dri2_egl_image *dri2_img; 1007 unsigned int attachments[1]; 1008 xcb_drawable_t drawable; 1009 xcb_dri2_get_buffers_cookie_t buffers_cookie; 1010 xcb_dri2_get_buffers_reply_t *buffers_reply; 1011 xcb_dri2_dri2_buffer_t *buffers; 1012 xcb_get_geometry_cookie_t geometry_cookie; 1013 xcb_get_geometry_reply_t *geometry_reply; 1014 xcb_generic_error_t *error; 1015 int stride, format; 1016 1017 (void) ctx; 1018 1019 drawable = (xcb_drawable_t) (uintptr_t) buffer; 1020 xcb_dri2_create_drawable (dri2_dpy->conn, drawable); 1021 attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT; 1022 buffers_cookie = 1023 xcb_dri2_get_buffers_unchecked (dri2_dpy->conn, 1024 drawable, 1, 1, attachments); 1025 geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable); 1026 buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, 1027 buffers_cookie, NULL); 1028 if (buffers_reply == NULL) 1029 return NULL; 1030 1031 buffers = xcb_dri2_get_buffers_buffers (buffers_reply); 1032 if (buffers == NULL) { 1033 return NULL; 1034 } 1035 1036 geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn, 1037 geometry_cookie, &error); 1038 if (geometry_reply == NULL || error != NULL) { 1039 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); 1040 free(error); 1041 free(buffers_reply); 1042 return NULL; 1043 } 1044 1045 switch (geometry_reply->depth) { 1046 case 16: 1047 format = __DRI_IMAGE_FORMAT_RGB565; 1048 break; 1049 case 24: 1050 format = __DRI_IMAGE_FORMAT_XRGB8888; 1051 break; 1052 case 30: 1053 format = __DRI_IMAGE_FORMAT_XRGB2101010; 1054 break; 1055 case 32: 1056 format = __DRI_IMAGE_FORMAT_ARGB8888; 1057 break; 1058 default: 1059 _eglError(EGL_BAD_PARAMETER, 1060 "dri2_create_image_khr: unsupported pixmap depth"); 1061 free(buffers_reply); 1062 free(geometry_reply); 1063 return NULL; 1064 } 1065 1066 dri2_img = malloc(sizeof *dri2_img); 1067 if (!dri2_img) { 1068 free(buffers_reply); 1069 free(geometry_reply); 1070 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 1071 return EGL_NO_IMAGE_KHR; 1072 } 1073 1074 _eglInitImage(&dri2_img->base, disp); 1075 1076 stride = buffers[0].pitch / buffers[0].cpp; 1077 dri2_img->dri_image = 1078 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 1079 buffers_reply->width, 1080 buffers_reply->height, 1081 format, 1082 buffers[0].name, 1083 stride, 1084 dri2_img); 1085 1086 free(buffers_reply); 1087 free(geometry_reply); 1088 1089 return &dri2_img->base; 1090 } 1091 1092 static _EGLImage * 1093 dri2_x11_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 1094 _EGLContext *ctx, EGLenum target, 1095 EGLClientBuffer buffer, const EGLint *attr_list) 1096 { 1097 (void) drv; 1098 1099 switch (target) { 1100 case EGL_NATIVE_PIXMAP_KHR: 1101 return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list); 1102 default: 1103 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list); 1104 } 1105 } 1106 1107 static EGLBoolean 1108 dri2_x11_get_sync_values(_EGLDisplay *display, _EGLSurface *surface, 1109 EGLuint64KHR *ust, EGLuint64KHR *msc, 1110 EGLuint64KHR *sbc) 1111 { 1112 struct dri2_egl_display *dri2_dpy = dri2_egl_display(display); 1113 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface); 1114 xcb_dri2_get_msc_cookie_t cookie; 1115 xcb_dri2_get_msc_reply_t *reply; 1116 1117 cookie = xcb_dri2_get_msc(dri2_dpy->conn, dri2_surf->drawable); 1118 reply = xcb_dri2_get_msc_reply(dri2_dpy->conn, cookie, NULL); 1119 1120 if (!reply) 1121 return _eglError(EGL_BAD_ACCESS, __func__); 1122 1123 *ust = ((EGLuint64KHR) reply->ust_hi << 32) | reply->ust_lo; 1124 *msc = ((EGLuint64KHR) reply->msc_hi << 32) | reply->msc_lo; 1125 *sbc = ((EGLuint64KHR) reply->sbc_hi << 32) | reply->sbc_lo; 1126 free(reply); 1127 1128 return EGL_TRUE; 1129 } 1130 1131 static const struct dri2_egl_display_vtbl dri2_x11_swrast_display_vtbl = { 1132 .authenticate = NULL, 1133 .create_window_surface = dri2_x11_create_window_surface, 1134 .create_pixmap_surface = dri2_x11_create_pixmap_surface, 1135 .create_pbuffer_surface = dri2_x11_create_pbuffer_surface, 1136 .destroy_surface = dri2_x11_destroy_surface, 1137 .create_image = dri2_create_image_khr, 1138 .swap_buffers = dri2_x11_swap_buffers, 1139 .set_damage_region = dri2_fallback_set_damage_region, 1140 .swap_buffers_region = dri2_fallback_swap_buffers_region, 1141 .post_sub_buffer = dri2_fallback_post_sub_buffer, 1142 .copy_buffers = dri2_x11_copy_buffers, 1143 .query_buffer_age = dri2_fallback_query_buffer_age, 1144 .query_surface = dri2_query_surface, 1145 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image, 1146 .get_sync_values = dri2_fallback_get_sync_values, 1147 .get_dri_drawable = dri2_surface_get_dri_drawable, 1148 }; 1149 1150 static const struct dri2_egl_display_vtbl dri2_x11_display_vtbl = { 1151 .authenticate = dri2_x11_authenticate, 1152 .create_window_surface = dri2_x11_create_window_surface, 1153 .create_pixmap_surface = dri2_x11_create_pixmap_surface, 1154 .create_pbuffer_surface = dri2_x11_create_pbuffer_surface, 1155 .destroy_surface = dri2_x11_destroy_surface, 1156 .create_image = dri2_x11_create_image_khr, 1157 .swap_interval = dri2_x11_swap_interval, 1158 .swap_buffers = dri2_x11_swap_buffers, 1159 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage, 1160 .swap_buffers_region = dri2_x11_swap_buffers_region, 1161 .set_damage_region = dri2_fallback_set_damage_region, 1162 .post_sub_buffer = dri2_x11_post_sub_buffer, 1163 .copy_buffers = dri2_x11_copy_buffers, 1164 .query_buffer_age = dri2_fallback_query_buffer_age, 1165 .query_surface = dri2_query_surface, 1166 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image, 1167 .get_sync_values = dri2_x11_get_sync_values, 1168 .get_dri_drawable = dri2_surface_get_dri_drawable, 1169 }; 1170 1171 static const __DRIswrastLoaderExtension swrast_loader_extension = { 1172 .base = { __DRI_SWRAST_LOADER, 1 }, 1173 1174 .getDrawableInfo = swrastGetDrawableInfo, 1175 .putImage = swrastPutImage, 1176 .getImage = swrastGetImage, 1177 }; 1178 1179 static const __DRIextension *swrast_loader_extensions[] = { 1180 &swrast_loader_extension.base, 1181 &image_lookup_extension.base, 1182 NULL, 1183 }; 1184 1185 static EGLBoolean 1186 dri2_get_xcb_connection(_EGLDriver *drv, _EGLDisplay *disp, 1187 struct dri2_egl_display *dri2_dpy) 1188 { 1189 xcb_screen_iterator_t s; 1190 int screen = (uintptr_t)disp->Options.Platform; 1191 const char *msg; 1192 1193 disp->DriverData = (void *) dri2_dpy; 1194 if (disp->PlatformDisplay == NULL) { 1195 dri2_dpy->conn = xcb_connect(NULL, &screen); 1196 dri2_dpy->own_device = true; 1197 } else { 1198 Display *dpy = disp->PlatformDisplay; 1199 1200 dri2_dpy->conn = XGetXCBConnection(dpy); 1201 screen = DefaultScreen(dpy); 1202 } 1203 1204 if (!dri2_dpy->conn || xcb_connection_has_error(dri2_dpy->conn)) { 1205 msg = "xcb_connect failed"; 1206 goto disconnect; 1207 } 1208 1209 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); 1210 dri2_dpy->screen = get_xcb_screen(s, screen); 1211 if (!dri2_dpy->screen) { 1212 msg = "failed to get xcb screen"; 1213 goto disconnect; 1214 } 1215 1216 return EGL_TRUE; 1217 disconnect: 1218 if (disp->PlatformDisplay == NULL) 1219 xcb_disconnect(dri2_dpy->conn); 1220 1221 return _eglError(EGL_BAD_ALLOC, msg); 1222 } 1223 1224 static EGLBoolean 1225 dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp) 1226 { 1227 struct dri2_egl_display *dri2_dpy; 1228 1229 dri2_dpy = calloc(1, sizeof *dri2_dpy); 1230 if (!dri2_dpy) 1231 return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 1232 1233 dri2_dpy->fd = -1; 1234 if (!dri2_get_xcb_connection(drv, disp, dri2_dpy)) 1235 goto cleanup; 1236 1237 /* 1238 * Every hardware driver_name is set using strdup. Doing the same in 1239 * here will allow is to simply free the memory at dri2_terminate(). 1240 */ 1241 dri2_dpy->driver_name = strdup("swrast"); 1242 if (!dri2_load_driver_swrast(disp)) 1243 goto cleanup; 1244 1245 dri2_dpy->loader_extensions = swrast_loader_extensions; 1246 1247 if (!dri2_create_screen(disp)) 1248 goto cleanup; 1249 1250 if (!dri2_setup_extensions(disp)) 1251 goto cleanup; 1252 1253 dri2_setup_screen(disp); 1254 1255 if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true)) 1256 goto cleanup; 1257 1258 /* Fill vtbl last to prevent accidentally calling virtual function during 1259 * initialization. 1260 */ 1261 dri2_dpy->vtbl = &dri2_x11_swrast_display_vtbl; 1262 1263 return EGL_TRUE; 1264 1265 cleanup: 1266 dri2_display_destroy(disp); 1267 return EGL_FALSE; 1268 } 1269 1270 static void 1271 dri2_x11_setup_swap_interval(_EGLDisplay *disp) 1272 { 1273 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1274 int arbitrary_max_interval = 1000; 1275 1276 /* default behavior for no SwapBuffers support: no vblank syncing 1277 * either. 1278 */ 1279 dri2_dpy->min_swap_interval = 0; 1280 dri2_dpy->max_swap_interval = 0; 1281 dri2_dpy->default_swap_interval = 0; 1282 1283 if (!dri2_dpy->swap_available) 1284 return; 1285 1286 /* If we do have swapbuffers, then we can support pretty much any swap 1287 * interval. 1288 */ 1289 dri2_setup_swap_interval(disp, arbitrary_max_interval); 1290 } 1291 1292 #ifdef HAVE_DRI3 1293 1294 static const __DRIextension *dri3_image_loader_extensions[] = { 1295 &dri3_image_loader_extension.base, 1296 &image_lookup_extension.base, 1297 &use_invalidate.base, 1298 &background_callable_extension.base, 1299 NULL, 1300 }; 1301 1302 static EGLBoolean 1303 dri2_initialize_x11_dri3(_EGLDriver *drv, _EGLDisplay *disp) 1304 { 1305 struct dri2_egl_display *dri2_dpy; 1306 1307 dri2_dpy = calloc(1, sizeof *dri2_dpy); 1308 if (!dri2_dpy) 1309 return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 1310 1311 dri2_dpy->fd = -1; 1312 if (!dri2_get_xcb_connection(drv, disp, dri2_dpy)) 1313 goto cleanup; 1314 1315 if (!dri3_x11_connect(dri2_dpy)) 1316 goto cleanup; 1317 1318 if (!dri2_load_driver_dri3(disp)) 1319 goto cleanup; 1320 1321 dri2_dpy->loader_extensions = dri3_image_loader_extensions; 1322 1323 dri2_dpy->swap_available = true; 1324 dri2_dpy->invalidate_available = true; 1325 1326 if (!dri2_create_screen(disp)) 1327 goto cleanup; 1328 1329 if (!dri2_setup_extensions(disp)) 1330 goto cleanup; 1331 1332 dri2_setup_screen(disp); 1333 1334 dri2_x11_setup_swap_interval(disp); 1335 1336 if (!dri2_dpy->is_different_gpu) 1337 disp->Extensions.KHR_image_pixmap = EGL_TRUE; 1338 disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE; 1339 disp->Extensions.CHROMIUM_sync_control = EGL_TRUE; 1340 disp->Extensions.EXT_buffer_age = EGL_TRUE; 1341 1342 dri2_set_WL_bind_wayland_display(drv, disp); 1343 1344 if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, false)) 1345 goto cleanup; 1346 1347 dri2_dpy->loader_dri3_ext.core = dri2_dpy->core; 1348 dri2_dpy->loader_dri3_ext.image_driver = dri2_dpy->image_driver; 1349 dri2_dpy->loader_dri3_ext.flush = dri2_dpy->flush; 1350 dri2_dpy->loader_dri3_ext.tex_buffer = dri2_dpy->tex_buffer; 1351 dri2_dpy->loader_dri3_ext.image = dri2_dpy->image; 1352 dri2_dpy->loader_dri3_ext.config = dri2_dpy->config; 1353 1354 /* Fill vtbl last to prevent accidentally calling virtual function during 1355 * initialization. 1356 */ 1357 dri2_dpy->vtbl = &dri3_x11_display_vtbl; 1358 1359 _eglLog(_EGL_INFO, "Using DRI3"); 1360 1361 return EGL_TRUE; 1362 1363 cleanup: 1364 dri2_display_destroy(disp); 1365 return EGL_FALSE; 1366 } 1367 #endif 1368 1369 static const __DRIdri2LoaderExtension dri2_loader_extension_old = { 1370 .base = { __DRI_DRI2_LOADER, 2 }, 1371 1372 .getBuffers = dri2_x11_get_buffers, 1373 .flushFrontBuffer = dri2_x11_flush_front_buffer, 1374 .getBuffersWithFormat = NULL, 1375 }; 1376 1377 static const __DRIdri2LoaderExtension dri2_loader_extension = { 1378 .base = { __DRI_DRI2_LOADER, 3 }, 1379 1380 .getBuffers = dri2_x11_get_buffers, 1381 .flushFrontBuffer = dri2_x11_flush_front_buffer, 1382 .getBuffersWithFormat = dri2_x11_get_buffers_with_format, 1383 }; 1384 1385 static const __DRIextension *dri2_loader_extensions_old[] = { 1386 &dri2_loader_extension_old.base, 1387 &image_lookup_extension.base, 1388 &background_callable_extension.base, 1389 NULL, 1390 }; 1391 1392 static const __DRIextension *dri2_loader_extensions[] = { 1393 &dri2_loader_extension.base, 1394 &image_lookup_extension.base, 1395 &use_invalidate.base, 1396 &background_callable_extension.base, 1397 NULL, 1398 }; 1399 1400 static EGLBoolean 1401 dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp) 1402 { 1403 struct dri2_egl_display *dri2_dpy; 1404 1405 dri2_dpy = calloc(1, sizeof *dri2_dpy); 1406 if (!dri2_dpy) 1407 return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 1408 1409 dri2_dpy->fd = -1; 1410 if (!dri2_get_xcb_connection(drv, disp, dri2_dpy)) 1411 goto cleanup; 1412 1413 if (!dri2_x11_connect(dri2_dpy)) 1414 goto cleanup; 1415 1416 if (!dri2_load_driver(disp)) 1417 goto cleanup; 1418 1419 if (dri2_dpy->dri2_minor >= 1) 1420 dri2_dpy->loader_extensions = dri2_loader_extensions; 1421 else 1422 dri2_dpy->loader_extensions = dri2_loader_extensions_old; 1423 1424 dri2_dpy->swap_available = (dri2_dpy->dri2_minor >= 2); 1425 dri2_dpy->invalidate_available = (dri2_dpy->dri2_minor >= 3); 1426 1427 if (!dri2_create_screen(disp)) 1428 goto cleanup; 1429 1430 if (!dri2_setup_extensions(disp)) 1431 goto cleanup; 1432 1433 dri2_setup_screen(disp); 1434 1435 dri2_x11_setup_swap_interval(disp); 1436 1437 disp->Extensions.KHR_image_pixmap = EGL_TRUE; 1438 disp->Extensions.NOK_swap_region = EGL_TRUE; 1439 disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE; 1440 disp->Extensions.NV_post_sub_buffer = EGL_TRUE; 1441 disp->Extensions.CHROMIUM_sync_control = EGL_TRUE; 1442 1443 dri2_set_WL_bind_wayland_display(drv, disp); 1444 1445 if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true)) 1446 goto cleanup; 1447 1448 /* Fill vtbl last to prevent accidentally calling virtual function during 1449 * initialization. 1450 */ 1451 dri2_dpy->vtbl = &dri2_x11_display_vtbl; 1452 1453 _eglLog(_EGL_INFO, "Using DRI2"); 1454 1455 return EGL_TRUE; 1456 1457 cleanup: 1458 dri2_display_destroy(disp); 1459 return EGL_FALSE; 1460 } 1461 1462 EGLBoolean 1463 dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) 1464 { 1465 EGLBoolean initialized = EGL_FALSE; 1466 1467 if (!disp->Options.ForceSoftware) { 1468 #ifdef HAVE_DRI3 1469 if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false)) 1470 initialized = dri2_initialize_x11_dri3(drv, disp); 1471 #endif 1472 1473 if (!initialized) 1474 initialized = dri2_initialize_x11_dri2(drv, disp); 1475 } 1476 1477 if (!initialized) 1478 initialized = dri2_initialize_x11_swrast(drv, disp); 1479 1480 return initialized; 1481 } 1482 1483 void 1484 dri2_teardown_x11(struct dri2_egl_display *dri2_dpy) 1485 { 1486 if (dri2_dpy->own_device) 1487 xcb_disconnect(dri2_dpy->conn); 1488 } 1489