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