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