XF86dri.c revision 016fc30839f0fb67bb37d4a7353a7e38749deab5
1/************************************************************************** 2 3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 4Copyright 2000 VA Linux Systems, Inc. 5All Rights Reserved. 6 7Permission is hereby granted, free of charge, to any person obtaining a 8copy of this software and associated documentation files (the 9"Software"), to deal in the Software without restriction, including 10without limitation the rights to use, copy, modify, merge, publish, 11distribute, sub license, and/or sell copies of the Software, and to 12permit persons to whom the Software is furnished to do so, subject to 13the following conditions: 14 15The above copyright notice and this permission notice (including the 16next paragraph) shall be included in all copies or substantial portions 17of the Software. 18 19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 23ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 27**************************************************************************/ 28 29/* 30 * Authors: 31 * Kevin E. Martin <martin@valinux.com> 32 * Jens Owen <jens@tungstengraphics.com> 33 * Rickard E. (Rik) Faith <faith@valinux.com> 34 * 35 */ 36 37/* THIS IS NOT AN X CONSORTIUM STANDARD */ 38 39#ifdef GLX_DIRECT_RENDERING 40 41#define NEED_REPLIES 42#include <X11/Xlibint.h> 43#include <X11/extensions/Xext.h> 44#include <X11/extensions/extutil.h> 45#include "xf86dristr.h" 46 47 48#if defined(__GNUC__) 49# define PUBLIC __attribute__((visibility("default"))) 50# define USED __attribute__((used)) 51#else 52# define PUBLIC 53# define USED 54#endif 55 56 57 58static XExtensionInfo _xf86dri_info_data; 59static XExtensionInfo *xf86dri_info = &_xf86dri_info_data; 60static char xf86dri_extension_name[] = XF86DRINAME; 61 62#define XF86DRICheckExtension(dpy,i,val) \ 63 XextCheckExtension (dpy, i, xf86dri_extension_name, val) 64 65/***************************************************************************** 66 * * 67 * private utility routines * 68 * * 69 *****************************************************************************/ 70 71static int close_display(Display * dpy, XExtCodes * extCodes); 72static /* const */ XExtensionHooks xf86dri_extension_hooks = { 73 NULL, /* create_gc */ 74 NULL, /* copy_gc */ 75 NULL, /* flush_gc */ 76 NULL, /* free_gc */ 77 NULL, /* create_font */ 78 NULL, /* free_font */ 79 close_display, /* close_display */ 80 NULL, /* wire_to_event */ 81 NULL, /* event_to_wire */ 82 NULL, /* error */ 83 NULL, /* error_string */ 84}; 85 86static 87XEXT_GENERATE_FIND_DISPLAY(find_display, xf86dri_info, 88 xf86dri_extension_name, 89 &xf86dri_extension_hooks, 0, NULL) 90 91static 92XEXT_GENERATE_CLOSE_DISPLAY(close_display, xf86dri_info) 93 94 95/***************************************************************************** 96 * * 97 * public XFree86-DRI Extension routines * 98 * * 99 *****************************************************************************/ 100#if 0 101#include <stdio.h> 102#define TRACE(msg) fprintf(stderr,"XF86DRI%s\n", msg); 103#else 104#define TRACE(msg) 105#endif 106 107Bool 108XF86DRIQueryExtension(Display * dpy, int *event_basep, 109 int *error_basep) 110{ 111 XExtDisplayInfo *info = find_display(dpy); 112 113 TRACE("QueryExtension..."); 114 if (XextHasExtension(info)) { 115 *event_basep = info->codes->first_event; 116 *error_basep = info->codes->first_error; 117 TRACE("QueryExtension... return True"); 118 return True; 119 } 120 else { 121 TRACE("QueryExtension... return False"); 122 return False; 123 } 124} 125 126Bool 127XF86DRIQueryVersion(Display * dpy, int *majorVersion, int *minorVersion, 128 int *patchVersion) 129{ 130 XExtDisplayInfo *info = find_display(dpy); 131 xXF86DRIQueryVersionReply rep; 132 xXF86DRIQueryVersionReq *req; 133 134 TRACE("QueryVersion..."); 135 XF86DRICheckExtension(dpy, info, False); 136 137 LockDisplay(dpy); 138 GetReq(XF86DRIQueryVersion, req); 139 req->reqType = info->codes->major_opcode; 140 req->driReqType = X_XF86DRIQueryVersion; 141 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 142 UnlockDisplay(dpy); 143 SyncHandle(); 144 TRACE("QueryVersion... return False"); 145 return False; 146 } 147 *majorVersion = rep.majorVersion; 148 *minorVersion = rep.minorVersion; 149 *patchVersion = rep.patchVersion; 150 UnlockDisplay(dpy); 151 SyncHandle(); 152 TRACE("QueryVersion... return True"); 153 return True; 154} 155 156Bool 157XF86DRIQueryDirectRenderingCapable(Display * dpy, int screen, 158 Bool * isCapable) 159{ 160 XExtDisplayInfo *info = find_display(dpy); 161 xXF86DRIQueryDirectRenderingCapableReply rep; 162 xXF86DRIQueryDirectRenderingCapableReq *req; 163 164 TRACE("QueryDirectRenderingCapable..."); 165 XF86DRICheckExtension(dpy, info, False); 166 167 LockDisplay(dpy); 168 GetReq(XF86DRIQueryDirectRenderingCapable, req); 169 req->reqType = info->codes->major_opcode; 170 req->driReqType = X_XF86DRIQueryDirectRenderingCapable; 171 req->screen = screen; 172 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 173 UnlockDisplay(dpy); 174 SyncHandle(); 175 TRACE("QueryDirectRenderingCapable... return False"); 176 return False; 177 } 178 *isCapable = rep.isCapable; 179 UnlockDisplay(dpy); 180 SyncHandle(); 181 TRACE("QueryDirectRenderingCapable... return True"); 182 return True; 183} 184 185Bool 186XF86DRIOpenConnection(Display * dpy, int screen, drm_handle_t * hSAREA, 187 char **busIdString) 188{ 189 XExtDisplayInfo *info = find_display(dpy); 190 xXF86DRIOpenConnectionReply rep; 191 xXF86DRIOpenConnectionReq *req; 192 193 TRACE("OpenConnection..."); 194 XF86DRICheckExtension(dpy, info, False); 195 196 LockDisplay(dpy); 197 GetReq(XF86DRIOpenConnection, req); 198 req->reqType = info->codes->major_opcode; 199 req->driReqType = X_XF86DRIOpenConnection; 200 req->screen = screen; 201 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 202 UnlockDisplay(dpy); 203 SyncHandle(); 204 TRACE("OpenConnection... return False"); 205 return False; 206 } 207 208 *hSAREA = rep.hSAREALow; 209 if (sizeof(drm_handle_t) == 8) { 210 int shift = 32; /* var to prevent warning on next line */ 211 *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift; 212 } 213 214 if (rep.length) { 215 if (!(*busIdString = (char *) Xcalloc(rep.busIdStringLength + 1, 1))) { 216 _XEatData(dpy, ((rep.busIdStringLength + 3) & ~3)); 217 UnlockDisplay(dpy); 218 SyncHandle(); 219 TRACE("OpenConnection... return False"); 220 return False; 221 } 222 _XReadPad(dpy, *busIdString, rep.busIdStringLength); 223 } 224 else { 225 *busIdString = NULL; 226 } 227 UnlockDisplay(dpy); 228 SyncHandle(); 229 TRACE("OpenConnection... return True"); 230 return True; 231} 232 233Bool 234XF86DRIAuthConnection(Display * dpy, int screen, drm_magic_t magic) 235{ 236 XExtDisplayInfo *info = find_display(dpy); 237 xXF86DRIAuthConnectionReq *req; 238 xXF86DRIAuthConnectionReply rep; 239 240 TRACE("AuthConnection..."); 241 XF86DRICheckExtension(dpy, info, False); 242 243 LockDisplay(dpy); 244 GetReq(XF86DRIAuthConnection, req); 245 req->reqType = info->codes->major_opcode; 246 req->driReqType = X_XF86DRIAuthConnection; 247 req->screen = screen; 248 req->magic = magic; 249 rep.authenticated = 0; 250 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse) || !rep.authenticated) { 251 UnlockDisplay(dpy); 252 SyncHandle(); 253 TRACE("AuthConnection... return False"); 254 return False; 255 } 256 UnlockDisplay(dpy); 257 SyncHandle(); 258 TRACE("AuthConnection... return True"); 259 return True; 260} 261 262Bool 263XF86DRICloseConnection(Display * dpy, int screen) 264{ 265 XExtDisplayInfo *info = find_display(dpy); 266 xXF86DRICloseConnectionReq *req; 267 268 TRACE("CloseConnection..."); 269 270 XF86DRICheckExtension(dpy, info, False); 271 272 LockDisplay(dpy); 273 GetReq(XF86DRICloseConnection, req); 274 req->reqType = info->codes->major_opcode; 275 req->driReqType = X_XF86DRICloseConnection; 276 req->screen = screen; 277 UnlockDisplay(dpy); 278 SyncHandle(); 279 TRACE("CloseConnection... return True"); 280 return True; 281} 282 283Bool 284XF86DRIGetClientDriverName(Display * dpy, int screen, 285 int *ddxDriverMajorVersion, 286 int *ddxDriverMinorVersion, 287 int *ddxDriverPatchVersion, 288 char **clientDriverName) 289{ 290 XExtDisplayInfo *info = find_display(dpy); 291 xXF86DRIGetClientDriverNameReply rep; 292 xXF86DRIGetClientDriverNameReq *req; 293 294 TRACE("GetClientDriverName..."); 295 XF86DRICheckExtension(dpy, info, False); 296 297 LockDisplay(dpy); 298 GetReq(XF86DRIGetClientDriverName, req); 299 req->reqType = info->codes->major_opcode; 300 req->driReqType = X_XF86DRIGetClientDriverName; 301 req->screen = screen; 302 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 303 UnlockDisplay(dpy); 304 SyncHandle(); 305 TRACE("GetClientDriverName... return False"); 306 return False; 307 } 308 309 *ddxDriverMajorVersion = rep.ddxDriverMajorVersion; 310 *ddxDriverMinorVersion = rep.ddxDriverMinorVersion; 311 *ddxDriverPatchVersion = rep.ddxDriverPatchVersion; 312 313 if (rep.length) { 314 if (! 315 (*clientDriverName = 316 (char *) Xcalloc(rep.clientDriverNameLength + 1, 1))) { 317 _XEatData(dpy, ((rep.clientDriverNameLength + 3) & ~3)); 318 UnlockDisplay(dpy); 319 SyncHandle(); 320 TRACE("GetClientDriverName... return False"); 321 return False; 322 } 323 _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength); 324 } 325 else { 326 *clientDriverName = NULL; 327 } 328 UnlockDisplay(dpy); 329 SyncHandle(); 330 TRACE("GetClientDriverName... return True"); 331 return True; 332} 333 334Bool 335XF86DRICreateContextWithConfig(Display * dpy, int screen, int configID, 336 XID * context, drm_context_t * hHWContext) 337{ 338 XExtDisplayInfo *info = find_display(dpy); 339 xXF86DRICreateContextReply rep; 340 xXF86DRICreateContextReq *req; 341 342 TRACE("CreateContext..."); 343 XF86DRICheckExtension(dpy, info, False); 344 345 LockDisplay(dpy); 346 GetReq(XF86DRICreateContext, req); 347 req->reqType = info->codes->major_opcode; 348 req->driReqType = X_XF86DRICreateContext; 349 req->visual = configID; 350 req->screen = screen; 351 *context = XAllocID(dpy); 352 req->context = *context; 353 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 354 UnlockDisplay(dpy); 355 SyncHandle(); 356 TRACE("CreateContext... return False"); 357 return False; 358 } 359 *hHWContext = rep.hHWContext; 360 UnlockDisplay(dpy); 361 SyncHandle(); 362 TRACE("CreateContext... return True"); 363 return True; 364} 365 366Bool 367XF86DRICreateContext(Display * dpy, int screen, Visual * visual, 368 XID * context, drm_context_t * hHWContext) 369{ 370 return XF86DRICreateContextWithConfig(dpy, screen, visual->visualid, 371 context, hHWContext); 372} 373 374Bool 375XF86DRIDestroyContext(Display * dpy, int screen, XID context) 376{ 377 XExtDisplayInfo *info = find_display(dpy); 378 xXF86DRIDestroyContextReq *req; 379 380 TRACE("DestroyContext..."); 381 XF86DRICheckExtension(dpy, info, False); 382 383 LockDisplay(dpy); 384 GetReq(XF86DRIDestroyContext, req); 385 req->reqType = info->codes->major_opcode; 386 req->driReqType = X_XF86DRIDestroyContext; 387 req->screen = screen; 388 req->context = context; 389 UnlockDisplay(dpy); 390 SyncHandle(); 391 TRACE("DestroyContext... return True"); 392 return True; 393} 394 395Bool 396XF86DRICreateDrawable(Display * dpy, int screen, 397 XID drawable, drm_drawable_t * hHWDrawable) 398{ 399 XExtDisplayInfo *info = find_display(dpy); 400 xXF86DRICreateDrawableReply rep; 401 xXF86DRICreateDrawableReq *req; 402 403 TRACE("CreateDrawable..."); 404 XF86DRICheckExtension(dpy, info, False); 405 406 LockDisplay(dpy); 407 GetReq(XF86DRICreateDrawable, req); 408 req->reqType = info->codes->major_opcode; 409 req->driReqType = X_XF86DRICreateDrawable; 410 req->screen = screen; 411 req->drawable = drawable; 412 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 413 UnlockDisplay(dpy); 414 SyncHandle(); 415 TRACE("CreateDrawable... return False"); 416 return False; 417 } 418 *hHWDrawable = rep.hHWDrawable; 419 UnlockDisplay(dpy); 420 SyncHandle(); 421 TRACE("CreateDrawable... return True"); 422 return True; 423} 424 425static int 426noopErrorHandler(Display * dpy, XErrorEvent * xerr) 427{ 428 return 0; 429} 430 431Bool 432XF86DRIDestroyDrawable(Display * dpy, int screen, XID drawable) 433{ 434 XExtDisplayInfo *info = find_display(dpy); 435 xXF86DRIDestroyDrawableReq *req; 436 int (*oldXErrorHandler) (Display *, XErrorEvent *); 437 438 TRACE("DestroyDrawable..."); 439 XF86DRICheckExtension(dpy, info, False); 440 441 /* This is called from the DRI driver, which used call it like this 442 * 443 * if (windowExists(drawable)) 444 * destroyDrawable(drawable); 445 * 446 * which is a textbook race condition - the window may disappear 447 * from the server between checking for its existance and 448 * destroying it. Instead we change the semantics of 449 * __DRIinterfaceMethodsRec::destroyDrawable() to succeed even if 450 * the windows is gone, by wrapping the destroy call in an error 451 * handler. */ 452 453 XSync(dpy, False); 454 oldXErrorHandler = XSetErrorHandler(noopErrorHandler); 455 456 LockDisplay(dpy); 457 GetReq(XF86DRIDestroyDrawable, req); 458 req->reqType = info->codes->major_opcode; 459 req->driReqType = X_XF86DRIDestroyDrawable; 460 req->screen = screen; 461 req->drawable = drawable; 462 UnlockDisplay(dpy); 463 SyncHandle(); 464 465 XSetErrorHandler(oldXErrorHandler); 466 467 TRACE("DestroyDrawable... return True"); 468 return True; 469} 470 471Bool 472XF86DRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable, 473 unsigned int *index, unsigned int *stamp, 474 int *X, int *Y, int *W, int *H, 475 int *numClipRects, drm_clip_rect_t ** pClipRects, 476 int *backX, int *backY, 477 int *numBackClipRects, 478 drm_clip_rect_t ** pBackClipRects) 479{ 480 XExtDisplayInfo *info = find_display(dpy); 481 xXF86DRIGetDrawableInfoReply rep; 482 xXF86DRIGetDrawableInfoReq *req; 483 int total_rects; 484 485 TRACE("GetDrawableInfo..."); 486 XF86DRICheckExtension(dpy, info, False); 487 488 LockDisplay(dpy); 489 GetReq(XF86DRIGetDrawableInfo, req); 490 req->reqType = info->codes->major_opcode; 491 req->driReqType = X_XF86DRIGetDrawableInfo; 492 req->screen = screen; 493 req->drawable = drawable; 494 495 if (!_XReply(dpy, (xReply *) & rep, 1, xFalse)) { 496 UnlockDisplay(dpy); 497 SyncHandle(); 498 TRACE("GetDrawableInfo... return False"); 499 return False; 500 } 501 *index = rep.drawableTableIndex; 502 *stamp = rep.drawableTableStamp; 503 *X = (int) rep.drawableX; 504 *Y = (int) rep.drawableY; 505 *W = (int) rep.drawableWidth; 506 *H = (int) rep.drawableHeight; 507 *numClipRects = rep.numClipRects; 508 total_rects = *numClipRects; 509 510 *backX = rep.backX; 511 *backY = rep.backY; 512 *numBackClipRects = rep.numBackClipRects; 513 total_rects += *numBackClipRects; 514 515#if 0 516 /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks 517 * backwards compatibility (Because of the >> 2 shift) but the fix 518 * enables multi-threaded apps to work. 519 */ 520 if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) - 521 SIZEOF(xGenericReply) + 522 total_rects * sizeof(drm_clip_rect_t)) + 523 3) & ~3) >> 2)) { 524 _XEatData(dpy, rep.length); 525 UnlockDisplay(dpy); 526 SyncHandle(); 527 TRACE("GetDrawableInfo... return False"); 528 return False; 529 } 530#endif 531 532 if (*numClipRects) { 533 int len = sizeof(drm_clip_rect_t) * (*numClipRects); 534 535 *pClipRects = (drm_clip_rect_t *) Xcalloc(len, 1); 536 if (*pClipRects) 537 _XRead(dpy, (char *) *pClipRects, len); 538 } 539 else { 540 *pClipRects = NULL; 541 } 542 543 if (*numBackClipRects) { 544 int len = sizeof(drm_clip_rect_t) * (*numBackClipRects); 545 546 *pBackClipRects = (drm_clip_rect_t *) Xcalloc(len, 1); 547 if (*pBackClipRects) 548 _XRead(dpy, (char *) *pBackClipRects, len); 549 } 550 else { 551 *pBackClipRects = NULL; 552 } 553 554 UnlockDisplay(dpy); 555 SyncHandle(); 556 TRACE("GetDrawableInfo... return True"); 557 return True; 558} 559 560Bool 561XF86DRIGetDeviceInfo(Display * dpy, int screen, drm_handle_t * hFrameBuffer, 562 int *fbOrigin, int *fbSize, int *fbStride, 563 int *devPrivateSize, void **pDevPrivate) 564{ 565 XExtDisplayInfo *info = find_display(dpy); 566 xXF86DRIGetDeviceInfoReply rep; 567 xXF86DRIGetDeviceInfoReq *req; 568 569 TRACE("GetDeviceInfo..."); 570 XF86DRICheckExtension(dpy, info, False); 571 572 LockDisplay(dpy); 573 GetReq(XF86DRIGetDeviceInfo, req); 574 req->reqType = info->codes->major_opcode; 575 req->driReqType = X_XF86DRIGetDeviceInfo; 576 req->screen = screen; 577 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 578 UnlockDisplay(dpy); 579 SyncHandle(); 580 TRACE("GetDeviceInfo... return False"); 581 return False; 582 } 583 584 *hFrameBuffer = rep.hFrameBufferLow; 585 if (sizeof(drm_handle_t) == 8) { 586 int shift = 32; /* var to prevent warning on next line */ 587 *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift; 588 } 589 590 *fbOrigin = rep.framebufferOrigin; 591 *fbSize = rep.framebufferSize; 592 *fbStride = rep.framebufferStride; 593 *devPrivateSize = rep.devPrivateSize; 594 595 if (rep.length) { 596 if (!(*pDevPrivate = (void *) Xcalloc(rep.devPrivateSize, 1))) { 597 _XEatData(dpy, ((rep.devPrivateSize + 3) & ~3)); 598 UnlockDisplay(dpy); 599 SyncHandle(); 600 TRACE("GetDeviceInfo... return False"); 601 return False; 602 } 603 _XRead(dpy, (char *) *pDevPrivate, rep.devPrivateSize); 604 } 605 else { 606 *pDevPrivate = NULL; 607 } 608 609 UnlockDisplay(dpy); 610 SyncHandle(); 611 TRACE("GetDeviceInfo... return True"); 612 return True; 613} 614 615Bool 616XF86DRIOpenFullScreen(Display * dpy, int screen, Drawable drawable) 617{ 618 /* This function and the underlying X protocol are deprecated. 619 */ 620 (void) dpy; 621 (void) screen; 622 (void) drawable; 623 return False; 624} 625 626Bool 627XF86DRICloseFullScreen(Display * dpy, int screen, Drawable drawable) 628{ 629 /* This function and the underlying X protocol are deprecated. 630 */ 631 (void) dpy; 632 (void) screen; 633 (void) drawable; 634 return True; 635} 636 637#endif /* GLX_DIRECT_RENDERING */ 638