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