1 2#ifdef HAVE_CONFIG_H 3#include "config.h" 4#endif 5 6#include "xf86.h" 7#include "xf86_OSproc.h" 8#include "xf86Pci.h" 9#include "fb.h" 10#include "miline.h" 11#include "tdfx.h" 12#include "tdfx_dri.h" 13#include "tdfx_dripriv.h" 14 15static char TDFXKernelDriverName[] = "tdfx"; 16static char TDFXClientDriverName[] = "tdfx"; 17 18static Bool TDFXCreateContext(ScreenPtr pScreen, VisualPtr visual, 19 drm_context_t hwContext, void *pVisualConfigPriv, 20 DRIContextType contextStore); 21static void TDFXDestroyContext(ScreenPtr pScreen, drm_context_t hwContext, 22 DRIContextType contextStore); 23static void TDFXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 24 DRIContextType readContextType, 25 void *readContextStore, 26 DRIContextType writeContextType, 27 void *writeContextStore); 28static Bool TDFXDRIOpenFullScreen(ScreenPtr pScreen); 29static Bool TDFXDRICloseFullScreen(ScreenPtr pScreen); 30static void TDFXDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index); 31static void TDFXDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, 32 RegionPtr prgnSrc, CARD32 index); 33static void TDFXDRITransitionTo2d(ScreenPtr pScreen); 34static void TDFXDRITransitionTo3d(ScreenPtr pScreen); 35 36static void 37TDFXDoWakeupHandler(WAKEUPHANDLER_ARGS_DECL) 38{ 39 SCREEN_PTR(arg); 40 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 41 TDFXPtr pTDFX = TDFXPTR(pScrn); 42 43 pTDFX->pDRIInfo->wrap.WakeupHandler = pTDFX->coreWakeupHandler; 44 (*pTDFX->pDRIInfo->wrap.WakeupHandler) (WAKEUPHANDLER_ARGS); 45 pTDFX->pDRIInfo->wrap.WakeupHandler = TDFXDoWakeupHandler; 46 47 48 TDFXNeedSync(pScrn); 49} 50 51static void 52TDFXDoBlockHandler(BLOCKHANDLER_ARGS_DECL) 53{ 54 SCREEN_PTR(arg); 55 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 56 TDFXPtr pTDFX = TDFXPTR(pScrn); 57 58 TDFXCheckSync(pScrn); 59 60 pTDFX->pDRIInfo->wrap.BlockHandler = pTDFX->coreBlockHandler; 61 (*pTDFX->pDRIInfo->wrap.BlockHandler) (BLOCKHANDLER_ARGS); 62 pTDFX->pDRIInfo->wrap.BlockHandler = TDFXDoBlockHandler; 63 64} 65 66Bool TDFXDRIScreenInit(ScreenPtr pScreen) 67{ 68 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 69 TDFXPtr pTDFX = TDFXPTR(pScrn); 70 DRIInfoPtr pDRIInfo; 71 TDFXDRIPtr pTDFXDRI; 72 Bool bppOk = FALSE; 73 74 switch (pScrn->bitsPerPixel) { 75 case 16: 76 bppOk = TRUE; 77 break; 78 case 32: 79 if (pTDFX->ChipType > PCI_CHIP_VOODOO3) { 80 bppOk = TRUE; 81 } 82 break; 83 } 84 if (!bppOk) { 85 xf86DrvMsg(pScreen->myNum, X_ERROR, 86 "[dri] tdfx DRI not supported in %d bpp mode, disabling DRI.\n", 87 (pScrn->bitsPerPixel)); 88 if (pTDFX->ChipType <= PCI_CHIP_VOODOO3) { 89 xf86DrvMsg(pScreen->myNum, X_INFO, 90 "[dri] To use DRI, invoke the server using 16 bpp\n" 91 "\t(-depth 15 or -depth 16).\n"); 92 } else { 93 xf86DrvMsg(pScreen->myNum, X_INFO, 94 "[dri] To use DRI, invoke the server using 16 bpp\n" 95 "\t(-depth 15 or -depth 16) or 32 bpp (-depth 24 -fbbpp 32).\n"); 96 } 97 return FALSE; 98 } 99 100 /* Check that the DRI, and DRM modules have been loaded by testing 101 for canonical symbols in each module. */ 102 if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE; 103 if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { 104 xf86DrvMsg(pScreen->myNum, X_ERROR, 105 "TDFXDRIScreenInit failed (libdri.a too old)\n"); 106 return FALSE; 107 } 108 109 /* Check the DRI version */ 110 { 111 int major, minor, patch; 112 DRIQueryVersion(&major, &minor, &patch); 113 if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { 114 xf86DrvMsg(pScreen->myNum, X_ERROR, 115 "[dri] TDFXDRIScreenInit failed because of a version mismatch.\n" 116 "[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n" 117 "[dri] Disabling the DRI.\n", 118 major, minor, patch, 119 DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); 120 return FALSE; 121 } 122 } 123 124 pDRIInfo = DRICreateInfoRec(); 125 if (!pDRIInfo) { 126 xf86DrvMsg(pScreen->myNum, X_ERROR, 127 "[dri] DRICreateInfoRect() failed, disabling DRI.\n"); 128 return FALSE; 129 } 130 131 pTDFX->pDRIInfo = pDRIInfo; 132 133 pDRIInfo->drmDriverName = TDFXKernelDriverName; 134 pDRIInfo->clientDriverName = TDFXClientDriverName; 135#ifdef XSERVER_LIBPCIACCESS 136 pDRIInfo->busIdString = DRICreatePCIBusID(pTDFX->PciInfo[0]); 137#else 138 if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { 139 pDRIInfo->busIdString = DRICreatePCIBusID(pTDFX->PciInfo); 140 } else { 141 pDRIInfo->busIdString = malloc(64); 142 sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", 143 ((pciConfigPtr)pTDFX->PciInfo->thisCard)->busnum, 144 ((pciConfigPtr)pTDFX->PciInfo->thisCard)->devnum, 145 ((pciConfigPtr)pTDFX->PciInfo->thisCard)->funcnum); 146 } 147#endif 148 pDRIInfo->ddxDriverMajorVersion = TDFX_MAJOR_VERSION; 149 pDRIInfo->ddxDriverMinorVersion = TDFX_MINOR_VERSION; 150 pDRIInfo->ddxDriverPatchVersion = TDFX_PATCHLEVEL; 151 pDRIInfo->frameBufferPhysicalAddress = (pointer) pTDFX->LinearAddr[0]; 152 pDRIInfo->frameBufferSize = pTDFX->FbMapSize; 153 pDRIInfo->frameBufferStride = pTDFX->stride; 154 pDRIInfo->ddxDrawableTableEntry = TDFX_MAX_DRAWABLES; 155 156 pTDFX->coreBlockHandler = pDRIInfo->wrap.BlockHandler; 157 pDRIInfo->wrap.BlockHandler = TDFXDoBlockHandler; 158 pTDFX->coreWakeupHandler = pDRIInfo->wrap.WakeupHandler; 159 pDRIInfo->wrap.WakeupHandler = TDFXDoWakeupHandler; 160 161 if (SAREA_MAX_DRAWABLES < TDFX_MAX_DRAWABLES) 162 pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES; 163 else 164 pDRIInfo->maxDrawableTableEntry = TDFX_MAX_DRAWABLES; 165 166#ifdef NOT_DONE 167 /* FIXME need to extend DRI protocol to pass this size back to client 168 * for SAREA mapping that includes a device private record 169 */ 170 pDRIInfo->SAREASize = 171 ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */ 172 /* + shared memory device private rec */ 173#else 174 /* For now the mapping works by using a fixed size defined 175 * in the SAREA header 176 */ 177 if (sizeof(XF86DRISAREARec)+sizeof(TDFXSAREAPriv)>SAREA_MAX) { 178 xf86DrvMsg(pScreen->myNum, X_ERROR, "Data does not fit in SAREA\n"); 179 return FALSE; 180 } 181 pDRIInfo->SAREASize = SAREA_MAX; 182#endif 183 184 if (!(pTDFXDRI = (TDFXDRIPtr)calloc(sizeof(TDFXDRIRec),1))) { 185 xf86DrvMsg(pScreen->myNum, X_ERROR, 186 "[dri] DRI memory allocation failed, disabling DRI.\n"); 187 DRIDestroyInfoRec(pTDFX->pDRIInfo); 188 pTDFX->pDRIInfo=0; 189 return FALSE; 190 } 191 pDRIInfo->devPrivate = pTDFXDRI; 192 pDRIInfo->devPrivateSize = sizeof(TDFXDRIRec); 193 pDRIInfo->contextSize = sizeof(TDFXDRIContextRec); 194 195 pDRIInfo->CreateContext = TDFXCreateContext; 196 pDRIInfo->DestroyContext = TDFXDestroyContext; 197 pDRIInfo->SwapContext = TDFXDRISwapContext; 198 pDRIInfo->InitBuffers = TDFXDRIInitBuffers; 199 pDRIInfo->MoveBuffers = TDFXDRIMoveBuffers; 200 pDRIInfo->OpenFullScreen = TDFXDRIOpenFullScreen; 201 pDRIInfo->CloseFullScreen = TDFXDRICloseFullScreen; 202 pDRIInfo->TransitionTo2d = TDFXDRITransitionTo2d; 203 pDRIInfo->TransitionTo3d = TDFXDRITransitionTo3d; 204 pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; 205 206 pDRIInfo->createDummyCtx = FALSE; 207 pDRIInfo->createDummyCtxPriv = FALSE; 208 209 if (!DRIScreenInit(pScreen, pDRIInfo, &pTDFX->drmSubFD)) { 210 free(pDRIInfo->devPrivate); 211 pDRIInfo->devPrivate=0; 212 DRIDestroyInfoRec(pTDFX->pDRIInfo); 213 pTDFX->pDRIInfo=0; 214 xf86DrvMsg(pScreen->myNum, X_ERROR, 215 "[dri] DRIScreenInit failed, disabling DRI.\n"); 216 217 return FALSE; 218 } 219 220 /* Check the TDFX DRM version */ 221 { 222 drmVersionPtr version = drmGetVersion(pTDFX->drmSubFD); 223 if (version) { 224 if (version->version_major != 1 || 225 version->version_minor < 0) { 226 /* incompatible drm version */ 227 xf86DrvMsg(pScreen->myNum, X_ERROR, 228 "[dri] TDFXDRIScreenInit failed because of a version mismatch.\n" 229 "[dri] tdfx.o kernel module version is %d.%d.%d but version 1.0.x is needed.\n" 230 "[dri] Disabling the DRI.\n", 231 version->version_major, 232 version->version_minor, 233 version->version_patchlevel); 234 TDFXDRICloseScreen(pScreen); 235 drmFreeVersion(version); 236 return FALSE; 237 } 238 drmFreeVersion(version); 239 } 240 } 241 242 pTDFXDRI->regsSize=TDFXIOMAPSIZE; 243 if (drmAddMap(pTDFX->drmSubFD, (drm_handle_t)pTDFX->MMIOAddr[0], 244 pTDFXDRI->regsSize, DRM_REGISTERS, 0, &pTDFXDRI->regs)<0) { 245 TDFXDRICloseScreen(pScreen); 246 xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap failed, disabling DRI.\n"); 247 return FALSE; 248 } 249 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n", 250 pTDFXDRI->regs); 251 252 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "visual configs initialized\n" ); 253 254 return TRUE; 255} 256 257void 258TDFXDRICloseScreen(ScreenPtr pScreen) 259{ 260 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 261 TDFXPtr pTDFX = TDFXPTR(pScrn); 262 263 DRICloseScreen(pScreen); 264 265 if (pTDFX->pDRIInfo) { 266 if (pTDFX->pDRIInfo->devPrivate) { 267 free(pTDFX->pDRIInfo->devPrivate); 268 pTDFX->pDRIInfo->devPrivate=0; 269 } 270 DRIDestroyInfoRec(pTDFX->pDRIInfo); 271 pTDFX->pDRIInfo=0; 272 } 273} 274 275static Bool 276TDFXCreateContext(ScreenPtr pScreen, VisualPtr visual, 277 drm_context_t hwContext, void *pVisualConfigPriv, 278 DRIContextType contextStore) 279{ 280 return TRUE; 281} 282 283static void 284TDFXDestroyContext(ScreenPtr pScreen, drm_context_t hwContext, 285 DRIContextType contextStore) 286{ 287} 288 289Bool 290TDFXDRIFinishScreenInit(ScreenPtr pScreen) 291{ 292 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 293 TDFXPtr pTDFX = TDFXPTR(pScrn); 294 TDFXDRIPtr pTDFXDRI; 295 296 pTDFX->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; 297 298 pTDFXDRI=(TDFXDRIPtr)pTDFX->pDRIInfo->devPrivate; 299#ifdef XSERVER_LIBPCIACCESS 300 pTDFXDRI->deviceID = DEVICE_ID(pTDFX->PciInfo[0]); 301#else 302 pTDFXDRI->deviceID = DEVICE_ID(pTDFX->PciInfo); 303#endif 304 pTDFXDRI->width=pScrn->virtualX; 305 pTDFXDRI->height=pScrn->virtualY; 306 pTDFXDRI->mem=pScrn->videoRam*1024; 307 pTDFXDRI->cpp=pTDFX->cpp; 308 pTDFXDRI->stride=pTDFX->stride; 309 pTDFXDRI->fifoOffset=pTDFX->fifoOffset; 310 pTDFXDRI->fifoSize=pTDFX->fifoSize; 311 pTDFXDRI->textureOffset=pTDFX->texOffset; 312 pTDFXDRI->textureSize=pTDFX->texSize; 313 pTDFXDRI->fbOffset=pTDFX->fbOffset; 314 pTDFXDRI->backOffset=pTDFX->backOffset; 315 pTDFXDRI->depthOffset=pTDFX->depthOffset; 316 pTDFXDRI->sarea_priv_offset = sizeof(XF86DRISAREARec); 317 return DRIFinishScreenInit(pScreen); 318} 319 320static void 321TDFXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 322 DRIContextType oldContextType, void *oldContext, 323 DRIContextType newContextType, void *newContext) 324{ 325} 326 327static void 328TDFXDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) 329{ 330#ifdef HAVE_XAA_H 331 ScreenPtr pScreen = pWin->drawable.pScreen; 332 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 333 TDFXPtr pTDFX = TDFXPTR(pScrn); 334 BoxPtr pbox; 335 int nbox; 336 337 /* It looks nicer if these start out black */ 338 pbox = REGION_RECTS(prgn); 339 nbox = REGION_NUM_RECTS(prgn); 340 341 TDFXSetupForSolidFill(pScrn, 0, GXcopy, -1); 342 while (nbox--) { 343 TDFXSelectBuffer(pTDFX, TDFX_BACK); 344 TDFXSubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, 345 pbox->x2-pbox->x1, pbox->y2-pbox->y1); 346 TDFXSelectBuffer(pTDFX, TDFX_DEPTH); 347 TDFXSubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, 348 pbox->x2-pbox->x1, pbox->y2-pbox->y1); 349 pbox++; 350 } 351 TDFXSelectBuffer(pTDFX, TDFX_FRONT); 352 353 354 pTDFX->AccelInfoRec->NeedToSync = TRUE; 355#endif 356} 357 358static void 359TDFXDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, 360 RegionPtr prgnSrc, CARD32 index) 361{ 362#ifdef HAVE_XAA_H 363 ScreenPtr pScreen = pParent->drawable.pScreen; 364 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 365 TDFXPtr pTDFX = TDFXPTR(pScrn); 366 int dx, dy, xdir, ydir, i, x, y, nbox; 367 BoxPtr pbox; 368 369 dx = pParent->drawable.x - ptOldOrg.x; 370 dy = pParent->drawable.y - ptOldOrg.y; 371 372 DRIMoveBuffersHelper(pScreen, dx, dy, &xdir, &ydir, prgnSrc); 373 374 pbox = REGION_RECTS(prgnSrc); 375 nbox = REGION_NUM_RECTS(prgnSrc); 376 377 TDFXSetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, ~0, -1); 378 379 TDFXSelectBuffer(pTDFX, TDFX_BACK); 380 for(i = 0; i < nbox; i++) { 381 x = pbox[i].x1; 382 y = pbox[i].y1; 383 TDFXSubsequentScreenToScreenCopy(pScrn, x, y, x+dx, y+dy, 384 pbox[i].x2 - x, pbox[i].y2 - y); 385 } 386 387 TDFXSelectBuffer(pTDFX, TDFX_DEPTH); 388 for(i = 0; i < nbox; i++) { 389 x = pbox[i].x1; 390 y = pbox[i].y1; 391 TDFXSubsequentScreenToScreenCopy(pScrn, x, y, x+dx, y+dy, 392 pbox[i].x2 - x, pbox[i].y2 - y); 393 } 394 395 TDFXSelectBuffer(pTDFX, TDFX_FRONT); 396 397 pTDFX->AccelInfoRec->NeedToSync = TRUE; 398#endif 399 400} 401 402/* 403 * the FullScreen DRI code is dead; this is just left in place to show how 404 * to set up SLI mode. 405 */ 406static Bool 407TDFXDRIOpenFullScreen(ScreenPtr pScreen) 408{ 409#if 0 410 ScrnInfoPtr pScrn; 411 TDFXPtr pTDFX; 412 413 xf86DrvMsg(pScreen->myNum, X_INFO, "OpenFullScreen\n"); 414 pScrn = xf86ScreenToScrn(pScreen); 415 pTDFX=TDFXPTR(pScrn); 416 if (pTDFX->numChips>1) { 417 TDFXSetupSLI(pScrn); 418 } 419#endif 420 return TRUE; 421} 422 423static Bool 424TDFXDRICloseFullScreen(ScreenPtr pScreen) 425{ 426#if 0 427 ScrnInfoPtr pScrn; 428 429 xf86DrvMsg(pScreen->myNum, X_INFO, "CloseFullScreen\n"); 430 pScrn = xf86ScreenToScrn(pScreen); 431 TDFXDisableSLI(pScrn); 432#endif 433 return TRUE; 434} 435 436static void 437TDFXDRITransitionTo2d(ScreenPtr pScreen) 438{ 439 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 440 TDFXPtr pTDFX = TDFXPTR(pScrn); 441 442 xf86FreeOffscreenArea(pTDFX->reservedArea); 443} 444 445static void 446TDFXDRITransitionTo3d(ScreenPtr pScreen) 447{ 448 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 449 TDFXPtr pTDFX = TDFXPTR(pScrn); 450 FBAreaPtr pArea; 451 452 if(pTDFX->overlayBuffer) { 453 xf86FreeOffscreenLinear(pTDFX->overlayBuffer); 454 pTDFX->overlayBuffer = NULL; 455 } 456 457 if(pTDFX->overlayBuffer2) { 458 xf86FreeOffscreenLinear(pTDFX->overlayBuffer2); 459 pTDFX->overlayBuffer2 = NULL; 460 } 461 462 if(pTDFX->textureBuffer) { 463 xf86FreeOffscreenArea(pTDFX->textureBuffer); 464 pTDFX->textureBuffer = NULL; 465 } 466 467 xf86PurgeUnlockedOffscreenAreas(pScreen); 468 469 pArea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, 470 pTDFX->pixmapCacheLinesMin, 471 pScrn->displayWidth, NULL, NULL, NULL); 472 pTDFX->reservedArea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, 473 pTDFX->pixmapCacheLinesMax - pTDFX->pixmapCacheLinesMin, 474 pScrn->displayWidth, NULL, NULL, NULL); 475 xf86FreeOffscreenArea(pArea); 476} 477