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