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