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