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#ifdef HAVE_CONFIG_H 41#include "config.h" 42#endif 43 44#define NEED_REPLIES 45#include <X11/Xlibint.h> 46#include <X11/extensions/Xext.h> 47#include <X11/extensions/extutil.h> 48#include <stdint.h> 49#include "xf86dristr.h" 50 51static XExtensionInfo _xf86dri_info_data; 52static XExtensionInfo *xf86dri_info = &_xf86dri_info_data; 53static char xf86dri_extension_name[] = XF86DRINAME; 54 55#define uniDRICheckExtension(dpy,i,val) \ 56 XextCheckExtension (dpy, i, xf86dri_extension_name, val) 57 58/***************************************************************************** 59 * * 60 * private utility routines * 61 * * 62 *****************************************************************************/ 63 64static int close_display(Display * dpy, XExtCodes * extCodes); 65static /* const */ XExtensionHooks xf86dri_extension_hooks = { 66 NULL, /* create_gc */ 67 NULL, /* copy_gc */ 68 NULL, /* flush_gc */ 69 NULL, /* free_gc */ 70 NULL, /* create_font */ 71 NULL, /* free_font */ 72 close_display, /* close_display */ 73 NULL, /* wire_to_event */ 74 NULL, /* event_to_wire */ 75 NULL, /* error */ 76 NULL, /* error_string */ 77}; 78 79static 80XEXT_GENERATE_FIND_DISPLAY(find_display, xf86dri_info, 81 xf86dri_extension_name, &xf86dri_extension_hooks, 0, NULL) 82 83 static XEXT_GENERATE_CLOSE_DISPLAY(close_display, xf86dri_info) 84 85/***************************************************************************** 86 * * 87 * public XFree86-DRI Extension routines * 88 * * 89 *****************************************************************************/ 90#if 0 91#include <stdio.h> 92#define TRACE(msg) fprintf(stderr,"uniDRI%s\n", msg); 93#else 94#define TRACE(msg) 95#endif 96 Bool uniDRIQueryExtension(dpy, event_basep, error_basep) 97 Display *dpy; 98 int *event_basep, *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 } else { 109 TRACE("QueryExtension... return False"); 110 return False; 111 } 112} 113 114Bool 115uniDRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion) 116 Display *dpy; 117 int *majorVersion; 118 int *minorVersion; 119 int *patchVersion; 120{ 121 XExtDisplayInfo *info = find_display(dpy); 122 xXF86DRIQueryVersionReply rep; 123 xXF86DRIQueryVersionReq *req; 124 125 TRACE("QueryVersion..."); 126 uniDRICheckExtension(dpy, info, False); 127 128 LockDisplay(dpy); 129 GetReq(XF86DRIQueryVersion, req); 130 req->reqType = info->codes->major_opcode; 131 req->driReqType = X_XF86DRIQueryVersion; 132 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 133 UnlockDisplay(dpy); 134 SyncHandle(); 135 TRACE("QueryVersion... return False"); 136 return False; 137 } 138 *majorVersion = rep.majorVersion; 139 *minorVersion = rep.minorVersion; 140 *patchVersion = rep.patchVersion; 141 UnlockDisplay(dpy); 142 SyncHandle(); 143 TRACE("QueryVersion... return True"); 144 return True; 145} 146 147Bool 148uniDRIQueryDirectRenderingCapable(dpy, screen, isCapable) 149 Display *dpy; 150 int screen; 151 Bool *isCapable; 152{ 153 XExtDisplayInfo *info = find_display(dpy); 154 xXF86DRIQueryDirectRenderingCapableReply rep; 155 xXF86DRIQueryDirectRenderingCapableReq *req; 156 157 TRACE("QueryDirectRenderingCapable..."); 158 uniDRICheckExtension(dpy, info, False); 159 160 LockDisplay(dpy); 161 GetReq(XF86DRIQueryDirectRenderingCapable, req); 162 req->reqType = info->codes->major_opcode; 163 req->driReqType = X_XF86DRIQueryDirectRenderingCapable; 164 req->screen = screen; 165 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 166 UnlockDisplay(dpy); 167 SyncHandle(); 168 TRACE("QueryDirectRenderingCapable... return False"); 169 return False; 170 } 171 *isCapable = rep.isCapable; 172 UnlockDisplay(dpy); 173 SyncHandle(); 174 TRACE("QueryDirectRenderingCapable... return True"); 175 return True; 176} 177 178Bool 179uniDRIOpenConnection(dpy, screen, hSAREA, busIdString) 180 Display *dpy; 181 int screen; 182 drm_handle_t *hSAREA; 183 char **busIdString; 184{ 185 XExtDisplayInfo *info = find_display(dpy); 186 xXF86DRIOpenConnectionReply rep; 187 xXF86DRIOpenConnectionReq *req; 188 189 TRACE("OpenConnection..."); 190 uniDRICheckExtension(dpy, info, False); 191 192 LockDisplay(dpy); 193 GetReq(XF86DRIOpenConnection, req); 194 req->reqType = info->codes->major_opcode; 195 req->driReqType = X_XF86DRIOpenConnection; 196 req->screen = screen; 197 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 198 UnlockDisplay(dpy); 199 SyncHandle(); 200 TRACE("OpenConnection... return False"); 201 return False; 202 } 203 204 *hSAREA = rep.hSAREALow; 205#ifdef LONG64 206 if (sizeof(drm_handle_t) == 8) { 207 *hSAREA |= ((unsigned long)rep.hSAREAHigh) << 32; 208 } 209#endif 210 if (rep.length) { 211 if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) { 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 (!(*clientDriverName = 318 (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) { 319 _XEatData(dpy, ((rep.clientDriverNameLength + 3) & ~3)); 320 UnlockDisplay(dpy); 321 SyncHandle(); 322 TRACE("GetClientDriverName... return False"); 323 return False; 324 } 325 _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength); 326 } else { 327 *clientDriverName = NULL; 328 } 329 UnlockDisplay(dpy); 330 SyncHandle(); 331 TRACE("GetClientDriverName... return True"); 332 return True; 333} 334 335Bool 336uniDRICreateContextWithConfig(dpy, screen, configID, context, hHWContext) 337 Display *dpy; 338 int screen; 339 int configID; 340 XID *context; 341 drm_context_t *hHWContext; 342{ 343 XExtDisplayInfo *info = find_display(dpy); 344 xXF86DRICreateContextReply rep; 345 xXF86DRICreateContextReq *req; 346 347 TRACE("CreateContext..."); 348 uniDRICheckExtension(dpy, info, False); 349 350 LockDisplay(dpy); 351 GetReq(XF86DRICreateContext, req); 352 req->reqType = info->codes->major_opcode; 353 req->driReqType = X_XF86DRICreateContext; 354 req->visual = configID; 355 req->screen = screen; 356 *context = XAllocID(dpy); 357 req->context = *context; 358 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 359 UnlockDisplay(dpy); 360 SyncHandle(); 361 TRACE("CreateContext... return False"); 362 return False; 363 } 364 *hHWContext = rep.hHWContext; 365 UnlockDisplay(dpy); 366 SyncHandle(); 367 TRACE("CreateContext... return True"); 368 return True; 369} 370 371Bool 372uniDRICreateContext(dpy, screen, visual, context, hHWContext) 373 Display *dpy; 374 int screen; 375 Visual *visual; 376 XID *context; 377 drm_context_t *hHWContext; 378{ 379 return uniDRICreateContextWithConfig(dpy, screen, visual->visualid, 380 context, hHWContext); 381} 382 383Bool 384uniDRIDestroyContext(Display * ndpy, int screen, XID context) 385{ 386 Display *const dpy = (Display *) ndpy; 387 XExtDisplayInfo *info = find_display(dpy); 388 xXF86DRIDestroyContextReq *req; 389 390 TRACE("DestroyContext..."); 391 uniDRICheckExtension(dpy, info, False); 392 393 LockDisplay(dpy); 394 GetReq(XF86DRIDestroyContext, req); 395 req->reqType = info->codes->major_opcode; 396 req->driReqType = X_XF86DRIDestroyContext; 397 req->screen = screen; 398 req->context = context; 399 UnlockDisplay(dpy); 400 SyncHandle(); 401 TRACE("DestroyContext... return True"); 402 return True; 403} 404 405Bool 406uniDRICreateDrawable(Display * ndpy, int screen, 407 Drawable drawable, drm_drawable_t * hHWDrawable) 408{ 409 Display *const dpy = (Display *) ndpy; 410 XExtDisplayInfo *info = find_display(dpy); 411 xXF86DRICreateDrawableReply rep; 412 xXF86DRICreateDrawableReq *req; 413 414 TRACE("CreateDrawable..."); 415 uniDRICheckExtension(dpy, info, False); 416 417 LockDisplay(dpy); 418 GetReq(XF86DRICreateDrawable, req); 419 req->reqType = info->codes->major_opcode; 420 req->driReqType = X_XF86DRICreateDrawable; 421 req->screen = screen; 422 req->drawable = drawable; 423 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 424 UnlockDisplay(dpy); 425 SyncHandle(); 426 TRACE("CreateDrawable... return False"); 427 return False; 428 } 429 *hHWDrawable = rep.hHWDrawable; 430 UnlockDisplay(dpy); 431 SyncHandle(); 432 TRACE("CreateDrawable... return True"); 433 return True; 434} 435 436Bool 437uniDRIDestroyDrawable(Display * ndpy, int screen, Drawable drawable) 438{ 439 Display *const dpy = (Display *) ndpy; 440 XExtDisplayInfo *info = find_display(dpy); 441 xXF86DRIDestroyDrawableReq *req; 442 443 TRACE("DestroyDrawable..."); 444 uniDRICheckExtension(dpy, info, False); 445 446 LockDisplay(dpy); 447 GetReq(XF86DRIDestroyDrawable, req); 448 req->reqType = info->codes->major_opcode; 449 req->driReqType = X_XF86DRIDestroyDrawable; 450 req->screen = screen; 451 req->drawable = drawable; 452 UnlockDisplay(dpy); 453 SyncHandle(); 454 TRACE("DestroyDrawable... return True"); 455 return True; 456} 457 458Bool 459uniDRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable, 460 unsigned int *index, unsigned int *stamp, 461 int *X, int *Y, int *W, int *H, 462 int *numClipRects, drm_clip_rect_t ** pClipRects, 463 int *backX, int *backY, 464 int *numBackClipRects, drm_clip_rect_t ** pBackClipRects) 465{ 466 XExtDisplayInfo *info = find_display(dpy); 467 xXF86DRIGetDrawableInfoReply rep; 468 xXF86DRIGetDrawableInfoReq *req; 469 int total_rects; 470 471 TRACE("GetDrawableInfo..."); 472 uniDRICheckExtension(dpy, info, False); 473 474 LockDisplay(dpy); 475 GetReq(XF86DRIGetDrawableInfo, req); 476 req->reqType = info->codes->major_opcode; 477 req->driReqType = X_XF86DRIGetDrawableInfo; 478 req->screen = screen; 479 req->drawable = drawable; 480 481 if (!_XReply(dpy, (xReply *) & rep, 1, xFalse)) { 482 UnlockDisplay(dpy); 483 SyncHandle(); 484 TRACE("GetDrawableInfo... return False"); 485 return False; 486 } 487 *index = rep.drawableTableIndex; 488 *stamp = rep.drawableTableStamp; 489 *X = (int)rep.drawableX; 490 *Y = (int)rep.drawableY; 491 *W = (int)rep.drawableWidth; 492 *H = (int)rep.drawableHeight; 493 *numClipRects = rep.numClipRects; 494 total_rects = *numClipRects; 495 496 *backX = rep.backX; 497 *backY = rep.backY; 498 *numBackClipRects = rep.numBackClipRects; 499 total_rects += *numBackClipRects; 500 501#if 0 502 /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks 503 * backwards compatibility (Because of the >> 2 shift) but the fix 504 * enables multi-threaded apps to work. 505 */ 506 if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) - 507 SIZEOF(xGenericReply) + 508 total_rects * sizeof(drm_clip_rect_t)) + 509 3) & ~3) >> 2)) { 510 _XEatData(dpy, rep.length); 511 UnlockDisplay(dpy); 512 SyncHandle(); 513 TRACE("GetDrawableInfo... return False"); 514 return False; 515 } 516#endif 517 518 if (*numClipRects) { 519 int len = sizeof(drm_clip_rect_t) * (*numClipRects); 520 521 *pClipRects = (drm_clip_rect_t *) Xcalloc(len, 1); 522 if (*pClipRects) 523 _XRead(dpy, (char *)*pClipRects, len); 524 } else { 525 *pClipRects = NULL; 526 } 527 528 if (*numBackClipRects) { 529 int len = sizeof(drm_clip_rect_t) * (*numBackClipRects); 530 531 *pBackClipRects = (drm_clip_rect_t *) Xcalloc(len, 1); 532 if (*pBackClipRects) 533 _XRead(dpy, (char *)*pBackClipRects, len); 534 } else { 535 *pBackClipRects = NULL; 536 } 537 538 UnlockDisplay(dpy); 539 SyncHandle(); 540 TRACE("GetDrawableInfo... return True"); 541 return True; 542} 543 544Bool 545uniDRIGetDeviceInfo(dpy, screen, hFrameBuffer, 546 fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate) 547 Display *dpy; 548 int screen; 549 drm_handle_t *hFrameBuffer; 550 int *fbOrigin; 551 int *fbSize; 552 int *fbStride; 553 int *devPrivateSize; 554 void **pDevPrivate; 555{ 556 XExtDisplayInfo *info = find_display(dpy); 557 xXF86DRIGetDeviceInfoReply rep; 558 xXF86DRIGetDeviceInfoReq *req; 559 560 TRACE("GetDeviceInfo..."); 561 uniDRICheckExtension(dpy, info, False); 562 563 LockDisplay(dpy); 564 GetReq(XF86DRIGetDeviceInfo, req); 565 req->reqType = info->codes->major_opcode; 566 req->driReqType = X_XF86DRIGetDeviceInfo; 567 req->screen = screen; 568 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 569 UnlockDisplay(dpy); 570 SyncHandle(); 571 TRACE("GetDeviceInfo... return False"); 572 return False; 573 } 574 575 *hFrameBuffer = rep.hFrameBufferLow; 576#ifdef LONG64 577 if (sizeof(drm_handle_t) == 8) { 578 *hFrameBuffer |= ((unsigned long)rep.hFrameBufferHigh) << 32; 579 } 580#endif 581 582 *fbOrigin = rep.framebufferOrigin; 583 *fbSize = rep.framebufferSize; 584 *fbStride = rep.framebufferStride; 585 *devPrivateSize = rep.devPrivateSize; 586 587 if (rep.length) { 588 if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) { 589 _XEatData(dpy, ((rep.devPrivateSize + 3) & ~3)); 590 UnlockDisplay(dpy); 591 SyncHandle(); 592 TRACE("GetDeviceInfo... return False"); 593 return False; 594 } 595 _XRead(dpy, (char *)*pDevPrivate, rep.devPrivateSize); 596 } else { 597 *pDevPrivate = NULL; 598 } 599 600 UnlockDisplay(dpy); 601 SyncHandle(); 602 TRACE("GetDeviceInfo... return True"); 603 return True; 604} 605