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