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