#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "xf86.h" #include "xf86_OSproc.h" #include "xf86Pci.h" #include "fb.h" #include "miline.h" #include "tdfx.h" #include "tdfx_dri.h" #include "tdfx_dripriv.h" static char TDFXKernelDriverName[] = "tdfx"; static char TDFXClientDriverName[] = "tdfx"; static Bool TDFXCreateContext(ScreenPtr pScreen, VisualPtr visual, drm_context_t hwContext, void *pVisualConfigPriv, DRIContextType contextStore); static void TDFXDestroyContext(ScreenPtr pScreen, drm_context_t hwContext, DRIContextType contextStore); static void TDFXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, DRIContextType readContextType, void *readContextStore, DRIContextType writeContextType, void *writeContextStore); static Bool TDFXDRIOpenFullScreen(ScreenPtr pScreen); static Bool TDFXDRICloseFullScreen(ScreenPtr pScreen); static void TDFXDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index); static void TDFXDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, RegionPtr prgnSrc, CARD32 index); static void TDFXDRITransitionTo2d(ScreenPtr pScreen); static void TDFXDRITransitionTo3d(ScreenPtr pScreen); static void TDFXDoWakeupHandler(WAKEUPHANDLER_ARGS_DECL) { SCREEN_PTR(arg); ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TDFXPtr pTDFX = TDFXPTR(pScrn); pTDFX->pDRIInfo->wrap.WakeupHandler = pTDFX->coreWakeupHandler; (*pTDFX->pDRIInfo->wrap.WakeupHandler) (WAKEUPHANDLER_ARGS); pTDFX->pDRIInfo->wrap.WakeupHandler = TDFXDoWakeupHandler; TDFXNeedSync(pScrn); } static void TDFXDoBlockHandler(BLOCKHANDLER_ARGS_DECL) { SCREEN_PTR(arg); ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TDFXPtr pTDFX = TDFXPTR(pScrn); TDFXCheckSync(pScrn); pTDFX->pDRIInfo->wrap.BlockHandler = pTDFX->coreBlockHandler; (*pTDFX->pDRIInfo->wrap.BlockHandler) (BLOCKHANDLER_ARGS); pTDFX->pDRIInfo->wrap.BlockHandler = TDFXDoBlockHandler; } Bool TDFXDRIScreenInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TDFXPtr pTDFX = TDFXPTR(pScrn); DRIInfoPtr pDRIInfo; TDFXDRIPtr pTDFXDRI; Bool bppOk = FALSE; switch (pScrn->bitsPerPixel) { case 16: bppOk = TRUE; break; case 32: if (pTDFX->ChipType > PCI_CHIP_VOODOO3) { bppOk = TRUE; } break; } if (!bppOk) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] tdfx DRI not supported in %d bpp mode, disabling DRI.\n", (pScrn->bitsPerPixel)); if (pTDFX->ChipType <= PCI_CHIP_VOODOO3) { xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] To use DRI, invoke the server using 16 bpp\n" "\t(-depth 15 or -depth 16).\n"); } else { xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] To use DRI, invoke the server using 16 bpp\n" "\t(-depth 15 or -depth 16) or 32 bpp (-depth 24 -fbbpp 32).\n"); } return FALSE; } /* Check that the DRI, and DRM modules have been loaded by testing for canonical symbols in each module. */ if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE; if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { xf86DrvMsg(pScreen->myNum, X_ERROR, "TDFXDRIScreenInit failed (libdri.a too old)\n"); return FALSE; } /* Check the DRI version */ { int major, minor, patch; DRIQueryVersion(&major, &minor, &patch); if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] TDFXDRIScreenInit failed because of a version mismatch.\n" "[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n" "[dri] Disabling the DRI.\n", major, minor, patch, DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); return FALSE; } } pDRIInfo = DRICreateInfoRec(); if (!pDRIInfo) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRICreateInfoRect() failed, disabling DRI.\n"); return FALSE; } pTDFX->pDRIInfo = pDRIInfo; pDRIInfo->drmDriverName = TDFXKernelDriverName; pDRIInfo->clientDriverName = TDFXClientDriverName; #ifdef XSERVER_LIBPCIACCESS pDRIInfo->busIdString = DRICreatePCIBusID(pTDFX->PciInfo[0]); #else if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { pDRIInfo->busIdString = DRICreatePCIBusID(pTDFX->PciInfo); } else { pDRIInfo->busIdString = malloc(64); sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", ((pciConfigPtr)pTDFX->PciInfo->thisCard)->busnum, ((pciConfigPtr)pTDFX->PciInfo->thisCard)->devnum, ((pciConfigPtr)pTDFX->PciInfo->thisCard)->funcnum); } #endif pDRIInfo->ddxDriverMajorVersion = TDFX_MAJOR_VERSION; pDRIInfo->ddxDriverMinorVersion = TDFX_MINOR_VERSION; pDRIInfo->ddxDriverPatchVersion = TDFX_PATCHLEVEL; pDRIInfo->frameBufferPhysicalAddress = (pointer) pTDFX->LinearAddr[0]; pDRIInfo->frameBufferSize = pTDFX->FbMapSize; pDRIInfo->frameBufferStride = pTDFX->stride; pDRIInfo->ddxDrawableTableEntry = TDFX_MAX_DRAWABLES; pTDFX->coreBlockHandler = pDRIInfo->wrap.BlockHandler; pDRIInfo->wrap.BlockHandler = TDFXDoBlockHandler; pTDFX->coreWakeupHandler = pDRIInfo->wrap.WakeupHandler; pDRIInfo->wrap.WakeupHandler = TDFXDoWakeupHandler; if (SAREA_MAX_DRAWABLES < TDFX_MAX_DRAWABLES) pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES; else pDRIInfo->maxDrawableTableEntry = TDFX_MAX_DRAWABLES; #ifdef NOT_DONE /* FIXME need to extend DRI protocol to pass this size back to client * for SAREA mapping that includes a device private record */ pDRIInfo->SAREASize = ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */ /* + shared memory device private rec */ #else /* For now the mapping works by using a fixed size defined * in the SAREA header */ if (sizeof(XF86DRISAREARec)+sizeof(TDFXSAREAPriv)>SAREA_MAX) { xf86DrvMsg(pScreen->myNum, X_ERROR, "Data does not fit in SAREA\n"); return FALSE; } pDRIInfo->SAREASize = SAREA_MAX; #endif if (!(pTDFXDRI = (TDFXDRIPtr)calloc(sizeof(TDFXDRIRec),1))) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRI memory allocation failed, disabling DRI.\n"); DRIDestroyInfoRec(pTDFX->pDRIInfo); pTDFX->pDRIInfo=0; return FALSE; } pDRIInfo->devPrivate = pTDFXDRI; pDRIInfo->devPrivateSize = sizeof(TDFXDRIRec); pDRIInfo->contextSize = sizeof(TDFXDRIContextRec); pDRIInfo->CreateContext = TDFXCreateContext; pDRIInfo->DestroyContext = TDFXDestroyContext; pDRIInfo->SwapContext = TDFXDRISwapContext; pDRIInfo->InitBuffers = TDFXDRIInitBuffers; pDRIInfo->MoveBuffers = TDFXDRIMoveBuffers; pDRIInfo->OpenFullScreen = TDFXDRIOpenFullScreen; pDRIInfo->CloseFullScreen = TDFXDRICloseFullScreen; pDRIInfo->TransitionTo2d = TDFXDRITransitionTo2d; pDRIInfo->TransitionTo3d = TDFXDRITransitionTo3d; pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; pDRIInfo->createDummyCtx = FALSE; pDRIInfo->createDummyCtxPriv = FALSE; if (!DRIScreenInit(pScreen, pDRIInfo, &pTDFX->drmSubFD)) { free(pDRIInfo->devPrivate); pDRIInfo->devPrivate=0; DRIDestroyInfoRec(pTDFX->pDRIInfo); pTDFX->pDRIInfo=0; xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRIScreenInit failed, disabling DRI.\n"); return FALSE; } /* Check the TDFX DRM version */ { drmVersionPtr version = drmGetVersion(pTDFX->drmSubFD); if (version) { if (version->version_major != 1 || version->version_minor < 0) { /* incompatible drm version */ xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] TDFXDRIScreenInit failed because of a version mismatch.\n" "[dri] tdfx.o kernel module version is %d.%d.%d but version 1.0.x is needed.\n" "[dri] Disabling the DRI.\n", version->version_major, version->version_minor, version->version_patchlevel); TDFXDRICloseScreen(pScreen); drmFreeVersion(version); return FALSE; } drmFreeVersion(version); } } pTDFXDRI->regsSize=TDFXIOMAPSIZE; if (drmAddMap(pTDFX->drmSubFD, (drm_handle_t)pTDFX->MMIOAddr[0], pTDFXDRI->regsSize, DRM_REGISTERS, 0, &pTDFXDRI->regs)<0) { TDFXDRICloseScreen(pScreen); xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap failed, disabling DRI.\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n", pTDFXDRI->regs); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "visual configs initialized\n" ); return TRUE; } void TDFXDRICloseScreen(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TDFXPtr pTDFX = TDFXPTR(pScrn); DRICloseScreen(pScreen); if (pTDFX->pDRIInfo) { if (pTDFX->pDRIInfo->devPrivate) { free(pTDFX->pDRIInfo->devPrivate); pTDFX->pDRIInfo->devPrivate=0; } DRIDestroyInfoRec(pTDFX->pDRIInfo); pTDFX->pDRIInfo=0; } } static Bool TDFXCreateContext(ScreenPtr pScreen, VisualPtr visual, drm_context_t hwContext, void *pVisualConfigPriv, DRIContextType contextStore) { return TRUE; } static void TDFXDestroyContext(ScreenPtr pScreen, drm_context_t hwContext, DRIContextType contextStore) { } Bool TDFXDRIFinishScreenInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TDFXPtr pTDFX = TDFXPTR(pScrn); TDFXDRIPtr pTDFXDRI; pTDFX->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; pTDFXDRI=(TDFXDRIPtr)pTDFX->pDRIInfo->devPrivate; #ifdef XSERVER_LIBPCIACCESS pTDFXDRI->deviceID = DEVICE_ID(pTDFX->PciInfo[0]); #else pTDFXDRI->deviceID = DEVICE_ID(pTDFX->PciInfo); #endif pTDFXDRI->width=pScrn->virtualX; pTDFXDRI->height=pScrn->virtualY; pTDFXDRI->mem=pScrn->videoRam*1024; pTDFXDRI->cpp=pTDFX->cpp; pTDFXDRI->stride=pTDFX->stride; pTDFXDRI->fifoOffset=pTDFX->fifoOffset; pTDFXDRI->fifoSize=pTDFX->fifoSize; pTDFXDRI->textureOffset=pTDFX->texOffset; pTDFXDRI->textureSize=pTDFX->texSize; pTDFXDRI->fbOffset=pTDFX->fbOffset; pTDFXDRI->backOffset=pTDFX->backOffset; pTDFXDRI->depthOffset=pTDFX->depthOffset; pTDFXDRI->sarea_priv_offset = sizeof(XF86DRISAREARec); return DRIFinishScreenInit(pScreen); } static void TDFXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, DRIContextType oldContextType, void *oldContext, DRIContextType newContextType, void *newContext) { } static void TDFXDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) { #ifdef HAVE_XAA_H ScreenPtr pScreen = pWin->drawable.pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TDFXPtr pTDFX = TDFXPTR(pScrn); BoxPtr pbox; int nbox; /* It looks nicer if these start out black */ pbox = REGION_RECTS(prgn); nbox = REGION_NUM_RECTS(prgn); TDFXSetupForSolidFill(pScrn, 0, GXcopy, -1); while (nbox--) { TDFXSelectBuffer(pTDFX, TDFX_BACK); TDFXSubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, pbox->x2-pbox->x1, pbox->y2-pbox->y1); TDFXSelectBuffer(pTDFX, TDFX_DEPTH); TDFXSubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, pbox->x2-pbox->x1, pbox->y2-pbox->y1); pbox++; } TDFXSelectBuffer(pTDFX, TDFX_FRONT); pTDFX->AccelInfoRec->NeedToSync = TRUE; #endif } static void TDFXDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, RegionPtr prgnSrc, CARD32 index) { #ifdef HAVE_XAA_H ScreenPtr pScreen = pParent->drawable.pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TDFXPtr pTDFX = TDFXPTR(pScrn); int dx, dy, xdir, ydir, i, x, y, nbox; BoxPtr pbox; dx = pParent->drawable.x - ptOldOrg.x; dy = pParent->drawable.y - ptOldOrg.y; DRIMoveBuffersHelper(pScreen, dx, dy, &xdir, &ydir, prgnSrc); pbox = REGION_RECTS(prgnSrc); nbox = REGION_NUM_RECTS(prgnSrc); TDFXSetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, ~0, -1); TDFXSelectBuffer(pTDFX, TDFX_BACK); for(i = 0; i < nbox; i++) { x = pbox[i].x1; y = pbox[i].y1; TDFXSubsequentScreenToScreenCopy(pScrn, x, y, x+dx, y+dy, pbox[i].x2 - x, pbox[i].y2 - y); } TDFXSelectBuffer(pTDFX, TDFX_DEPTH); for(i = 0; i < nbox; i++) { x = pbox[i].x1; y = pbox[i].y1; TDFXSubsequentScreenToScreenCopy(pScrn, x, y, x+dx, y+dy, pbox[i].x2 - x, pbox[i].y2 - y); } TDFXSelectBuffer(pTDFX, TDFX_FRONT); pTDFX->AccelInfoRec->NeedToSync = TRUE; #endif } /* * the FullScreen DRI code is dead; this is just left in place to show how * to set up SLI mode. */ static Bool TDFXDRIOpenFullScreen(ScreenPtr pScreen) { #if 0 ScrnInfoPtr pScrn; TDFXPtr pTDFX; xf86DrvMsg(pScreen->myNum, X_INFO, "OpenFullScreen\n"); pScrn = xf86ScreenToScrn(pScreen); pTDFX=TDFXPTR(pScrn); if (pTDFX->numChips>1) { TDFXSetupSLI(pScrn); } #endif return TRUE; } static Bool TDFXDRICloseFullScreen(ScreenPtr pScreen) { #if 0 ScrnInfoPtr pScrn; xf86DrvMsg(pScreen->myNum, X_INFO, "CloseFullScreen\n"); pScrn = xf86ScreenToScrn(pScreen); TDFXDisableSLI(pScrn); #endif return TRUE; } static void TDFXDRITransitionTo2d(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TDFXPtr pTDFX = TDFXPTR(pScrn); xf86FreeOffscreenArea(pTDFX->reservedArea); } static void TDFXDRITransitionTo3d(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TDFXPtr pTDFX = TDFXPTR(pScrn); FBAreaPtr pArea; if(pTDFX->overlayBuffer) { xf86FreeOffscreenLinear(pTDFX->overlayBuffer); pTDFX->overlayBuffer = NULL; } if(pTDFX->overlayBuffer2) { xf86FreeOffscreenLinear(pTDFX->overlayBuffer2); pTDFX->overlayBuffer2 = NULL; } if(pTDFX->textureBuffer) { xf86FreeOffscreenArea(pTDFX->textureBuffer); pTDFX->textureBuffer = NULL; } xf86PurgeUnlockedOffscreenAreas(pScreen); pArea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, pTDFX->pixmapCacheLinesMin, pScrn->displayWidth, NULL, NULL, NULL); pTDFX->reservedArea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, pTDFX->pixmapCacheLinesMax - pTDFX->pixmapCacheLinesMin, pScrn->displayWidth, NULL, NULL, NULL); xf86FreeOffscreenArea(pArea); }