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