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 15 static char TDFXKernelDriverName[] = "tdfx"; 16 static char TDFXClientDriverName[] = "tdfx"; 17 18 static Bool TDFXCreateContext(ScreenPtr pScreen, VisualPtr visual, 19 drm_context_t hwContext, void *pVisualConfigPriv, 20 DRIContextType contextStore); 21 static void TDFXDestroyContext(ScreenPtr pScreen, drm_context_t hwContext, 22 DRIContextType contextStore); 23 static void TDFXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 24 DRIContextType readContextType, 25 void *readContextStore, 26 DRIContextType writeContextType, 27 void *writeContextStore); 28 static Bool TDFXDRIOpenFullScreen(ScreenPtr pScreen); 29 static Bool TDFXDRICloseFullScreen(ScreenPtr pScreen); 30 static void TDFXDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index); 31 static void TDFXDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, 32 RegionPtr prgnSrc, CARD32 index); 33 static void TDFXDRITransitionTo2d(ScreenPtr pScreen); 34 static void TDFXDRITransitionTo3d(ScreenPtr pScreen); 35 36 static void 37 TDFXDoWakeupHandler(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 51 static void 52 TDFXDoBlockHandler(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 66 Bool 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 257 void 258 TDFXDRICloseScreen(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 275 static Bool 276 TDFXCreateContext(ScreenPtr pScreen, VisualPtr visual, 277 drm_context_t hwContext, void *pVisualConfigPriv, 278 DRIContextType contextStore) 279 { 280 return TRUE; 281 } 282 283 static void 284 TDFXDestroyContext(ScreenPtr pScreen, drm_context_t hwContext, 285 DRIContextType contextStore) 286 { 287 } 288 289 Bool 290 TDFXDRIFinishScreenInit(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 320 static void 321 TDFXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 322 DRIContextType oldContextType, void *oldContext, 323 DRIContextType newContextType, void *newContext) 324 { 325 } 326 327 static void 328 TDFXDRIInitBuffers(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 358 static void 359 TDFXDRIMoveBuffers(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 */ 406 static Bool 407 TDFXDRIOpenFullScreen(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 423 static Bool 424 TDFXDRICloseFullScreen(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 436 static void 437 TDFXDRITransitionTo2d(ScreenPtr pScreen) 438 { 439 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 440 TDFXPtr pTDFX = TDFXPTR(pScrn); 441 442 xf86FreeOffscreenArea(pTDFX->reservedArea); 443 } 444 445 static void 446 TDFXDRITransitionTo3d(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