1 /* 2 * Copyright 2013 Keith Packard 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 /* 24 * Portions of this code were adapted from dri2_glx.c which carries the 25 * following copyright: 26 * 27 * Copyright 2008 Red Hat, Inc. 28 * 29 * Permission is hereby granted, free of charge, to any person obtaining a 30 * copy of this software and associated documentation files (the "Soft- 31 * ware"), to deal in the Software without restriction, including without 32 * limitation the rights to use, copy, modify, merge, publish, distribute, 33 * and/or sell copies of the Software, and to permit persons to whom the 34 * Software is furnished to do so, provided that the above copyright 35 * notice(s) and this permission notice appear in all copies of the Soft- 36 * ware and that both the above copyright notice(s) and this permission 37 * notice appear in supporting documentation. 38 * 39 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 40 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 41 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 42 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 43 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 44 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 45 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 46 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 47 * MANCE OF THIS SOFTWARE. 48 * 49 * Except as contained in this notice, the name of a copyright holder shall 50 * not be used in advertising or otherwise to promote the sale, use or 51 * other dealings in this Software without prior written authorization of 52 * the copyright holder. 53 * 54 * Authors: 55 * Kristian Hgsberg (krh (at) redhat.com) 56 */ 57 58 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 59 60 #include <X11/Xlib.h> 61 #include <X11/extensions/Xfixes.h> 62 #include <X11/Xlib-xcb.h> 63 #include <X11/xshmfence.h> 64 #include <xcb/xcb.h> 65 #include <xcb/dri3.h> 66 #include <xcb/present.h> 67 #include <GL/gl.h> 68 #include "glxclient.h" 69 #include <dlfcn.h> 70 #include <fcntl.h> 71 #include <unistd.h> 72 #include <sys/types.h> 73 #include <sys/mman.h> 74 #include <sys/time.h> 75 76 #include "dri_common.h" 77 #include "dri3_priv.h" 78 #include "loader.h" 79 #include "dri2.h" 80 81 static struct dri3_drawable * 82 loader_drawable_to_dri3_drawable(struct loader_dri3_drawable *draw) { 83 size_t offset = offsetof(struct dri3_drawable, loader_drawable); 84 if (!draw) 85 return NULL; 86 return (struct dri3_drawable *)(((void*) draw) - offset); 87 } 88 89 static int 90 glx_dri3_get_swap_interval(struct loader_dri3_drawable *draw) 91 { 92 struct dri3_drawable *priv = loader_drawable_to_dri3_drawable(draw); 93 94 return priv->swap_interval; 95 } 96 97 static int 98 glx_dri3_clamp_swap_interval(struct loader_dri3_drawable *draw, int interval) 99 { 100 return interval; 101 } 102 103 static void 104 glx_dri3_set_swap_interval(struct loader_dri3_drawable *draw, int interval) 105 { 106 struct dri3_drawable *priv = loader_drawable_to_dri3_drawable(draw); 107 108 priv->swap_interval = interval; 109 } 110 111 static void 112 glx_dri3_set_drawable_size(struct loader_dri3_drawable *draw, 113 int width, int height) 114 { 115 /* Nothing to do */ 116 } 117 118 static bool 119 glx_dri3_in_current_context(struct loader_dri3_drawable *draw) 120 { 121 struct dri3_drawable *priv = loader_drawable_to_dri3_drawable(draw); 122 123 if (!priv) 124 return false; 125 126 struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext(); 127 struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc; 128 129 return (&pcp->base != &dummyContext) && pcp->base.psc == &psc->base; 130 } 131 132 static __DRIcontext * 133 glx_dri3_get_dri_context(struct loader_dri3_drawable *draw) 134 { 135 struct glx_context *gc = __glXGetCurrentContext(); 136 struct dri3_context *dri3Ctx = (struct dri3_context *) gc; 137 138 return (gc != &dummyContext) ? dri3Ctx->driContext : NULL; 139 } 140 141 static __DRIscreen * 142 glx_dri3_get_dri_screen(struct loader_dri3_drawable *draw) 143 { 144 struct glx_context *gc = __glXGetCurrentContext(); 145 struct dri3_context *pcp = (struct dri3_context *) gc; 146 struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc; 147 148 return (gc != &dummyContext && psc) ? psc->driScreen : NULL; 149 } 150 151 static void 152 glx_dri3_flush_drawable(struct loader_dri3_drawable *draw, unsigned flags) 153 { 154 loader_dri3_flush(draw, flags, __DRI2_THROTTLE_SWAPBUFFER); 155 } 156 157 static void 158 glx_dri3_show_fps(struct loader_dri3_drawable *draw, uint64_t current_ust) 159 { 160 struct dri3_drawable *priv = loader_drawable_to_dri3_drawable(draw); 161 const uint64_t interval = 162 ((struct dri3_screen *) priv->base.psc)->show_fps_interval; 163 164 if (!interval) 165 return; 166 167 priv->frames++; 168 169 /* DRI3+Present together uses microseconds for UST. */ 170 if (priv->previous_ust + interval * 1000000 <= current_ust) { 171 if (priv->previous_ust) { 172 fprintf(stderr, "libGL: FPS = %.1f\n", 173 ((uint64_t) priv->frames * 1000000) / 174 (double)(current_ust - priv->previous_ust)); 175 } 176 priv->frames = 0; 177 priv->previous_ust = current_ust; 178 } 179 } 180 181 static const struct loader_dri3_vtable glx_dri3_vtable = { 182 .get_swap_interval = glx_dri3_get_swap_interval, 183 .clamp_swap_interval = glx_dri3_clamp_swap_interval, 184 .set_swap_interval = glx_dri3_set_swap_interval, 185 .set_drawable_size = glx_dri3_set_drawable_size, 186 .in_current_context = glx_dri3_in_current_context, 187 .get_dri_context = glx_dri3_get_dri_context, 188 .get_dri_screen = glx_dri3_get_dri_screen, 189 .flush_drawable = glx_dri3_flush_drawable, 190 .show_fps = glx_dri3_show_fps, 191 }; 192 193 194 static const struct glx_context_vtable dri3_context_vtable; 195 196 static void 197 dri3_destroy_context(struct glx_context *context) 198 { 199 struct dri3_context *pcp = (struct dri3_context *) context; 200 struct dri3_screen *psc = (struct dri3_screen *) context->psc; 201 202 driReleaseDrawables(&pcp->base); 203 204 free((char *) context->extensions); 205 206 (*psc->core->destroyContext) (pcp->driContext); 207 208 free(pcp); 209 } 210 211 static Bool 212 dri3_bind_context(struct glx_context *context, struct glx_context *old, 213 GLXDrawable draw, GLXDrawable read) 214 { 215 struct dri3_context *pcp = (struct dri3_context *) context; 216 struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc; 217 struct dri3_drawable *pdraw, *pread; 218 __DRIdrawable *dri_draw = NULL, *dri_read = NULL; 219 220 pdraw = (struct dri3_drawable *) driFetchDrawable(context, draw); 221 pread = (struct dri3_drawable *) driFetchDrawable(context, read); 222 223 driReleaseDrawables(&pcp->base); 224 225 if (pdraw) 226 dri_draw = pdraw->loader_drawable.dri_drawable; 227 else if (draw != None) 228 return GLXBadDrawable; 229 230 if (pread) 231 dri_read = pread->loader_drawable.dri_drawable; 232 else if (read != None) 233 return GLXBadDrawable; 234 235 if (!(*psc->core->bindContext) (pcp->driContext, dri_draw, dri_read)) 236 return GLXBadContext; 237 238 return Success; 239 } 240 241 static void 242 dri3_unbind_context(struct glx_context *context, struct glx_context *new) 243 { 244 struct dri3_context *pcp = (struct dri3_context *) context; 245 struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc; 246 247 (*psc->core->unbindContext) (pcp->driContext); 248 } 249 250 static struct glx_context * 251 dri3_create_context_attribs(struct glx_screen *base, 252 struct glx_config *config_base, 253 struct glx_context *shareList, 254 unsigned num_attribs, 255 const uint32_t *attribs, 256 unsigned *error) 257 { 258 struct dri3_context *pcp = NULL; 259 struct dri3_context *pcp_shared = NULL; 260 struct dri3_screen *psc = (struct dri3_screen *) base; 261 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 262 __DRIcontext *shared = NULL; 263 264 uint32_t minor_ver = 1; 265 uint32_t major_ver = 2; 266 uint32_t flags = 0; 267 unsigned api; 268 int reset = __DRI_CTX_RESET_NO_NOTIFICATION; 269 uint32_t ctx_attribs[2 * 5]; 270 unsigned num_ctx_attribs = 0; 271 uint32_t render_type; 272 273 /* Remap the GLX tokens to DRI2 tokens. 274 */ 275 if (!dri2_convert_glx_attribs(num_attribs, attribs, 276 &major_ver, &minor_ver, 277 &render_type, &flags, &api, 278 &reset, error)) 279 goto error_exit; 280 281 /* Check the renderType value */ 282 if (!validate_renderType_against_config(config_base, render_type)) 283 goto error_exit; 284 285 if (shareList) { 286 pcp_shared = (struct dri3_context *) shareList; 287 shared = pcp_shared->driContext; 288 } 289 290 pcp = calloc(1, sizeof *pcp); 291 if (pcp == NULL) { 292 *error = __DRI_CTX_ERROR_NO_MEMORY; 293 goto error_exit; 294 } 295 296 if (!glx_context_init(&pcp->base, &psc->base, &config->base)) 297 goto error_exit; 298 299 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION; 300 ctx_attribs[num_ctx_attribs++] = major_ver; 301 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION; 302 ctx_attribs[num_ctx_attribs++] = minor_ver; 303 304 /* Only send a value when the non-default value is requested. By doing 305 * this we don't have to check the driver's DRI3 version before sending the 306 * default value. 307 */ 308 if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) { 309 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY; 310 ctx_attribs[num_ctx_attribs++] = reset; 311 } 312 313 if (flags != 0) { 314 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS; 315 316 /* The current __DRI_CTX_FLAG_* values are identical to the 317 * GLX_CONTEXT_*_BIT values. 318 */ 319 ctx_attribs[num_ctx_attribs++] = flags; 320 } 321 322 pcp->driContext = 323 (*psc->image_driver->createContextAttribs) (psc->driScreen, 324 api, 325 config->driConfig, 326 shared, 327 num_ctx_attribs / 2, 328 ctx_attribs, 329 error, 330 pcp); 331 332 if (pcp->driContext == NULL) 333 goto error_exit; 334 335 pcp->base.vtable = &dri3_context_vtable; 336 337 return &pcp->base; 338 339 error_exit: 340 free(pcp); 341 342 return NULL; 343 } 344 345 static struct glx_context * 346 dri3_create_context(struct glx_screen *base, 347 struct glx_config *config_base, 348 struct glx_context *shareList, int renderType) 349 { 350 unsigned int error; 351 352 return dri3_create_context_attribs(base, config_base, shareList, 353 0, NULL, &error); 354 } 355 356 static void 357 dri3_destroy_drawable(__GLXDRIdrawable *base) 358 { 359 struct dri3_drawable *pdraw = (struct dri3_drawable *) base; 360 361 loader_dri3_drawable_fini(&pdraw->loader_drawable); 362 363 free(pdraw); 364 } 365 366 static __GLXDRIdrawable * 367 dri3_create_drawable(struct glx_screen *base, XID xDrawable, 368 GLXDrawable drawable, struct glx_config *config_base) 369 { 370 struct dri3_drawable *pdraw; 371 struct dri3_screen *psc = (struct dri3_screen *) base; 372 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 373 374 pdraw = calloc(1, sizeof(*pdraw)); 375 if (!pdraw) 376 return NULL; 377 378 pdraw->base.destroyDrawable = dri3_destroy_drawable; 379 pdraw->base.xDrawable = xDrawable; 380 pdraw->base.drawable = drawable; 381 pdraw->base.psc = &psc->base; 382 383 (void) __glXInitialize(psc->base.dpy); 384 385 if (loader_dri3_drawable_init(XGetXCBConnection(base->dpy), 386 xDrawable, psc->driScreen, 387 psc->is_different_gpu, config->driConfig, 388 &psc->loader_dri3_ext, &glx_dri3_vtable, 389 &pdraw->loader_drawable)) { 390 free(pdraw); 391 return NULL; 392 } 393 394 return &pdraw->base; 395 } 396 397 /** dri3_wait_for_msc 398 * 399 * Get the X server to send an event when the target msc/divisor/remainder is 400 * reached. 401 */ 402 static int 403 dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 404 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) 405 { 406 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw; 407 408 loader_dri3_wait_for_msc(&priv->loader_drawable, target_msc, divisor, 409 remainder, ust, msc, sbc); 410 411 return 1; 412 } 413 414 /** dri3_drawable_get_msc 415 * 416 * Return the current UST/MSC/SBC triplet by asking the server 417 * for an event 418 */ 419 static int 420 dri3_drawable_get_msc(struct glx_screen *psc, __GLXDRIdrawable *pdraw, 421 int64_t *ust, int64_t *msc, int64_t *sbc) 422 { 423 return dri3_wait_for_msc(pdraw, 0, 0, 0, ust, msc,sbc); 424 } 425 426 /** dri3_wait_for_sbc 427 * 428 * Wait for the completed swap buffer count to reach the specified 429 * target. Presumably the application knows that this will be reached with 430 * outstanding complete events, or we're going to be here awhile. 431 */ 432 static int 433 dri3_wait_for_sbc(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, 434 int64_t *msc, int64_t *sbc) 435 { 436 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw; 437 438 return loader_dri3_wait_for_sbc(&priv->loader_drawable, target_sbc, 439 ust, msc, sbc); 440 } 441 442 static void 443 dri3_copy_sub_buffer(__GLXDRIdrawable *pdraw, int x, int y, 444 int width, int height, 445 Bool flush) 446 { 447 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw; 448 449 loader_dri3_copy_sub_buffer(&priv->loader_drawable, x, y, 450 width, height, flush); 451 } 452 453 static void 454 dri3_wait_x(struct glx_context *gc) 455 { 456 struct dri3_drawable *priv = (struct dri3_drawable *) 457 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 458 459 if (priv) 460 loader_dri3_wait_x(&priv->loader_drawable); 461 } 462 463 static void 464 dri3_wait_gl(struct glx_context *gc) 465 { 466 struct dri3_drawable *priv = (struct dri3_drawable *) 467 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 468 469 if (priv) 470 loader_dri3_wait_gl(&priv->loader_drawable); 471 } 472 473 /** 474 * Called by the driver when it needs to update the real front buffer with the 475 * contents of its fake front buffer. 476 */ 477 static void 478 dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate) 479 { 480 struct loader_dri3_drawable *draw = loaderPrivate; 481 struct dri3_drawable *pdraw = loader_drawable_to_dri3_drawable(draw); 482 struct dri3_screen *psc; 483 484 if (!pdraw) 485 return; 486 487 if (!pdraw->base.psc) 488 return; 489 490 psc = (struct dri3_screen *) pdraw->base.psc; 491 492 (void) __glXInitialize(psc->base.dpy); 493 494 loader_dri3_flush(draw, __DRI2_FLUSH_DRAWABLE, __DRI2_THROTTLE_FLUSHFRONT); 495 496 loader_dri3_wait_gl(draw); 497 } 498 499 /* The image loader extension record for DRI3 500 */ 501 static const __DRIimageLoaderExtension imageLoaderExtension = { 502 .base = { __DRI_IMAGE_LOADER, 1 }, 503 504 .getBuffers = loader_dri3_get_buffers, 505 .flushFrontBuffer = dri3_flush_front_buffer, 506 }; 507 508 const __DRIuseInvalidateExtension dri3UseInvalidate = { 509 .base = { __DRI_USE_INVALIDATE, 1 } 510 }; 511 512 static const __DRIextension *loader_extensions[] = { 513 &imageLoaderExtension.base, 514 &systemTimeExtension.base, 515 &dri3UseInvalidate.base, 516 NULL 517 }; 518 519 /** dri3_swap_buffers 520 * 521 * Make the current back buffer visible using the present extension 522 */ 523 static int64_t 524 dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 525 int64_t remainder, Bool flush) 526 { 527 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw; 528 unsigned flags = __DRI2_FLUSH_DRAWABLE; 529 530 if (flush) 531 flags |= __DRI2_FLUSH_CONTEXT; 532 533 return loader_dri3_swap_buffers_msc(&priv->loader_drawable, 534 target_msc, divisor, remainder, 535 flags, false); 536 } 537 538 static int 539 dri3_get_buffer_age(__GLXDRIdrawable *pdraw) 540 { 541 struct dri3_drawable *priv = (struct dri3_drawable *)pdraw; 542 543 return loader_dri3_query_buffer_age(&priv->loader_drawable); 544 } 545 546 /** dri3_destroy_screen 547 */ 548 static void 549 dri3_destroy_screen(struct glx_screen *base) 550 { 551 struct dri3_screen *psc = (struct dri3_screen *) base; 552 553 /* Free the direct rendering per screen data */ 554 (*psc->core->destroyScreen) (psc->driScreen); 555 driDestroyConfigs(psc->driver_configs); 556 close(psc->fd); 557 free(psc); 558 } 559 560 /** dri3_set_swap_interval 561 * 562 * Record the application swap interval specification, 563 */ 564 static int 565 dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval) 566 { 567 assert(pdraw != NULL); 568 569 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw; 570 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 571 struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc; 572 573 if (psc->config) 574 psc->config->configQueryi(psc->driScreen, 575 "vblank_mode", &vblank_mode); 576 577 switch (vblank_mode) { 578 case DRI_CONF_VBLANK_NEVER: 579 if (interval != 0) 580 return GLX_BAD_VALUE; 581 break; 582 case DRI_CONF_VBLANK_ALWAYS_SYNC: 583 if (interval <= 0) 584 return GLX_BAD_VALUE; 585 break; 586 default: 587 break; 588 } 589 590 loader_dri3_set_swap_interval(&priv->loader_drawable, interval); 591 592 return 0; 593 } 594 595 /** dri3_get_swap_interval 596 * 597 * Return the stored swap interval 598 */ 599 static int 600 dri3_get_swap_interval(__GLXDRIdrawable *pdraw) 601 { 602 assert(pdraw != NULL); 603 604 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw; 605 606 return priv->swap_interval; 607 } 608 609 static void 610 dri3_bind_tex_image(Display * dpy, 611 GLXDrawable drawable, 612 int buffer, const int *attrib_list) 613 { 614 struct glx_context *gc = __glXGetCurrentContext(); 615 struct dri3_context *pcp = (struct dri3_context *) gc; 616 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); 617 struct dri3_drawable *pdraw = (struct dri3_drawable *) base; 618 struct dri3_screen *psc; 619 620 if (pdraw != NULL) { 621 psc = (struct dri3_screen *) base->psc; 622 623 (*psc->f->invalidate)(pdraw->loader_drawable.dri_drawable); 624 625 XSync(dpy, false); 626 627 (*psc->texBuffer->setTexBuffer2) (pcp->driContext, 628 pdraw->base.textureTarget, 629 pdraw->base.textureFormat, 630 pdraw->loader_drawable.dri_drawable); 631 } 632 } 633 634 static void 635 dri3_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer) 636 { 637 struct glx_context *gc = __glXGetCurrentContext(); 638 struct dri3_context *pcp = (struct dri3_context *) gc; 639 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); 640 struct dri3_drawable *pdraw = (struct dri3_drawable *) base; 641 struct dri3_screen *psc; 642 643 if (pdraw != NULL) { 644 psc = (struct dri3_screen *) base->psc; 645 646 if (psc->texBuffer->base.version >= 3 && 647 psc->texBuffer->releaseTexBuffer != NULL) 648 (*psc->texBuffer->releaseTexBuffer) (pcp->driContext, 649 pdraw->base.textureTarget, 650 pdraw->loader_drawable.dri_drawable); 651 } 652 } 653 654 static const struct glx_context_vtable dri3_context_vtable = { 655 .destroy = dri3_destroy_context, 656 .bind = dri3_bind_context, 657 .unbind = dri3_unbind_context, 658 .wait_gl = dri3_wait_gl, 659 .wait_x = dri3_wait_x, 660 .use_x_font = DRI_glXUseXFont, 661 .bind_tex_image = dri3_bind_tex_image, 662 .release_tex_image = dri3_release_tex_image, 663 .get_proc_address = NULL, 664 .interop_query_device_info = dri3_interop_query_device_info, 665 .interop_export_object = dri3_interop_export_object 666 }; 667 668 /** dri3_bind_extensions 669 * 670 * Enable all of the extensions supported on DRI3 671 */ 672 static void 673 dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv, 674 const char *driverName) 675 { 676 const __DRIextension **extensions; 677 unsigned mask; 678 int i; 679 680 extensions = psc->core->getExtensions(psc->driScreen); 681 682 __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync"); 683 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control"); 684 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control"); 685 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read"); 686 __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event"); 687 688 mask = psc->image_driver->getAPIMask(psc->driScreen); 689 690 __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context"); 691 __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile"); 692 693 if ((mask & ((1 << __DRI_API_GLES) | 694 (1 << __DRI_API_GLES2) | 695 (1 << __DRI_API_GLES3))) != 0) { 696 __glXEnableDirectExtension(&psc->base, 697 "GLX_EXT_create_context_es_profile"); 698 __glXEnableDirectExtension(&psc->base, 699 "GLX_EXT_create_context_es2_profile"); 700 } 701 702 for (i = 0; extensions[i]; i++) { 703 /* when on a different gpu than the server, the server pixmaps 704 * can have a tiling mode we can't read. Thus we can't create 705 * a texture from them. 706 */ 707 if (!psc->is_different_gpu && 708 (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) { 709 psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; 710 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap"); 711 } 712 713 if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) { 714 psc->f = (__DRI2flushExtension *) extensions[i]; 715 /* internal driver extension, no GL extension exposed */ 716 } 717 718 if (strcmp(extensions[i]->name, __DRI_IMAGE) == 0) 719 psc->image = (__DRIimageExtension *) extensions[i]; 720 721 if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0)) 722 psc->config = (__DRI2configQueryExtension *) extensions[i]; 723 724 if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0) 725 __glXEnableDirectExtension(&psc->base, 726 "GLX_ARB_create_context_robustness"); 727 728 if (strcmp(extensions[i]->name, __DRI2_RENDERER_QUERY) == 0) { 729 psc->rendererQuery = (__DRI2rendererQueryExtension *) extensions[i]; 730 __glXEnableDirectExtension(&psc->base, "GLX_MESA_query_renderer"); 731 } 732 733 if (strcmp(extensions[i]->name, __DRI2_INTEROP) == 0) 734 psc->interop = (__DRI2interopExtension*)extensions[i]; 735 } 736 } 737 738 static const struct glx_screen_vtable dri3_screen_vtable = { 739 .create_context = dri3_create_context, 740 .create_context_attribs = dri3_create_context_attribs, 741 .query_renderer_integer = dri3_query_renderer_integer, 742 .query_renderer_string = dri3_query_renderer_string, 743 }; 744 745 /** dri3_create_screen 746 * 747 * Initialize DRI3 on the specified screen. 748 * 749 * Opens the DRI device, locates the appropriate DRI driver 750 * and loads that. 751 * 752 * Checks to see if the driver supports the necessary extensions 753 * 754 * Initializes the driver for the screen and sets up our structures 755 */ 756 757 static struct glx_screen * 758 dri3_create_screen(int screen, struct glx_display * priv) 759 { 760 xcb_connection_t *c = XGetXCBConnection(priv->dpy); 761 const __DRIconfig **driver_configs; 762 const __DRIextension **extensions; 763 const struct dri3_display *const pdp = (struct dri3_display *) 764 priv->dri3Display; 765 struct dri3_screen *psc; 766 __GLXDRIscreen *psp; 767 struct glx_config *configs = NULL, *visuals = NULL; 768 char *driverName, *deviceName, *tmp; 769 int i; 770 771 psc = calloc(1, sizeof *psc); 772 if (psc == NULL) 773 return NULL; 774 775 psc->fd = -1; 776 777 if (!glx_screen_init(&psc->base, screen, priv)) { 778 free(psc); 779 return NULL; 780 } 781 782 psc->fd = loader_dri3_open(c, RootWindow(priv->dpy, screen), None); 783 if (psc->fd < 0) { 784 int conn_error = xcb_connection_has_error(c); 785 786 glx_screen_cleanup(&psc->base); 787 free(psc); 788 InfoMessageF("screen %d does not appear to be DRI3 capable\n", screen); 789 790 if (conn_error) 791 ErrorMessageF("Connection closed during DRI3 initialization failure"); 792 793 return NULL; 794 } 795 796 psc->fd = loader_get_user_preferred_fd(psc->fd, &psc->is_different_gpu); 797 deviceName = NULL; 798 799 driverName = loader_get_driver_for_fd(psc->fd); 800 if (!driverName) { 801 ErrorMessageF("No driver found\n"); 802 goto handle_error; 803 } 804 805 psc->driver = driOpenDriver(driverName); 806 if (psc->driver == NULL) { 807 ErrorMessageF("driver pointer missing\n"); 808 goto handle_error; 809 } 810 811 extensions = driGetDriverExtensions(psc->driver, driverName); 812 if (extensions == NULL) 813 goto handle_error; 814 815 for (i = 0; extensions[i]; i++) { 816 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 817 psc->core = (__DRIcoreExtension *) extensions[i]; 818 if (strcmp(extensions[i]->name, __DRI_IMAGE_DRIVER) == 0) 819 psc->image_driver = (__DRIimageDriverExtension *) extensions[i]; 820 } 821 822 823 if (psc->core == NULL) { 824 ErrorMessageF("core dri driver extension not found\n"); 825 goto handle_error; 826 } 827 828 if (psc->image_driver == NULL) { 829 ErrorMessageF("image driver extension not found\n"); 830 goto handle_error; 831 } 832 833 psc->driScreen = 834 psc->image_driver->createNewScreen2(screen, psc->fd, 835 pdp->loader_extensions, 836 extensions, 837 &driver_configs, psc); 838 839 if (psc->driScreen == NULL) { 840 ErrorMessageF("failed to create dri screen\n"); 841 goto handle_error; 842 } 843 844 dri3_bind_extensions(psc, priv, driverName); 845 846 if (!psc->image || psc->image->base.version < 7 || !psc->image->createImageFromFds) { 847 ErrorMessageF("Version 7 or imageFromFds image extension not found\n"); 848 goto handle_error; 849 } 850 851 if (!psc->f || psc->f->base.version < 4) { 852 ErrorMessageF("Version 4 or later of flush extension not found\n"); 853 goto handle_error; 854 } 855 856 if (psc->is_different_gpu && psc->image->base.version < 9) { 857 ErrorMessageF("Different GPU, but image extension version 9 or later not found\n"); 858 goto handle_error; 859 } 860 861 if (psc->is_different_gpu && !psc->image->blitImage) { 862 ErrorMessageF("Different GPU, but blitImage not implemented for this driver\n"); 863 goto handle_error; 864 } 865 866 if (!psc->is_different_gpu && ( 867 !psc->texBuffer || psc->texBuffer->base.version < 2 || 868 !psc->texBuffer->setTexBuffer2 869 )) { 870 ErrorMessageF("Version 2 or later of texBuffer extension not found\n"); 871 goto handle_error; 872 } 873 874 psc->loader_dri3_ext.core = psc->core; 875 psc->loader_dri3_ext.image_driver = psc->image_driver; 876 psc->loader_dri3_ext.flush = psc->f; 877 psc->loader_dri3_ext.tex_buffer = psc->texBuffer; 878 psc->loader_dri3_ext.image = psc->image; 879 psc->loader_dri3_ext.config = psc->config; 880 881 configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs); 882 visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs); 883 884 if (!configs || !visuals) { 885 ErrorMessageF("No matching fbConfigs or visuals found\n"); 886 goto handle_error; 887 } 888 889 glx_config_destroy_list(psc->base.configs); 890 psc->base.configs = configs; 891 glx_config_destroy_list(psc->base.visuals); 892 psc->base.visuals = visuals; 893 894 psc->driver_configs = driver_configs; 895 896 psc->base.vtable = &dri3_screen_vtable; 897 psp = &psc->vtable; 898 psc->base.driScreen = psp; 899 psp->destroyScreen = dri3_destroy_screen; 900 psp->createDrawable = dri3_create_drawable; 901 psp->swapBuffers = dri3_swap_buffers; 902 903 psp->getDrawableMSC = dri3_drawable_get_msc; 904 psp->waitForMSC = dri3_wait_for_msc; 905 psp->waitForSBC = dri3_wait_for_sbc; 906 psp->setSwapInterval = dri3_set_swap_interval; 907 psp->getSwapInterval = dri3_get_swap_interval; 908 __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control"); 909 910 psp->copySubBuffer = dri3_copy_sub_buffer; 911 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer"); 912 913 psp->getBufferAge = dri3_get_buffer_age; 914 __glXEnableDirectExtension(&psc->base, "GLX_EXT_buffer_age"); 915 916 free(driverName); 917 free(deviceName); 918 919 tmp = getenv("LIBGL_SHOW_FPS"); 920 psc->show_fps_interval = tmp ? atoi(tmp) : 0; 921 if (psc->show_fps_interval < 0) 922 psc->show_fps_interval = 0; 923 924 InfoMessageF("Using DRI3 for screen %d\n", screen); 925 926 return &psc->base; 927 928 handle_error: 929 CriticalErrorMessageF("failed to load driver: %s\n", driverName); 930 931 if (configs) 932 glx_config_destroy_list(configs); 933 if (visuals) 934 glx_config_destroy_list(visuals); 935 if (psc->driScreen) 936 psc->core->destroyScreen(psc->driScreen); 937 psc->driScreen = NULL; 938 if (psc->fd >= 0) 939 close(psc->fd); 940 if (psc->driver) 941 dlclose(psc->driver); 942 943 free(driverName); 944 free(deviceName); 945 glx_screen_cleanup(&psc->base); 946 free(psc); 947 948 return NULL; 949 } 950 951 /** dri_destroy_display 952 * 953 * Called from __glXFreeDisplayPrivate. 954 */ 955 static void 956 dri3_destroy_display(__GLXDRIdisplay * dpy) 957 { 958 free(dpy); 959 } 960 961 /** dri3_create_display 962 * 963 * Allocate, initialize and return a __DRIdisplayPrivate object. 964 * This is called from __glXInitialize() when we are given a new 965 * display pointer. This is public to that function, but hidden from 966 * outside of libGL. 967 */ 968 _X_HIDDEN __GLXDRIdisplay * 969 dri3_create_display(Display * dpy) 970 { 971 struct dri3_display *pdp; 972 xcb_connection_t *c = XGetXCBConnection(dpy); 973 xcb_dri3_query_version_cookie_t dri3_cookie; 974 xcb_dri3_query_version_reply_t *dri3_reply; 975 xcb_present_query_version_cookie_t present_cookie; 976 xcb_present_query_version_reply_t *present_reply; 977 xcb_generic_error_t *error; 978 const xcb_query_extension_reply_t *extension; 979 980 xcb_prefetch_extension_data(c, &xcb_dri3_id); 981 xcb_prefetch_extension_data(c, &xcb_present_id); 982 983 extension = xcb_get_extension_data(c, &xcb_dri3_id); 984 if (!(extension && extension->present)) 985 return NULL; 986 987 extension = xcb_get_extension_data(c, &xcb_present_id); 988 if (!(extension && extension->present)) 989 return NULL; 990 991 dri3_cookie = xcb_dri3_query_version(c, 992 XCB_DRI3_MAJOR_VERSION, 993 XCB_DRI3_MINOR_VERSION); 994 995 996 present_cookie = xcb_present_query_version(c, 997 XCB_PRESENT_MAJOR_VERSION, 998 XCB_PRESENT_MINOR_VERSION); 999 1000 pdp = malloc(sizeof *pdp); 1001 if (pdp == NULL) 1002 return NULL; 1003 1004 dri3_reply = xcb_dri3_query_version_reply(c, dri3_cookie, &error); 1005 if (!dri3_reply) { 1006 free(error); 1007 goto no_extension; 1008 } 1009 1010 pdp->dri3Major = dri3_reply->major_version; 1011 pdp->dri3Minor = dri3_reply->minor_version; 1012 free(dri3_reply); 1013 1014 present_reply = xcb_present_query_version_reply(c, present_cookie, &error); 1015 if (!present_reply) { 1016 free(error); 1017 goto no_extension; 1018 } 1019 pdp->presentMajor = present_reply->major_version; 1020 pdp->presentMinor = present_reply->minor_version; 1021 free(present_reply); 1022 1023 pdp->base.destroyDisplay = dri3_destroy_display; 1024 pdp->base.createScreen = dri3_create_screen; 1025 1026 loader_set_logger(dri_message); 1027 1028 pdp->loader_extensions = loader_extensions; 1029 1030 return &pdp->base; 1031 no_extension: 1032 free(pdp); 1033 return NULL; 1034 } 1035 1036 #endif /* GLX_DIRECT_RENDERING */ 1037