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