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