dri2_glx.c revision 80b280db883edc9550484dba03bd5c124b6a9bf9
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#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 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#ifdef X_DRI2SwapInterval 208 /* 209 * Make sure server has the same swap interval we do for the new 210 * drawable. 211 */ 212 if (pdp->swapAvailable) 213 DRI2SwapInterval(psc->dpy, xDrawable, pdraw->swap_interval); 214#endif 215 216 return &pdraw->base; 217} 218 219#ifdef X_DRI2GetMSC 220 221static int 222dri2DrawableGetMSC(__GLXscreenConfigs *psc, __GLXDRIdrawable *pdraw, 223 int64_t *ust, int64_t *msc, int64_t *sbc) 224{ 225 return DRI2GetMSC(psc->dpy, pdraw->xDrawable, ust, msc, sbc); 226} 227 228#endif 229 230 231#ifdef X_DRI2WaitMSC 232 233static int 234dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 235 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) 236{ 237 return DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 238 remainder, ust, msc, sbc); 239} 240 241static int 242dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, 243 int64_t *msc, int64_t *sbc) 244{ 245 return DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable, target_sbc, ust, msc, 246 sbc); 247} 248 249#endif /* X_DRI2WaitMSC */ 250 251static void 252dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height) 253{ 254 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 255 XRectangle xrect; 256 XserverRegion region; 257 258 /* Check we have the right attachments */ 259 if (!priv->have_back) 260 return; 261 262 xrect.x = x; 263 xrect.y = priv->height - y - height; 264 xrect.width = width; 265 xrect.height = height; 266 267#ifdef __DRI2_FLUSH 268 if (pdraw->psc->f) 269 (*pdraw->psc->f->flush) (pdraw->driDrawable); 270#endif 271 272 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); 273 /* should get a fence ID back from here at some point */ 274 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region, 275 DRI2BufferFrontLeft, DRI2BufferBackLeft); 276 XFixesDestroyRegion(pdraw->psc->dpy, region); 277 278 /* Refresh the fake front (if present) after we just damaged the real 279 * front. 280 */ 281 dri2WaitX(pdraw); 282} 283 284static void 285dri2WaitX(__GLXDRIdrawable *pdraw) 286{ 287 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 288 XRectangle xrect; 289 XserverRegion region; 290 291 /* Check we have the right attachments */ 292 if (!priv->have_fake_front) 293 return; 294 295 xrect.x = 0; 296 xrect.y = 0; 297 xrect.width = priv->width; 298 xrect.height = priv->height; 299 300#ifdef __DRI2_FLUSH 301 if (pdraw->psc->f) 302 (*pdraw->psc->f->flush) (pdraw->driDrawable); 303#endif 304 305 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); 306 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region, 307 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 308 XFixesDestroyRegion(pdraw->psc->dpy, region); 309} 310 311static void 312dri2WaitGL(__GLXDRIdrawable * pdraw) 313{ 314 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 315 XRectangle xrect; 316 XserverRegion region; 317 318 if (!priv->have_fake_front) 319 return; 320 321 xrect.x = 0; 322 xrect.y = 0; 323 xrect.width = priv->width; 324 xrect.height = priv->height; 325 326#ifdef __DRI2_FLUSH 327 if (pdraw->psc->f) 328 (*pdraw->psc->f->flush) (pdraw->driDrawable); 329#endif 330 331 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); 332 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region, 333 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 334 XFixesDestroyRegion(pdraw->psc->dpy, region); 335} 336 337static void 338dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) 339{ 340 __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 341 __GLXdisplayPrivate *priv = __glXInitialize(pdraw->base.psc->dpy); 342 __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)priv->dri2Display; 343 344 /* Old servers don't send invalidate events */ 345 if (!pdp->invalidateAvailable) 346 dri2InvalidateBuffers(priv->dpy, pdraw->base.drawable); 347 348 dri2WaitGL(loaderPrivate); 349} 350 351 352static void 353dri2DestroyScreen(__GLXscreenConfigs * psc) 354{ 355 /* Free the direct rendering per screen data */ 356 (*psc->core->destroyScreen) (psc->__driScreen); 357 close(psc->fd); 358 psc->__driScreen = NULL; 359} 360 361/** 362 * Process list of buffer received from the server 363 * 364 * Processes the list of buffers received in a reply from the server to either 365 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. 366 */ 367static void 368process_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers, 369 unsigned count) 370{ 371 int i; 372 373 pdraw->bufferCount = count; 374 pdraw->have_fake_front = 0; 375 pdraw->have_back = 0; 376 377 /* This assumes the DRI2 buffer attachment tokens matches the 378 * __DRIbuffer tokens. */ 379 for (i = 0; i < count; i++) { 380 pdraw->buffers[i].attachment = buffers[i].attachment; 381 pdraw->buffers[i].name = buffers[i].name; 382 pdraw->buffers[i].pitch = buffers[i].pitch; 383 pdraw->buffers[i].cpp = buffers[i].cpp; 384 pdraw->buffers[i].flags = buffers[i].flags; 385 if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) 386 pdraw->have_fake_front = 1; 387 if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) 388 pdraw->have_back = 1; 389 } 390 391} 392 393static int64_t 394dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 395 int64_t remainder) 396{ 397 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 398 __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy); 399 __GLXDRIdisplayPrivate *pdp = 400 (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display; 401 int64_t ret; 402 403#ifdef __DRI2_FLUSH 404 if (pdraw->psc->f) 405 (*pdraw->psc->f->flush)(pdraw->driDrawable); 406#endif 407 408 /* Old servers don't send invalidate events */ 409 if (!pdp->invalidateAvailable) 410 dri2InvalidateBuffers(dpyPriv->dpy, pdraw->drawable); 411 412 /* Old servers can't handle swapbuffers */ 413 if (!pdp->swapAvailable) { 414 dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); 415 return 0; 416 } 417 418#ifdef X_DRI2SwapBuffers 419 DRI2SwapBuffers(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 420 remainder, &ret); 421#endif 422 423 return ret; 424} 425 426static __DRIbuffer * 427dri2GetBuffers(__DRIdrawable * driDrawable, 428 int *width, int *height, 429 unsigned int *attachments, int count, 430 int *out_count, void *loaderPrivate) 431{ 432 __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 433 DRI2Buffer *buffers; 434 435 buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable, 436 width, height, attachments, count, out_count); 437 if (buffers == NULL) 438 return NULL; 439 440 pdraw->width = *width; 441 pdraw->height = *height; 442 process_buffers(pdraw, buffers, *out_count); 443 444 Xfree(buffers); 445 446 return pdraw->buffers; 447} 448 449static __DRIbuffer * 450dri2GetBuffersWithFormat(__DRIdrawable * driDrawable, 451 int *width, int *height, 452 unsigned int *attachments, int count, 453 int *out_count, void *loaderPrivate) 454{ 455 __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 456 DRI2Buffer *buffers; 457 458 buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy, 459 pdraw->base.xDrawable, 460 width, height, attachments, 461 count, out_count); 462 if (buffers == NULL) 463 return NULL; 464 465 pdraw->width = *width; 466 pdraw->height = *height; 467 process_buffers(pdraw, buffers, *out_count); 468 469 Xfree(buffers); 470 471 return pdraw->buffers; 472} 473 474#ifdef X_DRI2SwapInterval 475 476static void 477dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval) 478{ 479 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 480 481 DRI2SwapInterval(priv->base.psc->dpy, pdraw->xDrawable, interval); 482 priv->swap_interval = interval; 483} 484 485static unsigned int 486dri2GetSwapInterval(__GLXDRIdrawable *pdraw) 487{ 488 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 489 490 return priv->swap_interval; 491} 492 493#endif /* X_DRI2SwapInterval */ 494 495static const __DRIdri2LoaderExtension dri2LoaderExtension = { 496 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 497 dri2GetBuffers, 498 dri2FlushFrontBuffer, 499 dri2GetBuffersWithFormat, 500}; 501 502static const __DRIdri2LoaderExtension dri2LoaderExtension_old = { 503 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 504 dri2GetBuffers, 505 dri2FlushFrontBuffer, 506 NULL, 507}; 508 509static const __DRIextension *loader_extensions[] = { 510 &dri2LoaderExtension.base, 511 &systemTimeExtension.base, 512 NULL 513}; 514 515static const __DRIextension *loader_extensions_old[] = { 516 &dri2LoaderExtension_old.base, 517 &systemTimeExtension.base, 518 NULL 519}; 520 521_X_HIDDEN void 522dri2InvalidateBuffers(Display *dpy, XID drawable) 523{ 524 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); 525 526#if __DRI2_FLUSH_VERSION >= 3 527 if (pdraw && pdraw->psc->f) 528 pdraw->psc->f->invalidate(pdraw->driDrawable); 529#endif 530} 531 532static __GLXDRIscreen * 533dri2CreateScreen(__GLXscreenConfigs * psc, int screen, 534 __GLXdisplayPrivate * priv) 535{ 536 const __DRIconfig **driver_configs; 537 const __DRIextension **extensions; 538 const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *) 539 priv->dri2Display; 540 __GLXDRIscreen *psp; 541 char *driverName, *deviceName; 542 drm_magic_t magic; 543 int i; 544 545 psp = Xmalloc(sizeof *psp); 546 if (psp == NULL) 547 return NULL; 548 549 if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen), 550 &driverName, &deviceName)) { 551 XFree(psp); 552 return NULL; 553 } 554 555 psc->driver = driOpenDriver(driverName); 556 if (psc->driver == NULL) { 557 ErrorMessageF("driver pointer missing\n"); 558 goto handle_error; 559 } 560 561 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); 562 if (extensions == NULL) { 563 ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 564 goto handle_error; 565 } 566 567 for (i = 0; extensions[i]; i++) { 568 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 569 psc->core = (__DRIcoreExtension *) extensions[i]; 570 if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) 571 psc->dri2 = (__DRIdri2Extension *) extensions[i]; 572 } 573 574 if (psc->core == NULL || psc->dri2 == NULL) { 575 ErrorMessageF("core dri or dri2 extension not found\n"); 576 goto handle_error; 577 } 578 579 psc->fd = open(deviceName, O_RDWR); 580 if (psc->fd < 0) { 581 ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); 582 goto handle_error; 583 } 584 585 if (drmGetMagic(psc->fd, &magic)) { 586 ErrorMessageF("failed to get magic\n"); 587 goto handle_error; 588 } 589 590 if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) { 591 ErrorMessageF("failed to authenticate magic %d\n", magic); 592 goto handle_error; 593 } 594 595 /* If the server does not support the protocol for 596 * DRI2GetBuffersWithFormat, don't supply that interface to the driver. 597 */ 598 psc->__driScreen = 599 psc->dri2->createNewScreen(screen, psc->fd, ((pdp->driMinor < 1) 600 ? loader_extensions_old 601 : loader_extensions), 602 &driver_configs, psc); 603 604 if (psc->__driScreen == NULL) { 605 ErrorMessageF("failed to create dri screen\n"); 606 goto handle_error; 607 } 608 609 driBindCommonExtensions(psc); 610 dri2BindExtensions(psc); 611 612 psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); 613 psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); 614 615 psc->driver_configs = driver_configs; 616 617 psp->destroyScreen = dri2DestroyScreen; 618 psp->createContext = dri2CreateContext; 619 psp->createDrawable = dri2CreateDrawable; 620 psp->swapBuffers = dri2SwapBuffers; 621 psp->waitGL = dri2WaitGL; 622 psp->waitX = dri2WaitX; 623 psp->getDrawableMSC = NULL; 624 psp->waitForMSC = NULL; 625 psp->waitForSBC = NULL; 626 psp->setSwapInterval = NULL; 627 psp->getSwapInterval = NULL; 628 629 if (pdp->driMinor >= 2) { 630#ifdef X_DRI2GetMSC 631 psp->getDrawableMSC = dri2DrawableGetMSC; 632#endif 633#ifdef X_DRI2WaitMSC 634 psp->waitForMSC = dri2WaitForMSC; 635 psp->waitForSBC = dri2WaitForSBC; 636#endif 637#ifdef X_DRI2SwapInterval 638 psp->setSwapInterval = dri2SetSwapInterval; 639 psp->getSwapInterval = dri2GetSwapInterval; 640#endif 641#if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval) 642 __glXEnableDirectExtension(psc, "GLX_OML_sync_control"); 643#endif 644 } 645 646 /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always 647 * available.*/ 648 psp->copySubBuffer = dri2CopySubBuffer; 649 __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); 650 651 Xfree(driverName); 652 Xfree(deviceName); 653 654 return psp; 655 656handle_error: 657 Xfree(driverName); 658 Xfree(deviceName); 659 XFree(psp); 660 661 /* FIXME: clean up here */ 662 663 return NULL; 664} 665 666/* Called from __glXFreeDisplayPrivate. 667 */ 668static void 669dri2DestroyDisplay(__GLXDRIdisplay * dpy) 670{ 671 Xfree(dpy); 672} 673 674/* 675 * Allocate, initialize and return a __DRIdisplayPrivate object. 676 * This is called from __glXInitialize() when we are given a new 677 * display pointer. 678 */ 679_X_HIDDEN __GLXDRIdisplay * 680dri2CreateDisplay(Display * dpy) 681{ 682 __GLXDRIdisplayPrivate *pdp; 683 int eventBase, errorBase; 684 685 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) 686 return NULL; 687 688 pdp = Xmalloc(sizeof *pdp); 689 if (pdp == NULL) 690 return NULL; 691 692 if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) { 693 Xfree(pdp); 694 return NULL; 695 } 696 697 pdp->driPatch = 0; 698 pdp->swapAvailable = (pdp->driMinor >= 2); 699 pdp->invalidateAvailable = (pdp->driMinor >= 3); 700 701 pdp->base.destroyDisplay = dri2DestroyDisplay; 702 pdp->base.createScreen = dri2CreateScreen; 703 704 return &pdp->base; 705} 706 707#endif /* GLX_DIRECT_RENDERING */ 708