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