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