dri2_glx.c revision c8f407bcec7619eb2030ea9fe52501ad33075699
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 51/* From xmlpool/options.h, user exposed so should be stable */ 52#define DRI_CONF_VBLANK_NEVER 0 53#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1 54#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2 55#define DRI_CONF_VBLANK_ALWAYS_SYNC 3 56 57#undef DRI2_MINOR 58#define DRI2_MINOR 1 59 60typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate; 61typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate; 62typedef struct __GLXDRIdrawablePrivateRec __GLXDRIdrawablePrivate; 63 64struct __GLXDRIdisplayPrivateRec 65{ 66 __GLXDRIdisplay base; 67 68 /* 69 ** XFree86-DRI version information 70 */ 71 int driMajor; 72 int driMinor; 73 int driPatch; 74 int swapAvailable; 75 int invalidateAvailable; 76 77 const __DRIextension *loader_extensions[4]; 78}; 79 80struct __GLXDRIcontextPrivateRec 81{ 82 __GLXDRIcontext base; 83 __DRIcontext *driContext; 84 __GLXscreenConfigs *psc; 85}; 86 87struct __GLXDRIdrawablePrivateRec 88{ 89 __GLXDRIdrawable base; 90 __DRIbuffer buffers[5]; 91 int bufferCount; 92 int width, height; 93 int have_back; 94 int have_fake_front; 95 int swap_interval; 96}; 97 98static void dri2WaitX(__GLXDRIdrawable * pdraw); 99 100static void 101dri2DestroyContext(__GLXDRIcontext * context, 102 __GLXscreenConfigs * psc, Display * dpy) 103{ 104 __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; 105 const __DRIcoreExtension *core = pcp->psc->core; 106 107 (*core->destroyContext) (pcp->driContext); 108 109 Xfree(pcp); 110} 111 112static Bool 113dri2BindContext(__GLXDRIcontext * context, 114 __GLXDRIdrawable * draw, __GLXDRIdrawable * read) 115{ 116 __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; 117 const __DRIcoreExtension *core = pcp->psc->core; 118 119 return (*core->bindContext) (pcp->driContext, 120 draw->driDrawable, read->driDrawable); 121} 122 123static void 124dri2UnbindContext(__GLXDRIcontext * context) 125{ 126 __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; 127 const __DRIcoreExtension *core = pcp->psc->core; 128 129 (*core->unbindContext) (pcp->driContext); 130} 131 132static __GLXDRIcontext * 133dri2CreateContext(__GLXscreenConfigs * psc, 134 const __GLcontextModes * mode, 135 GLXContext gc, GLXContext shareList, int renderType) 136{ 137 __GLXDRIcontextPrivate *pcp, *pcp_shared; 138 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode; 139 __DRIcontext *shared = NULL; 140 141 if (shareList) { 142 pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; 143 shared = pcp_shared->driContext; 144 } 145 146 pcp = Xmalloc(sizeof *pcp); 147 if (pcp == NULL) 148 return NULL; 149 150 pcp->psc = psc; 151 pcp->driContext = 152 (*psc->dri2->createNewContext) (psc->__driScreen, 153 config->driConfig, shared, pcp); 154 gc->__driContext = pcp->driContext; 155 156 if (pcp->driContext == NULL) { 157 Xfree(pcp); 158 return NULL; 159 } 160 161 pcp->base.destroyContext = dri2DestroyContext; 162 pcp->base.bindContext = dri2BindContext; 163 pcp->base.unbindContext = dri2UnbindContext; 164 165 return &pcp->base; 166} 167 168static void 169dri2DestroyDrawable(__GLXDRIdrawable * pdraw) 170{ 171 const __DRIcoreExtension *core = pdraw->psc->core; 172 173 (*core->destroyDrawable) (pdraw->driDrawable); 174 DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->xDrawable); 175 Xfree(pdraw); 176} 177 178static __GLXDRIdrawable * 179dri2CreateDrawable(__GLXscreenConfigs * psc, 180 XID xDrawable, 181 GLXDrawable drawable, const __GLcontextModes * modes) 182{ 183 __GLXDRIdrawablePrivate *pdraw; 184 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; 185 __GLXdisplayPrivate *dpyPriv; 186 __GLXDRIdisplayPrivate *pdp; 187 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 188 189 pdraw = Xmalloc(sizeof(*pdraw)); 190 if (!pdraw) 191 return NULL; 192 193 pdraw->base.destroyDrawable = dri2DestroyDrawable; 194 pdraw->base.xDrawable = xDrawable; 195 pdraw->base.drawable = drawable; 196 pdraw->base.psc = psc; 197 pdraw->bufferCount = 0; 198 pdraw->swap_interval = 1; /* default may be overridden below */ 199 pdraw->have_back = 0; 200 201 if (psc->config) 202 psc->config->configQueryi(psc->__driScreen, "vblank_mode", &vblank_mode); 203 204 switch (vblank_mode) { 205 case DRI_CONF_VBLANK_NEVER: 206 case DRI_CONF_VBLANK_DEF_INTERVAL_0: 207 pdraw->swap_interval = 0; 208 break; 209 case DRI_CONF_VBLANK_DEF_INTERVAL_1: 210 case DRI_CONF_VBLANK_ALWAYS_SYNC: 211 default: 212 pdraw->swap_interval = 1; 213 break; 214 } 215 216 DRI2CreateDrawable(psc->dpy, xDrawable); 217 218 dpyPriv = __glXInitialize(psc->dpy); 219 pdp = (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display;; 220 /* Create a new drawable */ 221 pdraw->base.driDrawable = 222 (*psc->dri2->createNewDrawable) (psc->__driScreen, 223 config->driConfig, pdraw); 224 225 if (!pdraw->base.driDrawable) { 226 DRI2DestroyDrawable(psc->dpy, xDrawable); 227 Xfree(pdraw); 228 return NULL; 229 } 230 231#ifdef X_DRI2SwapInterval 232 /* 233 * Make sure server has the same swap interval we do for the new 234 * drawable. 235 */ 236 if (pdp->swapAvailable) 237 DRI2SwapInterval(psc->dpy, xDrawable, pdraw->swap_interval); 238#endif 239 240 return &pdraw->base; 241} 242 243#ifdef X_DRI2GetMSC 244 245static int 246dri2DrawableGetMSC(__GLXscreenConfigs *psc, __GLXDRIdrawable *pdraw, 247 int64_t *ust, int64_t *msc, int64_t *sbc) 248{ 249 return DRI2GetMSC(psc->dpy, pdraw->xDrawable, ust, msc, sbc); 250} 251 252#endif 253 254 255#ifdef X_DRI2WaitMSC 256 257static int 258dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 259 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) 260{ 261 return DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 262 remainder, ust, msc, sbc); 263} 264 265static int 266dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, 267 int64_t *msc, int64_t *sbc) 268{ 269 return DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable, target_sbc, ust, msc, 270 sbc); 271} 272 273#endif /* X_DRI2WaitMSC */ 274 275static void 276dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height) 277{ 278 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 279 XRectangle xrect; 280 XserverRegion region; 281 282 /* Check we have the right attachments */ 283 if (!priv->have_back) 284 return; 285 286 xrect.x = x; 287 xrect.y = priv->height - y - height; 288 xrect.width = width; 289 xrect.height = height; 290 291#ifdef __DRI2_FLUSH 292 if (pdraw->psc->f) 293 (*pdraw->psc->f->flush) (pdraw->driDrawable); 294#endif 295 296 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); 297 /* should get a fence ID back from here at some point */ 298 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region, 299 DRI2BufferFrontLeft, DRI2BufferBackLeft); 300 XFixesDestroyRegion(pdraw->psc->dpy, region); 301 302 /* Refresh the fake front (if present) after we just damaged the real 303 * front. 304 */ 305 dri2WaitX(pdraw); 306} 307 308static void 309dri2WaitX(__GLXDRIdrawable *pdraw) 310{ 311 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 312 XRectangle xrect; 313 XserverRegion region; 314 315 /* Check we have the right attachments */ 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 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 332 XFixesDestroyRegion(pdraw->psc->dpy, region); 333} 334 335static void 336dri2WaitGL(__GLXDRIdrawable * pdraw) 337{ 338 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 339 XRectangle xrect; 340 XserverRegion region; 341 342 if (!priv->have_fake_front) 343 return; 344 345 xrect.x = 0; 346 xrect.y = 0; 347 xrect.width = priv->width; 348 xrect.height = priv->height; 349 350#ifdef __DRI2_FLUSH 351 if (pdraw->psc->f) 352 (*pdraw->psc->f->flush) (pdraw->driDrawable); 353#endif 354 355 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); 356 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region, 357 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 358 XFixesDestroyRegion(pdraw->psc->dpy, region); 359} 360 361static void 362dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) 363{ 364 dri2WaitGL(loaderPrivate); 365} 366 367 368static void 369dri2DestroyScreen(__GLXscreenConfigs * psc) 370{ 371 /* Free the direct rendering per screen data */ 372 (*psc->core->destroyScreen) (psc->__driScreen); 373 close(psc->fd); 374 psc->__driScreen = NULL; 375} 376 377/** 378 * Process list of buffer received from the server 379 * 380 * Processes the list of buffers received in a reply from the server to either 381 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. 382 */ 383static void 384process_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers, 385 unsigned count) 386{ 387 int i; 388 389 pdraw->bufferCount = count; 390 pdraw->have_fake_front = 0; 391 pdraw->have_back = 0; 392 393 /* This assumes the DRI2 buffer attachment tokens matches the 394 * __DRIbuffer tokens. */ 395 for (i = 0; i < count; i++) { 396 pdraw->buffers[i].attachment = buffers[i].attachment; 397 pdraw->buffers[i].name = buffers[i].name; 398 pdraw->buffers[i].pitch = buffers[i].pitch; 399 pdraw->buffers[i].cpp = buffers[i].cpp; 400 pdraw->buffers[i].flags = buffers[i].flags; 401 if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) 402 pdraw->have_fake_front = 1; 403 if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) 404 pdraw->have_back = 1; 405 } 406 407} 408 409static int64_t 410dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 411 int64_t remainder) 412{ 413 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 414 __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy); 415 __GLXDRIdisplayPrivate *pdp = 416 (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display; 417 int64_t ret; 418 419#ifdef __DRI2_FLUSH 420 if (pdraw->psc->f) 421 (*pdraw->psc->f->flush)(pdraw->driDrawable); 422#endif 423 424 /* Old servers can't handle swapbuffers */ 425 if (!pdp->swapAvailable) { 426 dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); 427 return 0; 428 } 429 430 /* Old servers don't send invalidate events */ 431 if (!pdp->invalidateAvailable) 432 dri2InvalidateBuffers(dpyPriv->dpy, pdraw->drawable); 433 434#ifdef X_DRI2SwapBuffers 435 DRI2SwapBuffers(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 436 remainder, &ret); 437#endif 438 439 return ret; 440} 441 442static __DRIbuffer * 443dri2GetBuffers(__DRIdrawable * driDrawable, 444 int *width, int *height, 445 unsigned int *attachments, int count, 446 int *out_count, void *loaderPrivate) 447{ 448 __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 449 DRI2Buffer *buffers; 450 451 buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable, 452 width, height, attachments, count, out_count); 453 if (buffers == NULL) 454 return NULL; 455 456 pdraw->width = *width; 457 pdraw->height = *height; 458 process_buffers(pdraw, buffers, *out_count); 459 460 Xfree(buffers); 461 462 return pdraw->buffers; 463} 464 465static __DRIbuffer * 466dri2GetBuffersWithFormat(__DRIdrawable * driDrawable, 467 int *width, int *height, 468 unsigned int *attachments, int count, 469 int *out_count, void *loaderPrivate) 470{ 471 __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 472 DRI2Buffer *buffers; 473 474 buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy, 475 pdraw->base.xDrawable, 476 width, height, attachments, 477 count, out_count); 478 if (buffers == NULL) 479 return NULL; 480 481 pdraw->width = *width; 482 pdraw->height = *height; 483 process_buffers(pdraw, buffers, *out_count); 484 485 Xfree(buffers); 486 487 return pdraw->buffers; 488} 489 490#ifdef X_DRI2SwapInterval 491 492static void 493dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval) 494{ 495 __GLXscreenConfigs *psc = pdraw->psc; 496 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 497 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 498 499 if (psc->config) 500 psc->config->configQueryi(psc->__driScreen, "vblank_mode", &vblank_mode); 501 502 switch (vblank_mode) { 503 case DRI_CONF_VBLANK_NEVER: 504 return; 505 case DRI_CONF_VBLANK_ALWAYS_SYNC: 506 if (interval <= 0) 507 return; 508 break; 509 default: 510 break; 511 } 512 513 DRI2SwapInterval(priv->base.psc->dpy, pdraw->xDrawable, interval); 514 priv->swap_interval = interval; 515} 516 517static unsigned int 518dri2GetSwapInterval(__GLXDRIdrawable *pdraw) 519{ 520 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 521 522 return priv->swap_interval; 523} 524 525#endif /* X_DRI2SwapInterval */ 526 527static const __DRIdri2LoaderExtension dri2LoaderExtension = { 528 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 529 dri2GetBuffers, 530 dri2FlushFrontBuffer, 531 dri2GetBuffersWithFormat, 532}; 533 534static const __DRIdri2LoaderExtension dri2LoaderExtension_old = { 535 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 536 dri2GetBuffers, 537 dri2FlushFrontBuffer, 538 NULL, 539}; 540 541#ifdef __DRI_USE_INVALIDATE 542static const __DRIuseInvalidateExtension dri2UseInvalidate = { 543 { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION } 544}; 545#endif 546 547_X_HIDDEN void 548dri2InvalidateBuffers(Display *dpy, XID drawable) 549{ 550 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); 551 552#if __DRI2_FLUSH_VERSION >= 3 553 if (pdraw && pdraw->psc->f) 554 pdraw->psc->f->invalidate(pdraw->driDrawable); 555#endif 556} 557 558static __GLXDRIscreen * 559dri2CreateScreen(__GLXscreenConfigs * psc, int screen, 560 __GLXdisplayPrivate * priv) 561{ 562 const __DRIconfig **driver_configs; 563 const __DRIextension **extensions; 564 const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *) 565 priv->dri2Display; 566 __GLXDRIscreen *psp; 567 char *driverName, *deviceName; 568 drm_magic_t magic; 569 int i; 570 571 psp = Xmalloc(sizeof *psp); 572 if (psp == NULL) 573 return NULL; 574 575 if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen), 576 &driverName, &deviceName)) { 577 XFree(psp); 578 return NULL; 579 } 580 581 psc->driver = driOpenDriver(driverName); 582 if (psc->driver == NULL) { 583 ErrorMessageF("driver pointer missing\n"); 584 goto handle_error; 585 } 586 587 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); 588 if (extensions == NULL) { 589 ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 590 goto handle_error; 591 } 592 593 for (i = 0; extensions[i]; i++) { 594 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 595 psc->core = (__DRIcoreExtension *) extensions[i]; 596 if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) 597 psc->dri2 = (__DRIdri2Extension *) extensions[i]; 598 } 599 600 if (psc->core == NULL || psc->dri2 == NULL) { 601 ErrorMessageF("core dri or dri2 extension not found\n"); 602 goto handle_error; 603 } 604 605 psc->fd = open(deviceName, O_RDWR); 606 if (psc->fd < 0) { 607 ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); 608 goto handle_error; 609 } 610 611 if (drmGetMagic(psc->fd, &magic)) { 612 ErrorMessageF("failed to get magic\n"); 613 goto handle_error; 614 } 615 616 if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) { 617 ErrorMessageF("failed to authenticate magic %d\n", magic); 618 goto handle_error; 619 } 620 621 622 /* If the server does not support the protocol for 623 * DRI2GetBuffersWithFormat, don't supply that interface to the driver. 624 */ 625 psc->__driScreen = 626 psc->dri2->createNewScreen(screen, psc->fd, 627 (const __DRIextension **) 628 &pdp->loader_extensions[0], 629 &driver_configs, psc); 630 631 if (psc->__driScreen == NULL) { 632 ErrorMessageF("failed to create dri screen\n"); 633 goto handle_error; 634 } 635 636 driBindCommonExtensions(psc); 637 dri2BindExtensions(psc); 638 639 psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); 640 psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); 641 642 psc->driver_configs = driver_configs; 643 644 psp->destroyScreen = dri2DestroyScreen; 645 psp->createContext = dri2CreateContext; 646 psp->createDrawable = dri2CreateDrawable; 647 psp->swapBuffers = dri2SwapBuffers; 648 psp->waitGL = dri2WaitGL; 649 psp->waitX = dri2WaitX; 650 psp->getDrawableMSC = NULL; 651 psp->waitForMSC = NULL; 652 psp->waitForSBC = NULL; 653 psp->setSwapInterval = NULL; 654 psp->getSwapInterval = NULL; 655 656 if (pdp->driMinor >= 2) { 657#ifdef X_DRI2GetMSC 658 psp->getDrawableMSC = dri2DrawableGetMSC; 659#endif 660#ifdef X_DRI2WaitMSC 661 psp->waitForMSC = dri2WaitForMSC; 662 psp->waitForSBC = dri2WaitForSBC; 663#endif 664#ifdef X_DRI2SwapInterval 665 psp->setSwapInterval = dri2SetSwapInterval; 666 psp->getSwapInterval = dri2GetSwapInterval; 667#endif 668#if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval) 669 __glXEnableDirectExtension(psc, "GLX_OML_sync_control"); 670#endif 671 } 672 673 /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always 674 * available.*/ 675 psp->copySubBuffer = dri2CopySubBuffer; 676 __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); 677 678 Xfree(driverName); 679 Xfree(deviceName); 680 681 return psp; 682 683handle_error: 684 Xfree(driverName); 685 Xfree(deviceName); 686 XFree(psp); 687 688 /* FIXME: clean up here */ 689 690 return NULL; 691} 692 693/* Called from __glXFreeDisplayPrivate. 694 */ 695static void 696dri2DestroyDisplay(__GLXDRIdisplay * dpy) 697{ 698 Xfree(dpy); 699} 700 701/* 702 * Allocate, initialize and return a __DRIdisplayPrivate object. 703 * This is called from __glXInitialize() when we are given a new 704 * display pointer. 705 */ 706_X_HIDDEN __GLXDRIdisplay * 707dri2CreateDisplay(Display * dpy) 708{ 709 __GLXDRIdisplayPrivate *pdp; 710 int eventBase, errorBase, i; 711 712 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) 713 return NULL; 714 715 pdp = Xmalloc(sizeof *pdp); 716 if (pdp == NULL) 717 return NULL; 718 719 if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) { 720 Xfree(pdp); 721 return NULL; 722 } 723 724 pdp->driPatch = 0; 725 pdp->swapAvailable = (pdp->driMinor >= 2); 726 pdp->invalidateAvailable = (pdp->driMinor >= 3); 727 728 pdp->base.destroyDisplay = dri2DestroyDisplay; 729 pdp->base.createScreen = dri2CreateScreen; 730 731 i = 0; 732 if (pdp->driMinor < 1) 733 pdp->loader_extensions[i++] = &dri2LoaderExtension_old.base; 734 else 735 pdp->loader_extensions[i++] = &dri2LoaderExtension.base; 736 737 pdp->loader_extensions[i++] = &systemTimeExtension.base; 738 739#ifdef __DRI_USE_INVALIDATE 740 if (pdp->invalidateAvailable) 741 pdp->loader_extensions[i++] = &dri2UseInvalidate.base; 742#endif 743 pdp->loader_extensions[i++] = NULL; 744 745 return &pdp->base; 746} 747 748#endif /* GLX_DIRECT_RENDERING */ 749