1 /* 2 * Copyright 2008 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Soft- 6 * ware"), to deal in the Software without restriction, including without 7 * limitation the rights to use, copy, modify, merge, publish, distribute, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, provided that the above copyright 10 * notice(s) and this permission notice appear in all copies of the Soft- 11 * ware and that both the above copyright notice(s) and this permission 12 * notice appear in supporting documentation. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 16 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 17 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 18 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 19 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 22 * MANCE OF THIS SOFTWARE. 23 * 24 * Except as contained in this notice, the name of a copyright holder shall 25 * not be used in advertising or otherwise to promote the sale, use or 26 * other dealings in this Software without prior written authorization of 27 * the copyright holder. 28 * 29 * Authors: 30 * Kristian Hgsberg (krh (at) redhat.com) 31 */ 32 33 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 34 35 #include <X11/Xlib.h> 36 #include <X11/extensions/Xfixes.h> 37 #include "glapi.h" 38 #include "glxclient.h" 39 #include <X11/extensions/dri2proto.h> 40 #include "xf86dri.h" 41 #include <dlfcn.h> 42 #include <fcntl.h> 43 #include <unistd.h> 44 #include <sys/types.h> 45 #include <sys/mman.h> 46 #include <sys/time.h> 47 #include "xf86drm.h" 48 #include "dri2.h" 49 #include "dri_common.h" 50 51 /* From xmlpool/options.h, user exposed so should be stable */ 52 #define DRI_CONF_VBLANK_NEVER 0 53 #define DRI_CONF_VBLANK_DEF_INTERVAL_0 1 54 #define DRI_CONF_VBLANK_DEF_INTERVAL_1 2 55 #define DRI_CONF_VBLANK_ALWAYS_SYNC 3 56 57 #undef DRI2_MINOR 58 #define DRI2_MINOR 1 59 60 struct dri2_display 61 { 62 __GLXDRIdisplay base; 63 64 /* 65 ** XFree86-DRI version information 66 */ 67 int driMajor; 68 int driMinor; 69 int driPatch; 70 int swapAvailable; 71 int invalidateAvailable; 72 73 __glxHashTable *dri2Hash; 74 75 const __DRIextension *loader_extensions[4]; 76 }; 77 78 struct dri2_screen { 79 struct glx_screen base; 80 81 __DRIscreen *driScreen; 82 __GLXDRIscreen vtable; 83 const __DRIdri2Extension *dri2; 84 const __DRIcoreExtension *core; 85 86 const __DRI2flushExtension *f; 87 const __DRI2configQueryExtension *config; 88 const __DRItexBufferExtension *texBuffer; 89 const __DRI2throttleExtension *throttle; 90 const __DRIconfig **driver_configs; 91 92 void *driver; 93 int fd; 94 95 Bool show_fps; 96 }; 97 98 struct dri2_context 99 { 100 struct glx_context base; 101 __DRIcontext *driContext; 102 }; 103 104 struct dri2_drawable 105 { 106 __GLXDRIdrawable base; 107 __DRIdrawable *driDrawable; 108 __DRIbuffer buffers[5]; 109 int bufferCount; 110 int width, height; 111 int have_back; 112 int have_fake_front; 113 int swap_interval; 114 115 double previous_time; 116 unsigned frames; 117 }; 118 119 static const struct glx_context_vtable dri2_context_vtable; 120 121 static void 122 dri2_destroy_context(struct glx_context *context) 123 { 124 struct dri2_context *pcp = (struct dri2_context *) context; 125 struct dri2_screen *psc = (struct dri2_screen *) context->psc; 126 127 driReleaseDrawables(&pcp->base); 128 129 if (context->extensions) 130 XFree((char *) context->extensions); 131 132 (*psc->core->destroyContext) (pcp->driContext); 133 134 Xfree(pcp); 135 } 136 137 static Bool 138 dri2_bind_context(struct glx_context *context, struct glx_context *old, 139 GLXDrawable draw, GLXDrawable read) 140 { 141 struct dri2_context *pcp = (struct dri2_context *) context; 142 struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc; 143 struct dri2_drawable *pdraw, *pread; 144 struct dri2_display *pdp; 145 146 pdraw = (struct dri2_drawable *) driFetchDrawable(context, draw); 147 pread = (struct dri2_drawable *) driFetchDrawable(context, read); 148 149 driReleaseDrawables(&pcp->base); 150 151 if (pdraw == NULL || pread == NULL) 152 return GLXBadDrawable; 153 154 if (!(*psc->core->bindContext) (pcp->driContext, 155 pdraw->driDrawable, pread->driDrawable)) 156 return GLXBadContext; 157 158 /* If the server doesn't send invalidate events, we may miss a 159 * resize before the rendering starts. Invalidate the buffers now 160 * so the driver will recheck before rendering starts. */ 161 pdp = (struct dri2_display *) psc->base.display; 162 if (!pdp->invalidateAvailable) { 163 dri2InvalidateBuffers(psc->base.dpy, pdraw->base.xDrawable); 164 if (pread != pdraw) 165 dri2InvalidateBuffers(psc->base.dpy, pread->base.xDrawable); 166 } 167 168 return Success; 169 } 170 171 static void 172 dri2_unbind_context(struct glx_context *context, struct glx_context *new) 173 { 174 struct dri2_context *pcp = (struct dri2_context *) context; 175 struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc; 176 177 (*psc->core->unbindContext) (pcp->driContext); 178 } 179 180 static struct glx_context * 181 dri2_create_context(struct glx_screen *base, 182 struct glx_config *config_base, 183 struct glx_context *shareList, int renderType) 184 { 185 struct dri2_context *pcp, *pcp_shared; 186 struct dri2_screen *psc = (struct dri2_screen *) base; 187 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 188 __DRIcontext *shared = NULL; 189 190 if (shareList) { 191 /* If the shareList context is not a DRI2 context, we cannot possibly 192 * create a DRI2 context that shares it. 193 */ 194 if (shareList->vtable->destroy != dri2_destroy_context) { 195 return NULL; 196 } 197 198 pcp_shared = (struct dri2_context *) shareList; 199 shared = pcp_shared->driContext; 200 } 201 202 pcp = Xmalloc(sizeof *pcp); 203 if (pcp == NULL) 204 return NULL; 205 206 memset(pcp, 0, sizeof *pcp); 207 if (!glx_context_init(&pcp->base, &psc->base, &config->base)) { 208 Xfree(pcp); 209 return NULL; 210 } 211 212 pcp->driContext = 213 (*psc->dri2->createNewContext) (psc->driScreen, 214 config->driConfig, shared, pcp); 215 216 if (pcp->driContext == NULL) { 217 Xfree(pcp); 218 return NULL; 219 } 220 221 pcp->base.vtable = &dri2_context_vtable; 222 223 return &pcp->base; 224 } 225 226 static struct glx_context * 227 dri2_create_context_attribs(struct glx_screen *base, 228 struct glx_config *config_base, 229 struct glx_context *shareList, 230 unsigned num_attribs, 231 const uint32_t *attribs, 232 unsigned *error) 233 { 234 struct dri2_context *pcp = NULL; 235 struct dri2_context *pcp_shared = NULL; 236 struct dri2_screen *psc = (struct dri2_screen *) base; 237 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 238 __DRIcontext *shared = NULL; 239 240 uint32_t minor_ver = 1; 241 uint32_t major_ver = 2; 242 uint32_t flags = 0; 243 unsigned api; 244 int reset = __DRI_CTX_RESET_NO_NOTIFICATION; 245 uint32_t ctx_attribs[2 * 5]; 246 unsigned num_ctx_attribs = 0; 247 248 if (psc->dri2->base.version < 3) { 249 *error = __DRI_CTX_ERROR_NO_MEMORY; 250 goto error_exit; 251 } 252 253 /* Remap the GLX tokens to DRI2 tokens. 254 */ 255 if (!dri2_convert_glx_attribs(num_attribs, attribs, 256 &major_ver, &minor_ver, &flags, &api, &reset, 257 error)) 258 goto error_exit; 259 260 if (shareList) { 261 pcp_shared = (struct dri2_context *) shareList; 262 shared = pcp_shared->driContext; 263 } 264 265 pcp = Xmalloc(sizeof *pcp); 266 if (pcp == NULL) { 267 *error = __DRI_CTX_ERROR_NO_MEMORY; 268 goto error_exit; 269 } 270 271 memset(pcp, 0, sizeof *pcp); 272 if (!glx_context_init(&pcp->base, &psc->base, &config->base)) 273 goto error_exit; 274 275 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION; 276 ctx_attribs[num_ctx_attribs++] = major_ver; 277 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION; 278 ctx_attribs[num_ctx_attribs++] = minor_ver; 279 280 /* Only send a value when the non-default value is requested. By doing 281 * this we don't have to check the driver's DRI2 version before sending the 282 * default value. 283 */ 284 if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) { 285 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY; 286 ctx_attribs[num_ctx_attribs++] = reset; 287 } 288 289 if (flags != 0) { 290 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS; 291 292 /* The current __DRI_CTX_FLAG_* values are identical to the 293 * GLX_CONTEXT_*_BIT values. 294 */ 295 ctx_attribs[num_ctx_attribs++] = flags; 296 } 297 298 pcp->driContext = 299 (*psc->dri2->createContextAttribs) (psc->driScreen, 300 api, 301 config->driConfig, 302 shared, 303 num_ctx_attribs / 2, 304 ctx_attribs, 305 error, 306 pcp); 307 308 if (pcp->driContext == NULL) 309 goto error_exit; 310 311 pcp->base.vtable = &dri2_context_vtable; 312 313 return &pcp->base; 314 315 error_exit: 316 if (pcp != NULL) 317 Xfree(pcp); 318 319 return NULL; 320 } 321 322 static void 323 dri2DestroyDrawable(__GLXDRIdrawable *base) 324 { 325 struct dri2_screen *psc = (struct dri2_screen *) base->psc; 326 struct dri2_drawable *pdraw = (struct dri2_drawable *) base; 327 struct glx_display *dpyPriv = psc->base.display; 328 struct dri2_display *pdp = (struct dri2_display *)dpyPriv->dri2Display; 329 330 __glxHashDelete(pdp->dri2Hash, pdraw->base.xDrawable); 331 (*psc->core->destroyDrawable) (pdraw->driDrawable); 332 333 /* If it's a GLX 1.3 drawables, we can destroy the DRI2 drawable 334 * now, as the application explicitly asked to destroy the GLX 335 * drawable. Otherwise, for legacy drawables, we let the DRI2 336 * drawable linger on the server, since there's no good way of 337 * knowing when the application is done with it. The server will 338 * destroy the DRI2 drawable when it destroys the X drawable or the 339 * client exits anyway. */ 340 if (pdraw->base.xDrawable != pdraw->base.drawable) 341 DRI2DestroyDrawable(psc->base.dpy, pdraw->base.xDrawable); 342 343 Xfree(pdraw); 344 } 345 346 static __GLXDRIdrawable * 347 dri2CreateDrawable(struct glx_screen *base, XID xDrawable, 348 GLXDrawable drawable, struct glx_config *config_base) 349 { 350 struct dri2_drawable *pdraw; 351 struct dri2_screen *psc = (struct dri2_screen *) base; 352 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 353 struct glx_display *dpyPriv; 354 struct dri2_display *pdp; 355 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 356 357 pdraw = Xmalloc(sizeof(*pdraw)); 358 if (!pdraw) 359 return NULL; 360 361 memset(pdraw, 0, sizeof *pdraw); 362 pdraw->base.destroyDrawable = dri2DestroyDrawable; 363 pdraw->base.xDrawable = xDrawable; 364 pdraw->base.drawable = drawable; 365 pdraw->base.psc = &psc->base; 366 pdraw->bufferCount = 0; 367 pdraw->swap_interval = 1; /* default may be overridden below */ 368 pdraw->have_back = 0; 369 370 if (psc->config) 371 psc->config->configQueryi(psc->driScreen, 372 "vblank_mode", &vblank_mode); 373 374 switch (vblank_mode) { 375 case DRI_CONF_VBLANK_NEVER: 376 case DRI_CONF_VBLANK_DEF_INTERVAL_0: 377 pdraw->swap_interval = 0; 378 break; 379 case DRI_CONF_VBLANK_DEF_INTERVAL_1: 380 case DRI_CONF_VBLANK_ALWAYS_SYNC: 381 default: 382 pdraw->swap_interval = 1; 383 break; 384 } 385 386 DRI2CreateDrawable(psc->base.dpy, xDrawable); 387 388 dpyPriv = __glXInitialize(psc->base.dpy); 389 pdp = (struct dri2_display *)dpyPriv->dri2Display;; 390 /* Create a new drawable */ 391 pdraw->driDrawable = 392 (*psc->dri2->createNewDrawable) (psc->driScreen, 393 config->driConfig, pdraw); 394 395 if (!pdraw->driDrawable) { 396 DRI2DestroyDrawable(psc->base.dpy, xDrawable); 397 Xfree(pdraw); 398 return NULL; 399 } 400 401 if (__glxHashInsert(pdp->dri2Hash, xDrawable, pdraw)) { 402 (*psc->core->destroyDrawable) (pdraw->driDrawable); 403 DRI2DestroyDrawable(psc->base.dpy, xDrawable); 404 Xfree(pdraw); 405 return None; 406 } 407 408 409 #ifdef X_DRI2SwapInterval 410 /* 411 * Make sure server has the same swap interval we do for the new 412 * drawable. 413 */ 414 if (pdp->swapAvailable) 415 DRI2SwapInterval(psc->base.dpy, xDrawable, pdraw->swap_interval); 416 #endif 417 418 return &pdraw->base; 419 } 420 421 #ifdef X_DRI2GetMSC 422 423 static int 424 dri2DrawableGetMSC(struct glx_screen *psc, __GLXDRIdrawable *pdraw, 425 int64_t *ust, int64_t *msc, int64_t *sbc) 426 { 427 CARD64 dri2_ust, dri2_msc, dri2_sbc; 428 int ret; 429 430 ret = DRI2GetMSC(psc->dpy, pdraw->xDrawable, 431 &dri2_ust, &dri2_msc, &dri2_sbc); 432 *ust = dri2_ust; 433 *msc = dri2_msc; 434 *sbc = dri2_sbc; 435 436 return ret; 437 } 438 439 #endif 440 441 442 #ifdef X_DRI2WaitMSC 443 444 static int 445 dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 446 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) 447 { 448 CARD64 dri2_ust, dri2_msc, dri2_sbc; 449 int ret; 450 451 ret = DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 452 remainder, &dri2_ust, &dri2_msc, &dri2_sbc); 453 *ust = dri2_ust; 454 *msc = dri2_msc; 455 *sbc = dri2_sbc; 456 457 return ret; 458 } 459 460 static int 461 dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, 462 int64_t *msc, int64_t *sbc) 463 { 464 CARD64 dri2_ust, dri2_msc, dri2_sbc; 465 int ret; 466 467 ret = DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable, 468 target_sbc, &dri2_ust, &dri2_msc, &dri2_sbc); 469 *ust = dri2_ust; 470 *msc = dri2_msc; 471 *sbc = dri2_sbc; 472 473 return ret; 474 } 475 476 #endif /* X_DRI2WaitMSC */ 477 478 /** 479 * dri2Throttle - Request driver throttling 480 * 481 * This function uses the DRI2 throttle extension to give the 482 * driver the opportunity to throttle on flush front, copysubbuffer 483 * and swapbuffers. 484 */ 485 static void 486 dri2Throttle(struct dri2_screen *psc, 487 struct dri2_drawable *draw, 488 enum __DRI2throttleReason reason) 489 { 490 if (psc->throttle) { 491 struct glx_context *gc = __glXGetCurrentContext(); 492 struct dri2_context *dri2Ctx = (struct dri2_context *)gc; 493 __DRIcontext *ctx = 494 (dri2Ctx) ? dri2Ctx->driContext : NULL; 495 496 psc->throttle->throttle(ctx, draw->driDrawable, reason); 497 } 498 } 499 500 static void 501 __dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, 502 int width, int height, 503 enum __DRI2throttleReason reason) 504 { 505 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 506 struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc; 507 XRectangle xrect; 508 XserverRegion region; 509 510 /* Check we have the right attachments */ 511 if (!priv->have_back) 512 return; 513 514 xrect.x = x; 515 xrect.y = priv->height - y - height; 516 xrect.width = width; 517 xrect.height = height; 518 519 #ifdef __DRI2_FLUSH 520 if (psc->f) 521 (*psc->f->flush) (priv->driDrawable); 522 #endif 523 524 dri2Throttle(psc, priv, reason); 525 526 region = XFixesCreateRegion(psc->base.dpy, &xrect, 1); 527 DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region, 528 DRI2BufferFrontLeft, DRI2BufferBackLeft); 529 530 /* Refresh the fake front (if present) after we just damaged the real 531 * front. 532 */ 533 if (priv->have_fake_front) 534 DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region, 535 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 536 537 XFixesDestroyRegion(psc->base.dpy, region); 538 } 539 540 static void 541 dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, 542 int width, int height) 543 { 544 __dri2CopySubBuffer(pdraw, x, y, width, height, 545 __DRI2_THROTTLE_COPYSUBBUFFER); 546 } 547 548 549 static void 550 dri2_copy_drawable(struct dri2_drawable *priv, int dest, int src) 551 { 552 XRectangle xrect; 553 XserverRegion region; 554 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc; 555 556 xrect.x = 0; 557 xrect.y = 0; 558 xrect.width = priv->width; 559 xrect.height = priv->height; 560 561 #ifdef __DRI2_FLUSH 562 if (psc->f) 563 (*psc->f->flush) (priv->driDrawable); 564 #endif 565 566 region = XFixesCreateRegion(psc->base.dpy, &xrect, 1); 567 DRI2CopyRegion(psc->base.dpy, priv->base.xDrawable, region, dest, src); 568 XFixesDestroyRegion(psc->base.dpy, region); 569 570 } 571 572 static void 573 dri2_wait_x(struct glx_context *gc) 574 { 575 struct dri2_drawable *priv = (struct dri2_drawable *) 576 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 577 578 if (priv == NULL || !priv->have_fake_front) 579 return; 580 581 dri2_copy_drawable(priv, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 582 } 583 584 static void 585 dri2_wait_gl(struct glx_context *gc) 586 { 587 struct dri2_drawable *priv = (struct dri2_drawable *) 588 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 589 590 if (priv == NULL || !priv->have_fake_front) 591 return; 592 593 dri2_copy_drawable(priv, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 594 } 595 596 static void 597 dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) 598 { 599 struct glx_display *priv; 600 struct dri2_display *pdp; 601 struct glx_context *gc; 602 struct dri2_drawable *pdraw = loaderPrivate; 603 struct dri2_screen *psc; 604 605 if (!pdraw) 606 return; 607 608 if (!pdraw->base.psc) 609 return; 610 611 psc = (struct dri2_screen *) pdraw->base.psc; 612 613 priv = __glXInitialize(psc->base.dpy); 614 pdp = (struct dri2_display *) priv->dri2Display; 615 gc = __glXGetCurrentContext(); 616 617 dri2Throttle(psc, pdraw, __DRI2_THROTTLE_FLUSHFRONT); 618 619 /* Old servers don't send invalidate events */ 620 if (!pdp->invalidateAvailable) 621 dri2InvalidateBuffers(priv->dpy, pdraw->base.xDrawable); 622 623 dri2_wait_gl(gc); 624 } 625 626 627 static void 628 dri2DestroyScreen(struct glx_screen *base) 629 { 630 struct dri2_screen *psc = (struct dri2_screen *) base; 631 632 /* Free the direct rendering per screen data */ 633 (*psc->core->destroyScreen) (psc->driScreen); 634 driDestroyConfigs(psc->driver_configs); 635 close(psc->fd); 636 Xfree(psc); 637 } 638 639 /** 640 * Process list of buffer received from the server 641 * 642 * Processes the list of buffers received in a reply from the server to either 643 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. 644 */ 645 static void 646 process_buffers(struct dri2_drawable * pdraw, DRI2Buffer * buffers, 647 unsigned count) 648 { 649 int i; 650 651 pdraw->bufferCount = count; 652 pdraw->have_fake_front = 0; 653 pdraw->have_back = 0; 654 655 /* This assumes the DRI2 buffer attachment tokens matches the 656 * __DRIbuffer tokens. */ 657 for (i = 0; i < count; i++) { 658 pdraw->buffers[i].attachment = buffers[i].attachment; 659 pdraw->buffers[i].name = buffers[i].name; 660 pdraw->buffers[i].pitch = buffers[i].pitch; 661 pdraw->buffers[i].cpp = buffers[i].cpp; 662 pdraw->buffers[i].flags = buffers[i].flags; 663 if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) 664 pdraw->have_fake_front = 1; 665 if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) 666 pdraw->have_back = 1; 667 } 668 669 } 670 671 unsigned dri2GetSwapEventType(Display* dpy, XID drawable) 672 { 673 struct glx_display *glx_dpy = __glXInitialize(dpy); 674 __GLXDRIdrawable *pdraw; 675 pdraw = dri2GetGlxDrawableFromXDrawableId(dpy, drawable); 676 if (!pdraw || !(pdraw->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK)) 677 return 0; 678 return glx_dpy->codes->first_event + GLX_BufferSwapComplete; 679 } 680 681 static void show_fps(struct dri2_drawable *draw) 682 { 683 struct timeval tv; 684 double current_time; 685 686 gettimeofday(&tv, 0); 687 current_time = (double)tv.tv_sec + (double)tv.tv_usec * 0.000001; 688 689 draw->frames++; 690 691 if (draw->previous_time + 1 < current_time) { 692 if (draw->previous_time) { 693 fprintf(stderr, "libGL: FPS = %.1f\n", 694 draw->frames / (current_time - draw->previous_time)); 695 } 696 draw->frames = 0; 697 draw->previous_time = current_time; 698 } 699 } 700 701 static int64_t 702 dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 703 int64_t remainder) 704 { 705 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 706 struct glx_display *dpyPriv = __glXInitialize(priv->base.psc->dpy); 707 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc; 708 struct dri2_display *pdp = 709 (struct dri2_display *)dpyPriv->dri2Display; 710 CARD64 ret = 0; 711 712 /* Check we have the right attachments */ 713 if (!priv->have_back) 714 return ret; 715 716 /* Old servers can't handle swapbuffers */ 717 if (!pdp->swapAvailable) { 718 __dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height, 719 __DRI2_THROTTLE_SWAPBUFFER); 720 } else { 721 #ifdef X_DRI2SwapBuffers 722 #ifdef __DRI2_FLUSH 723 if (psc->f) { 724 struct glx_context *gc = __glXGetCurrentContext(); 725 726 if (gc) { 727 (*psc->f->flush)(priv->driDrawable); 728 } 729 } 730 #endif 731 732 dri2Throttle(psc, priv, __DRI2_THROTTLE_SWAPBUFFER); 733 734 DRI2SwapBuffers(psc->base.dpy, pdraw->xDrawable, 735 target_msc, divisor, remainder, &ret); 736 #endif 737 } 738 739 if (psc->show_fps) { 740 show_fps(priv); 741 } 742 743 /* Old servers don't send invalidate events */ 744 if (!pdp->invalidateAvailable) 745 dri2InvalidateBuffers(dpyPriv->dpy, pdraw->xDrawable); 746 747 return ret; 748 } 749 750 static __DRIbuffer * 751 dri2GetBuffers(__DRIdrawable * driDrawable, 752 int *width, int *height, 753 unsigned int *attachments, int count, 754 int *out_count, void *loaderPrivate) 755 { 756 struct dri2_drawable *pdraw = loaderPrivate; 757 DRI2Buffer *buffers; 758 759 buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable, 760 width, height, attachments, count, out_count); 761 if (buffers == NULL) 762 return NULL; 763 764 pdraw->width = *width; 765 pdraw->height = *height; 766 process_buffers(pdraw, buffers, *out_count); 767 768 Xfree(buffers); 769 770 return pdraw->buffers; 771 } 772 773 static __DRIbuffer * 774 dri2GetBuffersWithFormat(__DRIdrawable * driDrawable, 775 int *width, int *height, 776 unsigned int *attachments, int count, 777 int *out_count, void *loaderPrivate) 778 { 779 struct dri2_drawable *pdraw = loaderPrivate; 780 DRI2Buffer *buffers; 781 782 buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy, 783 pdraw->base.xDrawable, 784 width, height, attachments, 785 count, out_count); 786 if (buffers == NULL) 787 return NULL; 788 789 pdraw->width = *width; 790 pdraw->height = *height; 791 process_buffers(pdraw, buffers, *out_count); 792 793 Xfree(buffers); 794 795 return pdraw->buffers; 796 } 797 798 #ifdef X_DRI2SwapInterval 799 800 static int 801 dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval) 802 { 803 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 804 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 805 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc; 806 807 if (psc->config) 808 psc->config->configQueryi(psc->driScreen, 809 "vblank_mode", &vblank_mode); 810 811 switch (vblank_mode) { 812 case DRI_CONF_VBLANK_NEVER: 813 return GLX_BAD_VALUE; 814 case DRI_CONF_VBLANK_ALWAYS_SYNC: 815 if (interval <= 0) 816 return GLX_BAD_VALUE; 817 break; 818 default: 819 break; 820 } 821 822 DRI2SwapInterval(priv->base.psc->dpy, priv->base.xDrawable, interval); 823 priv->swap_interval = interval; 824 825 return 0; 826 } 827 828 static int 829 dri2GetSwapInterval(__GLXDRIdrawable *pdraw) 830 { 831 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 832 833 return priv->swap_interval; 834 } 835 836 #endif /* X_DRI2SwapInterval */ 837 838 static const __DRIdri2LoaderExtension dri2LoaderExtension = { 839 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 840 dri2GetBuffers, 841 dri2FlushFrontBuffer, 842 dri2GetBuffersWithFormat, 843 }; 844 845 static const __DRIdri2LoaderExtension dri2LoaderExtension_old = { 846 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 847 dri2GetBuffers, 848 dri2FlushFrontBuffer, 849 NULL, 850 }; 851 852 #ifdef __DRI_USE_INVALIDATE 853 static const __DRIuseInvalidateExtension dri2UseInvalidate = { 854 { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION } 855 }; 856 #endif 857 858 _X_HIDDEN void 859 dri2InvalidateBuffers(Display *dpy, XID drawable) 860 { 861 __GLXDRIdrawable *pdraw = 862 dri2GetGlxDrawableFromXDrawableId(dpy, drawable); 863 struct dri2_screen *psc; 864 struct dri2_drawable *pdp = (struct dri2_drawable *) pdraw; 865 866 if (!pdraw) 867 return; 868 869 psc = (struct dri2_screen *) pdraw->psc; 870 871 #if __DRI2_FLUSH_VERSION >= 3 872 if (pdraw && psc->f && psc->f->base.version >= 3 && psc->f->invalidate) 873 psc->f->invalidate(pdp->driDrawable); 874 #endif 875 } 876 877 static void 878 dri2_bind_tex_image(Display * dpy, 879 GLXDrawable drawable, 880 int buffer, const int *attrib_list) 881 { 882 struct glx_context *gc = __glXGetCurrentContext(); 883 struct dri2_context *pcp = (struct dri2_context *) gc; 884 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); 885 struct glx_display *dpyPriv = __glXInitialize(dpy); 886 struct dri2_drawable *pdraw = (struct dri2_drawable *) base; 887 struct dri2_display *pdp = 888 (struct dri2_display *) dpyPriv->dri2Display; 889 struct dri2_screen *psc; 890 891 if (pdraw != NULL) { 892 psc = (struct dri2_screen *) base->psc; 893 894 #if __DRI2_FLUSH_VERSION >= 3 895 if (!pdp->invalidateAvailable && psc->f && 896 psc->f->base.version >= 3 && psc->f->invalidate) 897 psc->f->invalidate(pdraw->driDrawable); 898 #endif 899 900 if (psc->texBuffer->base.version >= 2 && 901 psc->texBuffer->setTexBuffer2 != NULL) { 902 (*psc->texBuffer->setTexBuffer2) (pcp->driContext, 903 pdraw->base.textureTarget, 904 pdraw->base.textureFormat, 905 pdraw->driDrawable); 906 } 907 else { 908 (*psc->texBuffer->setTexBuffer) (pcp->driContext, 909 pdraw->base.textureTarget, 910 pdraw->driDrawable); 911 } 912 } 913 } 914 915 static void 916 dri2_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer) 917 { 918 #if __DRI_TEX_BUFFER_VERSION >= 3 919 struct glx_context *gc = __glXGetCurrentContext(); 920 struct dri2_context *pcp = (struct dri2_context *) gc; 921 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); 922 struct glx_display *dpyPriv = __glXInitialize(dpy); 923 struct dri2_drawable *pdraw = (struct dri2_drawable *) base; 924 struct dri2_display *pdp = 925 (struct dri2_display *) dpyPriv->dri2Display; 926 struct dri2_screen *psc; 927 928 if (pdraw != NULL) { 929 psc = (struct dri2_screen *) base->psc; 930 931 if (psc->texBuffer->base.version >= 3 && 932 psc->texBuffer->releaseTexBuffer != NULL) { 933 (*psc->texBuffer->releaseTexBuffer) (pcp->driContext, 934 pdraw->base.textureTarget, 935 pdraw->driDrawable); 936 } 937 } 938 #endif 939 } 940 941 static const struct glx_context_vtable dri2_context_vtable = { 942 dri2_destroy_context, 943 dri2_bind_context, 944 dri2_unbind_context, 945 dri2_wait_gl, 946 dri2_wait_x, 947 DRI_glXUseXFont, 948 dri2_bind_tex_image, 949 dri2_release_tex_image, 950 NULL, /* get_proc_address */ 951 }; 952 953 static void 954 dri2BindExtensions(struct dri2_screen *psc, const __DRIextension **extensions, 955 const char *driverName) 956 { 957 int i; 958 959 __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync"); 960 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control"); 961 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control"); 962 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read"); 963 964 /* 965 * GLX_INTEL_swap_event is broken on the server side, where it's 966 * currently unconditionally enabled. This completely breaks 967 * systems running on drivers which don't support that extension. 968 * There's no way to test for its presence on this side, so instead 969 * of disabling it uncondtionally, just disable it for drivers 970 * which are known to not support it. 971 */ 972 if (strcmp(driverName, "vmwgfx") != 0) { 973 __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event"); 974 } 975 976 if (psc->dri2->base.version >= 3) { 977 const unsigned mask = psc->dri2->getAPIMask(psc->driScreen); 978 979 __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context"); 980 __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile"); 981 982 if ((mask & (1 << __DRI_API_GLES2)) != 0) 983 __glXEnableDirectExtension(&psc->base, 984 "GLX_EXT_create_context_es2_profile"); 985 } 986 987 for (i = 0; extensions[i]; i++) { 988 if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) { 989 psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; 990 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap"); 991 } 992 993 if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) { 994 psc->f = (__DRI2flushExtension *) extensions[i]; 995 /* internal driver extension, no GL extension exposed */ 996 } 997 998 if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0)) 999 psc->config = (__DRI2configQueryExtension *) extensions[i]; 1000 1001 if (((strcmp(extensions[i]->name, __DRI2_THROTTLE) == 0))) 1002 psc->throttle = (__DRI2throttleExtension *) extensions[i]; 1003 1004 /* DRI2 version 3 is also required because 1005 * GLX_ARB_create_context_robustness requires GLX_ARB_create_context. 1006 */ 1007 if (psc->dri2->base.version >= 3 1008 && strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0) 1009 __glXEnableDirectExtension(&psc->base, 1010 "GLX_ARB_create_context_robustness"); 1011 } 1012 } 1013 1014 static const struct glx_screen_vtable dri2_screen_vtable = { 1015 dri2_create_context, 1016 dri2_create_context_attribs 1017 }; 1018 1019 static struct glx_screen * 1020 dri2CreateScreen(int screen, struct glx_display * priv) 1021 { 1022 const __DRIconfig **driver_configs; 1023 const __DRIextension **extensions; 1024 const struct dri2_display *const pdp = (struct dri2_display *) 1025 priv->dri2Display; 1026 struct dri2_screen *psc; 1027 __GLXDRIscreen *psp; 1028 struct glx_config *configs = NULL, *visuals = NULL; 1029 char *driverName, *deviceName, *tmp; 1030 drm_magic_t magic; 1031 int i; 1032 1033 psc = Xmalloc(sizeof *psc); 1034 if (psc == NULL) 1035 return NULL; 1036 1037 memset(psc, 0, sizeof *psc); 1038 psc->fd = -1; 1039 1040 if (!glx_screen_init(&psc->base, screen, priv)) { 1041 Xfree(psc); 1042 return NULL; 1043 } 1044 1045 if (!DRI2Connect(priv->dpy, RootWindow(priv->dpy, screen), 1046 &driverName, &deviceName)) { 1047 glx_screen_cleanup(&psc->base); 1048 XFree(psc); 1049 InfoMessageF("screen %d does not appear to be DRI2 capable\n", screen); 1050 return NULL; 1051 } 1052 1053 psc->driver = driOpenDriver(driverName); 1054 if (psc->driver == NULL) { 1055 ErrorMessageF("driver pointer missing\n"); 1056 goto handle_error; 1057 } 1058 1059 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); 1060 if (extensions == NULL) { 1061 ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 1062 goto handle_error; 1063 } 1064 1065 for (i = 0; extensions[i]; i++) { 1066 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 1067 psc->core = (__DRIcoreExtension *) extensions[i]; 1068 if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) 1069 psc->dri2 = (__DRIdri2Extension *) extensions[i]; 1070 } 1071 1072 if (psc->core == NULL || psc->dri2 == NULL) { 1073 ErrorMessageF("core dri or dri2 extension not found\n"); 1074 goto handle_error; 1075 } 1076 1077 #ifdef O_CLOEXEC 1078 psc->fd = open(deviceName, O_RDWR | O_CLOEXEC); 1079 if (psc->fd == -1 && errno == EINVAL) 1080 #endif 1081 { 1082 psc->fd = open(deviceName, O_RDWR); 1083 if (psc->fd != -1) 1084 fcntl(psc->fd, F_SETFD, fcntl(psc->fd, F_GETFD) | FD_CLOEXEC); 1085 } 1086 if (psc->fd < 0) { 1087 ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); 1088 goto handle_error; 1089 } 1090 1091 if (drmGetMagic(psc->fd, &magic)) { 1092 ErrorMessageF("failed to get magic\n"); 1093 goto handle_error; 1094 } 1095 1096 if (!DRI2Authenticate(priv->dpy, RootWindow(priv->dpy, screen), magic)) { 1097 ErrorMessageF("failed to authenticate magic %d\n", magic); 1098 goto handle_error; 1099 } 1100 1101 1102 /* If the server does not support the protocol for 1103 * DRI2GetBuffersWithFormat, don't supply that interface to the driver. 1104 */ 1105 psc->driScreen = 1106 psc->dri2->createNewScreen(screen, psc->fd, 1107 (const __DRIextension **) 1108 &pdp->loader_extensions[0], 1109 &driver_configs, psc); 1110 1111 if (psc->driScreen == NULL) { 1112 ErrorMessageF("failed to create dri screen\n"); 1113 goto handle_error; 1114 } 1115 1116 extensions = psc->core->getExtensions(psc->driScreen); 1117 dri2BindExtensions(psc, extensions, driverName); 1118 1119 configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs); 1120 visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs); 1121 1122 if (!configs || !visuals) 1123 goto handle_error; 1124 1125 glx_config_destroy_list(psc->base.configs); 1126 psc->base.configs = configs; 1127 glx_config_destroy_list(psc->base.visuals); 1128 psc->base.visuals = visuals; 1129 1130 psc->driver_configs = driver_configs; 1131 1132 psc->base.vtable = &dri2_screen_vtable; 1133 psp = &psc->vtable; 1134 psc->base.driScreen = psp; 1135 psp->destroyScreen = dri2DestroyScreen; 1136 psp->createDrawable = dri2CreateDrawable; 1137 psp->swapBuffers = dri2SwapBuffers; 1138 psp->getDrawableMSC = NULL; 1139 psp->waitForMSC = NULL; 1140 psp->waitForSBC = NULL; 1141 psp->setSwapInterval = NULL; 1142 psp->getSwapInterval = NULL; 1143 1144 if (pdp->driMinor >= 2) { 1145 #ifdef X_DRI2GetMSC 1146 psp->getDrawableMSC = dri2DrawableGetMSC; 1147 #endif 1148 #ifdef X_DRI2WaitMSC 1149 psp->waitForMSC = dri2WaitForMSC; 1150 psp->waitForSBC = dri2WaitForSBC; 1151 #endif 1152 #ifdef X_DRI2SwapInterval 1153 psp->setSwapInterval = dri2SetSwapInterval; 1154 psp->getSwapInterval = dri2GetSwapInterval; 1155 #endif 1156 #if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval) 1157 __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control"); 1158 #endif 1159 } 1160 1161 /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always 1162 * available.*/ 1163 psp->copySubBuffer = dri2CopySubBuffer; 1164 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer"); 1165 1166 Xfree(driverName); 1167 Xfree(deviceName); 1168 1169 tmp = getenv("LIBGL_SHOW_FPS"); 1170 psc->show_fps = tmp && strcmp(tmp, "1") == 0; 1171 1172 return &psc->base; 1173 1174 handle_error: 1175 CriticalErrorMessageF("failed to load driver: %s\n", driverName); 1176 1177 if (configs) 1178 glx_config_destroy_list(configs); 1179 if (visuals) 1180 glx_config_destroy_list(visuals); 1181 if (psc->driScreen) 1182 psc->core->destroyScreen(psc->driScreen); 1183 psc->driScreen = NULL; 1184 if (psc->fd >= 0) 1185 close(psc->fd); 1186 if (psc->driver) 1187 dlclose(psc->driver); 1188 1189 Xfree(driverName); 1190 Xfree(deviceName); 1191 glx_screen_cleanup(&psc->base); 1192 XFree(psc); 1193 1194 return NULL; 1195 } 1196 1197 /* Called from __glXFreeDisplayPrivate. 1198 */ 1199 static void 1200 dri2DestroyDisplay(__GLXDRIdisplay * dpy) 1201 { 1202 struct dri2_display *pdp = (struct dri2_display *) dpy; 1203 1204 __glxHashDestroy(pdp->dri2Hash); 1205 Xfree(dpy); 1206 } 1207 1208 _X_HIDDEN __GLXDRIdrawable * 1209 dri2GetGlxDrawableFromXDrawableId(Display *dpy, XID id) 1210 { 1211 struct glx_display *d = __glXInitialize(dpy); 1212 struct dri2_display *pdp = (struct dri2_display *) d->dri2Display; 1213 __GLXDRIdrawable *pdraw; 1214 1215 if (__glxHashLookup(pdp->dri2Hash, id, (void *) &pdraw) == 0) 1216 return pdraw; 1217 1218 return NULL; 1219 } 1220 1221 /* 1222 * Allocate, initialize and return a __DRIdisplayPrivate object. 1223 * This is called from __glXInitialize() when we are given a new 1224 * display pointer. 1225 */ 1226 _X_HIDDEN __GLXDRIdisplay * 1227 dri2CreateDisplay(Display * dpy) 1228 { 1229 struct dri2_display *pdp; 1230 int eventBase, errorBase, i; 1231 1232 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) 1233 return NULL; 1234 1235 pdp = Xmalloc(sizeof *pdp); 1236 if (pdp == NULL) 1237 return NULL; 1238 1239 if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) { 1240 Xfree(pdp); 1241 return NULL; 1242 } 1243 1244 pdp->driPatch = 0; 1245 pdp->swapAvailable = (pdp->driMinor >= 2); 1246 pdp->invalidateAvailable = (pdp->driMinor >= 3); 1247 1248 pdp->base.destroyDisplay = dri2DestroyDisplay; 1249 pdp->base.createScreen = dri2CreateScreen; 1250 1251 i = 0; 1252 if (pdp->driMinor < 1) 1253 pdp->loader_extensions[i++] = &dri2LoaderExtension_old.base; 1254 else 1255 pdp->loader_extensions[i++] = &dri2LoaderExtension.base; 1256 1257 pdp->loader_extensions[i++] = &systemTimeExtension.base; 1258 1259 #ifdef __DRI_USE_INVALIDATE 1260 pdp->loader_extensions[i++] = &dri2UseInvalidate.base; 1261 #endif 1262 pdp->loader_extensions[i++] = NULL; 1263 1264 pdp->dri2Hash = __glxHashCreate(); 1265 if (pdp->dri2Hash == NULL) { 1266 Xfree(pdp); 1267 return NULL; 1268 } 1269 1270 return &pdp->base; 1271 } 1272 1273 #endif /* GLX_DIRECT_RENDERING */ 1274