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