dri.c revision 9ace9065
1/************************************************************************** 2 3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 4Copyright 2000 VA Linux Systems, Inc. 5All Rights Reserved. 6 7Permission is hereby granted, free of charge, to any person obtaining a 8copy of this software and associated documentation files (the 9"Software"), to deal in the Software without restriction, including 10without limitation the rights to use, copy, modify, merge, publish, 11distribute, sub license, and/or sell copies of the Software, and to 12permit persons to whom the Software is furnished to do so, subject to 13the following conditions: 14 15The above copyright notice and this permission notice (including the 16next paragraph) shall be included in all copies or substantial portions 17of the Software. 18 19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 23ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 27**************************************************************************/ 28 29/* 30 * Authors: 31 * Jens Owen <jens@tungstengraphics.com> 32 * Rickard E. (Rik) Faith <faith@valinux.com> 33 * 34 */ 35 36#ifdef HAVE_XORG_CONFIG_H 37#include <xorg-config.h> 38#endif 39 40#include "xf86.h" 41#include <sys/time.h> 42#include <unistd.h> 43#include <string.h> 44#include <stdio.h> 45#include <sys/ioctl.h> 46#include <errno.h> 47 48#include <X11/X.h> 49#include <X11/Xproto.h> 50#include "xf86drm.h" 51#include "misc.h" 52#include "dixstruct.h" 53#include "extnsionst.h" 54#include "colormapst.h" 55#include "cursorstr.h" 56#include "scrnintstr.h" 57#include "windowstr.h" 58#include "servermd.h" 59#define _XF86DRI_SERVER_ 60#include <X11/dri/xf86driproto.h> 61#include "swaprep.h" 62#include "xf86str.h" 63#include "dri.h" 64#include "sarea.h" 65#include "dristruct.h" 66#include "xf86.h" 67#include "xf86drm.h" 68#include "mi.h" 69#include "mipointer.h" 70#include "xf86_OSproc.h" 71#include "inputstr.h" 72#include "xf86VGAarbiter.h" 73 74static int DRIEntPrivIndex = -1; 75static DevPrivateKeyRec DRIScreenPrivKeyRec; 76#define DRIScreenPrivKey (&DRIScreenPrivKeyRec) 77static DevPrivateKeyRec DRIWindowPrivKeyRec; 78#define DRIWindowPrivKey (&DRIWindowPrivKeyRec) 79static unsigned long DRIGeneration = 0; 80static unsigned int DRIDrawableValidationStamp = 0; 81 82static RESTYPE DRIDrawablePrivResType; 83static RESTYPE DRIContextPrivResType; 84static void DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv); 85 86drmServerInfo DRIDRMServerInfo; 87 88 /* Wrapper just like xf86DrvMsg, but 89 without the verbosity level checking. 90 This will make it easy to turn off some 91 messages later, based on verbosity 92 level. */ 93 94/* 95 * Since we're already referencing things from the XFree86 common layer in 96 * this file, we'd might as well just call xf86VDrvMsgVerb, and have 97 * consistent message formatting. The verbosity of these messages can be 98 * easily changed here. 99 */ 100#define DRI_MSG_VERBOSITY 1 101static void 102DRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...) 103{ 104 va_list ap; 105 106 va_start(ap, format); 107 xf86VDrvMsgVerb(scrnIndex, type, DRI_MSG_VERBOSITY, format, ap); 108 va_end(ap); 109} 110 111 112static void 113DRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv) 114{ 115 if (pDRIEntPriv->pLSAREA != NULL) { 116 drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize); 117 pDRIEntPriv->pLSAREA = NULL; 118 } 119 if (pDRIEntPriv->hLSAREA != 0) { 120 drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA); 121 } 122 if (pDRIEntPriv->drmFD >= 0) { 123 drmClose(pDRIEntPriv->drmFD); 124 pDRIEntPriv->drmFD = 0; 125 } 126} 127 128int 129DRIMasterFD(ScrnInfoPtr pScrn) 130{ 131 return DRI_ENT_PRIV(pScrn)->drmFD; 132} 133 134void * 135DRIMasterSareaPointer(ScrnInfoPtr pScrn) 136{ 137 return DRI_ENT_PRIV(pScrn)->pLSAREA; 138} 139 140drm_handle_t 141DRIMasterSareaHandle(ScrnInfoPtr pScrn) 142{ 143 return DRI_ENT_PRIV(pScrn)->hLSAREA; 144} 145 146 147Bool 148DRIOpenDRMMaster(ScrnInfoPtr pScrn, 149 unsigned long sAreaSize, 150 const char *busID, 151 const char *drmDriverName) 152{ 153 drmSetVersion saveSv, sv; 154 Bool drmWasAvailable; 155 DRIEntPrivPtr pDRIEntPriv; 156 DRIEntPrivRec tmp; 157 drmVersionPtr drmlibv; 158 int drmlibmajor, drmlibminor; 159 const char *openBusID; 160 int count; 161 int err; 162 163 if (DRIEntPrivIndex == -1) 164 DRIEntPrivIndex = xf86AllocateEntityPrivateIndex(); 165 166 pDRIEntPriv = DRI_ENT_PRIV(pScrn); 167 168 if (pDRIEntPriv && pDRIEntPriv->drmFD != -1) 169 return TRUE; 170 171 drmWasAvailable = drmAvailable(); 172 173 memset(&tmp, 0, sizeof(tmp)); 174 175 /* Check the DRM lib version. 176 * drmGetLibVersion was not supported in version 1.0, so check for 177 * symbol first to avoid possible crash or hang. 178 */ 179 180 drmlibmajor = 1; 181 drmlibminor = 0; 182 if (xf86LoaderCheckSymbol("drmGetLibVersion")) { 183 drmlibv = drmGetLibVersion(-1); 184 if (drmlibv != NULL) { 185 drmlibmajor = drmlibv->version_major; 186 drmlibminor = drmlibv->version_minor; 187 drmFreeVersion(drmlibv); 188 } 189 } 190 191 /* Check if the libdrm can handle falling back to loading based on name 192 * if a busid string is passed. 193 */ 194 openBusID = (drmlibmajor == 1 && drmlibminor >= 2) ? busID : NULL; 195 196 tmp.drmFD = -1; 197 sv.drm_di_major = 1; 198 sv.drm_di_minor = 1; 199 sv.drm_dd_major = -1; 200 201 saveSv = sv; 202 count = 10; 203 while (count--) { 204 tmp.drmFD = drmOpen(drmDriverName, openBusID); 205 206 if (tmp.drmFD < 0) { 207 DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n"); 208 goto out_err; 209 } 210 211 err = drmSetInterfaceVersion(tmp.drmFD, &sv); 212 213 if (err != -EPERM) 214 break; 215 216 sv = saveSv; 217 drmClose(tmp.drmFD); 218 tmp.drmFD = -1; 219 usleep(100000); 220 } 221 222 if (tmp.drmFD <= 0) { 223 DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n"); 224 goto out_err; 225 } 226 227 if (!drmWasAvailable) { 228 DRIDrvMsg(-1, X_INFO, 229 "[drm] loaded kernel module for \"%s\" driver.\n", 230 drmDriverName); 231 } 232 233 if (err != 0) { 234 sv.drm_di_major = 1; 235 sv.drm_di_minor = 0; 236 } 237 238 DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n", 239 sv.drm_di_major, sv.drm_di_minor); 240 241 if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1) 242 err = 0; 243 else 244 err = drmSetBusid(tmp.drmFD, busID); 245 246 if (err) { 247 DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n"); 248 goto out_err; 249 } 250 251 /* 252 * Create a lock-containing sarea. 253 */ 254 255 if (drmAddMap( tmp.drmFD, 0, sAreaSize, DRM_SHM, 256 DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) { 257 DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n"); 258 tmp.hLSAREA = 0; 259 goto out_err; 260 } 261 262 if (drmMap( tmp.drmFD, tmp.hLSAREA, sAreaSize, 263 (drmAddressPtr)(&tmp.pLSAREA)) < 0) { 264 DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n"); 265 tmp.pLSAREA = NULL; 266 goto out_err; 267 } 268 269 memset(tmp.pLSAREA, 0, sAreaSize); 270 271 /* 272 * Reserved contexts are handled by the first opened screen. 273 */ 274 275 tmp.resOwner = NULL; 276 277 if (!pDRIEntPriv) 278 pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1); 279 280 if (!pDRIEntPriv) { 281 DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for " 282 "DRM device.\n"); 283 goto out_err; 284 } 285 *pDRIEntPriv = tmp; 286 xf86GetEntityPrivate((pScrn)->entityList[0],DRIEntPrivIndex)->ptr = 287 pDRIEntPriv; 288 289 DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n"); 290 return TRUE; 291 292 out_err: 293 294 DRIOpenDRMCleanup(&tmp); 295 return FALSE; 296} 297 298static void 299DRIClipNotifyAllDrawables(ScreenPtr pScreen); 300 301static void 302dri_crtc_notify(ScreenPtr pScreen) 303{ 304 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 305 DRIClipNotifyAllDrawables(pScreen); 306 xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify); 307 xf86_crtc_notify(pScreen); 308 pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, dri_crtc_notify); 309} 310 311Bool 312DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) 313{ 314 DRIScreenPrivPtr pDRIPriv; 315 drm_context_t * reserved; 316 int reserved_count; 317 int i; 318 DRIEntPrivPtr pDRIEntPriv; 319 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 320 DRIContextFlags flags = 0; 321 DRIContextPrivPtr pDRIContextPriv; 322 323 /* If the DRI extension is disabled, do not initialize the DRI */ 324 if (noXFree86DRIExtension) { 325 DRIDrvMsg(pScreen->myNum, X_WARNING, 326 "Direct rendering has been disabled.\n"); 327 return FALSE; 328 } 329 330 if (!xf86VGAarbiterAllowDRI(pScreen)) { 331 DRIDrvMsg(pScreen->myNum, X_WARNING, 332 "Direct rendering is not supported when VGA arb is necessary for the device\n"); 333 return FALSE; 334 } 335 336#ifdef PANORAMIX 337 /* 338 * If Xinerama is on, don't allow DRI to initialise. It won't be usable 339 * anyway. 340 */ 341 if (!noPanoramiXExtension) { 342 DRIDrvMsg(pScreen->myNum, X_WARNING, 343 "Direct rendering is not supported when Xinerama is enabled\n"); 344 return FALSE; 345 } 346#endif 347 348 if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize, 349 pDRIInfo->busIdString, 350 pDRIInfo->drmDriverName)) 351 return FALSE; 352 353 pDRIEntPriv = DRI_ENT_PRIV(pScrn); 354 355 if (DRIGeneration != serverGeneration) 356 DRIGeneration = serverGeneration; 357 358 if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0)) 359 return FALSE; 360 if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0)) 361 return FALSE; 362 363 pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec)); 364 if (!pDRIPriv) { 365 dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 366 return FALSE; 367 } 368 369 dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv); 370 pDRIPriv->drmFD = pDRIEntPriv->drmFD; 371 pDRIPriv->directRenderingSupport = TRUE; 372 pDRIPriv->pDriverInfo = pDRIInfo; 373 pDRIPriv->nrWindows = 0; 374 pDRIPriv->nrWindowsVisible = 0; 375 pDRIPriv->fullscreen = NULL; 376 377 pDRIPriv->createDummyCtx = pDRIInfo->createDummyCtx; 378 pDRIPriv->createDummyCtxPriv = pDRIInfo->createDummyCtxPriv; 379 380 pDRIPriv->grabbedDRILock = FALSE; 381 pDRIPriv->drmSIGIOHandlerInstalled = FALSE; 382 *pDRMFD = pDRIPriv->drmFD; 383 384 if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) { 385 386 if (drmAddMap( pDRIPriv->drmFD, 387 0, 388 pDRIPriv->pDriverInfo->SAREASize, 389 DRM_SHM, 390 0, 391 &pDRIPriv->hSAREA) < 0) 392 { 393 pDRIPriv->directRenderingSupport = FALSE; 394 dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 395 drmClose(pDRIPriv->drmFD); 396 DRIDrvMsg(pScreen->myNum, X_INFO, 397 "[drm] drmAddMap failed\n"); 398 return FALSE; 399 } 400 DRIDrvMsg(pScreen->myNum, X_INFO, 401 "[drm] added %d byte SAREA at %p\n", 402 pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA); 403 404 /* Backwards compat. */ 405 if (drmMap( pDRIPriv->drmFD, 406 pDRIPriv->hSAREA, 407 pDRIPriv->pDriverInfo->SAREASize, 408 (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0) 409 { 410 pDRIPriv->directRenderingSupport = FALSE; 411 dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 412 drmClose(pDRIPriv->drmFD); 413 DRIDrvMsg(pScreen->myNum, X_INFO, 414 "[drm] drmMap failed\n"); 415 return FALSE; 416 } 417 DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n", 418 pDRIPriv->hSAREA, pDRIPriv->pSAREA); 419 memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize); 420 } else { 421 DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock " 422 "SAREA also for drawables.\n"); 423 pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA; 424 pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA; 425 pDRIEntPriv->sAreaGrabbed = TRUE; 426 } 427 428 pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA; 429 pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA; 430 431 if (!pDRIPriv->pDriverInfo->dontMapFrameBuffer) 432 { 433 if (drmAddMap( pDRIPriv->drmFD, 434 (uintptr_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress, 435 pDRIPriv->pDriverInfo->frameBufferSize, 436 DRM_FRAME_BUFFER, 437 0, 438 &pDRIPriv->pDriverInfo->hFrameBuffer) < 0) 439 { 440 pDRIPriv->directRenderingSupport = FALSE; 441 dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 442 drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize); 443 drmClose(pDRIPriv->drmFD); 444 DRIDrvMsg(pScreen->myNum, X_INFO, 445 "[drm] drmAddMap failed\n"); 446 return FALSE; 447 } 448 DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n", 449 pDRIPriv->pDriverInfo->hFrameBuffer); 450 } else { 451 DRIDrvMsg(pScreen->myNum, X_INFO, 452 "[drm] framebuffer mapped by ddx driver\n"); 453 } 454 455 if (pDRIEntPriv->resOwner == NULL) { 456 pDRIEntPriv->resOwner = pScreen; 457 458 /* Add tags for reserved contexts */ 459 if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, 460 &reserved_count))) { 461 int i; 462 void *tag; 463 464 for (i = 0; i < reserved_count; i++) { 465 tag = DRICreateContextPrivFromHandle(pScreen, 466 reserved[i], 467 DRI_CONTEXT_RESERVED); 468 drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag); 469 } 470 drmFreeReservedContextList(reserved); 471 DRIDrvMsg(pScreen->myNum, X_INFO, 472 "[drm] added %d reserved context%s for kernel\n", 473 reserved_count, reserved_count > 1 ? "s" : ""); 474 } 475 } 476 477 /* validate max drawable table entry set by driver */ 478 if ((pDRIPriv->pDriverInfo->maxDrawableTableEntry <= 0) || 479 (pDRIPriv->pDriverInfo->maxDrawableTableEntry > SAREA_MAX_DRAWABLES)) { 480 DRIDrvMsg(pScreen->myNum, X_ERROR, 481 "Invalid max drawable table size set by driver: %d\n", 482 pDRIPriv->pDriverInfo->maxDrawableTableEntry); 483 } 484 485 /* Initialize drawable tables (screen private and SAREA) */ 486 for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { 487 pDRIPriv->DRIDrawables[i] = NULL; 488 pDRIPriv->pSAREA->drawableTable[i].stamp = 0; 489 pDRIPriv->pSAREA->drawableTable[i].flags = 0; 490 } 491 492 pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount; 493 pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext; 494 495 if (!pDRIEntPriv->keepFDOpen) 496 pDRIEntPriv->keepFDOpen = pDRIInfo->keepFDOpen; 497 498 pDRIEntPriv->refCount++; 499 500 /* Set up flags for DRICreateContextPriv */ 501 switch (pDRIInfo->driverSwapMethod) { 502 case DRI_KERNEL_SWAP: 503 flags = DRI_CONTEXT_2DONLY; 504 break; 505 case DRI_HIDE_X_CONTEXT: 506 flags = DRI_CONTEXT_PRESERVED; 507 break; 508 } 509 510 if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, 511 &pDRIPriv->myContext, 512 flags))) { 513 DRIDrvMsg(pScreen->myNum, X_ERROR, 514 "failed to create server context\n"); 515 return FALSE; 516 } 517 pDRIPriv->myContextPriv = pDRIContextPriv; 518 519 DRIDrvMsg(pScreen->myNum, X_INFO, 520 "X context handle = %p\n", pDRIPriv->myContext); 521 522 /* Now that we have created the X server's context, we can grab the 523 * hardware lock for the X server. 524 */ 525 DRILock(pScreen, 0); 526 pDRIPriv->grabbedDRILock = TRUE; 527 528 /* pointers so that we can prevent memory leaks later */ 529 pDRIPriv->hiddenContextStore = NULL; 530 pDRIPriv->partial3DContextStore = NULL; 531 532 switch(pDRIInfo->driverSwapMethod) { 533 case DRI_HIDE_X_CONTEXT: 534 /* Server will handle 3D swaps, and hide 2D swaps from kernel. 535 * Register server context as a preserved context. 536 */ 537 538 /* allocate memory for hidden context store */ 539 pDRIPriv->hiddenContextStore 540 = (void *)calloc(1, pDRIInfo->contextSize); 541 if (!pDRIPriv->hiddenContextStore) { 542 DRIDrvMsg(pScreen->myNum, X_ERROR, 543 "failed to allocate hidden context\n"); 544 DRIDestroyContextPriv(pDRIContextPriv); 545 return FALSE; 546 } 547 548 /* allocate memory for partial 3D context store */ 549 pDRIPriv->partial3DContextStore 550 = (void *)calloc(1, pDRIInfo->contextSize); 551 if (!pDRIPriv->partial3DContextStore) { 552 DRIDrvMsg(pScreen->myNum, X_ERROR, 553 "[DRI] failed to allocate partial 3D context\n"); 554 free(pDRIPriv->hiddenContextStore); 555 DRIDestroyContextPriv(pDRIContextPriv); 556 return FALSE; 557 } 558 559 /* save initial context store */ 560 if (pDRIInfo->SwapContext) { 561 (*pDRIInfo->SwapContext)( 562 pScreen, 563 DRI_NO_SYNC, 564 DRI_2D_CONTEXT, 565 pDRIPriv->hiddenContextStore, 566 DRI_NO_CONTEXT, 567 NULL); 568 } 569 /* fall through */ 570 571 case DRI_SERVER_SWAP: 572 /* For swap methods of DRI_SERVER_SWAP and DRI_HIDE_X_CONTEXT 573 * setup signal handler for receiving swap requests from kernel 574 */ 575 if (!(pDRIPriv->drmSIGIOHandlerInstalled = 576 drmInstallSIGIOHandler(pDRIPriv->drmFD, DRISwapContext))) { 577 DRIDrvMsg(pScreen->myNum, X_ERROR, 578 "[drm] failed to setup DRM signal handler\n"); 579 free(pDRIPriv->hiddenContextStore); 580 free(pDRIPriv->partial3DContextStore); 581 DRIDestroyContextPriv(pDRIContextPriv); 582 return FALSE; 583 } else { 584 DRIDrvMsg(pScreen->myNum, X_INFO, 585 "[drm] installed DRM signal handler\n"); 586 } 587 588 default: 589 break; 590 } 591 592 return TRUE; 593} 594 595Bool 596DRIFinishScreenInit(ScreenPtr pScreen) 597{ 598 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 599 DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 600 601 /* Wrap DRI support */ 602 if (pDRIInfo->wrap.ValidateTree) { 603 pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; 604 pScreen->ValidateTree = pDRIInfo->wrap.ValidateTree; 605 } 606 if (pDRIInfo->wrap.PostValidateTree) { 607 pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; 608 pScreen->PostValidateTree = pDRIInfo->wrap.PostValidateTree; 609 } 610 if (pDRIInfo->wrap.WindowExposures) { 611 pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; 612 pScreen->WindowExposures = pDRIInfo->wrap.WindowExposures; 613 } 614 615 pDRIPriv->DestroyWindow = pScreen->DestroyWindow; 616 pScreen->DestroyWindow = DRIDestroyWindow; 617 618 pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, 619 dri_crtc_notify); 620 621 if (pDRIInfo->wrap.CopyWindow) { 622 pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; 623 pScreen->CopyWindow = pDRIInfo->wrap.CopyWindow; 624 } 625 if (pDRIInfo->wrap.ClipNotify) { 626 pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; 627 pScreen->ClipNotify = pDRIInfo->wrap.ClipNotify; 628 } 629 if (pDRIInfo->wrap.AdjustFrame) { 630 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 631 pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; 632 pScrn->AdjustFrame = pDRIInfo->wrap.AdjustFrame; 633 } 634 pDRIPriv->wrapped = TRUE; 635 636 DRIDrvMsg(pScreen->myNum, X_INFO, "[DRI] installation complete\n"); 637 638 return TRUE; 639} 640 641void 642DRICloseScreen(ScreenPtr pScreen) 643{ 644 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 645 DRIInfoPtr pDRIInfo; 646 drm_context_t * reserved; 647 int reserved_count; 648 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 649 DRIEntPrivPtr pDRIEntPriv = DRI_ENT_PRIV(pScrn); 650 Bool closeMaster; 651 652 if (pDRIPriv) { 653 654 pDRIInfo = pDRIPriv->pDriverInfo; 655 656 if (pDRIPriv->wrapped) { 657 /* Unwrap DRI Functions */ 658 if (pDRIInfo->wrap.ValidateTree) { 659 pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; 660 pDRIPriv->wrap.ValidateTree = NULL; 661 } 662 if (pDRIInfo->wrap.PostValidateTree) { 663 pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; 664 pDRIPriv->wrap.PostValidateTree = NULL; 665 } 666 if (pDRIInfo->wrap.WindowExposures) { 667 pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; 668 pDRIPriv->wrap.WindowExposures = NULL; 669 } 670 if (pDRIPriv->DestroyWindow) { 671 pScreen->DestroyWindow = pDRIPriv->DestroyWindow; 672 pDRIPriv->DestroyWindow = NULL; 673 } 674 675 xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify); 676 677 if (pDRIInfo->wrap.CopyWindow) { 678 pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; 679 pDRIPriv->wrap.CopyWindow = NULL; 680 } 681 if (pDRIInfo->wrap.ClipNotify) { 682 pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; 683 pDRIPriv->wrap.ClipNotify = NULL; 684 } 685 if (pDRIInfo->wrap.AdjustFrame) { 686 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 687 pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; 688 pDRIPriv->wrap.AdjustFrame = NULL; 689 } 690 691 pDRIPriv->wrapped = FALSE; 692 } 693 694 if (pDRIPriv->drmSIGIOHandlerInstalled) { 695 if (!drmRemoveSIGIOHandler(pDRIPriv->drmFD)) { 696 DRIDrvMsg(pScreen->myNum, X_ERROR, 697 "[drm] failed to remove DRM signal handler\n"); 698 } 699 } 700 701 if (pDRIPriv->dummyCtxPriv && pDRIPriv->createDummyCtx) { 702 DRIDestroyDummyContext(pScreen, pDRIPriv->createDummyCtxPriv); 703 } 704 705 if (!DRIDestroyContextPriv(pDRIPriv->myContextPriv)) { 706 DRIDrvMsg(pScreen->myNum, X_ERROR, 707 "failed to destroy server context\n"); 708 } 709 710 /* Remove tags for reserved contexts */ 711 if (pDRIEntPriv->resOwner == pScreen) { 712 pDRIEntPriv->resOwner = NULL; 713 714 if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, 715 &reserved_count))) { 716 int i; 717 718 for (i = 0; i < reserved_count; i++) { 719 DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD, 720 reserved[i])); 721 } 722 drmFreeReservedContextList(reserved); 723 DRIDrvMsg(pScreen->myNum, X_INFO, 724 "[drm] removed %d reserved context%s for kernel\n", 725 reserved_count, reserved_count > 1 ? "s" : ""); 726 } 727 } 728 729 /* Make sure signals get unblocked etc. */ 730 drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext); 731 pDRIPriv->pLockRefCount = NULL; 732 closeMaster = (--pDRIEntPriv->refCount == 0) && 733 !pDRIEntPriv->keepFDOpen; 734 if (closeMaster || pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) { 735 DRIDrvMsg(pScreen->myNum, X_INFO, 736 "[drm] unmapping %d bytes of SAREA %p at %p\n", 737 pDRIInfo->SAREASize, 738 pDRIPriv->hSAREA, 739 pDRIPriv->pSAREA); 740 if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) { 741 DRIDrvMsg(pScreen->myNum, X_ERROR, 742 "[drm] unable to unmap %d bytes" 743 " of SAREA %p at %p\n", 744 pDRIInfo->SAREASize, 745 pDRIPriv->hSAREA, 746 pDRIPriv->pSAREA); 747 } 748 } else { 749 pDRIEntPriv->sAreaGrabbed = FALSE; 750 } 751 752 if (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) { 753 drmClose(pDRIPriv->drmFD); 754 if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) { 755 DRIDrvMsg(pScreen->myNum, X_INFO, 756 "[drm] Closed DRM master.\n"); 757 pDRIEntPriv->drmFD = -1; 758 } 759 } 760 761 free(pDRIPriv); 762 dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 763 } 764} 765 766#define DRM_MSG_VERBOSITY 3 767 768static int dri_drm_debug_print(const char *format, va_list ap) 769{ 770 xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap); 771 return 0; 772} 773 774static void dri_drm_get_perms(gid_t *group, mode_t *mode) 775{ 776 *group = xf86ConfigDRI.group; 777 *mode = xf86ConfigDRI.mode; 778} 779 780drmServerInfo DRIDRMServerInfo = { 781 dri_drm_debug_print, 782 xf86LoadKernelModule, 783 dri_drm_get_perms, 784}; 785 786Bool 787DRIExtensionInit(void) 788{ 789 if (DRIGeneration != serverGeneration) { 790 return FALSE; 791 } 792 793 DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete, 794 "DRIDrawable"); 795 DRIContextPrivResType = CreateNewResourceType(DRIContextPrivDelete, 796 "DRIContext"); 797 798 if (!DRIDrawablePrivResType || !DRIContextPrivResType) 799 return FALSE; 800 801 RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL); 802 803 return TRUE; 804} 805 806void 807DRIReset(void) 808{ 809 /* 810 * This stub routine is called when the X Server recycles, resources 811 * allocated by DRIExtensionInit need to be managed here. 812 * 813 * Currently this routine is a stub because all the interesting resources 814 * are managed via the screen init process. 815 */ 816} 817 818Bool 819DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable) 820{ 821 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 822 823 if (pDRIPriv) 824 *isCapable = pDRIPriv->directRenderingSupport; 825 else 826 *isCapable = FALSE; 827 828 return TRUE; 829} 830 831Bool 832DRIOpenConnection(ScreenPtr pScreen, drm_handle_t * hSAREA, char **busIdString) 833{ 834 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 835 836 *hSAREA = pDRIPriv->hSAREA; 837 *busIdString = pDRIPriv->pDriverInfo->busIdString; 838 839 return TRUE; 840} 841 842Bool 843DRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic) 844{ 845 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 846 847 if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE; 848 return TRUE; 849} 850 851Bool 852DRICloseConnection(ScreenPtr pScreen) 853{ 854 return TRUE; 855} 856 857Bool 858DRIGetClientDriverName(ScreenPtr pScreen, 859 int *ddxDriverMajorVersion, 860 int *ddxDriverMinorVersion, 861 int *ddxDriverPatchVersion, 862 char **clientDriverName) 863{ 864 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 865 866 *ddxDriverMajorVersion = pDRIPriv->pDriverInfo->ddxDriverMajorVersion; 867 *ddxDriverMinorVersion = pDRIPriv->pDriverInfo->ddxDriverMinorVersion; 868 *ddxDriverPatchVersion = pDRIPriv->pDriverInfo->ddxDriverPatchVersion; 869 *clientDriverName = pDRIPriv->pDriverInfo->clientDriverName; 870 871 return TRUE; 872} 873 874/* DRICreateContextPriv and DRICreateContextPrivFromHandle are helper 875 functions that layer on drmCreateContext and drmAddContextTag. 876 877 DRICreateContextPriv always creates a kernel drm_context_t and then calls 878 DRICreateContextPrivFromHandle to create a DRIContextPriv structure for 879 DRI tracking. For the SIGIO handler, the drm_context_t is associated with 880 DRIContextPrivPtr. Any special flags are stored in the DRIContextPriv 881 area and are passed to the kernel (if necessary). 882 883 DRICreateContextPriv returns a pointer to newly allocated 884 DRIContextPriv, and returns the kernel drm_context_t in pHWContext. */ 885 886DRIContextPrivPtr 887DRICreateContextPriv(ScreenPtr pScreen, 888 drm_context_t * pHWContext, 889 DRIContextFlags flags) 890{ 891 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 892 893 if (drmCreateContext(pDRIPriv->drmFD, pHWContext)) { 894 return NULL; 895 } 896 897 return DRICreateContextPrivFromHandle(pScreen, *pHWContext, flags); 898} 899 900DRIContextPrivPtr 901DRICreateContextPrivFromHandle(ScreenPtr pScreen, 902 drm_context_t hHWContext, 903 DRIContextFlags flags) 904{ 905 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 906 DRIContextPrivPtr pDRIContextPriv; 907 int contextPrivSize; 908 909 contextPrivSize = sizeof(DRIContextPrivRec) + 910 pDRIPriv->pDriverInfo->contextSize; 911 if (!(pDRIContextPriv = calloc(1, contextPrivSize))) { 912 return NULL; 913 } 914 pDRIContextPriv->pContextStore = (void *)(pDRIContextPriv + 1); 915 916 drmAddContextTag(pDRIPriv->drmFD, hHWContext, pDRIContextPriv); 917 918 pDRIContextPriv->hwContext = hHWContext; 919 pDRIContextPriv->pScreen = pScreen; 920 pDRIContextPriv->flags = flags; 921 pDRIContextPriv->valid3D = FALSE; 922 923 if (flags & DRI_CONTEXT_2DONLY) { 924 if (drmSetContextFlags(pDRIPriv->drmFD, 925 hHWContext, 926 DRM_CONTEXT_2DONLY)) { 927 DRIDrvMsg(pScreen->myNum, X_ERROR, 928 "[drm] failed to set 2D context flag\n"); 929 DRIDestroyContextPriv(pDRIContextPriv); 930 return NULL; 931 } 932 } 933 if (flags & DRI_CONTEXT_PRESERVED) { 934 if (drmSetContextFlags(pDRIPriv->drmFD, 935 hHWContext, 936 DRM_CONTEXT_PRESERVED)) { 937 DRIDrvMsg(pScreen->myNum, X_ERROR, 938 "[drm] failed to set preserved flag\n"); 939 DRIDestroyContextPriv(pDRIContextPriv); 940 return NULL; 941 } 942 } 943 return pDRIContextPriv; 944} 945 946Bool 947DRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv) 948{ 949 DRIScreenPrivPtr pDRIPriv; 950 951 if (!pDRIContextPriv) return TRUE; 952 953 pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); 954 955 if (!(pDRIContextPriv->flags & DRI_CONTEXT_RESERVED)) { 956 /* Don't delete reserved contexts from 957 kernel area -- the kernel manages its 958 reserved contexts itself. */ 959 if (drmDestroyContext(pDRIPriv->drmFD, pDRIContextPriv->hwContext)) 960 return FALSE; 961 } 962 963 /* Remove the tag last to prevent a race 964 condition where the context has pending 965 buffers. The context can't be re-used 966 while in this thread, but buffers can be 967 dispatched asynchronously. */ 968 drmDelContextTag(pDRIPriv->drmFD, pDRIContextPriv->hwContext); 969 free(pDRIContextPriv); 970 return TRUE; 971} 972 973static Bool 974DRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv) 975{ 976 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 977 DRIContextPrivPtr pDRIContextPriv; 978 void *contextStore; 979 980 if (!(pDRIContextPriv = 981 DRICreateContextPriv(pScreen, 982 &pDRIPriv->pSAREA->dummy_context, 0))) { 983 return FALSE; 984 } 985 986 contextStore = DRIGetContextStore(pDRIContextPriv); 987 if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) { 988 if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, NULL, 989 pDRIPriv->pSAREA->dummy_context, 990 NULL, 991 (DRIContextType)(long)contextStore)) { 992 DRIDestroyContextPriv(pDRIContextPriv); 993 return FALSE; 994 } 995 } 996 997 pDRIPriv->dummyCtxPriv = pDRIContextPriv; 998 return TRUE; 999} 1000 1001static void 1002DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv) 1003{ 1004 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1005 DRIContextPrivPtr pDRIContextPriv = pDRIPriv->dummyCtxPriv; 1006 void *contextStore; 1007 1008 if (!pDRIContextPriv) return; 1009 if (pDRIPriv->pDriverInfo->DestroyContext && hasCtxPriv) { 1010 contextStore = DRIGetContextStore(pDRIContextPriv); 1011 pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, 1012 pDRIContextPriv->hwContext, 1013 (DRIContextType)(long)contextStore); 1014 } 1015 1016 DRIDestroyContextPriv(pDRIPriv->dummyCtxPriv); 1017 pDRIPriv->dummyCtxPriv = NULL; 1018} 1019 1020Bool 1021DRICreateContext(ScreenPtr pScreen, VisualPtr visual, 1022 XID context, drm_context_t * pHWContext) 1023{ 1024 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1025 DRIContextPrivPtr pDRIContextPriv; 1026 void *contextStore; 1027 1028 if (pDRIPriv->createDummyCtx && !pDRIPriv->dummyCtxPriv) { 1029 if (!DRICreateDummyContext(pScreen, pDRIPriv->createDummyCtxPriv)) { 1030 DRIDrvMsg(pScreen->myNum, X_INFO, 1031 "[drm] Could not create dummy context\n"); 1032 return FALSE; 1033 } 1034 } 1035 1036 if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) { 1037 return FALSE; 1038 } 1039 1040 contextStore = DRIGetContextStore(pDRIContextPriv); 1041 if (pDRIPriv->pDriverInfo->CreateContext) { 1042 if (!((*pDRIPriv->pDriverInfo->CreateContext)(pScreen, NULL, 1043 *pHWContext, NULL, 1044 (DRIContextType)(long)contextStore))) { 1045 DRIDestroyContextPriv(pDRIContextPriv); 1046 return FALSE; 1047 } 1048 } 1049 1050 /* track this in case the client dies before cleanup */ 1051 AddResource(context, DRIContextPrivResType, (pointer)pDRIContextPriv); 1052 1053 return TRUE; 1054} 1055 1056Bool 1057DRIDestroyContext(ScreenPtr pScreen, XID context) 1058{ 1059 FreeResourceByType(context, DRIContextPrivResType, FALSE); 1060 1061 return TRUE; 1062} 1063 1064/* DRIContextPrivDelete is called by the resource manager. */ 1065Bool 1066DRIContextPrivDelete(pointer pResource, XID id) 1067{ 1068 DRIContextPrivPtr pDRIContextPriv = (DRIContextPrivPtr)pResource; 1069 DRIScreenPrivPtr pDRIPriv; 1070 void *contextStore; 1071 1072 pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); 1073 if (pDRIPriv->pDriverInfo->DestroyContext) { 1074 contextStore = DRIGetContextStore(pDRIContextPriv); 1075 pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, 1076 pDRIContextPriv->hwContext, 1077 (DRIContextType)(long)contextStore); 1078 } 1079 return DRIDestroyContextPriv(pDRIContextPriv); 1080} 1081 1082 1083/* This walks the drawable timestamp array and invalidates all of them 1084 * in the case of transition from private to shared backbuffers. It's 1085 * not necessary for correctness, because DRIClipNotify gets called in 1086 * time to prevent any conflict, but the transition from 1087 * shared->private is sometimes missed if we don't do this. 1088 */ 1089static void 1090DRIClipNotifyAllDrawables(ScreenPtr pScreen) 1091{ 1092 int i; 1093 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1094 1095 for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { 1096 pDRIPriv->pSAREA->drawableTable[i].stamp = DRIDrawableValidationStamp++; 1097 } 1098} 1099 1100 1101static void 1102DRITransitionToSharedBuffers(ScreenPtr pScreen) 1103{ 1104 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1105 DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 1106 1107 DRIClipNotifyAllDrawables( pScreen ); 1108 1109 if (pDRIInfo->TransitionSingleToMulti3D) 1110 pDRIInfo->TransitionSingleToMulti3D( pScreen ); 1111} 1112 1113 1114static void 1115DRITransitionToPrivateBuffers(ScreenPtr pScreen) 1116{ 1117 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1118 DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 1119 1120 DRIClipNotifyAllDrawables( pScreen ); 1121 1122 if (pDRIInfo->TransitionMultiToSingle3D) 1123 pDRIInfo->TransitionMultiToSingle3D( pScreen ); 1124} 1125 1126 1127static void 1128DRITransitionTo3d(ScreenPtr pScreen) 1129{ 1130 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1131 DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 1132 1133 DRIClipNotifyAllDrawables( pScreen ); 1134 1135 if (pDRIInfo->TransitionTo3d) 1136 pDRIInfo->TransitionTo3d( pScreen ); 1137} 1138 1139static void 1140DRITransitionTo2d(ScreenPtr pScreen) 1141{ 1142 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1143 DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 1144 1145 DRIClipNotifyAllDrawables( pScreen ); 1146 1147 if (pDRIInfo->TransitionTo2d) 1148 pDRIInfo->TransitionTo2d( pScreen ); 1149} 1150 1151 1152static int 1153DRIDCNTreeTraversal(WindowPtr pWin, pointer data) 1154{ 1155 DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 1156 1157 if (pDRIDrawablePriv) { 1158 ScreenPtr pScreen = pWin->drawable.pScreen; 1159 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1160 1161 if (RegionNumRects(&pWin->clipList) > 0) { 1162 WindowPtr *pDRIWindows = (WindowPtr*)data; 1163 int i = 0; 1164 1165 while (pDRIWindows[i]) 1166 i++; 1167 1168 pDRIWindows[i] = pWin; 1169 1170 pDRIPriv->nrWalked++; 1171 } 1172 1173 if (pDRIPriv->nrWindows == pDRIPriv->nrWalked) 1174 return WT_STOPWALKING; 1175 } 1176 1177 return WT_WALKCHILDREN; 1178} 1179 1180static void 1181DRIDriverClipNotify(ScreenPtr pScreen) 1182{ 1183 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1184 1185 if (pDRIPriv->pDriverInfo->ClipNotify) { 1186 WindowPtr *pDRIWindows = calloc(sizeof(WindowPtr), pDRIPriv->nrWindows); 1187 DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; 1188 1189 if (pDRIPriv->nrWindows > 0) { 1190 pDRIPriv->nrWalked = 0; 1191 TraverseTree(pScreen->root, DRIDCNTreeTraversal, 1192 (pointer)pDRIWindows); 1193 } 1194 1195 pDRIInfo->ClipNotify(pScreen, pDRIWindows, pDRIPriv->nrWindows); 1196 1197 free(pDRIWindows); 1198 } 1199} 1200 1201static void 1202DRIIncreaseNumberVisible(ScreenPtr pScreen) 1203{ 1204 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1205 1206 switch (++pDRIPriv->nrWindowsVisible) { 1207 case 1: 1208 DRITransitionTo3d( pScreen ); 1209 break; 1210 case 2: 1211 DRITransitionToSharedBuffers( pScreen ); 1212 break; 1213 default: 1214 break; 1215 } 1216 1217 DRIDriverClipNotify(pScreen); 1218} 1219 1220static void 1221DRIDecreaseNumberVisible(ScreenPtr pScreen) 1222{ 1223 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1224 1225 switch (--pDRIPriv->nrWindowsVisible) { 1226 case 0: 1227 DRITransitionTo2d( pScreen ); 1228 break; 1229 case 1: 1230 DRITransitionToPrivateBuffers( pScreen ); 1231 break; 1232 default: 1233 break; 1234 } 1235 1236 DRIDriverClipNotify(pScreen); 1237} 1238 1239Bool 1240DRICreateDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable, 1241 drm_drawable_t * hHWDrawable) 1242{ 1243 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1244 DRIDrawablePrivPtr pDRIDrawablePriv; 1245 WindowPtr pWin; 1246 1247 if (pDrawable->type == DRAWABLE_WINDOW) { 1248 pWin = (WindowPtr)pDrawable; 1249 if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { 1250 pDRIDrawablePriv->refCount++; 1251 1252 if (!pDRIDrawablePriv->hwDrawable) { 1253 drmCreateDrawable(pDRIPriv->drmFD, &pDRIDrawablePriv->hwDrawable); 1254 } 1255 } 1256 else { 1257 /* allocate a DRI Window Private record */ 1258 if (!(pDRIDrawablePriv = malloc(sizeof(DRIDrawablePrivRec)))) { 1259 return FALSE; 1260 } 1261 1262 /* Only create a drm_drawable_t once */ 1263 if (drmCreateDrawable(pDRIPriv->drmFD, 1264 &pDRIDrawablePriv->hwDrawable)) { 1265 free(pDRIDrawablePriv); 1266 return FALSE; 1267 } 1268 1269 /* add it to the list of DRI drawables for this screen */ 1270 pDRIDrawablePriv->pScreen = pScreen; 1271 pDRIDrawablePriv->refCount = 1; 1272 pDRIDrawablePriv->drawableIndex = -1; 1273 pDRIDrawablePriv->nrects = RegionNumRects(&pWin->clipList); 1274 1275 /* save private off of preallocated index */ 1276 dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, 1277 pDRIDrawablePriv); 1278 pDRIPriv->nrWindows++; 1279 1280 if (pDRIDrawablePriv->nrects) 1281 DRIIncreaseNumberVisible(pScreen); 1282 } 1283 1284 /* track this in case the client dies */ 1285 AddResource(FakeClientID(client->index), DRIDrawablePrivResType, 1286 (pointer)(intptr_t)pDrawable->id); 1287 1288 if (pDRIDrawablePriv->hwDrawable) { 1289 drmUpdateDrawableInfo(pDRIPriv->drmFD, 1290 pDRIDrawablePriv->hwDrawable, 1291 DRM_DRAWABLE_CLIPRECTS, 1292 RegionNumRects(&pWin->clipList), 1293 RegionRects(&pWin->clipList)); 1294 *hHWDrawable = pDRIDrawablePriv->hwDrawable; 1295 } 1296 } 1297 else if (pDrawable->type != DRAWABLE_PIXMAP) { /* PBuffer */ 1298 /* NOT_DONE */ 1299 return FALSE; 1300 } 1301 1302 return TRUE; 1303} 1304 1305static void 1306DRIDrawablePrivDestroy(WindowPtr pWin) 1307{ 1308 DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 1309 ScreenPtr pScreen; 1310 DRIScreenPrivPtr pDRIPriv; 1311 1312 if (!pDRIDrawablePriv) 1313 return; 1314 1315 pScreen = pWin->drawable.pScreen; 1316 pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1317 1318 if (pDRIDrawablePriv->drawableIndex != -1) { 1319 /* bump stamp to force outstanding 3D requests to resync */ 1320 pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp 1321 = DRIDrawableValidationStamp++; 1322 1323 /* release drawable table entry */ 1324 pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; 1325 } 1326 1327 pDRIPriv->nrWindows--; 1328 1329 if (pDRIDrawablePriv->nrects) 1330 DRIDecreaseNumberVisible(pScreen); 1331 1332 drmDestroyDrawable(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable); 1333 1334 free(pDRIDrawablePriv); 1335 dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); 1336} 1337 1338static Bool 1339DRIDestroyDrawableCB(pointer value, XID id, pointer data) 1340{ 1341 if (value == data) { 1342 /* This calls back DRIDrawablePrivDelete which frees private area */ 1343 FreeResourceByType(id, DRIDrawablePrivResType, FALSE); 1344 1345 return TRUE; 1346 } 1347 1348 return FALSE; 1349} 1350 1351Bool 1352DRIDestroyDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable) 1353{ 1354 if (pDrawable->type == DRAWABLE_WINDOW) { 1355 LookupClientResourceComplex(client, DRIDrawablePrivResType, 1356 DRIDestroyDrawableCB, 1357 (pointer)(intptr_t)pDrawable->id); 1358 } 1359 else { /* pixmap (or for GLX 1.3, a PBuffer) */ 1360 /* NOT_DONE */ 1361 return FALSE; 1362 } 1363 1364 return TRUE; 1365} 1366 1367Bool 1368DRIDrawablePrivDelete(pointer pResource, XID id) 1369{ 1370 WindowPtr pWin; 1371 int rc; 1372 1373 /* For DRIDrawablePrivResType, the XID is the client's fake ID. The 1374 * important XID is the value in pResource. */ 1375 id = (XID)(intptr_t)pResource; 1376 rc = dixLookupWindow(&pWin, id, serverClient, DixGetAttrAccess); 1377 1378 if (rc == Success) { 1379 DRIDrawablePrivPtr pDRIDrwPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 1380 1381 if (!pDRIDrwPriv) 1382 return FALSE; 1383 1384 if (--pDRIDrwPriv->refCount == 0) 1385 DRIDrawablePrivDestroy(pWin); 1386 1387 return TRUE; 1388 } 1389 else { /* pixmap (or for GLX 1.3, a PBuffer) */ 1390 /* NOT_DONE */ 1391 return FALSE; 1392 } 1393} 1394 1395Bool 1396DRIGetDrawableInfo(ScreenPtr pScreen, 1397 DrawablePtr pDrawable, 1398 unsigned int* index, 1399 unsigned int* stamp, 1400 int* X, 1401 int* Y, 1402 int* W, 1403 int* H, 1404 int* numClipRects, 1405 drm_clip_rect_t ** pClipRects, 1406 int* backX, 1407 int* backY, 1408 int* numBackClipRects, 1409 drm_clip_rect_t ** pBackClipRects) 1410{ 1411 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1412 DRIDrawablePrivPtr pDRIDrawablePriv, pOldDrawPriv; 1413 WindowPtr pWin, pOldWin; 1414 int i; 1415 1416#if 0 1417 printf("maxDrawableTableEntry = %d\n", pDRIPriv->pDriverInfo->maxDrawableTableEntry); 1418#endif 1419 1420 if (pDrawable->type == DRAWABLE_WINDOW) { 1421 pWin = (WindowPtr)pDrawable; 1422 if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { 1423 1424 /* Manage drawable table */ 1425 if (pDRIDrawablePriv->drawableIndex == -1) { /* load SAREA table */ 1426 1427 /* Search table for empty entry */ 1428 i = 0; 1429 while (i < pDRIPriv->pDriverInfo->maxDrawableTableEntry) { 1430 if (!(pDRIPriv->DRIDrawables[i])) { 1431 pDRIPriv->DRIDrawables[i] = pDrawable; 1432 pDRIDrawablePriv->drawableIndex = i; 1433 pDRIPriv->pSAREA->drawableTable[i].stamp = 1434 DRIDrawableValidationStamp++; 1435 break; 1436 } 1437 i++; 1438 } 1439 1440 /* Search table for oldest entry */ 1441 if (i == pDRIPriv->pDriverInfo->maxDrawableTableEntry) { 1442 unsigned int oldestStamp = ~0; 1443 int oldestIndex = 0; 1444 i = pDRIPriv->pDriverInfo->maxDrawableTableEntry; 1445 while (i--) { 1446 if (pDRIPriv->pSAREA->drawableTable[i].stamp < 1447 oldestStamp) { 1448 oldestIndex = i; 1449 oldestStamp = 1450 pDRIPriv->pSAREA->drawableTable[i].stamp; 1451 } 1452 } 1453 pDRIDrawablePriv->drawableIndex = oldestIndex; 1454 1455 /* release oldest drawable table entry */ 1456 pOldWin = (WindowPtr)pDRIPriv->DRIDrawables[oldestIndex]; 1457 pOldDrawPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin); 1458 pOldDrawPriv->drawableIndex = -1; 1459 1460 /* claim drawable table entry */ 1461 pDRIPriv->DRIDrawables[oldestIndex] = pDrawable; 1462 1463 /* validate SAREA entry */ 1464 pDRIPriv->pSAREA->drawableTable[oldestIndex].stamp = 1465 DRIDrawableValidationStamp++; 1466 1467 /* check for stamp wrap around */ 1468 if (oldestStamp > DRIDrawableValidationStamp) { 1469 1470 /* walk SAREA table and invalidate all drawables */ 1471 for( i=0; 1472 i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; 1473 i++) { 1474 pDRIPriv->pSAREA->drawableTable[i].stamp = 1475 DRIDrawableValidationStamp++; 1476 } 1477 } 1478 } 1479 1480 /* If the driver wants to be notified when the index is 1481 * set for a drawable, let it know now. 1482 */ 1483 if (pDRIPriv->pDriverInfo->SetDrawableIndex) 1484 pDRIPriv->pDriverInfo->SetDrawableIndex(pWin, 1485 pDRIDrawablePriv->drawableIndex); 1486 1487 /* reinit drawable ID if window is visible */ 1488 if ((pWin->viewable) && 1489 (pDRIPriv->pDriverInfo->bufferRequests != DRI_NO_WINDOWS)) 1490 { 1491 (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, 1492 &pWin->clipList, pDRIDrawablePriv->drawableIndex); 1493 } 1494 } 1495 1496 *index = pDRIDrawablePriv->drawableIndex; 1497 *stamp = pDRIPriv->pSAREA->drawableTable[*index].stamp; 1498 *X = (int)(pWin->drawable.x); 1499 *Y = (int)(pWin->drawable.y); 1500#if 0 1501 *W = (int)(pWin->winSize.extents.x2 - pWin->winSize.extents.x1); 1502 *H = (int)(pWin->winSize.extents.y2 - pWin->winSize.extents.y1); 1503#endif 1504 *W = (int)(pWin->drawable.width); 1505 *H = (int)(pWin->drawable.height); 1506 *numClipRects = RegionNumRects(&pWin->clipList); 1507 *pClipRects = (drm_clip_rect_t *)RegionRects(&pWin->clipList); 1508 1509 if (!*numClipRects && pDRIPriv->fullscreen) { 1510 /* use fake full-screen clip rect */ 1511 pDRIPriv->fullscreen_rect.x1 = *X; 1512 pDRIPriv->fullscreen_rect.y1 = *Y; 1513 pDRIPriv->fullscreen_rect.x2 = *X + *W; 1514 pDRIPriv->fullscreen_rect.y2 = *Y + *H; 1515 1516 *numClipRects = 1; 1517 *pClipRects = &pDRIPriv->fullscreen_rect; 1518 } 1519 1520 *backX = *X; 1521 *backY = *Y; 1522 1523 if (pDRIPriv->nrWindowsVisible == 1 && *numClipRects) { 1524 /* Use a single cliprect. */ 1525 1526 int x0 = *X; 1527 int y0 = *Y; 1528 int x1 = x0 + *W; 1529 int y1 = y0 + *H; 1530 1531 if (x0 < 0) x0 = 0; 1532 if (y0 < 0) y0 = 0; 1533 if (x1 > pScreen->width) x1 = pScreen->width; 1534 if (y1 > pScreen->height) y1 = pScreen->height; 1535 1536 if (y0 >= y1 || x0 >= x1) { 1537 *numBackClipRects = 0; 1538 *pBackClipRects = NULL; 1539 } else { 1540 pDRIPriv->private_buffer_rect.x1 = x0; 1541 pDRIPriv->private_buffer_rect.y1 = y0; 1542 pDRIPriv->private_buffer_rect.x2 = x1; 1543 pDRIPriv->private_buffer_rect.y2 = y1; 1544 1545 *numBackClipRects = 1; 1546 *pBackClipRects = &(pDRIPriv->private_buffer_rect); 1547 } 1548 } else { 1549 /* Use the frontbuffer cliprects for back buffers. */ 1550 *numBackClipRects = 0; 1551 *pBackClipRects = 0; 1552 } 1553 } 1554 else { 1555 /* Not a DRIDrawable */ 1556 return FALSE; 1557 } 1558 } 1559 else { /* pixmap (or for GLX 1.3, a PBuffer) */ 1560 /* NOT_DONE */ 1561 return FALSE; 1562 } 1563 1564 return TRUE; 1565} 1566 1567Bool 1568DRIGetDeviceInfo(ScreenPtr pScreen, 1569 drm_handle_t * hFrameBuffer, 1570 int* fbOrigin, 1571 int* fbSize, 1572 int* fbStride, 1573 int* devPrivateSize, 1574 void** pDevPrivate) 1575{ 1576 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1577 1578 *hFrameBuffer = pDRIPriv->pDriverInfo->hFrameBuffer; 1579 *fbOrigin = 0; 1580 *fbSize = pDRIPriv->pDriverInfo->frameBufferSize; 1581 *fbStride = pDRIPriv->pDriverInfo->frameBufferStride; 1582 *devPrivateSize = pDRIPriv->pDriverInfo->devPrivateSize; 1583 *pDevPrivate = pDRIPriv->pDriverInfo->devPrivate; 1584 1585 return TRUE; 1586} 1587 1588DRIInfoPtr 1589DRICreateInfoRec(void) 1590{ 1591 DRIInfoPtr inforec = (DRIInfoPtr)calloc(1, sizeof(DRIInfoRec)); 1592 if (!inforec) return NULL; 1593 1594 /* Initialize defaults */ 1595 inforec->busIdString = NULL; 1596 1597 /* Wrapped function defaults */ 1598 inforec->wrap.WakeupHandler = DRIDoWakeupHandler; 1599 inforec->wrap.BlockHandler = DRIDoBlockHandler; 1600 inforec->wrap.WindowExposures = DRIWindowExposures; 1601 inforec->wrap.CopyWindow = DRICopyWindow; 1602 inforec->wrap.ValidateTree = DRIValidateTree; 1603 inforec->wrap.PostValidateTree = DRIPostValidateTree; 1604 inforec->wrap.ClipNotify = DRIClipNotify; 1605 inforec->wrap.AdjustFrame = DRIAdjustFrame; 1606 1607 inforec->TransitionTo2d = 0; 1608 inforec->TransitionTo3d = 0; 1609 inforec->SetDrawableIndex = 0; 1610 1611 return inforec; 1612} 1613 1614void 1615DRIDestroyInfoRec(DRIInfoPtr DRIInfo) 1616{ 1617 free(DRIInfo->busIdString); 1618 free((char*)DRIInfo); 1619} 1620 1621 1622void 1623DRIWakeupHandler(pointer wakeupData, int result, pointer pReadmask) 1624{ 1625 int i; 1626 1627 for (i = 0; i < screenInfo.numScreens; i++) { 1628 ScreenPtr pScreen = screenInfo.screens[i]; 1629 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1630 1631 if (pDRIPriv && 1632 pDRIPriv->pDriverInfo->wrap.WakeupHandler) 1633 (*pDRIPriv->pDriverInfo->wrap.WakeupHandler)(i, wakeupData, 1634 result, pReadmask); 1635 } 1636} 1637 1638void 1639DRIBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) 1640{ 1641 int i; 1642 1643 for (i = 0; i < screenInfo.numScreens; i++) { 1644 ScreenPtr pScreen = screenInfo.screens[i]; 1645 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1646 1647 if (pDRIPriv && 1648 pDRIPriv->pDriverInfo->wrap.BlockHandler) 1649 (*pDRIPriv->pDriverInfo->wrap.BlockHandler)(i, blockData, 1650 pTimeout, pReadmask); 1651 } 1652} 1653 1654void 1655DRIDoWakeupHandler(int screenNum, pointer wakeupData, 1656 unsigned long result, pointer pReadmask) 1657{ 1658 ScreenPtr pScreen = screenInfo.screens[screenNum]; 1659 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1660 1661 DRILock(pScreen, 0); 1662 if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 1663 /* hide X context by swapping 2D component here */ 1664 (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, 1665 DRI_3D_SYNC, 1666 DRI_2D_CONTEXT, 1667 pDRIPriv->partial3DContextStore, 1668 DRI_2D_CONTEXT, 1669 pDRIPriv->hiddenContextStore); 1670 } 1671} 1672 1673void 1674DRIDoBlockHandler(int screenNum, pointer blockData, 1675 pointer pTimeout, pointer pReadmask) 1676{ 1677 ScreenPtr pScreen = screenInfo.screens[screenNum]; 1678 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1679 1680 if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 1681 /* hide X context by swapping 2D component here */ 1682 (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, 1683 DRI_2D_SYNC, 1684 DRI_NO_CONTEXT, 1685 NULL, 1686 DRI_2D_CONTEXT, 1687 pDRIPriv->partial3DContextStore); 1688 } 1689 1690 if (pDRIPriv->windowsTouched) 1691 DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1); 1692 pDRIPriv->windowsTouched = FALSE; 1693 1694 DRIUnlock(pScreen); 1695} 1696 1697void 1698DRISwapContext(int drmFD, void *oldctx, void *newctx) 1699{ 1700 DRIContextPrivPtr oldContext = (DRIContextPrivPtr)oldctx; 1701 DRIContextPrivPtr newContext = (DRIContextPrivPtr)newctx; 1702 ScreenPtr pScreen = newContext->pScreen; 1703 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1704 void* oldContextStore = NULL; 1705 DRIContextType oldContextType; 1706 void* newContextStore = NULL; 1707 DRIContextType newContextType; 1708 DRISyncType syncType; 1709#ifdef DEBUG 1710 static int count = 0; 1711 1712 if (!newContext) { 1713 DRIDrvMsg(pScreen->myNum, X_ERROR, 1714 "[DRI] Context Switch Error: oldContext=%x, newContext=%x\n", 1715 oldContext, newContext); 1716 return; 1717 } 1718 1719 /* usefull for debugging, just print out after n context switches */ 1720 if (!count || !(count % 1)) { 1721 DRIDrvMsg(pScreen->myNum, X_INFO, 1722 "[DRI] Context switch %5d from %p/0x%08x (%d)\n", 1723 count, 1724 oldContext, 1725 oldContext ? oldContext->flags : 0, 1726 oldContext ? oldContext->hwContext : -1); 1727 DRIDrvMsg(pScreen->myNum, X_INFO, 1728 "[DRI] Context switch %5d to %p/0x%08x (%d)\n", 1729 count, 1730 newContext, 1731 newContext ? newContext->flags : 0, 1732 newContext ? newContext->hwContext : -1); 1733 } 1734 ++count; 1735#endif 1736 1737 if (!pDRIPriv->pDriverInfo->SwapContext) { 1738 DRIDrvMsg(pScreen->myNum, X_ERROR, 1739 "[DRI] DDX driver missing context swap call back\n"); 1740 return; 1741 } 1742 1743 if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 1744 1745 /* only 3D contexts are swapped in this case */ 1746 if (oldContext) { 1747 oldContextStore = DRIGetContextStore(oldContext); 1748 oldContext->valid3D = TRUE; 1749 oldContextType = DRI_3D_CONTEXT; 1750 } else { 1751 oldContextType = DRI_NO_CONTEXT; 1752 } 1753 newContextStore = DRIGetContextStore(newContext); 1754 if ((newContext->valid3D) && 1755 (newContext->hwContext != pDRIPriv->myContext)) { 1756 newContextType = DRI_3D_CONTEXT; 1757 } 1758 else { 1759 newContextType = DRI_2D_CONTEXT; 1760 } 1761 syncType = DRI_3D_SYNC; 1762 } 1763 else /* default: driverSwapMethod == DRI_SERVER_SWAP */ { 1764 1765 /* optimize 2D context swaps */ 1766 1767 if (newContext->flags & DRI_CONTEXT_2DONLY) { 1768 /* go from 3D context to 2D context and only save 2D 1769 * subset of 3D state 1770 */ 1771 oldContextStore = DRIGetContextStore(oldContext); 1772 oldContextType = DRI_2D_CONTEXT; 1773 newContextStore = DRIGetContextStore(newContext); 1774 newContextType = DRI_2D_CONTEXT; 1775 syncType = DRI_3D_SYNC; 1776 pDRIPriv->lastPartial3DContext = oldContext; 1777 } 1778 else if (oldContext->flags & DRI_CONTEXT_2DONLY) { 1779 if (pDRIPriv->lastPartial3DContext == newContext) { 1780 /* go from 2D context back to previous 3D context and 1781 * only restore 2D subset of previous 3D state 1782 */ 1783 oldContextStore = DRIGetContextStore(oldContext); 1784 oldContextType = DRI_2D_CONTEXT; 1785 newContextStore = DRIGetContextStore(newContext); 1786 newContextType = DRI_2D_CONTEXT; 1787 syncType = DRI_2D_SYNC; 1788 } 1789 else { 1790 /* go from 2D context to a different 3D context */ 1791 1792 /* call DDX driver to do partial restore */ 1793 oldContextStore = DRIGetContextStore(oldContext); 1794 newContextStore = 1795 DRIGetContextStore(pDRIPriv->lastPartial3DContext); 1796 (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, 1797 DRI_2D_SYNC, 1798 DRI_2D_CONTEXT, 1799 oldContextStore, 1800 DRI_2D_CONTEXT, 1801 newContextStore); 1802 1803 /* now setup for a complete 3D swap */ 1804 oldContextStore = newContextStore; 1805 oldContext->valid3D = TRUE; 1806 oldContextType = DRI_3D_CONTEXT; 1807 newContextStore = DRIGetContextStore(newContext); 1808 if ((newContext->valid3D) && 1809 (newContext->hwContext != pDRIPriv->myContext)) { 1810 newContextType = DRI_3D_CONTEXT; 1811 } 1812 else { 1813 newContextType = DRI_2D_CONTEXT; 1814 } 1815 syncType = DRI_NO_SYNC; 1816 } 1817 } 1818 else { 1819 /* now setup for a complete 3D swap */ 1820 oldContextStore = newContextStore; 1821 oldContext->valid3D = TRUE; 1822 oldContextType = DRI_3D_CONTEXT; 1823 newContextStore = DRIGetContextStore(newContext); 1824 if ((newContext->valid3D) && 1825 (newContext->hwContext != pDRIPriv->myContext)) { 1826 newContextType = DRI_3D_CONTEXT; 1827 } 1828 else { 1829 newContextType = DRI_2D_CONTEXT; 1830 } 1831 syncType = DRI_3D_SYNC; 1832 } 1833 } 1834 1835 /* call DDX driver to perform the swap */ 1836 (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, 1837 syncType, 1838 oldContextType, 1839 oldContextStore, 1840 newContextType, 1841 newContextStore); 1842} 1843 1844void* 1845DRIGetContextStore(DRIContextPrivPtr context) 1846{ 1847 return((void *)context->pContextStore); 1848} 1849 1850void 1851DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg) 1852{ 1853 ScreenPtr pScreen = pWin->drawable.pScreen; 1854 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1855 DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 1856 1857 if(pDRIDrawablePriv) { 1858 (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, prgn, 1859 pDRIDrawablePriv->drawableIndex); 1860 } 1861 1862 /* call lower wrapped functions */ 1863 if (pDRIPriv && pDRIPriv->wrap.WindowExposures) { 1864 1865 /* unwrap */ 1866 pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; 1867 1868 /* call lower layers */ 1869 (*pScreen->WindowExposures)(pWin, prgn, bsreg); 1870 1871 /* rewrap */ 1872 pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; 1873 pScreen->WindowExposures = DRIWindowExposures; 1874 } 1875} 1876 1877 1878static int 1879DRITreeTraversal(WindowPtr pWin, pointer data) 1880{ 1881 DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 1882 1883 if(pDRIDrawablePriv) { 1884 ScreenPtr pScreen = pWin->drawable.pScreen; 1885 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1886 1887 if(RegionNumRects(&(pWin->clipList)) > 0) { 1888 RegionPtr reg = (RegionPtr)data; 1889 1890 RegionUnion(reg, reg, &(pWin->clipList)); 1891 pDRIPriv->nrWalked++; 1892 } 1893 1894 if(pDRIPriv->nrWindows == pDRIPriv->nrWalked) 1895 return WT_STOPWALKING; 1896 } 1897 return WT_WALKCHILDREN; 1898} 1899 1900Bool 1901DRIDestroyWindow(WindowPtr pWin) 1902{ 1903 ScreenPtr pScreen = pWin->drawable.pScreen; 1904 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1905 Bool retval = TRUE; 1906 1907 DRIDrawablePrivDestroy(pWin); 1908 1909 /* call lower wrapped functions */ 1910 if(pDRIPriv->DestroyWindow) { 1911 /* unwrap */ 1912 pScreen->DestroyWindow = pDRIPriv->DestroyWindow; 1913 1914 /* call lower layers */ 1915 retval = (*pScreen->DestroyWindow)(pWin); 1916 1917 /* rewrap */ 1918 pDRIPriv->DestroyWindow = pScreen->DestroyWindow; 1919 pScreen->DestroyWindow = DRIDestroyWindow; 1920 } 1921 1922 return retval; 1923} 1924 1925void 1926DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 1927{ 1928 ScreenPtr pScreen = pWin->drawable.pScreen; 1929 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 1930 1931 if(!pDRIPriv) return; 1932 1933 if(pDRIPriv->nrWindowsVisible > 0) { 1934 RegionRec reg; 1935 1936 RegionNull(®); 1937 pDRIPriv->nrWalked = 0; 1938 TraverseTree(pWin, DRITreeTraversal, (pointer)(®)); 1939 1940 if(RegionNotEmpty(®)) { 1941 RegionTranslate(®, ptOldOrg.x - pWin->drawable.x, 1942 ptOldOrg.y - pWin->drawable.y); 1943 RegionIntersect(®, ®, prgnSrc); 1944 1945 /* The MoveBuffers interface is not ideal */ 1946 (*pDRIPriv->pDriverInfo->MoveBuffers)(pWin, ptOldOrg, ®, 1947 pDRIPriv->pDriverInfo->ddxDrawableTableEntry); 1948 } 1949 1950 RegionUninit(®); 1951 } 1952 1953 /* call lower wrapped functions */ 1954 if(pDRIPriv->wrap.CopyWindow) { 1955 /* unwrap */ 1956 pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; 1957 1958 /* call lower layers */ 1959 (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); 1960 1961 /* rewrap */ 1962 pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; 1963 pScreen->CopyWindow = DRICopyWindow; 1964 } 1965} 1966 1967static void 1968DRIGetSecs(long *secs, long *usecs) 1969{ 1970 struct timeval tv; 1971 1972 gettimeofday(&tv, NULL); 1973 1974 *secs = tv.tv_sec; 1975 *usecs = tv.tv_usec; 1976} 1977 1978static unsigned long 1979DRIComputeMilliSeconds(unsigned long s_secs, unsigned long s_usecs, 1980 unsigned long f_secs, unsigned long f_usecs) 1981{ 1982 if (f_usecs < s_usecs) { 1983 --f_secs; 1984 f_usecs += 1000000; 1985 } 1986 return (f_secs - s_secs) * 1000 + (f_usecs - s_usecs) / 1000; 1987} 1988 1989static void 1990DRISpinLockTimeout(drmLock *lock, int val, unsigned long timeout /* in mS */) 1991{ 1992 int count = 10000; 1993#if !defined(__alpha__) && !defined(__powerpc__) 1994 char ret; 1995#else 1996 int ret; 1997#endif 1998 long s_secs, s_usecs; 1999 long f_secs, f_usecs; 2000 long msecs; 2001 long prev = 0; 2002 2003 DRIGetSecs(&s_secs, &s_usecs); 2004 2005 do { 2006 DRM_SPINLOCK_COUNT(lock, val, count, ret); 2007 if (!ret) return; /* Got lock */ 2008 DRIGetSecs(&f_secs, &f_usecs); 2009 msecs = DRIComputeMilliSeconds(s_secs, s_usecs, f_secs, f_usecs); 2010 if (msecs - prev < 250) count *= 2; /* Not more than 0.5S */ 2011 } while (msecs < timeout); 2012 2013 /* Didn't get lock, so take it. The worst 2014 that can happen is that there is some 2015 garbage written to the wrong part of the 2016 framebuffer that a refresh will repair. 2017 That's undesirable, but better than 2018 locking the server. This should be a 2019 very rare event. */ 2020 DRM_SPINLOCK_TAKE(lock, val); 2021} 2022 2023static void 2024DRILockTree(ScreenPtr pScreen) 2025{ 2026 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2027 2028 if(!pDRIPriv) return; 2029 2030 /* Restore the last known 3D context if the X context is hidden */ 2031 if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 2032 (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, 2033 DRI_2D_SYNC, 2034 DRI_NO_CONTEXT, 2035 NULL, 2036 DRI_2D_CONTEXT, 2037 pDRIPriv->partial3DContextStore); 2038 } 2039 2040 /* Call kernel to release lock */ 2041 DRIUnlock(pScreen); 2042 2043 /* Grab drawable spin lock: a time out between 10 and 30 seconds is 2044 appropriate, since this should never time out except in the case of 2045 client death while the lock is being held. The timeout must be 2046 greater than any reasonable rendering time. */ 2047 DRISpinLockTimeout(&pDRIPriv->pSAREA->drawable_lock, 1, 10000); /*10 secs*/ 2048 2049 /* Call kernel flush outstanding buffers and relock */ 2050 DRILock(pScreen, DRM_LOCK_QUIESCENT|DRM_LOCK_FLUSH_ALL); 2051 2052 /* Switch back to our 2D context if the X context is hidden */ 2053 if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { 2054 /* hide X context by swapping 2D component here */ 2055 (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, 2056 DRI_3D_SYNC, 2057 DRI_2D_CONTEXT, 2058 pDRIPriv->partial3DContextStore, 2059 DRI_2D_CONTEXT, 2060 pDRIPriv->hiddenContextStore); 2061 } 2062} 2063 2064int 2065DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 2066{ 2067 ScreenPtr pScreen = pParent->drawable.pScreen; 2068 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2069 2070 int returnValue = 1; /* always return 1, not checked by dix/window.c */ 2071 2072 if(!pDRIPriv) return returnValue; 2073 2074 /* call lower wrapped functions */ 2075 if(pDRIPriv->wrap.ValidateTree) { 2076 /* unwrap */ 2077 pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; 2078 2079 /* call lower layers */ 2080 returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind); 2081 2082 /* rewrap */ 2083 pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; 2084 pScreen->ValidateTree = DRIValidateTree; 2085 } 2086 2087 return returnValue; 2088} 2089 2090void 2091DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 2092{ 2093 ScreenPtr pScreen; 2094 DRIScreenPrivPtr pDRIPriv; 2095 2096 if (pParent) { 2097 pScreen = pParent->drawable.pScreen; 2098 } else { 2099 pScreen = pChild->drawable.pScreen; 2100 } 2101 if(!(pDRIPriv = DRI_SCREEN_PRIV(pScreen))) return; 2102 2103 if (pDRIPriv->wrap.PostValidateTree) { 2104 /* unwrap */ 2105 pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; 2106 2107 /* call lower layers */ 2108 (*pScreen->PostValidateTree)(pParent, pChild, kind); 2109 2110 /* rewrap */ 2111 pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; 2112 pScreen->PostValidateTree = DRIPostValidateTree; 2113 } 2114} 2115 2116void 2117DRIClipNotify(WindowPtr pWin, int dx, int dy) 2118{ 2119 ScreenPtr pScreen = pWin->drawable.pScreen; 2120 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2121 DRIDrawablePrivPtr pDRIDrawablePriv; 2122 2123 if(!pDRIPriv) return; 2124 2125 if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { 2126 int nrects = RegionNumRects(&pWin->clipList); 2127 2128 if(!pDRIPriv->windowsTouched) { 2129 DRILockTree(pScreen); 2130 pDRIPriv->windowsTouched = TRUE; 2131 } 2132 2133 if (nrects && !pDRIDrawablePriv->nrects) 2134 DRIIncreaseNumberVisible(pScreen); 2135 else if (!nrects && pDRIDrawablePriv->nrects) 2136 DRIDecreaseNumberVisible(pScreen); 2137 else 2138 DRIDriverClipNotify(pScreen); 2139 2140 pDRIDrawablePriv->nrects = nrects; 2141 2142 pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp 2143 = DRIDrawableValidationStamp++; 2144 2145 drmUpdateDrawableInfo(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable, 2146 DRM_DRAWABLE_CLIPRECTS, 2147 nrects, RegionRects(&pWin->clipList)); 2148 } 2149 2150 /* call lower wrapped functions */ 2151 if(pDRIPriv->wrap.ClipNotify) { 2152 2153 /* unwrap */ 2154 pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; 2155 2156 /* call lower layers */ 2157 (*pScreen->ClipNotify)(pWin, dx, dy); 2158 2159 /* rewrap */ 2160 pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; 2161 pScreen->ClipNotify = DRIClipNotify; 2162 } 2163} 2164 2165CARD32 2166DRIGetDrawableIndex(WindowPtr pWin) 2167{ 2168 ScreenPtr pScreen = pWin->drawable.pScreen; 2169 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2170 DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 2171 CARD32 index; 2172 2173 if (pDRIDrawablePriv) { 2174 index = pDRIDrawablePriv->drawableIndex; 2175 } 2176 else { 2177 index = pDRIPriv->pDriverInfo->ddxDrawableTableEntry; 2178 } 2179 2180 return index; 2181} 2182 2183unsigned int 2184DRIGetDrawableStamp(ScreenPtr pScreen, CARD32 drawable_index) 2185{ 2186 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2187 return pDRIPriv->pSAREA->drawableTable[drawable_index].stamp; 2188} 2189 2190 2191void 2192DRIPrintDrawableLock(ScreenPtr pScreen, char *msg) 2193{ 2194 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2195 2196 ErrorF("%s: %d\n", msg, pDRIPriv->pSAREA->drawable_lock.lock); 2197} 2198 2199void 2200DRILock(ScreenPtr pScreen, int flags) 2201{ 2202 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2203 2204 if(!pDRIPriv || !pDRIPriv->pLockRefCount) return; 2205 2206 if (!*pDRIPriv->pLockRefCount) { 2207 DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext, flags); 2208 *pDRIPriv->pLockingContext = pDRIPriv->myContext; 2209 } else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) { 2210 DRIDrvMsg(pScreen->myNum, X_ERROR, 2211 "[DRI] Locking deadlock.\n" 2212 "\tAlready locked with context %d,\n" 2213 "\ttrying to lock with context %d.\n", 2214 pDRIPriv->pLockingContext, 2215 pDRIPriv->myContext); 2216 } 2217 (*pDRIPriv->pLockRefCount)++; 2218} 2219 2220void 2221DRIUnlock(ScreenPtr pScreen) 2222{ 2223 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2224 2225 if(!pDRIPriv || !pDRIPriv->pLockRefCount) return; 2226 2227 if (*pDRIPriv->pLockRefCount > 0) { 2228 if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) { 2229 DRIDrvMsg(pScreen->myNum, X_ERROR, 2230 "[DRI] Unlocking inconsistency:\n" 2231 "\tContext %d trying to unlock lock held by context %d\n", 2232 pDRIPriv->pLockingContext, 2233 pDRIPriv->myContext); 2234 } 2235 (*pDRIPriv->pLockRefCount)--; 2236 } else { 2237 DRIDrvMsg(pScreen->myNum, X_ERROR, 2238 "DRIUnlock called when not locked.\n"); 2239 return; 2240 } 2241 if (! *pDRIPriv->pLockRefCount) 2242 DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext); 2243} 2244 2245void * 2246DRIGetSAREAPrivate(ScreenPtr pScreen) 2247{ 2248 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2249 if (!pDRIPriv) return 0; 2250 2251 return (void *)(((char*)pDRIPriv->pSAREA)+sizeof(XF86DRISAREARec)); 2252} 2253 2254drm_context_t 2255DRIGetContext(ScreenPtr pScreen) 2256{ 2257 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2258 if (!pDRIPriv) return 0; 2259 2260 return pDRIPriv->myContext; 2261} 2262 2263void 2264DRIGetTexOffsetFuncs(ScreenPtr pScreen, 2265 DRITexOffsetStartProcPtr *texOffsetStartFunc, 2266 DRITexOffsetFinishProcPtr *texOffsetFinishFunc) 2267{ 2268 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2269 2270 if (!pDRIPriv) return; 2271 2272 *texOffsetStartFunc = pDRIPriv->pDriverInfo->texOffsetStart; 2273 *texOffsetFinishFunc = pDRIPriv->pDriverInfo->texOffsetFinish; 2274} 2275 2276/* This lets get at the unwrapped functions so that they can correctly 2277 * call the lowerlevel functions, and choose whether they will be 2278 * called at every level of recursion (eg in validatetree). 2279 */ 2280DRIWrappedFuncsRec * 2281DRIGetWrappedFuncs(ScreenPtr pScreen) 2282{ 2283 return &(DRI_SCREEN_PRIV(pScreen)->wrap); 2284} 2285 2286/* note that this returns the library version, not the protocol version */ 2287void 2288DRIQueryVersion(int *majorVersion, 2289 int *minorVersion, 2290 int *patchVersion) 2291{ 2292 *majorVersion = DRIINFO_MAJOR_VERSION; 2293 *minorVersion = DRIINFO_MINOR_VERSION; 2294 *patchVersion = DRIINFO_PATCH_VERSION; 2295} 2296 2297static void 2298_DRIAdjustFrame(ScrnInfoPtr pScrn, DRIScreenPrivPtr pDRIPriv, int x, int y) 2299{ 2300 pDRIPriv->pSAREA->frame.x = x; 2301 pDRIPriv->pSAREA->frame.y = y; 2302 pDRIPriv->pSAREA->frame.width = pScrn->frameX1 - x + 1; 2303 pDRIPriv->pSAREA->frame.height = pScrn->frameY1 - y + 1; 2304} 2305 2306void 2307DRIAdjustFrame(int scrnIndex, int x, int y, int flags) 2308{ 2309 ScreenPtr pScreen = screenInfo.screens[scrnIndex]; 2310 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 2311 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 2312 int px, py; 2313 2314 if (!pDRIPriv || !pDRIPriv->pSAREA) { 2315 DRIDrvMsg(scrnIndex, X_ERROR, "[DRI] No SAREA (%p %p)\n", 2316 pDRIPriv, pDRIPriv ? pDRIPriv->pSAREA : NULL); 2317 return; 2318 } 2319 2320 if (pDRIPriv->fullscreen) { 2321 /* Fix up frame */ 2322 pScrn->frameX0 = pDRIPriv->pSAREA->frame.x; 2323 pScrn->frameY0 = pDRIPriv->pSAREA->frame.y; 2324 pScrn->frameX1 = pScrn->frameX0 + pDRIPriv->pSAREA->frame.width - 1; 2325 pScrn->frameY1 = pScrn->frameY0 + pDRIPriv->pSAREA->frame.height - 1; 2326 2327 /* Fix up cursor */ 2328 miPointerGetPosition(inputInfo.pointer, &px, &py); 2329 if (px < pScrn->frameX0) px = pScrn->frameX0; 2330 if (px > pScrn->frameX1) px = pScrn->frameX1; 2331 if (py < pScrn->frameY0) py = pScrn->frameY0; 2332 if (py > pScrn->frameY1) py = pScrn->frameY1; 2333 pScreen->SetCursorPosition(inputInfo.pointer, pScreen, px, py, TRUE); 2334 return; 2335 } 2336 2337 if (pDRIPriv->wrap.AdjustFrame) { 2338 /* unwrap */ 2339 pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; 2340 /* call lower layers */ 2341 (*pScrn->AdjustFrame)(scrnIndex, x, y, flags); 2342 /* rewrap */ 2343 pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; 2344 pScrn->AdjustFrame = DRIAdjustFrame; 2345 } 2346 2347 _DRIAdjustFrame(pScrn, pDRIPriv, x, y); 2348} 2349 2350/* 2351 * DRIMoveBuffersHelper swaps the regions rects in place leaving you 2352 * a region with the rects in the order that you need to blit them, 2353 * but it is possibly (likely) an invalid region afterwards. If you 2354 * need to use the region again for anything you have to call 2355 * REGION_VALIDATE on it, or better yet, save a copy first. 2356 */ 2357 2358void 2359DRIMoveBuffersHelper( 2360 ScreenPtr pScreen, 2361 int dx, 2362 int dy, 2363 int *xdir, 2364 int *ydir, 2365 RegionPtr reg 2366) 2367{ 2368 BoxPtr extents, pbox, firstBox, lastBox; 2369 BoxRec tmpBox; 2370 int y, nbox; 2371 2372 extents = RegionExtents(reg); 2373 nbox = RegionNumRects(reg); 2374 pbox = RegionRects(reg); 2375 2376 if((dy > 0) && (dy < (extents->y2 - extents->y1))) { 2377 *ydir = -1; 2378 if(nbox > 1) { 2379 firstBox = pbox; 2380 lastBox = pbox + nbox - 1; 2381 while((unsigned long)firstBox < (unsigned long)lastBox) { 2382 tmpBox = *firstBox; 2383 *firstBox = *lastBox; 2384 *lastBox = tmpBox; 2385 firstBox++; 2386 lastBox--; 2387 } 2388 } 2389 } else *ydir = 1; 2390 2391 if((dx > 0) && (dx < (extents->x2 - extents->x1))) { 2392 *xdir = -1; 2393 if(nbox > 1) { 2394 firstBox = lastBox = pbox; 2395 y = pbox->y1; 2396 while(--nbox) { 2397 pbox++; 2398 if(pbox->y1 == y) lastBox++; 2399 else { 2400 while((unsigned long)firstBox < (unsigned long)lastBox) { 2401 tmpBox = *firstBox; 2402 *firstBox = *lastBox; 2403 *lastBox = tmpBox; 2404 firstBox++; 2405 lastBox--; 2406 } 2407 2408 firstBox = lastBox = pbox; 2409 y = pbox->y1; 2410 } 2411 } 2412 while((unsigned long)firstBox < (unsigned long)lastBox) { 2413 tmpBox = *firstBox; 2414 *firstBox = *lastBox; 2415 *lastBox = tmpBox; 2416 firstBox++; 2417 lastBox--; 2418 } 2419 } 2420 } else *xdir = 1; 2421 2422} 2423 2424char * 2425DRICreatePCIBusID(const struct pci_device * dev) 2426{ 2427 char *busID; 2428 2429 if (asprintf(&busID, "pci:%04x:%02x:%02x.%d", 2430 dev->domain, dev->bus, dev->dev, dev->func) == -1) 2431 return NULL; 2432 2433 return busID; 2434} 2435 2436static void drmSIGIOHandler(int interrupt, void *closure) 2437{ 2438 unsigned long key; 2439 void *value; 2440 ssize_t count; 2441 drm_ctx_t ctx; 2442 typedef void (*_drmCallback)(int, void *, void *); 2443 char buf[256]; 2444 drm_context_t old; 2445 drm_context_t new; 2446 void *oldctx; 2447 void *newctx; 2448 char *pt; 2449 drmHashEntry *entry; 2450 void *hash_table; 2451 2452 hash_table = drmGetHashTable(); 2453 2454 if (!hash_table) return; 2455 if (drmHashFirst(hash_table, &key, &value)) { 2456 entry = value; 2457 do { 2458#if 0 2459 fprintf(stderr, "Trying %d\n", entry->fd); 2460#endif 2461 if ((count = read(entry->fd, buf, sizeof(buf) - 1)) > 0) { 2462 buf[count] = '\0'; 2463#if 0 2464 fprintf(stderr, "Got %s\n", buf); 2465#endif 2466 2467 for (pt = buf; *pt != ' '; ++pt); /* Find first space */ 2468 ++pt; 2469 old = strtol(pt, &pt, 0); 2470 new = strtol(pt, NULL, 0); 2471 oldctx = drmGetContextTag(entry->fd, old); 2472 newctx = drmGetContextTag(entry->fd, new); 2473#if 0 2474 fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx); 2475#endif 2476 ((_drmCallback)entry->f)(entry->fd, oldctx, newctx); 2477 ctx.handle = new; 2478 ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx); 2479 } 2480 } while (drmHashNext(hash_table, &key, &value)); 2481 } 2482} 2483 2484 2485int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *)) 2486{ 2487 drmHashEntry *entry; 2488 2489 entry = drmGetEntry(fd); 2490 entry->f = f; 2491 2492 return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0); 2493} 2494 2495int drmRemoveSIGIOHandler(int fd) 2496{ 2497 drmHashEntry *entry = drmGetEntry(fd); 2498 2499 entry->f = NULL; 2500 2501 return xf86RemoveSIGIOHandler(fd); 2502} 2503