1 /************************************************************************** 2 3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 4 All Rights Reserved. 5 6 Permission is hereby granted, free of charge, to any person obtaining a 7 copy of this software and associated documentation files (the 8 "Software"), to deal in the Software without restriction, including 9 without limitation the rights to use, copy, modify, merge, publish, 10 distribute, sub license, and/or sell copies of the Software, and to 11 permit persons to whom the Software is furnished to do so, subject to 12 the following conditions: 13 14 The above copyright notice and this permission notice (including the 15 next paragraph) shall be included in all copies or substantial portions 16 of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 22 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 26 **************************************************************************/ 27 28 /* 29 * Authors: 30 * Kevin E. Martin <kevin (at) precisioninsight.com> 31 * Brian Paul <brian (at) precisioninsight.com> 32 * 33 */ 34 35 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 36 37 #include <X11/Xlib.h> 38 #include <X11/extensions/Xfixes.h> 39 #include <X11/extensions/Xdamage.h> 40 #include "glxclient.h" 41 #include "xf86dri.h" 42 #include "dri2.h" 43 #include "sarea.h" 44 #include <dlfcn.h> 45 #include <sys/types.h> 46 #include <sys/mman.h> 47 #include "xf86drm.h" 48 #include "dri_common.h" 49 50 struct dri_display 51 { 52 __GLXDRIdisplay base; 53 54 /* 55 ** XFree86-DRI version information 56 */ 57 int driMajor; 58 int driMinor; 59 int driPatch; 60 }; 61 62 struct dri_screen 63 { 64 struct glx_screen base; 65 66 __DRIscreen *driScreen; 67 __GLXDRIscreen vtable; 68 const __DRIlegacyExtension *legacy; 69 const __DRIcoreExtension *core; 70 const __DRIswapControlExtension *swapControl; 71 const __DRImediaStreamCounterExtension *msc; 72 const __DRIconfig **driver_configs; 73 const __DRIcopySubBufferExtension *driCopySubBuffer; 74 75 void *driver; 76 int fd; 77 }; 78 79 struct dri_context 80 { 81 struct glx_context base; 82 __DRIcontext *driContext; 83 XID hwContextID; 84 }; 85 86 struct dri_drawable 87 { 88 __GLXDRIdrawable base; 89 90 __DRIdrawable *driDrawable; 91 }; 92 93 static const struct glx_context_vtable dri_context_vtable; 94 95 /* 96 * Given a display pointer and screen number, determine the name of 97 * the DRI driver for the screen (i.e., "i965", "radeon", "nouveau", etc). 98 * Return True for success, False for failure. 99 */ 100 static Bool 101 driGetDriverName(Display * dpy, int scrNum, char **driverName) 102 { 103 int directCapable; 104 Bool b; 105 int event, error; 106 int driverMajor, driverMinor, driverPatch; 107 108 *driverName = NULL; 109 110 if (XF86DRIQueryExtension(dpy, &event, &error)) { /* DRI1 */ 111 if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) { 112 ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n"); 113 return False; 114 } 115 if (!directCapable) { 116 ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n"); 117 return False; 118 } 119 120 b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor, 121 &driverPatch, driverName); 122 if (!b) { 123 ErrorMessageF("Cannot determine driver name for screen %d\n", 124 scrNum); 125 return False; 126 } 127 128 InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n", 129 driverMajor, driverMinor, driverPatch, *driverName, 130 scrNum); 131 132 return True; 133 } 134 else if (DRI2QueryExtension(dpy, &event, &error)) { /* DRI2 */ 135 char *dev; 136 Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev); 137 138 if (ret) 139 Xfree(dev); 140 141 return ret; 142 } 143 144 return False; 145 } 146 147 /* 148 * Exported function for querying the DRI driver for a given screen. 149 * 150 * The returned char pointer points to a static array that will be 151 * overwritten by subsequent calls. 152 */ 153 _X_EXPORT const char * 154 glXGetScreenDriver(Display * dpy, int scrNum) 155 { 156 static char ret[32]; 157 char *driverName; 158 if (driGetDriverName(dpy, scrNum, &driverName)) { 159 int len; 160 if (!driverName) 161 return NULL; 162 len = strlen(driverName); 163 if (len >= 31) 164 return NULL; 165 memcpy(ret, driverName, len + 1); 166 Xfree(driverName); 167 return ret; 168 } 169 return NULL; 170 } 171 172 /* 173 * Exported function for obtaining a driver's option list (UTF-8 encoded XML). 174 * 175 * The returned char pointer points directly into the driver. Therefore 176 * it should be treated as a constant. 177 * 178 * If the driver was not found or does not support configuration NULL is 179 * returned. 180 * 181 * Note: The driver remains opened after this function returns. 182 */ 183 _X_EXPORT const char * 184 glXGetDriverConfig(const char *driverName) 185 { 186 void *handle = driOpenDriver(driverName); 187 if (handle) 188 return dlsym(handle, "__driConfigOptions"); 189 else 190 return NULL; 191 } 192 193 #ifdef XDAMAGE_1_1_INTERFACE 194 195 static GLboolean 196 has_damage_post(Display * dpy) 197 { 198 static GLboolean inited = GL_FALSE; 199 static GLboolean has_damage; 200 201 if (!inited) { 202 int major, minor; 203 204 if (XDamageQueryVersion(dpy, &major, &minor) && 205 major == 1 && minor >= 1) { 206 has_damage = GL_TRUE; 207 } 208 else { 209 has_damage = GL_FALSE; 210 } 211 inited = GL_TRUE; 212 } 213 214 return has_damage; 215 } 216 217 static void 218 __glXReportDamage(__DRIdrawable * driDraw, 219 int x, int y, 220 drm_clip_rect_t * rects, int num_rects, 221 GLboolean front_buffer, void *loaderPrivate) 222 { 223 XRectangle *xrects; 224 XserverRegion region; 225 int i; 226 int x_off, y_off; 227 __GLXDRIdrawable *glxDraw = loaderPrivate; 228 struct glx_screen *psc = glxDraw->psc; 229 Display *dpy = psc->dpy; 230 Drawable drawable; 231 232 if (!has_damage_post(dpy)) 233 return; 234 235 if (front_buffer) { 236 x_off = x; 237 y_off = y; 238 drawable = RootWindow(dpy, psc->scr); 239 } 240 else { 241 x_off = 0; 242 y_off = 0; 243 drawable = glxDraw->xDrawable; 244 } 245 246 xrects = malloc(sizeof(XRectangle) * num_rects); 247 if (xrects == NULL) 248 return; 249 250 for (i = 0; i < num_rects; i++) { 251 xrects[i].x = rects[i].x1 + x_off; 252 xrects[i].y = rects[i].y1 + y_off; 253 xrects[i].width = rects[i].x2 - rects[i].x1; 254 xrects[i].height = rects[i].y2 - rects[i].y1; 255 } 256 region = XFixesCreateRegion(dpy, xrects, num_rects); 257 free(xrects); 258 XDamageAdd(dpy, drawable, region); 259 XFixesDestroyRegion(dpy, region); 260 } 261 262 static const __DRIdamageExtension damageExtension = { 263 {__DRI_DAMAGE, __DRI_DAMAGE_VERSION}, 264 __glXReportDamage, 265 }; 266 267 #endif 268 269 static GLboolean 270 __glXDRIGetDrawableInfo(__DRIdrawable * drawable, 271 unsigned int *index, unsigned int *stamp, 272 int *X, int *Y, int *W, int *H, 273 int *numClipRects, drm_clip_rect_t ** pClipRects, 274 int *backX, int *backY, 275 int *numBackClipRects, 276 drm_clip_rect_t ** pBackClipRects, 277 void *loaderPrivate) 278 { 279 __GLXDRIdrawable *glxDraw = loaderPrivate; 280 struct glx_screen *psc = glxDraw->psc; 281 Display *dpy = psc->dpy; 282 283 return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable, 284 index, stamp, X, Y, W, H, 285 numClipRects, pClipRects, 286 backX, backY, 287 numBackClipRects, pBackClipRects); 288 } 289 290 static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = { 291 {__DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION}, 292 __glXDRIGetDrawableInfo 293 }; 294 295 static const __DRIextension *loader_extensions[] = { 296 &systemTimeExtension.base, 297 &getDrawableInfoExtension.base, 298 #ifdef XDAMAGE_1_1_INTERFACE 299 &damageExtension.base, 300 #endif 301 NULL 302 }; 303 304 /** 305 * Perform the required libGL-side initialization and call the client-side 306 * driver's \c __driCreateNewScreen function. 307 * 308 * \param dpy Display pointer. 309 * \param scrn Screen number on the display. 310 * \param psc DRI screen information. 311 * \param driDpy DRI display information. 312 * \param createNewScreen Pointer to the client-side driver's 313 * \c __driCreateNewScreen function. 314 * \returns A pointer to the \c __DRIscreen structure returned by 315 * the client-side driver on success, or \c NULL on failure. 316 */ 317 static void * 318 CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc, 319 struct dri_display * driDpy) 320 { 321 void *psp = NULL; 322 drm_handle_t hSAREA; 323 drmAddress pSAREA = MAP_FAILED; 324 char *BusID; 325 __DRIversion ddx_version; 326 __DRIversion dri_version; 327 __DRIversion drm_version; 328 __DRIframebuffer framebuffer; 329 int fd = -1; 330 int status; 331 332 drm_magic_t magic; 333 drmVersionPtr version; 334 int newlyopened; 335 char *driverName; 336 drm_handle_t hFB; 337 int junk; 338 const __DRIconfig **driver_configs; 339 struct glx_config *visual, *configs = NULL, *visuals = NULL; 340 341 /* DRI protocol version. */ 342 dri_version.major = driDpy->driMajor; 343 dri_version.minor = driDpy->driMinor; 344 dri_version.patch = driDpy->driPatch; 345 346 framebuffer.base = MAP_FAILED; 347 framebuffer.dev_priv = NULL; 348 framebuffer.size = 0; 349 350 if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) { 351 ErrorMessageF("XF86DRIOpenConnection failed\n"); 352 goto handle_error; 353 } 354 355 fd = drmOpenOnce(NULL, BusID, &newlyopened); 356 357 Xfree(BusID); /* No longer needed */ 358 359 if (fd < 0) { 360 ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd)); 361 goto handle_error; 362 } 363 364 if (drmGetMagic(fd, &magic)) { 365 ErrorMessageF("drmGetMagic failed\n"); 366 goto handle_error; 367 } 368 369 version = drmGetVersion(fd); 370 if (version) { 371 drm_version.major = version->version_major; 372 drm_version.minor = version->version_minor; 373 drm_version.patch = version->version_patchlevel; 374 drmFreeVersion(version); 375 } 376 else { 377 drm_version.major = -1; 378 drm_version.minor = -1; 379 drm_version.patch = -1; 380 } 381 382 if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) { 383 ErrorMessageF("XF86DRIAuthConnection failed\n"); 384 goto handle_error; 385 } 386 387 /* Get device name (like "radeon") and the ddx version numbers. 388 * We'll check the version in each DRI driver's "createNewScreen" 389 * function. */ 390 if (!XF86DRIGetClientDriverName(dpy, scrn, 391 &ddx_version.major, 392 &ddx_version.minor, 393 &ddx_version.patch, &driverName)) { 394 ErrorMessageF("XF86DRIGetClientDriverName failed\n"); 395 goto handle_error; 396 } 397 398 Xfree(driverName); /* No longer needed. */ 399 400 /* 401 * Get device-specific info. pDevPriv will point to a struct 402 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that 403 * has information about the screen size, depth, pitch, ancilliary 404 * buffers, DRM mmap handles, etc. 405 */ 406 if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk, 407 &framebuffer.size, &framebuffer.stride, 408 &framebuffer.dev_priv_size, 409 &framebuffer.dev_priv)) { 410 ErrorMessageF("XF86DRIGetDeviceInfo failed"); 411 goto handle_error; 412 } 413 414 framebuffer.width = DisplayWidth(dpy, scrn); 415 framebuffer.height = DisplayHeight(dpy, scrn); 416 417 /* Map the framebuffer region. */ 418 status = drmMap(fd, hFB, framebuffer.size, 419 (drmAddressPtr) & framebuffer.base); 420 if (status != 0) { 421 ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status)); 422 goto handle_error; 423 } 424 425 /* Map the SAREA region. Further mmap regions may be setup in 426 * each DRI driver's "createNewScreen" function. 427 */ 428 status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA); 429 if (status != 0) { 430 ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status)); 431 goto handle_error; 432 } 433 434 psp = (*psc->legacy->createNewScreen) (scrn, 435 &ddx_version, 436 &dri_version, 437 &drm_version, 438 &framebuffer, 439 pSAREA, 440 fd, 441 loader_extensions, 442 &driver_configs, psc); 443 444 if (psp == NULL) { 445 ErrorMessageF("Calling driver entry point failed"); 446 goto handle_error; 447 } 448 449 configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs); 450 visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs); 451 452 if (!configs || !visuals) 453 goto handle_error; 454 455 glx_config_destroy_list(psc->base.configs); 456 psc->base.configs = configs; 457 glx_config_destroy_list(psc->base.visuals); 458 psc->base.visuals = visuals; 459 460 psc->driver_configs = driver_configs; 461 462 /* Visuals with depth != screen depth are subject to automatic compositing 463 * in the X server, so DRI1 can't render to them properly. Mark them as 464 * non-conformant to prevent apps from picking them up accidentally. 465 */ 466 for (visual = psc->base.visuals; visual; visual = visual->next) { 467 XVisualInfo template; 468 XVisualInfo *visuals; 469 int num_visuals; 470 long mask; 471 472 template.visualid = visual->visualID; 473 mask = VisualIDMask; 474 visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals); 475 476 if (visuals) { 477 if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn)) 478 visual->visualRating = GLX_NON_CONFORMANT_CONFIG; 479 480 XFree(visuals); 481 } 482 } 483 484 return psp; 485 486 handle_error: 487 if (configs) 488 glx_config_destroy_list(configs); 489 if (visuals) 490 glx_config_destroy_list(visuals); 491 492 if (pSAREA != MAP_FAILED) 493 drmUnmap(pSAREA, SAREA_MAX); 494 495 if (framebuffer.base != MAP_FAILED) 496 drmUnmap((drmAddress) framebuffer.base, framebuffer.size); 497 498 if (framebuffer.dev_priv != NULL) 499 Xfree(framebuffer.dev_priv); 500 501 if (fd >= 0) 502 drmCloseOnce(fd); 503 504 XF86DRICloseConnection(dpy, scrn); 505 506 ErrorMessageF("reverting to software direct rendering\n"); 507 508 return NULL; 509 } 510 511 static void 512 dri_destroy_context(struct glx_context * context) 513 { 514 struct dri_context *pcp = (struct dri_context *) context; 515 struct dri_screen *psc = (struct dri_screen *) context->psc; 516 517 driReleaseDrawables(&pcp->base); 518 519 if (context->extensions) 520 XFree((char *) context->extensions); 521 522 (*psc->core->destroyContext) (pcp->driContext); 523 524 XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID); 525 Xfree(pcp); 526 } 527 528 static int 529 dri_bind_context(struct glx_context *context, struct glx_context *old, 530 GLXDrawable draw, GLXDrawable read) 531 { 532 struct dri_context *pcp = (struct dri_context *) context; 533 struct dri_screen *psc = (struct dri_screen *) pcp->base.psc; 534 struct dri_drawable *pdraw, *pread; 535 536 pdraw = (struct dri_drawable *) driFetchDrawable(context, draw); 537 pread = (struct dri_drawable *) driFetchDrawable(context, read); 538 539 driReleaseDrawables(&pcp->base); 540 541 if (pdraw == NULL || pread == NULL) 542 return GLXBadDrawable; 543 544 if ((*psc->core->bindContext) (pcp->driContext, 545 pdraw->driDrawable, pread->driDrawable)) 546 return Success; 547 548 return GLXBadContext; 549 } 550 551 static void 552 dri_unbind_context(struct glx_context *context, struct glx_context *new) 553 { 554 struct dri_context *pcp = (struct dri_context *) context; 555 struct dri_screen *psc = (struct dri_screen *) pcp->base.psc; 556 557 (*psc->core->unbindContext) (pcp->driContext); 558 } 559 560 static const struct glx_context_vtable dri_context_vtable = { 561 dri_destroy_context, 562 dri_bind_context, 563 dri_unbind_context, 564 NULL, 565 NULL, 566 DRI_glXUseXFont, 567 NULL, 568 NULL, 569 NULL, /* get_proc_address */ 570 }; 571 572 static struct glx_context * 573 dri_create_context(struct glx_screen *base, 574 struct glx_config *config_base, 575 struct glx_context *shareList, int renderType) 576 { 577 struct dri_context *pcp, *pcp_shared; 578 struct dri_screen *psc = (struct dri_screen *) base; 579 drm_context_t hwContext; 580 __DRIcontext *shared = NULL; 581 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 582 583 if (!psc->base.driScreen) 584 return NULL; 585 586 if (shareList) { 587 /* If the shareList context is not a DRI context, we cannot possibly 588 * create a DRI context that shares it. 589 */ 590 if (shareList->vtable->destroy != dri_destroy_context) { 591 return NULL; 592 } 593 594 pcp_shared = (struct dri_context *) shareList; 595 shared = pcp_shared->driContext; 596 } 597 598 pcp = Xmalloc(sizeof *pcp); 599 if (pcp == NULL) 600 return NULL; 601 602 memset(pcp, 0, sizeof *pcp); 603 if (!glx_context_init(&pcp->base, &psc->base, &config->base)) { 604 Xfree(pcp); 605 return NULL; 606 } 607 608 if (!XF86DRICreateContextWithConfig(psc->base.dpy, psc->base.scr, 609 config->base.visualID, 610 &pcp->hwContextID, &hwContext)) { 611 Xfree(pcp); 612 return NULL; 613 } 614 615 pcp->driContext = 616 (*psc->legacy->createNewContext) (psc->driScreen, 617 config->driConfig, 618 renderType, shared, hwContext, pcp); 619 if (pcp->driContext == NULL) { 620 XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID); 621 Xfree(pcp); 622 return NULL; 623 } 624 625 pcp->base.vtable = &dri_context_vtable; 626 627 return &pcp->base; 628 } 629 630 static void 631 driDestroyDrawable(__GLXDRIdrawable * pdraw) 632 { 633 struct dri_screen *psc = (struct dri_screen *) pdraw->psc; 634 struct dri_drawable *pdp = (struct dri_drawable *) pdraw; 635 636 (*psc->core->destroyDrawable) (pdp->driDrawable); 637 XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, pdraw->drawable); 638 Xfree(pdraw); 639 } 640 641 static __GLXDRIdrawable * 642 driCreateDrawable(struct glx_screen *base, 643 XID xDrawable, 644 GLXDrawable drawable, struct glx_config *config_base) 645 { 646 drm_drawable_t hwDrawable; 647 void *empty_attribute_list = NULL; 648 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 649 struct dri_screen *psc = (struct dri_screen *) base; 650 struct dri_drawable *pdp; 651 652 /* Old dri can't handle GLX 1.3+ drawable constructors. */ 653 if (xDrawable != drawable) 654 return NULL; 655 656 pdp = Xmalloc(sizeof *pdp); 657 if (!pdp) 658 return NULL; 659 660 memset(pdp, 0, sizeof *pdp); 661 pdp->base.drawable = drawable; 662 pdp->base.psc = &psc->base; 663 664 if (!XF86DRICreateDrawable(psc->base.dpy, psc->base.scr, 665 drawable, &hwDrawable)) { 666 Xfree(pdp); 667 return NULL; 668 } 669 670 /* Create a new drawable */ 671 pdp->driDrawable = 672 (*psc->legacy->createNewDrawable) (psc->driScreen, 673 config->driConfig, 674 hwDrawable, 675 GLX_WINDOW_BIT, 676 empty_attribute_list, pdp); 677 678 if (!pdp->driDrawable) { 679 XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, drawable); 680 Xfree(pdp); 681 return NULL; 682 } 683 684 pdp->base.destroyDrawable = driDestroyDrawable; 685 686 return &pdp->base; 687 } 688 689 static int64_t 690 driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2, 691 int64_t unused3) 692 { 693 struct dri_screen *psc = (struct dri_screen *) pdraw->psc; 694 struct dri_drawable *pdp = (struct dri_drawable *) pdraw; 695 696 (*psc->core->swapBuffers) (pdp->driDrawable); 697 return 0; 698 } 699 700 static void 701 driCopySubBuffer(__GLXDRIdrawable * pdraw, 702 int x, int y, int width, int height) 703 { 704 struct dri_drawable *pdp = (struct dri_drawable *) pdraw; 705 struct dri_screen *psc = (struct dri_screen *) pdp->base.psc; 706 707 (*psc->driCopySubBuffer->copySubBuffer) (pdp->driDrawable, 708 x, y, width, height); 709 } 710 711 static void 712 driDestroyScreen(struct glx_screen *base) 713 { 714 struct dri_screen *psc = (struct dri_screen *) base; 715 716 /* Free the direct rendering per screen data */ 717 if (psc->driScreen) 718 (*psc->core->destroyScreen) (psc->driScreen); 719 driDestroyConfigs(psc->driver_configs); 720 psc->driScreen = NULL; 721 if (psc->driver) 722 dlclose(psc->driver); 723 } 724 725 #ifdef __DRI_SWAP_BUFFER_COUNTER 726 727 static int 728 driDrawableGetMSC(struct glx_screen *base, __GLXDRIdrawable *pdraw, 729 int64_t *ust, int64_t *msc, int64_t *sbc) 730 { 731 struct dri_screen *psc = (struct dri_screen *) base; 732 struct dri_drawable *pdp = (struct dri_drawable *) pdraw; 733 734 if (pdp && psc->sbc && psc->msc) 735 return ( (*psc->msc->getMSC)(psc->driScreen, msc) == 0 && 736 (*psc->sbc->getSBC)(pdp->driDrawable, sbc) == 0 && 737 __glXGetUST(ust) == 0 ); 738 } 739 740 static int 741 driWaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 742 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) 743 { 744 struct dri_screen *psc = (struct dri_screen *) pdraw->psc; 745 struct dri_drawable *pdp = (struct dri_drawable *) pdraw; 746 747 if (pdp != NULL && psc->msc != NULL) { 748 ret = (*psc->msc->waitForMSC) (pdp->driDrawable, target_msc, 749 divisor, remainder, msc, sbc); 750 751 /* __glXGetUST returns zero on success and non-zero on failure. 752 * This function returns True on success and False on failure. 753 */ 754 return ret == 0 && __glXGetUST(ust) == 0; 755 } 756 } 757 758 static int 759 driWaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, 760 int64_t *msc, int64_t *sbc) 761 { 762 struct dri_drawable *pdp = (struct dri_drawable *) pdraw; 763 764 if (pdp != NULL && psc->sbc != NULL) { 765 ret = 766 (*psc->sbc->waitForSBC) (pdp->driDrawable, target_sbc, msc, sbc); 767 768 /* __glXGetUST returns zero on success and non-zero on failure. 769 * This function returns True on success and False on failure. 770 */ 771 return ((ret == 0) && (__glXGetUST(ust) == 0)); 772 } 773 774 return DRI2WaitSBC(pdp->base.psc->dpy, 775 pdp->base.xDrawable, target_sbc, ust, msc, sbc); 776 } 777 778 #endif 779 780 static int 781 driSetSwapInterval(__GLXDRIdrawable *pdraw, int interval) 782 { 783 struct dri_drawable *pdp = (struct dri_drawable *) pdraw; 784 struct dri_screen *psc = (struct dri_screen *) pdraw->psc; 785 786 if (psc->swapControl != NULL && pdraw != NULL) { 787 psc->swapControl->setSwapInterval(pdp->driDrawable, interval); 788 return 0; 789 } 790 791 return GLX_BAD_CONTEXT; 792 } 793 794 static int 795 driGetSwapInterval(__GLXDRIdrawable *pdraw) 796 { 797 struct dri_drawable *pdp = (struct dri_drawable *) pdraw; 798 struct dri_screen *psc = (struct dri_screen *) pdraw->psc; 799 800 if (psc->swapControl != NULL && pdraw != NULL) 801 return psc->swapControl->getSwapInterval(pdp->driDrawable); 802 803 return 0; 804 } 805 806 /* Bind DRI1 specific extensions */ 807 static void 808 driBindExtensions(struct dri_screen *psc, const __DRIextension **extensions) 809 { 810 int i; 811 812 for (i = 0; extensions[i]; i++) { 813 /* No DRI2 support for swap_control at the moment, since SwapBuffers 814 * is done by the X server */ 815 if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) { 816 psc->swapControl = (__DRIswapControlExtension *) extensions[i]; 817 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control"); 818 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control"); 819 } 820 821 if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) { 822 psc->msc = (__DRImediaStreamCounterExtension *) extensions[i]; 823 __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync"); 824 } 825 826 if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) { 827 psc->driCopySubBuffer = (__DRIcopySubBufferExtension *) extensions[i]; 828 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer"); 829 } 830 831 if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) { 832 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read"); 833 } 834 /* Ignore unknown extensions */ 835 } 836 } 837 838 static const struct glx_screen_vtable dri_screen_vtable = { 839 dri_create_context, 840 NULL 841 }; 842 843 static struct glx_screen * 844 driCreateScreen(int screen, struct glx_display *priv) 845 { 846 struct dri_display *pdp; 847 __GLXDRIscreen *psp; 848 const __DRIextension **extensions; 849 struct dri_screen *psc; 850 char *driverName; 851 int i; 852 853 psc = Xcalloc(1, sizeof *psc); 854 if (psc == NULL) 855 return NULL; 856 857 memset(psc, 0, sizeof *psc); 858 if (!glx_screen_init(&psc->base, screen, priv)) { 859 Xfree(psc); 860 return NULL; 861 } 862 863 if (!driGetDriverName(priv->dpy, screen, &driverName)) { 864 goto cleanup; 865 } 866 867 psc->driver = driOpenDriver(driverName); 868 if (psc->driver == NULL) 869 goto cleanup; 870 871 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); 872 if (extensions == NULL) { 873 ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 874 goto cleanup; 875 } 876 877 for (i = 0; extensions[i]; i++) { 878 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 879 psc->core = (__DRIcoreExtension *) extensions[i]; 880 if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0) 881 psc->legacy = (__DRIlegacyExtension *) extensions[i]; 882 } 883 884 if (psc->core == NULL || psc->legacy == NULL) 885 goto cleanup; 886 887 pdp = (struct dri_display *) priv->driDisplay; 888 psc->driScreen = 889 CallCreateNewScreen(psc->base.dpy, screen, psc, pdp); 890 if (psc->driScreen == NULL) 891 goto cleanup; 892 893 extensions = psc->core->getExtensions(psc->driScreen); 894 driBindExtensions(psc, extensions); 895 896 psc->base.vtable = &dri_screen_vtable; 897 psp = &psc->vtable; 898 psc->base.driScreen = psp; 899 if (psc->driCopySubBuffer) 900 psp->copySubBuffer = driCopySubBuffer; 901 902 psp->destroyScreen = driDestroyScreen; 903 psp->createDrawable = driCreateDrawable; 904 psp->swapBuffers = driSwapBuffers; 905 906 #ifdef __DRI_SWAP_BUFFER_COUNTER 907 psp->getDrawableMSC = driDrawableGetMSC; 908 psp->waitForMSC = driWaitForMSC; 909 psp->waitForSBC = driWaitForSBC; 910 #endif 911 912 psp->setSwapInterval = driSetSwapInterval; 913 psp->getSwapInterval = driGetSwapInterval; 914 915 free(driverName); 916 917 return &psc->base; 918 919 cleanup: 920 CriticalErrorMessageF("failed to load driver: %s\n", driverName); 921 922 free(driverName); 923 924 if (psc->driver) 925 dlclose(psc->driver); 926 glx_screen_cleanup(&psc->base); 927 Xfree(psc); 928 929 return NULL; 930 } 931 932 /* Called from __glXFreeDisplayPrivate. 933 */ 934 static void 935 driDestroyDisplay(__GLXDRIdisplay * dpy) 936 { 937 Xfree(dpy); 938 } 939 940 /* 941 * Allocate, initialize and return a __DRIdisplayPrivate object. 942 * This is called from __glXInitialize() when we are given a new 943 * display pointer. 944 */ 945 _X_HIDDEN __GLXDRIdisplay * 946 driCreateDisplay(Display * dpy) 947 { 948 struct dri_display *pdpyp; 949 int eventBase, errorBase; 950 int major, minor, patch; 951 952 if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) { 953 return NULL; 954 } 955 956 if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) { 957 return NULL; 958 } 959 960 pdpyp = Xmalloc(sizeof *pdpyp); 961 if (!pdpyp) { 962 return NULL; 963 } 964 965 pdpyp->driMajor = major; 966 pdpyp->driMinor = minor; 967 pdpyp->driPatch = patch; 968 969 pdpyp->base.destroyDisplay = driDestroyDisplay; 970 pdpyp->base.createScreen = driCreateScreen; 971 972 return &pdpyp->base; 973 } 974 975 #endif /* GLX_DIRECT_RENDERING */ 976