dri2_glx.c revision ab780bccb737e0dc25a55b5e54faad9c4a790ac0
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 __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 365 __GLXdisplayPrivate *priv = __glXInitialize(pdraw->base.psc->dpy); 366 __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)priv->dri2Display; 367 368 /* Old servers don't send invalidate events */ 369 if (!pdp->invalidateAvailable) 370 dri2InvalidateBuffers(priv->dpy, pdraw->base.drawable); 371 372 dri2WaitGL(loaderPrivate); 373} 374 375 376static void 377dri2DestroyScreen(__GLXscreenConfigs * psc) 378{ 379 /* Free the direct rendering per screen data */ 380 (*psc->core->destroyScreen) (psc->__driScreen); 381 close(psc->fd); 382 psc->__driScreen = NULL; 383} 384 385/** 386 * Process list of buffer received from the server 387 * 388 * Processes the list of buffers received in a reply from the server to either 389 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. 390 */ 391static void 392process_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers, 393 unsigned count) 394{ 395 int i; 396 397 pdraw->bufferCount = count; 398 pdraw->have_fake_front = 0; 399 pdraw->have_back = 0; 400 401 /* This assumes the DRI2 buffer attachment tokens matches the 402 * __DRIbuffer tokens. */ 403 for (i = 0; i < count; i++) { 404 pdraw->buffers[i].attachment = buffers[i].attachment; 405 pdraw->buffers[i].name = buffers[i].name; 406 pdraw->buffers[i].pitch = buffers[i].pitch; 407 pdraw->buffers[i].cpp = buffers[i].cpp; 408 pdraw->buffers[i].flags = buffers[i].flags; 409 if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) 410 pdraw->have_fake_front = 1; 411 if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) 412 pdraw->have_back = 1; 413 } 414 415} 416 417static int64_t 418dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 419 int64_t remainder) 420{ 421 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 422 __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy); 423 __GLXDRIdisplayPrivate *pdp = 424 (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display; 425 int64_t ret; 426 427#ifdef __DRI2_FLUSH 428 if (pdraw->psc->f) 429 (*pdraw->psc->f->flush)(pdraw->driDrawable); 430#endif 431 432 /* Old servers don't send invalidate events */ 433 if (!pdp->invalidateAvailable) 434 dri2InvalidateBuffers(dpyPriv->dpy, pdraw->drawable); 435 436 /* Old servers can't handle swapbuffers */ 437 if (!pdp->swapAvailable) { 438 dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); 439 return 0; 440 } 441 442#ifdef X_DRI2SwapBuffers 443 DRI2SwapBuffers(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 444 remainder, &ret); 445#endif 446 447 return ret; 448} 449 450static __DRIbuffer * 451dri2GetBuffers(__DRIdrawable * driDrawable, 452 int *width, int *height, 453 unsigned int *attachments, int count, 454 int *out_count, void *loaderPrivate) 455{ 456 __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 457 DRI2Buffer *buffers; 458 459 buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable, 460 width, height, attachments, count, out_count); 461 if (buffers == NULL) 462 return NULL; 463 464 pdraw->width = *width; 465 pdraw->height = *height; 466 process_buffers(pdraw, buffers, *out_count); 467 468 Xfree(buffers); 469 470 return pdraw->buffers; 471} 472 473static __DRIbuffer * 474dri2GetBuffersWithFormat(__DRIdrawable * driDrawable, 475 int *width, int *height, 476 unsigned int *attachments, int count, 477 int *out_count, void *loaderPrivate) 478{ 479 __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 480 DRI2Buffer *buffers; 481 482 buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy, 483 pdraw->base.xDrawable, 484 width, height, attachments, 485 count, out_count); 486 if (buffers == NULL) 487 return NULL; 488 489 pdraw->width = *width; 490 pdraw->height = *height; 491 process_buffers(pdraw, buffers, *out_count); 492 493 Xfree(buffers); 494 495 return pdraw->buffers; 496} 497 498#ifdef X_DRI2SwapInterval 499 500static void 501dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval) 502{ 503 __GLXscreenConfigs *psc = pdraw->psc; 504 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 505 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 506 507 if (psc->config) 508 psc->config->configQueryi(psc->__driScreen, "vblank_mode", &vblank_mode); 509 510 switch (vblank_mode) { 511 case DRI_CONF_VBLANK_NEVER: 512 return; 513 case DRI_CONF_VBLANK_ALWAYS_SYNC: 514 if (interval <= 0) 515 return; 516 break; 517 default: 518 break; 519 } 520 521 DRI2SwapInterval(priv->base.psc->dpy, pdraw->xDrawable, interval); 522 priv->swap_interval = interval; 523} 524 525static unsigned int 526dri2GetSwapInterval(__GLXDRIdrawable *pdraw) 527{ 528 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 529 530 return priv->swap_interval; 531} 532 533#endif /* X_DRI2SwapInterval */ 534 535static const __DRIdri2LoaderExtension dri2LoaderExtension = { 536 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 537 dri2GetBuffers, 538 dri2FlushFrontBuffer, 539 dri2GetBuffersWithFormat, 540}; 541 542static const __DRIdri2LoaderExtension dri2LoaderExtension_old = { 543 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 544 dri2GetBuffers, 545 dri2FlushFrontBuffer, 546 NULL, 547}; 548 549#ifdef __DRI_USE_INVALIDATE 550static const __DRIuseInvalidateExtension dri2UseInvalidate = { 551 { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION } 552}; 553#endif 554 555_X_HIDDEN void 556dri2InvalidateBuffers(Display *dpy, XID drawable) 557{ 558 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); 559 560#if __DRI2_FLUSH_VERSION >= 3 561 if (pdraw && pdraw->psc->f) 562 pdraw->psc->f->invalidate(pdraw->driDrawable); 563#endif 564} 565 566static void 567dri2_bind_tex_image(Display * dpy, 568 GLXDrawable drawable, 569 int buffer, const int *attrib_list) 570{ 571 GLXContext gc = __glXGetCurrentContext(); 572 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); 573 __GLXdisplayPrivate *dpyPriv = __glXInitialize(dpy); 574 __GLXDRIdisplayPrivate *pdp = 575 (__GLXDRIdisplayPrivate *) dpyPriv->dri2Display; 576 577 if (pdraw != NULL) { 578 579#if __DRI2_FLUSH_VERSION >= 3 580 if (!pdp->invalidateAvailable && pdraw->psc->f) 581 pdraw->psc->f->invalidate(pdraw->driDrawable); 582#endif 583 584 if (pdraw->psc->texBuffer->base.version >= 2 && 585 pdraw->psc->texBuffer->setTexBuffer2 != NULL) { 586 (*pdraw->psc->texBuffer->setTexBuffer2) (gc->__driContext, 587 pdraw->textureTarget, 588 pdraw->textureFormat, 589 pdraw->driDrawable); 590 } 591 else { 592 (*pdraw->psc->texBuffer->setTexBuffer) (gc->__driContext, 593 pdraw->textureTarget, 594 pdraw->driDrawable); 595 } 596 } 597} 598 599static void 600dri2_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer) 601{ 602} 603 604static const struct glx_context_vtable dri2_context_vtable = { 605 dri2_bind_tex_image, 606 dri2_release_tex_image, 607}; 608 609static __GLXDRIscreen * 610dri2CreateScreen(__GLXscreenConfigs * psc, int screen, 611 __GLXdisplayPrivate * priv) 612{ 613 const __DRIconfig **driver_configs; 614 const __DRIextension **extensions; 615 const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *) 616 priv->dri2Display; 617 __GLXDRIscreen *psp; 618 char *driverName, *deviceName; 619 drm_magic_t magic; 620 int i; 621 622 psp = Xmalloc(sizeof *psp); 623 if (psp == NULL) 624 return NULL; 625 626 if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen), 627 &driverName, &deviceName)) { 628 XFree(psp); 629 return NULL; 630 } 631 632 psc->driver = driOpenDriver(driverName); 633 if (psc->driver == NULL) { 634 ErrorMessageF("driver pointer missing\n"); 635 goto handle_error; 636 } 637 638 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); 639 if (extensions == NULL) { 640 ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 641 goto handle_error; 642 } 643 644 for (i = 0; extensions[i]; i++) { 645 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 646 psc->core = (__DRIcoreExtension *) extensions[i]; 647 if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) 648 psc->dri2 = (__DRIdri2Extension *) extensions[i]; 649 } 650 651 if (psc->core == NULL || psc->dri2 == NULL) { 652 ErrorMessageF("core dri or dri2 extension not found\n"); 653 goto handle_error; 654 } 655 656 psc->fd = open(deviceName, O_RDWR); 657 if (psc->fd < 0) { 658 ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); 659 goto handle_error; 660 } 661 662 if (drmGetMagic(psc->fd, &magic)) { 663 ErrorMessageF("failed to get magic\n"); 664 goto handle_error; 665 } 666 667 if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) { 668 ErrorMessageF("failed to authenticate magic %d\n", magic); 669 goto handle_error; 670 } 671 672 673 /* If the server does not support the protocol for 674 * DRI2GetBuffersWithFormat, don't supply that interface to the driver. 675 */ 676 psc->__driScreen = 677 psc->dri2->createNewScreen(screen, psc->fd, 678 (const __DRIextension **) 679 &pdp->loader_extensions[0], 680 &driver_configs, psc); 681 682 if (psc->__driScreen == NULL) { 683 ErrorMessageF("failed to create dri screen\n"); 684 goto handle_error; 685 } 686 687 driBindCommonExtensions(psc); 688 dri2BindExtensions(psc); 689 690 psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); 691 psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); 692 693 psc->driver_configs = driver_configs; 694 695 psp->destroyScreen = dri2DestroyScreen; 696 psp->createContext = dri2CreateContext; 697 psp->createDrawable = dri2CreateDrawable; 698 psp->swapBuffers = dri2SwapBuffers; 699 psp->waitGL = dri2WaitGL; 700 psp->waitX = dri2WaitX; 701 psp->getDrawableMSC = NULL; 702 psp->waitForMSC = NULL; 703 psp->waitForSBC = NULL; 704 psp->setSwapInterval = NULL; 705 psp->getSwapInterval = NULL; 706 707 if (pdp->driMinor >= 2) { 708#ifdef X_DRI2GetMSC 709 psp->getDrawableMSC = dri2DrawableGetMSC; 710#endif 711#ifdef X_DRI2WaitMSC 712 psp->waitForMSC = dri2WaitForMSC; 713 psp->waitForSBC = dri2WaitForSBC; 714#endif 715#ifdef X_DRI2SwapInterval 716 psp->setSwapInterval = dri2SetSwapInterval; 717 psp->getSwapInterval = dri2GetSwapInterval; 718#endif 719#if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval) 720 __glXEnableDirectExtension(psc, "GLX_OML_sync_control"); 721#endif 722 } 723 724 /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always 725 * available.*/ 726 psp->copySubBuffer = dri2CopySubBuffer; 727 __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); 728 729 psc->direct_context_vtable = &dri2_context_vtable; 730 731 Xfree(driverName); 732 Xfree(deviceName); 733 734 return psp; 735 736handle_error: 737 Xfree(driverName); 738 Xfree(deviceName); 739 XFree(psp); 740 741 /* FIXME: clean up here */ 742 743 return NULL; 744} 745 746/* Called from __glXFreeDisplayPrivate. 747 */ 748static void 749dri2DestroyDisplay(__GLXDRIdisplay * dpy) 750{ 751 Xfree(dpy); 752} 753 754/* 755 * Allocate, initialize and return a __DRIdisplayPrivate object. 756 * This is called from __glXInitialize() when we are given a new 757 * display pointer. 758 */ 759_X_HIDDEN __GLXDRIdisplay * 760dri2CreateDisplay(Display * dpy) 761{ 762 __GLXDRIdisplayPrivate *pdp; 763 int eventBase, errorBase, i; 764 765 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) 766 return NULL; 767 768 pdp = Xmalloc(sizeof *pdp); 769 if (pdp == NULL) 770 return NULL; 771 772 if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) { 773 Xfree(pdp); 774 return NULL; 775 } 776 777 pdp->driPatch = 0; 778 pdp->swapAvailable = (pdp->driMinor >= 2); 779 pdp->invalidateAvailable = (pdp->driMinor >= 3); 780 781 pdp->base.destroyDisplay = dri2DestroyDisplay; 782 pdp->base.createScreen = dri2CreateScreen; 783 784 i = 0; 785 if (pdp->driMinor < 1) 786 pdp->loader_extensions[i++] = &dri2LoaderExtension_old.base; 787 else 788 pdp->loader_extensions[i++] = &dri2LoaderExtension.base; 789 790 pdp->loader_extensions[i++] = &systemTimeExtension.base; 791 792#ifdef __DRI_USE_INVALIDATE 793 pdp->loader_extensions[i++] = &dri2UseInvalidate.base; 794#endif 795 pdp->loader_extensions[i++] = NULL; 796 797 return &pdp->base; 798} 799 800#endif /* GLX_DIRECT_RENDERING */ 801