dri2_glx.c revision 0a18cdb0ed2f4b747688f653d9947d174fae77ff
1/* 2 * Copyright © 2008 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Soft- 6 * ware"), to deal in the Software without restriction, including without 7 * limitation the rights to use, copy, modify, merge, publish, distribute, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, provided that the above copyright 10 * notice(s) and this permission notice appear in all copies of the Soft- 11 * ware and that both the above copyright notice(s) and this permission 12 * notice appear in supporting documentation. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 16 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 17 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 18 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 19 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 22 * MANCE OF THIS SOFTWARE. 23 * 24 * Except as contained in this notice, the name of a copyright holder shall 25 * not be used in advertising or otherwise to promote the sale, use or 26 * other dealings in this Software without prior written authorization of 27 * the copyright holder. 28 * 29 * Authors: 30 * Kristian Høgsberg (krh@redhat.com) 31 */ 32 33#ifdef GLX_DIRECT_RENDERING 34 35#include <X11/Xlib.h> 36#include <X11/extensions/Xfixes.h> 37#include <X11/extensions/Xdamage.h> 38#include "glapi.h" 39#include "glxclient.h" 40#include <X11/extensions/dri2proto.h> 41#include "xf86dri.h" 42#include <dlfcn.h> 43#include <fcntl.h> 44#include <unistd.h> 45#include <sys/types.h> 46#include <sys/mman.h> 47#include "xf86drm.h" 48#include "dri2.h" 49#include "dri_common.h" 50#include "../../mesa/drivers/dri/common/dri_util.h" 51 52#undef DRI2_MINOR 53#define DRI2_MINOR 1 54 55typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate; 56typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate; 57typedef struct __GLXDRIdrawablePrivateRec __GLXDRIdrawablePrivate; 58 59struct __GLXDRIdisplayPrivateRec 60{ 61 __GLXDRIdisplay base; 62 63 /* 64 ** XFree86-DRI version information 65 */ 66 int driMajor; 67 int driMinor; 68 int driPatch; 69 int swapAvailable; 70 int invalidateAvailable; 71}; 72 73struct __GLXDRIcontextPrivateRec 74{ 75 __GLXDRIcontext base; 76 __DRIcontext *driContext; 77 __GLXscreenConfigs *psc; 78}; 79 80struct __GLXDRIdrawablePrivateRec 81{ 82 __GLXDRIdrawable base; 83 __DRIbuffer buffers[5]; 84 int bufferCount; 85 int width, height; 86 int have_back; 87 int have_fake_front; 88 int swap_interval; 89}; 90 91static void dri2WaitX(__GLXDRIdrawable * pdraw); 92 93static void 94dri2DestroyContext(__GLXDRIcontext * context, 95 __GLXscreenConfigs * psc, Display * dpy) 96{ 97 __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; 98 const __DRIcoreExtension *core = pcp->psc->core; 99 100 (*core->destroyContext) (pcp->driContext); 101 102 Xfree(pcp); 103} 104 105static Bool 106dri2BindContext(__GLXDRIcontext * context, 107 __GLXDRIdrawable * draw, __GLXDRIdrawable * read) 108{ 109 __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; 110 const __DRIcoreExtension *core = pcp->psc->core; 111 112 return (*core->bindContext) (pcp->driContext, 113 draw->driDrawable, read->driDrawable); 114} 115 116static void 117dri2UnbindContext(__GLXDRIcontext * context) 118{ 119 __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; 120 const __DRIcoreExtension *core = pcp->psc->core; 121 122 (*core->unbindContext) (pcp->driContext); 123} 124 125static __GLXDRIcontext * 126dri2CreateContext(__GLXscreenConfigs * psc, 127 const __GLcontextModes * mode, 128 GLXContext gc, GLXContext shareList, int renderType) 129{ 130 __GLXDRIcontextPrivate *pcp, *pcp_shared; 131 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode; 132 __DRIcontext *shared = NULL; 133 134 if (shareList) { 135 pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; 136 shared = pcp_shared->driContext; 137 } 138 139 pcp = Xmalloc(sizeof *pcp); 140 if (pcp == NULL) 141 return NULL; 142 143 pcp->psc = psc; 144 pcp->driContext = 145 (*psc->dri2->createNewContext) (psc->__driScreen, 146 config->driConfig, shared, pcp); 147 gc->__driContext = pcp->driContext; 148 149 if (pcp->driContext == NULL) { 150 Xfree(pcp); 151 return NULL; 152 } 153 154 pcp->base.destroyContext = dri2DestroyContext; 155 pcp->base.bindContext = dri2BindContext; 156 pcp->base.unbindContext = dri2UnbindContext; 157 158 return &pcp->base; 159} 160 161static void 162dri2DestroyDrawable(__GLXDRIdrawable * pdraw) 163{ 164 const __DRIcoreExtension *core = pdraw->psc->core; 165 166 (*core->destroyDrawable) (pdraw->driDrawable); 167 DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->xDrawable); 168 Xfree(pdraw); 169} 170 171static __GLXDRIdrawable * 172dri2CreateDrawable(__GLXscreenConfigs * psc, 173 XID xDrawable, 174 GLXDrawable drawable, const __GLcontextModes * modes) 175{ 176 __GLXDRIdrawablePrivate *pdraw; 177 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; 178 __GLXdisplayPrivate *dpyPriv; 179 __GLXDRIdisplayPrivate *pdp; 180 181 pdraw = Xmalloc(sizeof(*pdraw)); 182 if (!pdraw) 183 return NULL; 184 185 pdraw->base.destroyDrawable = dri2DestroyDrawable; 186 pdraw->base.xDrawable = xDrawable; 187 pdraw->base.drawable = drawable; 188 pdraw->base.psc = psc; 189 pdraw->bufferCount = 0; 190 pdraw->swap_interval = 1; 191 192 DRI2CreateDrawable(psc->dpy, xDrawable); 193 194 dpyPriv = __glXInitialize(psc->dpy); 195 pdp = (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display;; 196 /* Create a new drawable */ 197 pdraw->base.driDrawable = 198 (*psc->dri2->createNewDrawable) (psc->__driScreen, 199 config->driConfig, pdraw); 200 201 if (!pdraw->base.driDrawable) { 202 DRI2DestroyDrawable(psc->dpy, xDrawable); 203 Xfree(pdraw); 204 return NULL; 205 } 206 207 /* 208 * Make sure server has the same swap interval we do for the new 209 * drawable. 210 */ 211 if (pdp->swapAvailable) 212 DRI2SwapInterval(psc->dpy, xDrawable, pdraw->swap_interval); 213 214 return &pdraw->base; 215} 216 217#ifdef X_DRI2GetMSC 218 219static int 220dri2DrawableGetMSC(__GLXscreenConfigs *psc, __GLXDRIdrawable *pdraw, 221 int64_t *ust, int64_t *msc, int64_t *sbc) 222{ 223 return DRI2GetMSC(psc->dpy, pdraw->xDrawable, ust, msc, sbc); 224} 225 226#endif 227 228 229#ifdef X_DRI2WaitMSC 230 231static int 232dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 233 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) 234{ 235 return DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 236 remainder, ust, msc, sbc); 237} 238 239static int 240dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, 241 int64_t *msc, int64_t *sbc) 242{ 243 return DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable, target_sbc, ust, msc, 244 sbc); 245} 246 247#endif /* X_DRI2WaitMSC */ 248 249static void 250dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height) 251{ 252 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 253 XRectangle xrect; 254 XserverRegion region; 255 256 /* Check we have the right attachments */ 257 if (!priv->have_back) 258 return; 259 260 xrect.x = x; 261 xrect.y = priv->height - y - height; 262 xrect.width = width; 263 xrect.height = height; 264 265#ifdef __DRI2_FLUSH 266 if (pdraw->psc->f) 267 (*pdraw->psc->f->flush) (pdraw->driDrawable); 268#endif 269 270 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); 271 /* should get a fence ID back from here at some point */ 272 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region, 273 DRI2BufferFrontLeft, DRI2BufferBackLeft); 274 XFixesDestroyRegion(pdraw->psc->dpy, region); 275 276 /* Refresh the fake front (if present) after we just damaged the real 277 * front. 278 */ 279 dri2WaitX(pdraw); 280} 281 282static void 283dri2WaitX(__GLXDRIdrawable *pdraw) 284{ 285 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 286 XRectangle xrect; 287 XserverRegion region; 288 289 /* Check we have the right attachments */ 290 if (!priv->have_fake_front) 291 return; 292 293 xrect.x = 0; 294 xrect.y = 0; 295 xrect.width = priv->width; 296 xrect.height = priv->height; 297 298#ifdef __DRI2_FLUSH 299 if (pdraw->psc->f) 300 (*pdraw->psc->f->flush) (pdraw->driDrawable); 301#endif 302 303 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); 304 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region, 305 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 306 XFixesDestroyRegion(pdraw->psc->dpy, region); 307} 308 309static void 310dri2WaitGL(__GLXDRIdrawable * pdraw) 311{ 312 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 313 XRectangle xrect; 314 XserverRegion region; 315 316 if (!priv->have_fake_front) 317 return; 318 319 xrect.x = 0; 320 xrect.y = 0; 321 xrect.width = priv->width; 322 xrect.height = priv->height; 323 324#ifdef __DRI2_FLUSH 325 if (pdraw->psc->f) 326 (*pdraw->psc->f->flush) (pdraw->driDrawable); 327#endif 328 329 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); 330 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region, 331 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 332 XFixesDestroyRegion(pdraw->psc->dpy, region); 333} 334 335static void 336dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) 337{ 338 __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 339 __GLXdisplayPrivate *priv = __glXInitialize(pdraw->base.psc->dpy); 340 __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)priv->dri2Display; 341 342 /* Old servers don't send invalidate events */ 343 if (!pdp->invalidateAvailable) 344 dri2InvalidateBuffers(priv->dpy, pdraw->base.drawable); 345 346 dri2WaitGL(loaderPrivate); 347} 348 349 350static void 351dri2DestroyScreen(__GLXscreenConfigs * psc) 352{ 353 /* Free the direct rendering per screen data */ 354 (*psc->core->destroyScreen) (psc->__driScreen); 355 close(psc->fd); 356 psc->__driScreen = NULL; 357} 358 359/** 360 * Process list of buffer received from the server 361 * 362 * Processes the list of buffers received in a reply from the server to either 363 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. 364 */ 365static void 366process_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers, 367 unsigned count) 368{ 369 int i; 370 371 pdraw->bufferCount = count; 372 pdraw->have_fake_front = 0; 373 pdraw->have_back = 0; 374 375 /* This assumes the DRI2 buffer attachment tokens matches the 376 * __DRIbuffer tokens. */ 377 for (i = 0; i < count; i++) { 378 pdraw->buffers[i].attachment = buffers[i].attachment; 379 pdraw->buffers[i].name = buffers[i].name; 380 pdraw->buffers[i].pitch = buffers[i].pitch; 381 pdraw->buffers[i].cpp = buffers[i].cpp; 382 pdraw->buffers[i].flags = buffers[i].flags; 383 if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) 384 pdraw->have_fake_front = 1; 385 if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) 386 pdraw->have_back = 1; 387 } 388 389} 390 391static int64_t 392dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 393 int64_t remainder) 394{ 395 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 396 __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy); 397 __GLXDRIdisplayPrivate *pdp = 398 (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display; 399 int64_t ret; 400 401#ifdef __DRI2_FLUSH 402 if (pdraw->psc->f) 403 (*pdraw->psc->f->flush)(pdraw->driDrawable); 404#endif 405 406 /* Old servers don't send invalidate events */ 407 if (!pdp->invalidateAvailable) 408 dri2InvalidateBuffers(dpyPriv->dpy, pdraw->drawable); 409 410 /* Old servers can't handle swapbuffers */ 411 if (!pdp->swapAvailable) { 412 dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); 413 return 0; 414 } 415 416#ifdef X_DRI2SwapBuffers 417 DRI2SwapBuffers(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 418 remainder, &ret); 419#endif 420 421 return ret; 422} 423 424static __DRIbuffer * 425dri2GetBuffers(__DRIdrawable * driDrawable, 426 int *width, int *height, 427 unsigned int *attachments, int count, 428 int *out_count, void *loaderPrivate) 429{ 430 __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 431 DRI2Buffer *buffers; 432 433 buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable, 434 width, height, attachments, count, out_count); 435 if (buffers == NULL) 436 return NULL; 437 438 pdraw->width = *width; 439 pdraw->height = *height; 440 process_buffers(pdraw, buffers, *out_count); 441 442 Xfree(buffers); 443 444 return pdraw->buffers; 445} 446 447static __DRIbuffer * 448dri2GetBuffersWithFormat(__DRIdrawable * driDrawable, 449 int *width, int *height, 450 unsigned int *attachments, int count, 451 int *out_count, void *loaderPrivate) 452{ 453 __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 454 DRI2Buffer *buffers; 455 456 buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy, 457 pdraw->base.xDrawable, 458 width, height, attachments, 459 count, out_count); 460 if (buffers == NULL) 461 return NULL; 462 463 pdraw->width = *width; 464 pdraw->height = *height; 465 process_buffers(pdraw, buffers, *out_count); 466 467 Xfree(buffers); 468 469 return pdraw->buffers; 470} 471 472#ifdef X_DRI2SwapInterval 473 474static void 475dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval) 476{ 477 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 478 479 DRI2SwapInterval(priv->base.psc->dpy, pdraw->xDrawable, interval); 480 priv->swap_interval = interval; 481} 482 483static unsigned int 484dri2GetSwapInterval(__GLXDRIdrawable *pdraw) 485{ 486 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 487 488 return priv->swap_interval; 489} 490 491#endif /* X_DRI2SwapInterval */ 492 493static const __DRIdri2LoaderExtension dri2LoaderExtension = { 494 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 495 dri2GetBuffers, 496 dri2FlushFrontBuffer, 497 dri2GetBuffersWithFormat, 498}; 499 500static const __DRIdri2LoaderExtension dri2LoaderExtension_old = { 501 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 502 dri2GetBuffers, 503 dri2FlushFrontBuffer, 504 NULL, 505}; 506 507static const __DRIextension *loader_extensions[] = { 508 &dri2LoaderExtension.base, 509 &systemTimeExtension.base, 510 NULL 511}; 512 513static const __DRIextension *loader_extensions_old[] = { 514 &dri2LoaderExtension_old.base, 515 &systemTimeExtension.base, 516 NULL 517}; 518 519_X_HIDDEN void 520dri2InvalidateBuffers(Display *dpy, XID drawable) 521{ 522 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); 523 524#if __DRI2_FLUSH_VERSION >= 3 525 if (pdraw && pdraw->psc->f) 526 pdraw->psc->f->invalidate(pdraw->driDrawable); 527#endif 528} 529 530static __GLXDRIscreen * 531dri2CreateScreen(__GLXscreenConfigs * psc, int screen, 532 __GLXdisplayPrivate * priv) 533{ 534 const __DRIconfig **driver_configs; 535 const __DRIextension **extensions; 536 const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *) 537 priv->dri2Display; 538 __GLXDRIscreen *psp; 539 char *driverName, *deviceName; 540 drm_magic_t magic; 541 int i; 542 543 psp = Xmalloc(sizeof *psp); 544 if (psp == NULL) 545 return NULL; 546 547 if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen), 548 &driverName, &deviceName)) { 549 XFree(psp); 550 return NULL; 551 } 552 553 psc->driver = driOpenDriver(driverName); 554 if (psc->driver == NULL) { 555 ErrorMessageF("driver pointer missing\n"); 556 goto handle_error; 557 } 558 559 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); 560 if (extensions == NULL) { 561 ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 562 goto handle_error; 563 } 564 565 for (i = 0; extensions[i]; i++) { 566 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 567 psc->core = (__DRIcoreExtension *) extensions[i]; 568 if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) 569 psc->dri2 = (__DRIdri2Extension *) extensions[i]; 570 } 571 572 if (psc->core == NULL || psc->dri2 == NULL) { 573 ErrorMessageF("core dri or dri2 extension not found\n"); 574 goto handle_error; 575 } 576 577 psc->fd = open(deviceName, O_RDWR); 578 if (psc->fd < 0) { 579 ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); 580 goto handle_error; 581 } 582 583 if (drmGetMagic(psc->fd, &magic)) { 584 ErrorMessageF("failed to get magic\n"); 585 goto handle_error; 586 } 587 588 if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) { 589 ErrorMessageF("failed to authenticate magic %d\n", magic); 590 goto handle_error; 591 } 592 593 /* If the server does not support the protocol for 594 * DRI2GetBuffersWithFormat, don't supply that interface to the driver. 595 */ 596 psc->__driScreen = 597 psc->dri2->createNewScreen(screen, psc->fd, ((pdp->driMinor < 1) 598 ? loader_extensions_old 599 : loader_extensions), 600 &driver_configs, psc); 601 602 if (psc->__driScreen == NULL) { 603 ErrorMessageF("failed to create dri screen\n"); 604 goto handle_error; 605 } 606 607 driBindCommonExtensions(psc); 608 dri2BindExtensions(psc); 609 610 psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); 611 psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); 612 613 psc->driver_configs = driver_configs; 614 615 psp->destroyScreen = dri2DestroyScreen; 616 psp->createContext = dri2CreateContext; 617 psp->createDrawable = dri2CreateDrawable; 618 psp->swapBuffers = dri2SwapBuffers; 619 psp->waitGL = dri2WaitGL; 620 psp->waitX = dri2WaitX; 621 psp->getDrawableMSC = NULL; 622 psp->waitForMSC = NULL; 623 psp->waitForSBC = NULL; 624 psp->setSwapInterval = NULL; 625 psp->getSwapInterval = NULL; 626 627 if (pdp->driMinor >= 2) { 628#ifdef X_DRI2GetMSC 629 psp->getDrawableMSC = dri2DrawableGetMSC; 630#endif 631#ifdef X_DRI2WaitMSC 632 psp->waitForMSC = dri2WaitForMSC; 633 psp->waitForSBC = dri2WaitForSBC; 634#endif 635#ifdef X_DRI2SwapInterval 636 psp->setSwapInterval = dri2SetSwapInterval; 637 psp->getSwapInterval = dri2GetSwapInterval; 638#endif 639#if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval) 640 __glXEnableDirectExtension(psc, "GLX_OML_sync_control"); 641#endif 642 } 643 644 /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always 645 * available.*/ 646 psp->copySubBuffer = dri2CopySubBuffer; 647 __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); 648 649 Xfree(driverName); 650 Xfree(deviceName); 651 652 return psp; 653 654handle_error: 655 Xfree(driverName); 656 Xfree(deviceName); 657 XFree(psp); 658 659 /* FIXME: clean up here */ 660 661 return NULL; 662} 663 664/* Called from __glXFreeDisplayPrivate. 665 */ 666static void 667dri2DestroyDisplay(__GLXDRIdisplay * dpy) 668{ 669 Xfree(dpy); 670} 671 672/* 673 * Allocate, initialize and return a __DRIdisplayPrivate object. 674 * This is called from __glXInitialize() when we are given a new 675 * display pointer. 676 */ 677_X_HIDDEN __GLXDRIdisplay * 678dri2CreateDisplay(Display * dpy) 679{ 680 __GLXDRIdisplayPrivate *pdp; 681 int eventBase, errorBase; 682 683 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) 684 return NULL; 685 686 pdp = Xmalloc(sizeof *pdp); 687 if (pdp == NULL) 688 return NULL; 689 690 if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) { 691 Xfree(pdp); 692 return NULL; 693 } 694 695 pdp->driPatch = 0; 696 pdp->swapAvailable = (pdp->driMinor >= 2); 697 pdp->invalidateAvailable = (pdp->driMinor >= 3); 698 699 pdp->base.destroyDisplay = dri2DestroyDisplay; 700 pdp->base.createScreen = dri2CreateScreen; 701 702 return &pdp->base; 703} 704 705#endif /* GLX_DIRECT_RENDERING */ 706