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