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/* THIS IS NOT AN X CONSORTIUM STANDARD */ 39 40#define NEED_REPLIES 41#include <X11/Xlibint.h> 42#include <X11/extensions/Xext.h> 43#include <X11/extensions/extutil.h> 44#include "xf86dristr.h" 45#include <limits.h> 46 47static XExtensionInfo _xf86dri_info_data; 48static XExtensionInfo *xf86dri_info = &_xf86dri_info_data; 49static char xf86dri_extension_name[] = XF86DRINAME; 50 51#define uniDRICheckExtension(dpy,i,val) \ 52 XextCheckExtension (dpy, i, xf86dri_extension_name, val) 53 54/***************************************************************************** 55 * * 56 * private utility routines * 57 * * 58 *****************************************************************************/ 59 60static int close_display(Display * dpy, XExtCodes * extCodes); 61static /* 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 75static 76XEXT_GENERATE_FIND_DISPLAY(find_display, xf86dri_info, 77 xf86dri_extension_name, &xf86dri_extension_hooks, 0, NULL) 78 79 static XEXT_GENERATE_CLOSE_DISPLAY(close_display, xf86dri_info) 80 81/***************************************************************************** 82 * * 83 * public XFree86-DRI Extension routines * 84 * * 85 *****************************************************************************/ 86#if 0 87#include <stdio.h> 88#define TRACE(msg) fprintf(stderr,"uniDRI%s\n", msg); 89#else 90#define TRACE(msg) 91#endif 92 Bool uniDRIQueryExtension(dpy, event_basep, error_basep) 93 Display *dpy; 94 int *event_basep, *error_basep; 95{ 96 XExtDisplayInfo *info = find_display(dpy); 97 98 TRACE("QueryExtension..."); 99 if (XextHasExtension(info)) { 100 *event_basep = info->codes->first_event; 101 *error_basep = info->codes->first_error; 102 TRACE("QueryExtension... return True"); 103 return True; 104 } else { 105 TRACE("QueryExtension... return False"); 106 return False; 107 } 108} 109 110Bool 111uniDRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion) 112 Display *dpy; 113 int *majorVersion; 114 int *minorVersion; 115 int *patchVersion; 116{ 117 XExtDisplayInfo *info = find_display(dpy); 118 xXF86DRIQueryVersionReply rep; 119 xXF86DRIQueryVersionReq *req; 120 121 TRACE("QueryVersion..."); 122 uniDRICheckExtension(dpy, info, False); 123 124 LockDisplay(dpy); 125 GetReq(XF86DRIQueryVersion, req); 126 req->reqType = info->codes->major_opcode; 127 req->driReqType = X_XF86DRIQueryVersion; 128 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 129 UnlockDisplay(dpy); 130 SyncHandle(); 131 TRACE("QueryVersion... return False"); 132 return False; 133 } 134 *majorVersion = rep.majorVersion; 135 *minorVersion = rep.minorVersion; 136 *patchVersion = rep.patchVersion; 137 UnlockDisplay(dpy); 138 SyncHandle(); 139 TRACE("QueryVersion... return True"); 140 return True; 141} 142 143Bool 144uniDRIQueryDirectRenderingCapable(dpy, screen, isCapable) 145 Display *dpy; 146 int screen; 147 Bool *isCapable; 148{ 149 XExtDisplayInfo *info = find_display(dpy); 150 xXF86DRIQueryDirectRenderingCapableReply rep; 151 xXF86DRIQueryDirectRenderingCapableReq *req; 152 153 TRACE("QueryDirectRenderingCapable..."); 154 uniDRICheckExtension(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 174Bool 175uniDRIOpenConnection(dpy, screen, hSAREA, busIdString) 176 Display *dpy; 177 int screen; 178 drm_handle_t *hSAREA; 179 char **busIdString; 180{ 181 XExtDisplayInfo *info = find_display(dpy); 182 xXF86DRIOpenConnectionReply rep; 183 xXF86DRIOpenConnectionReq *req; 184 185 TRACE("OpenConnection..."); 186 uniDRICheckExtension(dpy, info, False); 187 188 LockDisplay(dpy); 189 GetReq(XF86DRIOpenConnection, req); 190 req->reqType = info->codes->major_opcode; 191 req->driReqType = X_XF86DRIOpenConnection; 192 req->screen = screen; 193 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 194 UnlockDisplay(dpy); 195 SyncHandle(); 196 TRACE("OpenConnection... return False"); 197 return False; 198 } 199 200 *hSAREA = rep.hSAREALow; 201#ifdef LONG64 202 if (sizeof(drm_handle_t) == 8) { 203 *hSAREA |= ((unsigned long)rep.hSAREAHigh) << 32; 204 } 205#endif 206 if (rep.length) { 207 if (rep.busIdStringLength < INT_MAX) 208 *busIdString = Xcalloc(rep.busIdStringLength + 1, 1); 209 else 210 *busIdString = NULL; 211 if (*busIdString == NULL) { 212 _XEatData(dpy, ((rep.busIdStringLength + 3) & ~3)); 213 UnlockDisplay(dpy); 214 SyncHandle(); 215 TRACE("OpenConnection... return False"); 216 return False; 217 } 218 _XReadPad(dpy, *busIdString, rep.busIdStringLength); 219 } else { 220 *busIdString = NULL; 221 } 222 UnlockDisplay(dpy); 223 SyncHandle(); 224 TRACE("OpenConnection... return True"); 225 return True; 226} 227 228Bool 229uniDRIAuthConnection(dpy, screen, magic) 230 Display *dpy; 231 int screen; 232 drm_magic_t magic; 233{ 234 XExtDisplayInfo *info = find_display(dpy); 235 xXF86DRIAuthConnectionReq *req; 236 xXF86DRIAuthConnectionReply rep; 237 238 TRACE("AuthConnection..."); 239 uniDRICheckExtension(dpy, info, False); 240 241 LockDisplay(dpy); 242 GetReq(XF86DRIAuthConnection, req); 243 req->reqType = info->codes->major_opcode; 244 req->driReqType = X_XF86DRIAuthConnection; 245 req->screen = screen; 246 req->magic = magic; 247 rep.authenticated = 0; 248 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse) || !rep.authenticated) { 249 UnlockDisplay(dpy); 250 SyncHandle(); 251 TRACE("AuthConnection... return False"); 252 return False; 253 } 254 UnlockDisplay(dpy); 255 SyncHandle(); 256 TRACE("AuthConnection... return True"); 257 return True; 258} 259 260Bool 261uniDRICloseConnection(dpy, screen) 262 Display *dpy; 263 int screen; 264{ 265 XExtDisplayInfo *info = find_display(dpy); 266 xXF86DRICloseConnectionReq *req; 267 268 TRACE("CloseConnection..."); 269 270 uniDRICheckExtension(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 284uniDRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion, 285 ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName) 286 Display *dpy; 287 int screen; 288 int *ddxDriverMajorVersion; 289 int *ddxDriverMinorVersion; 290 int *ddxDriverPatchVersion; 291 char **clientDriverName; 292{ 293 XExtDisplayInfo *info = find_display(dpy); 294 xXF86DRIGetClientDriverNameReply rep; 295 xXF86DRIGetClientDriverNameReq *req; 296 297 TRACE("GetClientDriverName..."); 298 uniDRICheckExtension(dpy, info, False); 299 300 LockDisplay(dpy); 301 GetReq(XF86DRIGetClientDriverName, req); 302 req->reqType = info->codes->major_opcode; 303 req->driReqType = X_XF86DRIGetClientDriverName; 304 req->screen = screen; 305 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 306 UnlockDisplay(dpy); 307 SyncHandle(); 308 TRACE("GetClientDriverName... return False"); 309 return False; 310 } 311 312 *ddxDriverMajorVersion = rep.ddxDriverMajorVersion; 313 *ddxDriverMinorVersion = rep.ddxDriverMinorVersion; 314 *ddxDriverPatchVersion = rep.ddxDriverPatchVersion; 315 316 if (rep.length) { 317 if (rep.clientDriverNameLength < INT_MAX) 318 *clientDriverName = Xcalloc(rep.clientDriverNameLength + 1, 1); 319 else 320 *clientDriverName = NULL; 321 if (*clientDriverName == NULL) { 322 _XEatData(dpy, ((rep.clientDriverNameLength + 3) & ~3)); 323 UnlockDisplay(dpy); 324 SyncHandle(); 325 TRACE("GetClientDriverName... return False"); 326 return False; 327 } 328 _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength); 329 } else { 330 *clientDriverName = NULL; 331 } 332 UnlockDisplay(dpy); 333 SyncHandle(); 334 TRACE("GetClientDriverName... return True"); 335 return True; 336} 337 338Bool 339uniDRICreateContextWithConfig(dpy, screen, configID, context, hHWContext) 340 Display *dpy; 341 int screen; 342 int configID; 343 XID *context; 344 drm_context_t *hHWContext; 345{ 346 XExtDisplayInfo *info = find_display(dpy); 347 xXF86DRICreateContextReply rep; 348 xXF86DRICreateContextReq *req; 349 350 TRACE("CreateContext..."); 351 uniDRICheckExtension(dpy, info, False); 352 353 LockDisplay(dpy); 354 GetReq(XF86DRICreateContext, req); 355 req->reqType = info->codes->major_opcode; 356 req->driReqType = X_XF86DRICreateContext; 357 req->visual = configID; 358 req->screen = screen; 359 *context = XAllocID(dpy); 360 req->context = *context; 361 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 362 UnlockDisplay(dpy); 363 SyncHandle(); 364 TRACE("CreateContext... return False"); 365 return False; 366 } 367 *hHWContext = rep.hHWContext; 368 UnlockDisplay(dpy); 369 SyncHandle(); 370 TRACE("CreateContext... return True"); 371 return True; 372} 373 374Bool 375uniDRICreateContext(dpy, screen, visual, context, hHWContext) 376 Display *dpy; 377 int screen; 378 Visual *visual; 379 XID *context; 380 drm_context_t *hHWContext; 381{ 382 return uniDRICreateContextWithConfig(dpy, screen, visual->visualid, 383 context, hHWContext); 384} 385 386Bool 387uniDRIDestroyContext(Display * ndpy, int screen, XID context) 388{ 389 Display *const dpy = (Display *) ndpy; 390 XExtDisplayInfo *info = find_display(dpy); 391 xXF86DRIDestroyContextReq *req; 392 393 TRACE("DestroyContext..."); 394 uniDRICheckExtension(dpy, info, False); 395 396 LockDisplay(dpy); 397 GetReq(XF86DRIDestroyContext, req); 398 req->reqType = info->codes->major_opcode; 399 req->driReqType = X_XF86DRIDestroyContext; 400 req->screen = screen; 401 req->context = context; 402 UnlockDisplay(dpy); 403 SyncHandle(); 404 TRACE("DestroyContext... return True"); 405 return True; 406} 407 408Bool 409uniDRICreateDrawable(Display * ndpy, int screen, 410 Drawable drawable, drm_drawable_t * hHWDrawable) 411{ 412 Display *const dpy = (Display *) ndpy; 413 XExtDisplayInfo *info = find_display(dpy); 414 xXF86DRICreateDrawableReply rep; 415 xXF86DRICreateDrawableReq *req; 416 417 TRACE("CreateDrawable..."); 418 uniDRICheckExtension(dpy, info, False); 419 420 LockDisplay(dpy); 421 GetReq(XF86DRICreateDrawable, req); 422 req->reqType = info->codes->major_opcode; 423 req->driReqType = X_XF86DRICreateDrawable; 424 req->screen = screen; 425 req->drawable = drawable; 426 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 427 UnlockDisplay(dpy); 428 SyncHandle(); 429 TRACE("CreateDrawable... return False"); 430 return False; 431 } 432 *hHWDrawable = rep.hHWDrawable; 433 UnlockDisplay(dpy); 434 SyncHandle(); 435 TRACE("CreateDrawable... return True"); 436 return True; 437} 438 439Bool 440uniDRIDestroyDrawable(Display * ndpy, int screen, Drawable drawable) 441{ 442 Display *const dpy = (Display *) ndpy; 443 XExtDisplayInfo *info = find_display(dpy); 444 xXF86DRIDestroyDrawableReq *req; 445 446 TRACE("DestroyDrawable..."); 447 uniDRICheckExtension(dpy, info, False); 448 449 LockDisplay(dpy); 450 GetReq(XF86DRIDestroyDrawable, req); 451 req->reqType = info->codes->major_opcode; 452 req->driReqType = X_XF86DRIDestroyDrawable; 453 req->screen = screen; 454 req->drawable = drawable; 455 UnlockDisplay(dpy); 456 SyncHandle(); 457 TRACE("DestroyDrawable... return True"); 458 return True; 459} 460 461Bool 462uniDRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable, 463 unsigned int *index, unsigned int *stamp, 464 int *X, int *Y, int *W, int *H, 465 int *numClipRects, drm_clip_rect_t ** pClipRects, 466 int *backX, int *backY, 467 int *numBackClipRects, 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 uniDRICheckExtension(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 } else { 528 *pClipRects = NULL; 529 } 530 531 if (*numBackClipRects) { 532 int len = sizeof(drm_clip_rect_t) * (*numBackClipRects); 533 534 *pBackClipRects = (drm_clip_rect_t *) Xcalloc(len, 1); 535 if (*pBackClipRects) 536 _XRead(dpy, (char *)*pBackClipRects, len); 537 } else { 538 *pBackClipRects = NULL; 539 } 540 541 UnlockDisplay(dpy); 542 SyncHandle(); 543 TRACE("GetDrawableInfo... return True"); 544 return True; 545} 546 547Bool 548uniDRIGetDeviceInfo(dpy, screen, hFrameBuffer, 549 fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate) 550 Display *dpy; 551 int screen; 552 drm_handle_t *hFrameBuffer; 553 int *fbOrigin; 554 int *fbSize; 555 int *fbStride; 556 int *devPrivateSize; 557 void **pDevPrivate; 558{ 559 XExtDisplayInfo *info = find_display(dpy); 560 xXF86DRIGetDeviceInfoReply rep; 561 xXF86DRIGetDeviceInfoReq *req; 562 563 TRACE("GetDeviceInfo..."); 564 uniDRICheckExtension(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#ifdef LONG64 580 if (sizeof(drm_handle_t) == 8) { 581 *hFrameBuffer |= ((unsigned long)rep.hFrameBufferHigh) << 32; 582 } 583#endif 584 585 *fbOrigin = rep.framebufferOrigin; 586 *fbSize = rep.framebufferSize; 587 *fbStride = rep.framebufferStride; 588 *devPrivateSize = rep.devPrivateSize; 589 590 if (rep.length) { 591 if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) { 592 _XEatData(dpy, ((rep.devPrivateSize + 3) & ~3)); 593 UnlockDisplay(dpy); 594 SyncHandle(); 595 TRACE("GetDeviceInfo... return False"); 596 return False; 597 } 598 _XRead(dpy, (char *)*pDevPrivate, rep.devPrivateSize); 599 } else { 600 *pDevPrivate = NULL; 601 } 602 603 UnlockDisplay(dpy); 604 SyncHandle(); 605 TRACE("GetDeviceInfo... return True"); 606 return True; 607} 608