diff options
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/drivers/tdfx')
7 files changed, 1253 insertions, 735 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx.h b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx.h index 62ee2add7..beee925a7 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx.h @@ -12,6 +12,7 @@ #include "xf86PciInfo.h" #include "xf86Pci.h" +#include "xf86xv.h" #include "tdfxdefs.h" #ifdef XF86DRI @@ -35,16 +36,11 @@ struct _TDFXRec; typedef struct _TDFXRec *TDFXPtr; -#ifdef XF86DRI -#define PIXMAP_CACHE_LINES 750 -#else -#define PIXMAP_CACHE_LINES 2048 -#endif - - #include "tdfx_priv.h" extern void TDFXSwapContextFifo(ScreenPtr pScreen); extern void TDFXLostContext(ScreenPtr pScreen); +extern Bool TDFXSetupSLI(ScrnInfoPtr pScrn, Bool sliEnable, int aaSamples); +extern Bool TDFXDisableSLI(TDFXPtr pTDFX); #ifdef XF86DRI extern void FillPrivateDRI(TDFXPtr pTDFX, TDFXDRIPtr pTDFXDRI); @@ -205,7 +201,19 @@ typedef struct _TDFXRec { * shadow everything and make it happen automatically for every write. */ INT32 sst2DSrcFmtShadow; INT32 sst2DDstFmtShadow; - int pixmapCacheLines; + int pixmapCacheLinesMin; + int pixmapCacheLinesMax; + FBAreaPtr reservedArea; + Bool ShowCache; + Bool OverlayXvideo; + Bool TextureXvideo; + int videoKey; + void (*VideoTimerCallback)(ScrnInfoPtr, Time); + FBLinearPtr overlayBuffer; + FBAreaPtr textureBuffer; + XF86VideoAdaptorPtr overlayAdaptor; + XF86VideoAdaptorPtr textureAdaptor; + ScreenBlockHandlerProcPtr BlockHandler; } TDFXRec; typedef struct { @@ -215,6 +223,15 @@ typedef struct { int TexOwner; } TDFXSAREAPriv; +typedef struct { + RegionRec clip; + CARD32 colorKey; + int filterQuality; + CARD32 videoStatus; + Time offTime; + Time freeTime; +} TDFXPortPrivRec, *TDFXPortPrivPtr; + #define TDFXPTR(p) ((TDFXPtr)((p)->driverPrivate)) #define DRAW_STATE_CLIPPING 0x1 @@ -269,5 +286,3 @@ extern void TDFXSelectBuffer(TDFXPtr pTDFX, int which); #endif - - diff --git a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dga.c b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dga.c index 896add046..d97363b57 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dga.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dga.c @@ -6,6 +6,7 @@ #include "dgaproc.h" #include "tdfx.h" +#include "vgaHW.h" static Bool TDFX_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, int *, int *, int *); @@ -93,24 +94,20 @@ SECOND_PASS: currentMode->imageHeight = pScrn->virtualY; currentMode->pixmapWidth = currentMode->imageWidth; currentMode->pixmapHeight = currentMode->imageHeight; - currentMode->maxViewportX = currentMode->imageWidth - - currentMode->viewportWidth; + currentMode->maxViewportX = currentMode->imageWidth - currentMode->viewportWidth; /* this might need to get clamped to some maximum */ - currentMode->maxViewportY = currentMode->imageHeight - - currentMode->viewportHeight; + currentMode->maxViewportY = currentMode->imageHeight - currentMode->viewportHeight; oneMore = FALSE; goto SECOND_PASS; } else { currentMode->bytesPerScanline = ((pScrn->displayWidth * pTDFX->cpp) + 3) & ~3L; currentMode->imageWidth = pScrn->displayWidth; - currentMode->imageHeight = pScrn->virtualY; + currentMode->imageHeight = pScrn->virtualY; currentMode->pixmapWidth = currentMode->imageWidth; currentMode->pixmapHeight = currentMode->imageHeight; - currentMode->maxViewportX = currentMode->imageWidth - - currentMode->viewportWidth; + currentMode->maxViewportX = currentMode->imageWidth - currentMode->viewportWidth; /* this might need to get clamped to some maximum */ - currentMode->maxViewportY = currentMode->imageHeight - - currentMode->viewportHeight; + currentMode->maxViewportY = currentMode->imageHeight - currentMode->viewportHeight; } pMode = pMode->next; @@ -125,25 +122,26 @@ SECOND_PASS: static Bool TDFX_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode) { - static int OldDisplayWidth[MAXSCREENS]; + static DisplayModePtr OldModes[MAXSCREENS]; int index = pScrn->pScreen->myNum; TDFXPtr pTDFX = TDFXPTR(pScrn); if (!pMode) { /* restore the original mode */ /* put the ScreenParameters back */ - pScrn->displayWidth = OldDisplayWidth[index]; - TDFXSwitchMode(index, pScrn->currentMode, 0); - pTDFX->DGAactive = FALSE; + if (pTDFX->DGAactive) { + TDFXSwitchMode(index, OldModes[index], 0); + TDFXAdjustFrame(pScrn->pScreen->myNum, 0, 0, 0); + pTDFX->DGAactive = FALSE; + } } else { - if (!pTDFX->DGAactive) { /* save the old parameters */ - OldDisplayWidth[index] = pScrn->displayWidth; - + /* save the old ScreenParameters */ + if (!pTDFX->DGAactive) { + OldModes[index] = pScrn->currentMode; pTDFX->DGAactive = TRUE; } pScrn->displayWidth = pMode->bytesPerScanline / pTDFX->cpp; - TDFXSwitchMode(index, pMode->mode, 0); } @@ -162,9 +160,14 @@ static void TDFX_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) { TDFXPtr pTDFX = TDFXPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); TDFXAdjustFrame(pScrn->pScreen->myNum, x, y, flags); - pTDFX->DGAViewportStatus = 0; /* TDFXAdjustFrame loops until finished */ + + while (hwp->readST01(hwp) & 0x08); + while (!(hwp->readST01(hwp) & 0x08)); + + pTDFX->DGAViewportStatus = 0; } static void @@ -189,10 +192,8 @@ TDFX_BlitRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; int ydir = (srcy < dsty) ? -1 : 1; - (*pTDFX->AccelInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, - GXcopy, ~0, -1); - (*pTDFX->AccelInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, - dstx, dsty, w, h); + (*pTDFX->AccelInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, ~0, -1); + (*pTDFX->AccelInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, dstx, dsty, w, h); } } @@ -224,7 +225,7 @@ TDFX_OpenFramebuffer( *name = NULL; /* no special device */ *mem = (unsigned char*)pTDFX->LinearAddr[0]; *size = pTDFX->FbMapSize; - *offset = 0; + *offset = 0; *flags = DGA_NEED_ROOT; return TRUE; diff --git a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dri.c b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dri.c index 8c5831420..f5e7306a2 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dri.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dri.c @@ -31,6 +31,8 @@ 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 Bool TDFXInitVisualConfigs(ScreenPtr pScreen) @@ -375,6 +377,8 @@ Bool TDFXDRIScreenInit(ScreenPtr pScreen) pDRIInfo->MoveBuffers = TDFXDRIMoveBuffers; pDRIInfo->OpenFullScreen = TDFXDRIOpenFullScreen; pDRIInfo->CloseFullScreen = TDFXDRICloseFullScreen; + pDRIInfo->TransitionTo2d = TDFXDRITransitionTo2d; + pDRIInfo->TransitionTo3d = TDFXDRITransitionTo3d; pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; if (!DRIScreenInit(pScreen, pDRIInfo, &pTDFX->drmSubFD)) { @@ -704,3 +708,42 @@ TDFXDRICloseFullScreen(ScreenPtr pScreen) return TRUE; } + +static void +TDFXDRITransitionTo2d(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TDFXPtr pTDFX = TDFXPTR(pScrn); + + xf86FreeOffscreenArea(pTDFX->reservedArea); +} + + +static void +TDFXDRITransitionTo3d(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TDFXPtr pTDFX = TDFXPTR(pScrn); + FBAreaPtr pArea; + + if(pTDFX->overlayBuffer) { + xf86FreeOffscreenLinear(pTDFX->overlayBuffer); + pTDFX->overlayBuffer = NULL; + } + + if(pTDFX->textureBuffer) { + xf86FreeOffscreenArea(pTDFX->textureBuffer); + pTDFX->textureBuffer = NULL; + } + + xf86PurgeUnlockedOffscreenAreas(pScreen); + + /* this is an ugly hack! isnt there a resize? */ + 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); +} diff --git a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_driver.c b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_driver.c index a39c9b780..e3c72918d 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_driver.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_driver.c @@ -89,6 +89,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "tdfx.h" #include "miscstruct.h" +#include "dixstruct.h" #include "xf86xv.h" #include "Xv.h" @@ -135,6 +136,8 @@ static void TDFXFreeScreen(int scrnIndex, int flags); static int TDFXValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags); +static void TDFXBlockHandler(int, pointer, pointer, pointer); + #ifdef DPMSExtension /* Switch to various Display Power Management System levels */ static void TDFXDisplayPowerManagementSet(ScrnInfoPtr pScrn, @@ -178,14 +181,22 @@ typedef enum { OPTION_NOACCEL, OPTION_SW_CURSOR, OPTION_USE_PIO, - OPTION_NO_SLI + OPTION_SHOWCACHE, + OPTION_VIDEO_KEY, + OPTION_NO_SLI, + OPTION_OVERLAY_XV, + OPTION_TEXTURE_XV } TDFXOpts; static OptionInfoRec TDFXOptions[] = { { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_USE_PIO, "UsePIO", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE}, { OPTION_NO_SLI, "NoSLI", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_OVERLAY_XV, "OverlayXvideo", OPTV_BOOLEAN, {1}, TRUE}, + { OPTION_TEXTURE_XV, "TextureXvideo", OPTV_BOOLEAN, {1}, TRUE}, { -1, NULL, OPTV_NONE, {0}, FALSE} }; @@ -399,7 +410,7 @@ TDFXProbeDDC(ScrnInfoPtr pScrn, int index) #endif { pVbe = VBEInit(NULL,index); - vbeDoEDID(pVbe, NULL); + ConfiguredMonitor = vbeDoEDID(pVbe, NULL); } } @@ -949,6 +960,30 @@ TDFXPreInit(ScrnInfoPtr pScrn, int flags) } } + if (!xf86GetOptValBool(TDFXOptions, OPTION_SHOWCACHE, &(pTDFX->ShowCache))) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache %s\n", pTDFX->ShowCache ? "Enabled" : "Disabled"); + } else { + pTDFX->ShowCache = FALSE; + } + + if (xf86GetOptValBool(TDFXOptions, OPTION_OVERLAY_XV, &(pTDFX->OverlayXvideo))) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Overlay Xvideo Adaptor %s\n", pTDFX->OverlayXvideo ? "Enabled" : "Disabled"); + } else { + pTDFX->OverlayXvideo = TRUE; + } + + if (xf86GetOptValBool(TDFXOptions, OPTION_TEXTURE_XV, &(pTDFX->TextureXvideo))) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Texture Xvideo Adaptor %s\n", pTDFX->TextureXvideo ? "Enabled" : "Disabled"); + } else { + pTDFX->TextureXvideo = TRUE; + } + + if (xf86GetOptValInteger(TDFXOptions, OPTION_VIDEO_KEY, &(pTDFX->videoKey))) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", pTDFX->videoKey); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key default 0x%x\n", pTDFX->videoKey = 0x1E); + } + if (!xf86ReturnOptValBool(TDFXOptions, OPTION_SW_CURSOR, FALSE)) { if (!xf86LoadSubModule(pScrn, "ramdac")) { TDFXFreeRec(pScrn); @@ -1440,6 +1475,7 @@ TDFXModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) int hd, hbs, hss, hse, hbe, ht, hskew; Bool dbl; + hd = hbs = hss = hse = hbe = ht = hskew = 0; hwp = VGAHWPTR(pScrn); pTDFX = TDFXPTR(pScrn); @@ -1500,35 +1536,35 @@ TDFXModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) static void TDFXLoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, - short visualClass) { + VisualPtr pVisual) { TDFXPtr pTDFX; int i, j, index, v, repeat, max; TDFXTRACE("TDFXLoadPalette16 start\n"); pTDFX = TDFXPTR(pScrn); + for (i=0; i<numColors; i++) { index=indices[i]; v=(colors[index/2].red<<16)|(colors[index].green<<8)|colors[index/2].blue; - if (i<numColors-1) max=indices[i+1]<<2; - else max=256; - for (j=index<<2; j<max; j++) { + max=min((index+1)<<2, 256); + for (j = index<<2; j < max; j++) + { repeat=100; do { TDFXWriteLongMMIO(pTDFX, DACADDR, j); } while (--repeat && TDFXReadLongMMIO(pTDFX, DACADDR)!=j); if (!repeat) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac index, " - "bypassing CLUT\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac index, bypassing CLUT\n"); pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS; return; } + repeat=100; do { TDFXWriteLongMMIO(pTDFX, DACDATA, v); } while (--repeat && TDFXReadLongMMIO(pTDFX, DACDATA)!=v); if (!repeat) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac value, " - "bypassing CLUT\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac value, bypassing CLUT\n"); pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS; return; } @@ -1538,7 +1574,7 @@ TDFXLoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, static void TDFXLoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, - short visualClass) { + VisualPtr pVisual) { TDFXPtr pTDFX; int i, index, v, repeat; @@ -1635,11 +1671,8 @@ calcBufferSize(int xres, int yres, Bool tiled, int cpp) } /* calcBufferSize */ static void allocateMemory(ScrnInfoPtr pScrn) { - TDFXPtr pTDFX; - int memRemaining, texSize, fifoSize, screenSizeInTiles; - - pTDFX = TDFXPTR(pScrn); - pTDFX->stride = pScrn->displayWidth*pTDFX->cpp; + TDFXPtr pTDFX = TDFXPTR(pScrn); + int memRemaining, fbSize, cursorSize, fifoSize, screenSizeInTiles; if (pTDFX->cpp!=3) { screenSizeInTiles=calcBufferSize(pScrn->virtualX, pScrn->virtualY, @@ -1658,7 +1691,7 @@ static void allocateMemory(ScrnInfoPtr pScrn) { /* it to be on an *odd* page boundary. */ pTDFX->depthOffset = (memRemaining - screenSizeInTiles) &~ 0xFFF; if ((pTDFX->depthOffset & (0x1 << 12)) == 0) { -#if 0 +#if 1 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Changing depth offset from 0x%08x to 0x%08x\n", pTDFX->depthOffset, @@ -1670,7 +1703,7 @@ static void allocateMemory(ScrnInfoPtr pScrn) { /* to be on an *even* page boundary. */ pTDFX->backOffset = (pTDFX->depthOffset - screenSizeInTiles) &~ 0xFFF; if (pTDFX->backOffset & (0x1 << 12)) { -#if 0 +#if 1 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Changing back offset from 0x%08x to 0x%08x\n", pTDFX->backOffset, @@ -1678,52 +1711,59 @@ static void allocateMemory(ScrnInfoPtr pScrn) { #endif pTDFX->backOffset -= (0x1 << 12); } - /* Now, place the front buffer, forcing */ - /* it to be on a page boundary too, just */ - /* for giggles. */ - pTDFX->fbOffset - = (pTDFX->backOffset - (pScrn->virtualY+PIXMAP_CACHE_LINES)*pTDFX->stride) &~ 0xFFF; /* Give the cmd fifo at least */ /* CMDFIFO_PAGES pages, but no more than */ /* 255. */ fifoSize = ((255 <= CMDFIFO_PAGES) ? 255 : CMDFIFO_PAGES) << 12; + fbSize = (pScrn->virtualY + pTDFX->pixmapCacheLinesMin) * pTDFX->stride; + cursorSize = 4096; /* We give 4096 bytes to the cursor, fifoSize to the */ /* FIFO, and everything to textures. */ /* Bump everything by 64k to move it past VGA memory */ - texSize = (pTDFX->fbOffset - fifoSize - 4096 - 64*1024); - pTDFX->texOffset = pTDFX->fbOffset - texSize + 64*1024; - pTDFX->texSize = texSize; - pTDFX->fifoOffset = 4096+64*1024; + pTDFX->cursorOffset = 64*1024; + pTDFX->fifoOffset = pTDFX->cursorOffset + cursorSize; pTDFX->fifoSize = fifoSize; - pTDFX->cursorOffset = 0+64*1024; -#if 0 + /* Now, place the front buffer, forcing */ + /* it to be on a page boundary too, just */ + /* for giggles. */ + pTDFX->fbOffset = (pTDFX->fifoOffset + pTDFX->fifoSize) &~ 0xFFF; + pTDFX->texOffset = pTDFX->fbOffset + fbSize; + pTDFX->texSize = pTDFX->backOffset - pTDFX->texOffset; + + if (pTDFX->texSize <= 0) { + pTDFX->backOffset = -1; + pTDFX->depthOffset = -1; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No Texture Memory available, disabling DRI\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Texture Memory %0.02f MB\n", pTDFX->texSize / 1024.0 / 1024.0); + } + +#if 1 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Cursor Offset: [0x%08X,0x%08X)\n", pTDFX->cursorOffset, - pTDFX->cursorOffset+1024); + pTDFX->cursorOffset + cursorSize); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Fifo Offset: [0x%08X, 0x%08X)\n", pTDFX->fifoOffset, - pTDFX->fifoOffset+fifoSize); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Texture Offset: [0x%08X, 0x%08X)\n", - pTDFX->texOffset, - pTDFX->texOffset + texSize); + pTDFX->fifoOffset + pTDFX->fifoSize); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front Buffer Offset: [0x%08X, 0x%08X)\n", pTDFX->fbOffset, - pTDFX->fbOffset + (pScrn->virtualY+PIXMAP_CHACHE_LINES)*pTDFX->stride); + pTDFX->fbOffset + fbSize); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Texture Offset: [0x%08X, 0x%08X)\n", + pTDFX->texOffset, + pTDFX->texOffset + pTDFX->texSize); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BackOffset: [0x%08X, 0x%08X)\n", pTDFX->backOffset, - pTDFX->backOffset+screenSizeInTiles); + pTDFX->backOffset + screenSizeInTiles); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DepthOffset: [0x%08X, 0x%08X)\n", pTDFX->depthOffset, - pTDFX->depthOffset+screenSizeInTiles); + pTDFX->depthOffset + screenSizeInTiles); #endif /* 0/1 */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Textures Memory %0.02f MB\n", - (float)texSize/1024.0/1024.0); } static Bool @@ -1734,7 +1774,6 @@ TDFXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { VisualPtr visual; int maxy; BoxRec MemBox; - RegionRec MemRegion; TDFXTRACE("TDFXScreenInit start\n"); pScrn = xf86Screens[pScreen->myNum]; @@ -1748,6 +1787,10 @@ TDFXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { vgaHWGetIOBase(hwp); if (!vgaHWMapMem(pScrn)) return FALSE; + /* we want at least enough pixmap cache to do DVD */ + pTDFX->stride = pScrn->displayWidth*pTDFX->cpp; + pTDFX->pixmapCacheLinesMin = ((720*480*2) + pTDFX->stride - 1) / pTDFX->stride; + allocateMemory(pScrn); #if 0 @@ -1769,13 +1812,30 @@ TDFXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { return FALSE; } - maxy=pScrn->virtualY+PIXMAP_CACHE_LINES; - MemBox.y1 = pScrn->virtualY; + pTDFX->pixmapCacheLinesMax = (pTDFX->backOffset - pTDFX->fbOffset) / pTDFX->stride; + if(pTDFX->ChipType < PCI_CHIP_VOODOO5) { + if (pTDFX->pixmapCacheLinesMax > 2048) + pTDFX->pixmapCacheLinesMax = 2048; + } else { + if (pTDFX->pixmapCacheLinesMax > 4095) + pTDFX->pixmapCacheLinesMax = 4095; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "%d pixmap cache lines for 2D/video when 3D inactive\n", + pTDFX->pixmapCacheLinesMax); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "%d pixmap cache lines for 2D/video when 3D active\n", + pTDFX->pixmapCacheLinesMin); + + /* region the whole memory (framebuffer+pixmapcache) and let + * xf86InitFBManager do the visible region subtraction + */ MemBox.x1 = 0; + MemBox.y1 = 0; MemBox.x2 = pScrn->displayWidth; - MemBox.y2 = maxy; - - pTDFX->maxClip=((pScrn->virtualX+1)&0xFFF) | (((maxy+1)&0xFFF)<<16); + MemBox.y2 = pTDFX->pixmapCacheLinesMax; + pTDFX->maxClip = (MemBox.x2) | (MemBox.y2 << 16); TDFXSave(pScrn); if (!TDFXModeInit(pScrn, pScrn->currentMode)) return FALSE; @@ -1797,8 +1857,11 @@ TDFXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { * is called. fbScreenInit will eventually call into the drivers * InitGLXVisuals call back. */ - if (!pTDFX->NoAccel) - pTDFX->directRenderingEnabled = TDFXDRIScreenInit(pScreen); + if (!pTDFX->NoAccel) { + if ((pTDFX->backOffset != -1) && (pTDFX->depthOffset != -1)) { + pTDFX->directRenderingEnabled = TDFXDRIScreenInit(pScreen); + } + } #endif switch (pScrn->bitsPerPixel) { @@ -1840,13 +1903,7 @@ TDFXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { TDFXDGAInit(pScreen); - REGION_INIT(pScreen, &MemRegion, &MemBox, 1); - if (!xf86InitFBManagerRegion(pScreen, &MemRegion)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to init memory manager\n"); - REGION_UNINIT(pScreen, &MemRegion); - return FALSE; - } - REGION_UNINIT(pScreen, &MemRegion); + xf86InitFBManager(pScreen, &MemBox); if (!pTDFX->NoAccel) { if (!TDFXAccelInit(pScreen)) { @@ -1912,6 +1969,9 @@ TDFXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { pTDFX->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = TDFXCloseScreen; + pTDFX->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = TDFXBlockHandler; + if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); @@ -1936,6 +1996,10 @@ TDFXAdjustFrame(int scrnIndex, int x, int y, int flags) { TDFXTRACE("TDFXAdjustFrame start\n"); pScrn = xf86Screens[scrnIndex]; pTDFX = TDFXPTR(pScrn); + + if (pTDFX->ShowCache && y && pScrn->vtSema) + y += pScrn->virtualY - 1; + tdfxReg = &pTDFX->ModeReg; tdfxReg->startaddr = pTDFX->fbOffset+y*pTDFX->stride+(x*pTDFX->cpp); TDFXTRACE("TDFXAdjustFrame to x=%d y=%d offset=%d\n", x, y, tdfxReg->startaddr); @@ -1945,14 +2009,15 @@ TDFXAdjustFrame(int scrnIndex, int x, int y, int flags) { static Bool TDFXEnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn; -#ifdef XF86DRI ScreenPtr pScreen; +#ifdef XF86DRI TDFXPtr pTDFX; #endif TDFXTRACE("TDFXEnterVT start\n"); pScrn = xf86Screens[scrnIndex]; - InstallFifo(pScrn); + pScreen = screenInfo.screens[scrnIndex]; + TDFXInitFifo(pScreen); #ifdef XF86DRI pTDFX = TDFXPTR(pScrn); if (pTDFX->directRenderingEnabled) { @@ -2029,9 +2094,22 @@ TDFXCloseScreen(int scrnIndex, ScreenPtr pScreen) if (pTDFX->scanlineColorExpandBuffers[1]) xfree(pTDFX->scanlineColorExpandBuffers[1]); pTDFX->scanlineColorExpandBuffers[1]=0; + + if (pTDFX->overlayAdaptor) { + xfree(pTDFX->overlayAdaptor->pPortPrivates[0].ptr); + xf86XVFreeVideoAdaptorRec(pTDFX->overlayAdaptor); + pTDFX->overlayAdaptor = NULL; + } + + if (pTDFX->textureAdaptor) { + xfree(pTDFX->textureAdaptor->pPortPrivates[0].ptr); /* FIXME: use loop */ + xf86XVFreeVideoAdaptorRec(pTDFX->textureAdaptor); + pTDFX->textureAdaptor = NULL; + } pScrn->vtSema=FALSE; + pScreen->BlockHandler = pTDFX->BlockHandler; pScreen->CloseScreen = pTDFX->CloseScreen; return (*pScreen->CloseScreen)(scrnIndex, pScreen); } @@ -2077,7 +2155,7 @@ TDFXBlankScreen(ScrnInfoPtr pScrn, Bool unblank) scrn |= 0x20; /* blank screen */ } - vgaHWSeqReset(hwp, TRUE); + vgaHWSeqReset(hwp, TRUE); hwp->writeSeq(hwp, 0x01, scrn); /* change mode */ vgaHWSeqReset(hwp, FALSE); } @@ -2101,6 +2179,22 @@ TDFXSaveScreen(ScreenPtr pScreen, int mode) return TRUE; } +static void +TDFXBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + ScrnInfoPtr pScrn = xf86Screens[i]; + TDFXPtr pTDFX = TDFXPTR(pScrn); + + pScreen->BlockHandler = pTDFX->BlockHandler; + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + pScreen->BlockHandler = TDFXBlockHandler; + + if(pTDFX->VideoTimerCallback) { + (*pTDFX->VideoTimerCallback)(pScrn, currentTime.milliseconds); + } +} + #ifdef DPMSExtension static void TDFXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, diff --git a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_priv.c b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_priv.c index 58e49d1cf..1e590d546 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_priv.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_priv.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_priv.c,v 1.13 2000/12/15 15:19:35 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_priv.c,v 1.11 2000/12/01 14:29:00 dawes Exp $ */ #include "xf86.h" @@ -11,13 +11,19 @@ /* Memory layout of card is as follows: - 000000-003fff: Cursor - 001000-xxxxxx: Fifo (Min of CMDFIFO pages) - xxxxxx-420fff: Texture maps - 421000- A-1 : Framebuffer - A - B-1 : Offscreen pixmaps - B - C-1 : Back buffer - C - D-1 : Z buffer + 000000-00ffff: VGA memory + 010000-013fff: Cursor + 011000-xxxxxx: Fifo (Min of CMDFIFO pages) + xxxxxx- A-1 : Front Buffer (framebuffer) + A - B-1 : Pixmap Cache (framebuffer) + B - C-1 : Texture Memory + C - D-1 : Back Buffer + D - E-1 : Depth Buffer + + NB: pixmap cache usually butts right up against texture memory. when + 3d is disabled (via Transition2D) then the pixmap cache is increased + to overlap the texture memory. maximum pixmap cache of 4095 lines on + voodoo5 and 2048 on voodoo3/4 applies. */ void TDFXSendNOPFifo3D(ScrnInfoPtr pScrn) @@ -117,9 +123,9 @@ void TDFXResetFifo(ScrnInfoPtr pScrn) static void TDFXSyncFifo(ScrnInfoPtr pScrn) { TDFXPtr pTDFX; - int i, cnt; + int i, cnt, resets=0; int stat; - long start_sec, end_sec, dummy; + long start_sec, end_sec, dummy, readptr; TDFXTRACEACCEL("TDFXSyncFifo start\n"); pTDFX=TDFXPTR(pScrn); @@ -127,7 +133,9 @@ static void TDFXSyncFifo(ScrnInfoPtr pScrn) i=0; cnt=0; start_sec=0; + readptr=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0); do { + readptr=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0); stat=TDFXReadLongMMIO(pTDFX, 0); if (stat&SST_BUSY) i=0; else i++; cnt++; @@ -137,7 +145,17 @@ static void TDFXSyncFifo(ScrnInfoPtr pScrn) } else { getsecs(&end_sec, &dummy); if (end_sec-start_sec>3) { - TDFXResetFifo(pScrn); + dummy=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0); + if (dummy==readptr) { + TDFXResetFifo(pScrn); + readptr=dummy; + resets++; + if (resets==3) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Board is not responding.\n"); + return; + } + } start_sec=0; } } @@ -237,24 +255,6 @@ void TDFXSwapContextFifo(ScreenPtr pScreen) pTDFX->fifoSlots = pTDFX->fifoEnd-pTDFX->fifoPtr-8; } -void TDFXLostContext(ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn; - TDFXPtr pTDFX; - TDFXSAREAPriv *sPriv; - - pScrn = xf86Screens[pScreen->myNum]; - pTDFX=TDFXPTR(pScrn); - sPriv=(TDFXSAREAPriv*)DRIGetSAREAPrivate(pScreen); - if (!sPriv) return; - if (sPriv->fifoPtr!=(((unsigned char*)pTDFX->fifoPtr)-pTDFX->FbBase) || - sPriv->fifoRead!=(((unsigned char*)pTDFX->fifoRead)-pTDFX->FbBase)) { - sPriv->fifoPtr=(((unsigned char*)pTDFX->fifoPtr)-pTDFX->FbBase); - sPriv->fifoRead=(((unsigned char*)pTDFX->fifoRead)-pTDFX->FbBase); - sPriv->fifoOwner=DRIGetContext(pScreen); - /* ErrorF("Out FifoPtr=%d FifoRead=%d\n", sPriv->fifoPtr, sPriv->fifoRead); */ - } -} #endif static void diff --git a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c index 8480de20a..d63592085 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c @@ -1,85 +1,134 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c,v 1.5 2000/12/08 21:53:37 mvojkovi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c,v 1.2 2000/12/02 15:30:57 tsi Exp $ */ -/* Adapted from ../mga/mga_video.c */ +#ifndef XvExtension +void TDFXInitVideo(ScreenPtr pScreen) {} +void TDFXCloseVideo(ScreenPtr pScreen) {} +#else #include "xf86.h" -#include "xf86_OSproc.h" -#include "xf86Resources.h" -#include "xf86_ansic.h" -#include "compiler.h" -#include "xf86PciInfo.h" -#include "xf86Pci.h" -#include "xf86fbman.h" -#include "regionstr.h" - #include "tdfx.h" +#include "dixstruct.h" -#include "xf86xv.h" #include "Xv.h" -#include "xaa.h" -#include "xaalocal.h" -#include "dixstruct.h" #include "fourcc.h" +static Atom xvColorKey, xvFilterQuality; + /* These should move into tdfxdefs.h with better names */ -#define YUV_Y_BASE 0xC00000 -#define YUV_U_BASE 0xD00000 -#define YUV_V_BASE 0xE00000 +#define YUV_Y_BASE 0xC00000 +#define YUV_U_BASE 0xD00000 +#define YUV_V_BASE 0xE00000 -#define SST_2D_FORMAT_YUYV 0x8 -#define SST_2D_FORMAT_UYVY 0x9 +#define SST_2D_FORMAT_YUYV 0x8 +#define SST_2D_FORMAT_UYVY 0x9 #define YUVBASEADDR 0x80100 -/* This should move to tdfx.h - * Only one port for now due to need for better memory allocation. */ -#define TDFX_MAX_PORTS 1 - #define YUVSTRIDE 0x80104 +#define VIDPROCCFGMASK 0xa2e3eb6c -#ifndef XvExtension -void TDFXInitVideo(ScreenPtr pScreen) {} -#else +#define OFF_DELAY 250 /* milliseconds */ +#define FREE_DELAY 15000 + +#define OFF_TIMER 0x01 +#define FREE_TIMER 0x02 +#define CLIENT_VIDEO_ON 0x04 +#define TIMER_MASK (OFF_TIMER | FREE_TIMER) + +#define TDFX_MAX_OVERLAY_PORTS 1 +#define TDFX_MAX_TEXTURE_PORTS 32 + +/* Doesn't matter what screen we use */ +#define DummyScreen screenInfo.screens[0] +/* Needed for attribute atoms */ +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +/* + * PROTOTYPES + */ void TDFXInitVideo(ScreenPtr pScreen); -void TDFXCloseVideo (ScreenPtr pScreen); - -static XF86VideoAdaptorPtr TDFXSetupImageVideo(ScreenPtr); -static int TDFXSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); -static int TDFXGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); - -static void TDFXStopVideo(ScrnInfoPtr, pointer, Bool); -static void TDFXQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, - unsigned int *, unsigned int *, pointer); -static int TDFXPutImage(ScrnInfoPtr, short, short, short, short, short, - short, short, short, int, unsigned char*, short, - short, Bool, RegionPtr, pointer); -#if 0 -/* This isn't done yet, but eventually it will put images to the - * video overlay. */ -static int TDFXPutImageOverlay(ScrnInfoPtr pScrn, short, short, - short, short, short, short, - short, short, int, unsigned char*, - short, short, Bool, RegionPtr , pointer); -#endif - -static int TDFXQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, - unsigned short *, int *, int *); - -/* These function is from tdfx_accel.c */ -extern void TDFXFirstSync(ScrnInfoPtr pScrn); +void TDFXCloseVideo(ScreenPtr pScreen); -static FBAreaPtr -TDFXAllocateOffscreenBuffer (ScrnInfoPtr pScrn, int id, int width, int height); +static FBAreaPtr TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height); +static FBLinearPtr TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size); +static void TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time); -static void -TDFXDeallocateOffscreenBuffer (ScrnInfoPtr pScrn, int id); +static XF86VideoAdaptorPtr TDFXSetupImageVideoTexture(ScreenPtr); +static int TDFXSetPortAttributeTexture(ScrnInfoPtr, Atom, INT32, pointer); +static int TDFXGetPortAttributeTexture(ScrnInfoPtr, Atom ,INT32 *, pointer); +static int TDFXPutImageTexture(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer); +static void TDFXStopVideoTexture(ScrnInfoPtr, pointer, Bool); + +static XF86VideoAdaptorPtr TDFXSetupImageVideoOverlay(ScreenPtr); +static int TDFXSetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer); +static int TDFXGetPortAttributeOverlay(ScrnInfoPtr, Atom ,INT32 *, pointer); +static int TDFXPutImageOverlay(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer); +static void TDFXStopVideoOverlay(ScrnInfoPtr, pointer, Bool); +static void TDFXResetVideoOverlay(ScrnInfoPtr); + +static void TDFXQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer); +static int TDFXQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *); + +/* + * ADAPTOR INFORMATION + */ + +static XF86VideoEncodingRec OverlayEncoding[] = +{ + { 0, "XV_IMAGE", 2048, 2048, {1, 1} } +}; + +static XF86VideoEncodingRec TextureEncoding[] = +{ + { 0, "XV_IMAGE", 1024, 1024, {1, 1} } +}; + +static XF86VideoFormatRec OverlayFormats[] = +{ + {8, TrueColor}, {8, DirectColor}, {8, PseudoColor}, + {8, GrayScale}, {8, StaticGray}, {8, StaticColor}, + {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, + {15, DirectColor}, {16, DirectColor}, {24, DirectColor} +}; + +static XF86VideoFormatRec TextureFormats[] = +{ + {15, TrueColor}, {16, TrueColor}, {24, TrueColor} +}; + +static XF86AttributeRec OverlayAttributes[] = +{ + {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, + {XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"} +}; + +static XF86AttributeRec TextureAttributes[] = +{ + {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, + {XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"} +}; + +static XF86ImageRec OverlayImages[] = +{ + XVIMAGE_YUY2, XVIMAGE_UYVY, XVIMAGE_YV12, XVIMAGE_I420 +}; + +static XF86ImageRec TextureImages[] = +{ + XVIMAGE_YV12, XVIMAGE_I420 +}; + +/* + * COMMON SETUP FUNCTIONS + */ void TDFXInitVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; - XF86VideoAdaptorPtr newAdaptor = NULL; + XF86VideoAdaptorPtr newOverlayAdaptor = NULL; + XF86VideoAdaptorPtr newTextureAdaptor = NULL; TDFXPtr pTDFX = TDFXPTR(pScrn); int num_adaptors; @@ -87,685 +136,997 @@ void TDFXInitVideo(ScreenPtr pScreen) if(pTDFX->cpp == 1) return; - newAdaptor = TDFXSetupImageVideo(pScreen); - - /* Initialize the offscreen buffer */ - pTDFX->offscreenYUVBuf = 0; - + /* Start with the generic adaptors */ num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); - if(newAdaptor) { - if(!num_adaptors) { - num_adaptors = 1; - adaptors = &newAdaptor; - } else { - newAdaptors = /* need to free this someplace */ - xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); - if(newAdaptors) { - memcpy(newAdaptors, adaptors, num_adaptors * - sizeof(XF86VideoAdaptorPtr)); - newAdaptors[num_adaptors] = newAdaptor; - adaptors = newAdaptors; - num_adaptors++; - } - } + /* Overlay adaptor */ + if(pTDFX->AccelInfoRec && pTDFX->AccelInfoRec->FillSolidRects) + newOverlayAdaptor = TDFXSetupImageVideoOverlay(pScreen); + + /* Texture adaptor */ + if(pTDFX->AccelInfoRec && pTDFX->AccelInfoRec->FillSolidRects) + newTextureAdaptor = TDFXSetupImageVideoTexture(pScreen); + + /* Add the overlay adaptor to the list */ + if(newOverlayAdaptor) { + newAdaptors = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); + if(newAdaptors) { + if (num_adaptors) memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); + newAdaptors[num_adaptors] = newOverlayAdaptor; + adaptors = newAdaptors; /* FIXME: leak? */ + num_adaptors++; + } } - if(num_adaptors) - { - xf86XVScreenInit(pScreen, adaptors, num_adaptors); + /* Add the texture adaptor to the list */ + if(newTextureAdaptor) { + newAdaptors = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); + if(newAdaptors) { + if (num_adaptors) memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); + newAdaptors[num_adaptors] = newTextureAdaptor; + adaptors = newAdaptors; /* FIXME: leak? */ + num_adaptors++; + } } + if(num_adaptors) + xf86XVScreenInit(pScreen, adaptors, num_adaptors); + if(newAdaptors) - xfree(newAdaptors); + xfree(newAdaptors); } + void TDFXCloseVideo (ScreenPtr pScreen) { - } -/* client libraries expect an encoding */ -static XF86VideoEncodingRec DummyEncoding[1] = + +static XF86VideoAdaptorPtr +TDFXAllocAdaptor(ScrnInfoPtr pScrn, int numberPorts) { - { /* blit limit */ - 0, - "XV_IMAGE", - 1024, 0, /* Height is a limitation of pixmap space, and filled in later. */ - {1, 1} - } -}; + XF86VideoAdaptorPtr adapt; + TDFXPtr pTDFX = TDFXPTR(pScrn); + TDFXPortPrivPtr pPriv; + int i; -#define NUM_FORMATS_OVERLAY 3 + if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) + return NULL; -static XF86VideoFormatRec Formats[NUM_FORMATS_OVERLAY] = -{ - {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, -}; + if(!(pPriv = xcalloc(1, sizeof(TDFXPortPrivRec) + numberPorts * sizeof(DevUnion)))) + { + xfree(adapt); + return NULL; + } -/* #define NUM_IMAGES 4*/ -#define NUM_IMAGES 2 + adapt->pPortPrivates = (DevUnion*)(&pPriv[1]); + for(i = 0; i < numberPorts; i++) + adapt->pPortPrivates[i].val = i; -static XF86ImageRec Images[NUM_IMAGES] = -{ - XVIMAGE_YV12, /* YVU planar */ - XVIMAGE_I420 /* YUV planar */ -#if 0 - /* These could be supported (without a temp bufer) using the - * host-to-screen-stretch */ - XVIMAGE_YUY2, /* YUYV packed */ - XVIMAGE_UYVY /* UYVY packed */ -#endif -}; + xvColorKey = MAKE_ATOM("XV_COLORKEY"); /* FIXME: twice, leak */ + xvFilterQuality = MAKE_ATOM("XV_FILTER_QUALITY"); /* FIXME: twice, leak */ + + pPriv->colorKey = pTDFX->videoKey; + pPriv->videoStatus = 0; + pPriv->filterQuality = 1; + + return adapt; +} static XF86VideoAdaptorPtr -TDFXAllocAdaptor(ScrnInfoPtr pScrn) +TDFXSetupImageVideoOverlay(ScreenPtr pScreen) { - DevUnion *devUnions; - int i; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + TDFXPtr pTDFX = TDFXPTR(pScrn); + TDFXPortPrivPtr pPriv; XF86VideoAdaptorPtr adapt; - if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) - return NULL; - /* Allocate a TDFX private structure */ - /* There is no need for a TDFX private structure at this time. But a - * DevUnion has to be provided to the core Xv code. */ - if (!(devUnions = xcalloc (1, sizeof (DevUnion) * TDFX_MAX_PORTS))) - { - xfree (adapt); - return NULL; - } - adapt->pPortPrivates = &devUnions[0]; - - /* Fill in some of the DevUnion */ - for (i = 0; i < TDFX_MAX_PORTS; i++) - { - adapt->pPortPrivates[i].val = i; - adapt->pPortPrivates[i].ptr = NULL; /* No private data */ - } - - return adapt; -} + if (!pTDFX->OverlayXvideo) + return NULL; + if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_OVERLAY_PORTS))) + return NULL; + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->name = "3dfx Video Overlay"; + adapt->nPorts = TDFX_MAX_OVERLAY_PORTS; + adapt->nEncodings = sizeof(OverlayEncoding) / sizeof(XF86VideoEncodingRec); + adapt->pEncodings = OverlayEncoding; + adapt->nFormats = sizeof(OverlayFormats) / sizeof(XF86VideoFormatRec); + adapt->pFormats = OverlayFormats; + adapt->nAttributes = sizeof(OverlayAttributes) / sizeof(XF86AttributeRec); + adapt->pAttributes = OverlayAttributes; + adapt->nImages = sizeof(OverlayImages) / sizeof(XF86ImageRec); + adapt->pImages = OverlayImages; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = TDFXStopVideoOverlay; + adapt->SetPortAttribute = TDFXSetPortAttributeOverlay; + adapt->GetPortAttribute = TDFXGetPortAttributeOverlay; + adapt->QueryBestSize = TDFXQueryBestSize; + adapt->PutImage = TDFXPutImageOverlay; + adapt->QueryImageAttributes = TDFXQueryImageAttributes; -static XF86VideoAdaptorPtr -TDFXSetupImageVideo(ScreenPtr pScreen) + pPriv = (TDFXPortPrivPtr)(adapt->pPortPrivates[0].ptr); + REGION_INIT(pScreen, &(pPriv->clip), NullBox, 0); + + pTDFX->overlayAdaptor = adapt; + + TDFXResetVideoOverlay(pScrn); + + return adapt; +} + +static XF86VideoAdaptorPtr +TDFXSetupImageVideoTexture(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - XF86VideoAdaptorPtr adapt; TDFXPtr pTDFX = TDFXPTR(pScrn); + XF86VideoAdaptorPtr adapt; - DummyEncoding[0].height = pTDFX->pixmapCacheLines; + if (!pTDFX->TextureXvideo) + return NULL; - adapt = TDFXAllocAdaptor(pScrn); + if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_TEXTURE_PORTS))) + return NULL; adapt->type = XvWindowMask | XvInputMask | XvImageMask; - /* Add VIDEO_OVERLAID_IMAGES if using the overlay */ adapt->flags = 0; - adapt->name = "3dfx Accelerated Video Engine"; - adapt->nEncodings = 1; - adapt->pEncodings = &DummyEncoding[0]; - adapt->nFormats = NUM_FORMATS_OVERLAY; - adapt->pFormats = Formats; - adapt->nPorts = TDFX_MAX_PORTS; - adapt->nAttributes = 0; - adapt->pAttributes = NULL; - adapt->nImages = NUM_IMAGES; - adapt->pImages = Images; - - /* XXX For now all I'm implementing is PutImage so that programs like OMS - * will work. More will follow as I have time and need. */ + adapt->name = "3dfx Video Texture"; + adapt->nPorts = TDFX_MAX_TEXTURE_PORTS; + adapt->nEncodings = sizeof(TextureEncoding) / sizeof(XF86VideoEncodingRec); + adapt->pEncodings = TextureEncoding; + adapt->nFormats = sizeof(TextureFormats) / sizeof(XF86VideoFormatRec); + adapt->pFormats = TextureFormats; + adapt->nAttributes = sizeof(TextureAttributes) / sizeof(XF86AttributeRec); + adapt->pAttributes = TextureAttributes; + adapt->nImages = sizeof(TextureImages) / sizeof(XF86ImageRec); + adapt->pImages = TextureImages; adapt->PutVideo = NULL; adapt->PutStill = NULL; adapt->GetVideo = NULL; adapt->GetStill = NULL; - adapt->StopVideo = TDFXStopVideo; - adapt->SetPortAttribute = TDFXSetPortAttribute; - adapt->GetPortAttribute = TDFXGetPortAttribute; + adapt->StopVideo = TDFXStopVideoTexture; + adapt->SetPortAttribute = TDFXSetPortAttributeTexture; + adapt->GetPortAttribute = TDFXGetPortAttributeTexture; adapt->QueryBestSize = TDFXQueryBestSize; - adapt->PutImage = TDFXPutImage; - /*adapt->PutImage = TDFXPutImageOverlay; */ + adapt->PutImage = TDFXPutImageTexture; adapt->QueryImageAttributes = TDFXQueryImageAttributes; + pTDFX->textureAdaptor = adapt; + return adapt; } -static void -TDFXStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup) -{ - if (cleanup) - { - /* Deallocate the offscreen temporary buffer. */ - TDFXDeallocateOffscreenBuffer (pScrn, 0); - } +/* + * MISCELLANEOUS ROUTINES + */ + + +static int +TDFXQueryImageAttributes( + ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets +){ + int size, tmp; + + if(*w > 1024) *w = 1024; + if(*h > 1024) *h = 1024; + + *w = (*w + 1) & ~1; + if(offsets) offsets[0] = 0; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if(pitches) pitches[0] = size; + size *= *h; + if(offsets) offsets[1] = size; + tmp = ((*w >> 1) + 3) & ~3; + if(pitches) pitches[1] = pitches[2] = tmp; + tmp *= (*h >> 1); + size += tmp; + if(offsets) offsets[2] = size; + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + size = *w << 1; + if(pitches) pitches[0] = size; + size *= *h; + break; + } + + return size; } -static int -TDFXSetPortAttribute (ScrnInfoPtr pScrn, - Atom attribute, - INT32 value, - pointer data) -{ - return BadMatch; +static int +TDFXSetPortAttributeOverlay( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value, + pointer data +){ + + TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data; + TDFXPtr pTDFX = TDFXPTR(pScrn); + + if(attribute == xvColorKey) { + pPriv->colorKey = value; + pTDFX->writeLong(pTDFX, VIDCHROMAMIN, pPriv->colorKey); + pTDFX->writeLong(pTDFX, VIDCHROMAMAX, pPriv->colorKey); + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + } else if(attribute == xvFilterQuality) { + if((value < 0) || (value > 1)) + return BadValue; + pPriv->filterQuality = value; + } else return BadMatch; + + return Success; +} + +static int +TDFXGetPortAttributeOverlay( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value, + pointer data +){ + TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data; + + if(attribute == xvColorKey) { + *value = pPriv->colorKey; + } else if(attribute == xvFilterQuality) { + *value = pPriv->filterQuality; + } else return BadMatch; + + return Success; } static int -TDFXGetPortAttribute(ScrnInfoPtr pScrn, - Atom attribute, - INT32 *value, - pointer data) -{ - return BadMatch; +TDFXSetPortAttributeTexture( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value, + pointer data +) { + return Success; } +static int +TDFXGetPortAttributeTexture( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value, + pointer data +){ + return Success; +} -static void -TDFXQueryBestSize(ScrnInfoPtr pScrn, - Bool motion, - short vid_w, short vid_h, - short drw_w, short drw_h, - unsigned int *p_w, unsigned int *p_h, - pointer data) -{ - /* No alignment restrictions */ + +static void +TDFXQueryBestSize( + ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, + pointer data +){ + if(vid_w > drw_w) drw_w = vid_w; + if(vid_h > drw_h) drw_h = vid_h; + *p_w = drw_w; - *p_h = drw_h; + *p_h = drw_h; } - -/* This performs a screen to screen stretch blit. All coordinates are - * in screen memory. This function assumes that the src and dst format - * registers have been setup already. This function does not save - * the registers it trashes. */ static void -TDFXScreenToScreenYUVStretchBlit (ScrnInfoPtr pScrn, - short src_x1, short src_y1, - short src_x2, short src_y2, - short dst_x1, short dst_y1, - short dst_x2, short dst_y2) -{ - TDFXPtr pTDFX = TDFXPTR(pScrn); +TDFXCopyData( + unsigned char *src, + unsigned char *dst, + int srcPitch, + int dstPitch, + int h, + int w +){ + while(h--) { + memcpy(dst, src, w); + src += srcPitch; + dst += dstPitch; + } +} - /* reformulate the paramaters the way the hardware wants them */ - INT32 - src_x = src_x1 & 0x1FFF, - src_y = src_y1 & 0x1FFF, - dst_x = dst_x1 & 0x1FFF, - dst_y = dst_y1 & 0x1FFF, - src_w = (src_x2 - src_x) & 0x1FFF, - src_h = (src_y2 - src_y) & 0x1FFF, - dst_w = (dst_x2 - dst_x) & 0x1FFF, - dst_h = (dst_y2 - dst_y) & 0x1FFF; - - /* Setup for blit src and dest */ - TDFXMakeRoom(pTDFX, 5); - DECLARE(SSTCP_DSTSIZE|SSTCP_SRCSIZE|SSTCP_DSTXY| - SSTCP_COMMAND|SSTCP_COMMANDEXTRA); - /* We want the blit to wait for vsync. */ - TDFXWriteLong(pTDFX, SST_2D_COMMANDEXTRA, 4); - TDFXWriteLong(pTDFX, SST_2D_SRCSIZE, src_w | (src_h<<16)); - TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, dst_w | (dst_h<<16)); - TDFXWriteLong(pTDFX, SST_2D_DSTXY, dst_x | (dst_y<<16)); - /* XXX find the ROP table and figure out why CC is the right choice. */ - TDFXWriteLong(pTDFX, SST_2D_COMMAND, - (0xCC<<24)|SST_2D_SCRNTOSCRNSTRETCH); - /* Write to the launch area to start the blit */ - TDFXMakeRoom(pTDFX, 1); - DECLARE_LAUNCH (1, 0); - TDFXWriteLong(pTDFX, SST_2D_LAUNCH, src_x | (src_y<<16)); +static void +TDFXCopyMungedData( + unsigned char *src1, + unsigned char *src2, + unsigned char *src3, + unsigned char *dst1, + int srcPitch, + int srcPitch2, + int dstPitch, + int h, + int w +){ + CARD32 *dst; + CARD8 *s1, *s2, *s3; + int i, j; + + w >>= 1; + + for(j = 0; j < h; j++) { + dst = (CARD32*)dst1; + s1 = src1; s2 = src2; s3 = src3; + i = w; + while(i > 4) { + dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); + dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24); + dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24); + dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24); + dst += 4; s2 += 4; s3 += 4; s1 += 8; + i -= 4; + } + while(i--) { + dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); + dst++; s2++; s3++; + s1 += 2; + } + + dst1 += dstPitch; + src1 += srcPitch; + if(j & 1) { + src2 += srcPitch2; + src3 += srcPitch2; + } + } } + +/* + * TEXTURE DRAWING FUNCTIONS + */ + + static void -YUVPlanarToPacked (ScrnInfoPtr pScrn, - short src_x, short src_y, - short src_h, short src_w, - int id, char *buf, - short width, short height, - FBAreaPtr fbarea) +TDFXStopVideoTexture(ScrnInfoPtr pScrn, pointer data, Bool cleanup) { TDFXPtr pTDFX = TDFXPTR(pScrn); + TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data; - INT32 y; - void *dst; - char *psrc = buf, - *pdst = 0; - int count = 0; - - /* Register saves */ - INT32 - yuvBaseAddr, - yuvStride; - - /* Save these registers so I can restore them when we are done. */ - yuvBaseAddr = TDFXReadLongMMIO(pTDFX, YUVBASEADDR); - yuvStride = TDFXReadLongMMIO(pTDFX, YUVSTRIDE); - - - dst = 0; - - /* Set yuvBaseAddress register to point to the buffer. */ - TDFXWriteLongMMIO (pTDFX, YUVBASEADDR, pTDFX->fbOffset + - pTDFX->stride * (fbarea->box.y1 + pScrn->virtualY) - + fbarea->box.x1); - /* Set yuvStride register to reflect stride of U and V planes */ - /* There is a subtle issue involved with copying the Y plane. Y is - * sampled at twice the rate of the U and V data, in both - * directions. But when packing their needs to be two Y values for - * each U,V pair. So if src_x is odd we will end up missing on - * of the Y values. To correct for this we will always adjust the src - * x value. This adjust is done both in computing the address of the - * pixels to copy and when determining the amount of pixels to copy. - * Note that care needs to be taken to insure that the offscreen - * temporary buffer is allocated with enough space to hold the possible - * extra column of data. - */ - TDFXWriteLongMMIO (pTDFX, YUVSTRIDE, pTDFX->stride); - psrc = (char*)buf; - - /* psrc points to the base of the Y plane, move out to src_x, src_y */ - psrc += (src_x & ~0x1) + src_y * width; - pdst = (char *)pTDFX->MMIOBase[0] + YUV_Y_BASE; - for (y = 0; y < src_h; y++) - { - memcpy (pdst, psrc, src_w + (src_x & 0x1)); - psrc += width; - /* YUV planar region is always 1024 bytes wide */ - pdst += 1024; - } + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); - /* The difference between FOURCC_YV12 and FOURCC_I420 is the order - * that the U and V planes appear in the buffer. But at this point - * I just send the second buffer as V and the third buffer as U. - * Depending on the format, the packing will be different and we - * handle it in the the way we pick the source format for the blit - * later on. */ - - pdst = (char *)pTDFX->MMIOBase[0] + YUV_V_BASE; - psrc = (char*)buf + width * height; - /* psrc now points to the base of the V plane, move out to src_x/2, - * src_y/2 */ - psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1); - for (y = 0; y < src_h >> 1; y++) - { - /* YUV planar region is always 1024 bytes wide */ - memcpy (pdst, psrc, src_w >> 1); - psrc += width >> 1; - pdst += 1024; - } - pdst = (char *)pTDFX->MMIOBase[0] + YUV_U_BASE; - psrc = (char*)buf + width * height + (width >> 1) * (height >> 1); - /* psrc now points to the base of the U plane, move out to src_x/2, - * src_y/2 */ - psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1); - for (y = 0; y < src_h >> 1; y++) - { - /* YUV planar region is always 1024 bytes wide */ - memcpy (pdst, psrc, src_w >> 1); - psrc += width >> 1; - pdst += 1024; + if (cleanup) { + if(pTDFX->textureBuffer) { + xf86FreeOffscreenArea(pTDFX->textureBuffer); + pTDFX->textureBuffer = NULL; + } } +} - /* Before restoring trashed registers we have to wait for the conversion - * to finish. We aren't using the FIFO for this but the hardware can - * take a little extra time even after we finish all the writes. If we - * restore the registers before it finishes it can store some of the YUV - * data to the wrong place. One particular wrong place is often on top - * of the hardware cursor data. So we wait for the status register - * to go idle. */ - /* XXX Right now wait for the whole chip to go idle. This is more than - * is required. Find out which subsystem is handles the YUV packing and - * wait only on that status bit. */ - count = 0; - do - { - count++; - } while ((TDFXReadLongMMIO(pTDFX, 0) & SST_BUSY) && count < 1000); - - /* Restore trashed registers */ - TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, yuvBaseAddr); - TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, yuvStride); + +static void +TDFXScreenToScreenYUVStretchBlit (ScrnInfoPtr pScrn, + short src_x1, short src_y1, + short src_x2, short src_y2, + short dst_x1, short dst_y1, + short dst_x2, short dst_y2) +{ + TDFXPtr pTDFX = TDFXPTR(pScrn); + /* reformulate the paramaters the way the hardware wants them */ + INT32 src_x = src_x1 & 0x1FFF; + INT32 src_y = src_y1 & 0x1FFF; + INT32 dst_x = dst_x1 & 0x1FFF; + INT32 dst_y = dst_y1 & 0x1FFF; + INT32 src_w = (src_x2 - src_x1) & 0x1FFF; + INT32 src_h = (src_y2 - src_y1) & 0x1FFF; + INT32 dst_w = (dst_x2 - dst_x1) & 0x1FFF; + INT32 dst_h = (dst_y2 - dst_y1) & 0x1FFF; + /* Setup for blit src and dest */ + TDFXMakeRoom(pTDFX, 4); + DECLARE(SSTCP_DSTSIZE|SSTCP_SRCSIZE|SSTCP_DSTXY|SSTCP_COMMAND/*|SSTCP_COMMANDEXTRA*/); + /* TDFXWriteLong(pTDFX, SST_2D_COMMANDEXTRA, SST_COMMANDEXTRA_VSYNC);*/ + TDFXWriteLong(pTDFX, SST_2D_SRCSIZE, src_w | (src_h<<16)); + TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, dst_w | (dst_h<<16)); + TDFXWriteLong(pTDFX, SST_2D_DSTXY, dst_x | (dst_y<<16)); + TDFXWriteLong(pTDFX, SST_2D_COMMAND, SST_2D_SCRNTOSCRNSTRETCH | 0xCC000000); + /* Write to the launch area to start the blit */ + TDFXMakeRoom(pTDFX, 1); + DECLARE_LAUNCH(1, 0); + TDFXWriteLong(pTDFX, SST_2D_LAUNCH, (src_x<<1) | (src_y<<16)); + /* Wait for it to happen */ + TDFXSendNOPFifo2D(pScrn); } -static int -TDFXPutImage( - ScrnInfoPtr pScrn, - short src_x, short src_y, - short drw_x, short drw_y, - short src_w, short src_h, - short drw_w, short drw_h, - int id, unsigned char* buf, - short width, short height, - Bool sync, - RegionPtr clipBoxes, pointer data - ) + +static void +YUVPlanarToPacked (ScrnInfoPtr pScrn, + short src_x, short src_y, + short src_h, short src_w, + int id, char *buf, + short width, short height, + FBAreaPtr fbarea) { TDFXPtr pTDFX = TDFXPTR(pScrn); + char *psrc, *pdst; + int count; + int baseaddr; + INT32 yuvBaseAddr, yuvStride; + + /* Save these registers so I can restore them when we are done. */ + yuvBaseAddr = TDFXReadLongMMIO(pTDFX, YUVBASEADDR); + yuvStride = TDFXReadLongMMIO(pTDFX, YUVSTRIDE); + + /* Set yuvBaseAddress and yuvStride. */ + baseaddr = pTDFX->fbOffset + pTDFX->cpp * fbarea->box.x1 + pTDFX->stride * fbarea->box.y1; + TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, pTDFX->stride); + TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, baseaddr); + + /* Copy Y plane (twice as much Y as U or V) */ + psrc = (char *)buf; + psrc += (src_x & ~0x1) + src_y * width; + pdst = (char *)pTDFX->MMIOBase[0] + YUV_Y_BASE; + TDFXCopyData(psrc, pdst, width, 1024, src_h, src_w + (src_x & 0x1)); + + /* Copy V plane */ + psrc = (char*)buf + width * height; + psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1); + pdst = (char *)pTDFX->MMIOBase[0] + YUV_V_BASE; + TDFXCopyData(psrc, pdst, width >> 1, 1024, src_h >> 1, src_w >> 1); + + /* Copy U plane */ + psrc = (char*)buf + width * height + (width >> 1) * (height >> 1); + psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1); + pdst = (char *)pTDFX->MMIOBase[0] + YUV_U_BASE; + TDFXCopyData(psrc, pdst, width >> 1, 1024, src_h >> 1, src_w >> 1); + + /* IDLE until the copy finished, timeout for safety */ + for (count = 0; count < 1000; count++) + if (!((TDFXReadLongMMIO(pTDFX, STATUS) & SST_BUSY))) + break; + + /* Restore trashed registers */ + TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, yuvBaseAddr); + TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, yuvStride); + + /* Wait for it to happen */ + TDFXSendNOPFifo2D(pScrn); +} + +static int +TDFXPutImageTexture( + ScrnInfoPtr pScrn, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + int id, unsigned char* buf, + short width, short height, + Bool sync, + RegionPtr clipBoxes, pointer data + ) +{ + TDFXPtr pTDFX = TDFXPTR(pScrn); BoxPtr pbox; int nbox; + int format; + + /* Check the source format */ + if (id == FOURCC_YV12) format = SST_2D_FORMAT_YUYV; + else if (id == FOURCC_UYVY) format = SST_2D_FORMAT_UYVY; + else return BadAlloc; + + /* Get a buffer to store the packed YUV data */ + if (!(pTDFX->textureBuffer = TDFXAllocateMemoryArea(pScrn, pTDFX->textureBuffer, src_w, src_h))) + return BadAlloc; + + /* Pack the YUV data in offscreen memory using YUV framebuffer (0x[CDE]0000) */ + YUVPlanarToPacked (pScrn, src_x, src_y, src_h, src_w, + id, (char *)buf, width, height, + pTDFX->textureBuffer); + + /* Setup source and destination pixel formats (yuv -> rgb) */ + TDFXMakeRoom(pTDFX, 2); + DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT); + TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->stride|((pTDFX->cpp+1)<<16)); + TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->stride|((format)<<16)); + + /* Blit packed YUV data from offscreen memory, respecting clips */ +#define SRC_X1 (pTDFX->textureBuffer->box.x1) +#define SRC_Y1 (pTDFX->textureBuffer->box.y1) +#define SCALEX(dx) ((int)(((dx) * src_w) / drw_w)) +#define SCALEY(dy) ((int)(((dy) * src_h) / drw_h)) + for (nbox = REGION_NUM_RECTS(clipBoxes), + pbox = REGION_RECTS(clipBoxes); nbox > 0; nbox--, pbox++) + { + TDFXScreenToScreenYUVStretchBlit (pScrn, + SRC_X1 + SCALEX(pbox->x1 - drw_x), + SRC_Y1 + SCALEY(pbox->y1 - drw_y), + SRC_X1 + SCALEX(pbox->x2 - drw_x), + SRC_Y1 + SCALEY(pbox->y2 - drw_y), + pbox->x1, pbox->y1, + pbox->x2, pbox->y2); + } - FBAreaPtr fbarea; + /* Restore the WAX registers we trashed */ + TDFXMakeRoom(pTDFX, 2); + DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT); + TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->sst2DDstFmtShadow); + TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->sst2DSrcFmtShadow); - /* Make sure we are synced up (this really means, lock and find the - * fifo pointer. */ - TDFXFirstSync (pScrn); + /* Wait for it to happen */ + TDFXSendNOPFifo2D(pScrn); - /* Do the right thing for the given format */ - switch (id) - { - case FOURCC_YV12: - case FOURCC_I420: - /* Get a buffer to use to store the packed YUV data */ - fbarea = TDFXAllocateOffscreenBuffer (pScrn, id, src_w, src_h); - - if (!fbarea) - { - return Success; - } + return Success; +} - YUVPlanarToPacked (pScrn, src_x, src_y, src_h, src_w, - id, (char *)buf, width, height, - fbarea); - /* Don't know what executed last so we need to send a NOP */ - TDFXSendNOP(pScrn); - - /* Setup the dst and src format once, they don't change for all the - * blits. */ - TDFXMakeRoom(pTDFX, 2); - DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT); - TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, - pTDFX->stride|((pTDFX->cpp+1)<<16)); - if (id == FOURCC_YV12) - { - /* Packed format is YUYV */ - TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, - pTDFX->stride|((SST_2D_FORMAT_YUYV)<<16)); - } - else - { - /* Packed format is UYVY */ - TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, - pTDFX->stride|((SST_2D_FORMAT_UYVY)<<16)); - } - /* Traverse the clip boxes */ - nbox = REGION_NUM_RECTS(clipBoxes); - pbox = REGION_RECTS(clipBoxes); - - while (nbox--) - { - /* The destination clip regions come with the clip boxes, but - * the src coordinates have to be computed because we are doing - * a stretch blit. These macros perform that compuation, but - * they could use some work. When testing with still images these - * computations caused some jitter in the resulting output, but - * with actual video playback I haven't noticed any problems. */ -#define SRC_X1 (fbarea->box.x1) -#define SRC_Y1 (fbarea->box.y1 + pScrn->virtualY) -#define SCALEX(dx) ((int)(((dx) * src_w + (drw_w>>1)) / drw_w)) -#define SCALEY(dy) ((int)(((dy) * src_h + (drw_h>>1)) / drw_h)) - - /* Do the screen-to-screen blit clipped to the clip boxes. */ - TDFXScreenToScreenYUVStretchBlit - (pScrn, - SRC_X1 + SCALEX(pbox->x1 - drw_x), - SRC_Y1 + SCALEY(pbox->y1 - drw_y), - SRC_X1 + SCALEX(pbox->x2 - drw_x), - SRC_Y1 + SCALEY(pbox->y2 - drw_y), - /* these destination coordinates come - * right from the clip box. */ - pbox->x1, pbox->y1, - pbox->x2, pbox->y2); - pbox++; - } +/* + * COMMON DRAWING FUNCTIONS + */ - /* Restore the WAX registers we trashed */ - TDFXMakeRoom(pTDFX, 2); - DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT); - TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->sst2DDstFmtShadow); - TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->sst2DSrcFmtShadow); +static Bool +RegionsEqual(RegionPtr A, RegionPtr B) +{ + int *dataA, *dataB; + int num; + + num = REGION_NUM_RECTS(A); + if(num != REGION_NUM_RECTS(B)) + return FALSE; + + if((A->extents.x1 != B->extents.x1) || + (A->extents.x2 != B->extents.x2) || + (A->extents.y1 != B->extents.y1) || + (A->extents.y2 != B->extents.y2)) + return FALSE; + + dataA = (int*)REGION_RECTS(A); + dataB = (int*)REGION_RECTS(B); + + while(num--) { + if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) + return FALSE; + dataA += 2; + dataB += 2; + } - /* The rest of the driver won't know what I have done so I do a stall to - * make sure the next command sent will work. */ - TDFXSendNOP(pScrn); - break; - /* XXX What am I supposed to do about the sync flag? */ + return TRUE; +} - } - return Success; +static Bool +TDFXClipVideo( + BoxPtr dst, + INT32 *xa, + INT32 *xb, + INT32 *ya, + INT32 *yb, + RegionPtr reg, + INT32 width, + INT32 height +){ + INT32 vscale, hscale, delta; + BoxPtr extents = REGION_EXTENTS(DummyScreen, reg); + int diff; + + hscale = ((*xb - *xa) << 16) / (dst->x2 - dst->x1); + vscale = ((*yb - *ya) << 16) / (dst->y2 - dst->y1); + + *xa <<= 16; *xb <<= 16; + *ya <<= 16; *yb <<= 16; + + diff = extents->x1 - dst->x1; + if(diff > 0) { + dst->x1 = extents->x1; + *xa += diff * hscale; + } + diff = dst->x2 - extents->x2; + if(diff > 0) { + dst->x2 = extents->x2; + *xb -= diff * hscale; + } + diff = extents->y1 - dst->y1; + if(diff > 0) { + dst->y1 = extents->y1; + *ya += diff * vscale; + } + diff = dst->y2 - extents->y2; + if(diff > 0) { + dst->y2 = extents->y2; + *yb -= diff * vscale; + } + + if(*xa < 0) { + diff = (- *xa + hscale - 1)/ hscale; + dst->x1 += diff; + *xa += diff * hscale; + } + delta = *xb - (width << 16); + if(delta > 0) { + diff = (delta + hscale - 1)/ hscale; + dst->x2 -= diff; + *xb -= diff * hscale; + } + if(*xa >= *xb) return FALSE; + + if(*ya < 0) { + diff = (- *ya + vscale - 1)/ vscale; + dst->y1 += diff; + *ya += diff * vscale; + } + delta = *yb - (height << 16); + if(delta > 0) { + diff = (delta + vscale - 1)/ vscale; + dst->y2 -= diff; + *yb -= diff * vscale; + } + if(*ya >= *yb) return FALSE; + + if((dst->x1 != extents->x1) || (dst->x2 != extents->x2) || + (dst->y1 != extents->y1) || (dst->y2 != extents->y2)) + { + RegionRec clipReg; + REGION_INIT(DummyScreen, &clipReg, dst, 1); + REGION_INTERSECT(DummyScreen, reg, reg, &clipReg); + REGION_UNINIT(DummyScreen, &clipReg); + } + return TRUE; } -/* This code doesn't work yet. Eventually this should use the video overlay - * instead of the YUV-stretch-blit. The overlay is better because it uses - * bilinear filtering when scaling. */ -#if 0 -static int -TDFXPutImageOverlay( - ScrnInfoPtr pScrn, - short src_x, short src_y, - short drw_x, short drw_y, - short src_w, short src_h, - short drw_w, short drw_h, - int id, unsigned char* buf, - short width, short height, - Bool sync, - RegionPtr clipBoxes, pointer data - ) -{ - TDFXPtr pTDFX = TDFXPTR(pScrn); - BoxPtr pbox; - int nbox; +/* + * OVERLAY DRAWING FUNCTIONS + */ - /* Computed Register values */ - INT32 - vidInFormat; - static FBAreaPtr fbarea; +static void +TDFXResetVideoOverlay(ScrnInfoPtr pScrn) +{ + TDFXPtr pTDFX = TDFXPTR(pScrn); + TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr; + + /* reset the video */ + pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK; + pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg); + pTDFX->writeLong(pTDFX, RGBMAXDELTA, 0x0080808); + pTDFX->writeLong(pTDFX, VIDCHROMAMIN, pPriv->colorKey); + pTDFX->writeLong(pTDFX, VIDCHROMAMAX, pPriv->colorKey); +} - /* Do the right thing for the given format */ - switch (id) - { - case FOURCC_YV12: - case FOURCC_I420: - - /* Get a buffer to use to store the packed YUV data */ - fbarea = TDFXAllocateOffscreenBuffer (pScrn, id, src_w, src_h); - - if (!fbarea) - return Success; - - YUVPlanarToPacked (pScrn, - src_x, src_y, src_h, src_w, - id, buf, width, height, - fbarea); - - /* Setup the overlay */ - TDFXWriteLongMMIO(pTDFX, VIDOVERLAYSTARTCOORDS, - (drw_x&0x7FF) | ((drw_y & 0x7FF) << 12) - /* XXX Lower 2 bits of X and Y? */); - TDFXWriteLongMMIO(pTDFX, VIDOVERLAYENDSCREENCOORDS, - ((drw_x+drw_w)&0x7FF) | (((drw_y+drw_h)&0x7FF) << 12)); - - /* Set the Video in format */ - vidInFormat = 0; - /* These magic numbers come from the spec on page 151 */ - if (id == FOURCC_YV12) - { - /* Packed format is YUYV */ - vidInFormat = 0x9 << 1; - } - else - { - /* Packed format is UYVY */ - vidInFormat = 0xA << 1; - } +static void +TDFXStopVideoOverlay(ScrnInfoPtr pScrn, pointer data, Bool cleanup) +{ + TDFXPtr pTDFX = TDFXPTR(pScrn); + TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data; - TDFXWriteLongMMIO (pTDFX, VIDINFORMAT, vidInFormat); - TDFXWriteLongMMIO (pTDFX, VIDINSTRIDE, src_w); + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); - /* Use magenta as the chroma color */ - if (pTDFX->cpp == 2) - { - TDFXWriteLongMMIO(pTDFX, VIDCHROMAMIN, - 0x0000F71F); - TDFXWriteLongMMIO(pTDFX, VIDCHROMAMAX, - 0x0000F71F); + if(cleanup) { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK; + pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg); } - else /* (pTDFX->cpp == 3) */ - { - TDFXWriteLongMMIO(pTDFX, VIDCHROMAMIN, - 0x00FF00FF); - TDFXWriteLongMMIO(pTDFX, VIDCHROMAMAX, - 0x00FF00FF); + if(pTDFX->overlayBuffer) { + xf86FreeOffscreenLinear(pTDFX->overlayBuffer); + pTDFX->overlayBuffer = NULL; } - - /* Set the src address */ - TDFXWriteLongMMIO (pTDFX, VIDINADDR0, - pTDFX->fbOffset - + pTDFX->stride * (fbarea->box.y1 + pScrn->virtualY) - + fbarea->box.x1); - - /* Traverse the clip boxes */ - nbox = REGION_NUM_RECTS(clipBoxes); - pbox = REGION_RECTS(clipBoxes); - - while (nbox--) - { - pbox++; + pPriv->videoStatus = 0; + } else { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + pPriv->videoStatus |= OFF_TIMER; + pPriv->offTime = currentTime.milliseconds + OFF_DELAY; } - break; + } +} + + +static void +TDFXDisplayVideoOverlay( + ScrnInfoPtr pScrn, + int id, + int offset, + short width, short height, + int pitch, + int left, int right, int top, + BoxPtr dstBox, + short src_w, short src_h, + short drw_w, short drw_h +){ + TDFXPtr pTDFX = TDFXPTR(pScrn); + TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr; + int dudx, dvdy; + + dudx = (src_w << 20) / drw_w; + dvdy = (src_h << 20) / drw_h; + + offset += ((left >> 16) & ~1) << 1; + left = (left & 0x0001ffff) << 3; + + pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK; + pTDFX->ModeReg.vidcfg |= 0x00000320; + + if(drw_w != src_w) pTDFX->ModeReg.vidcfg |= (1 << 14); + if(drw_h != src_h) pTDFX->ModeReg.vidcfg |= (1 << 15); + if(id == FOURCC_UYVY) pTDFX->ModeReg.vidcfg |= (6 << 21); + else pTDFX->ModeReg.vidcfg |= (5 << 21); + if(pScrn->depth == 8) pTDFX->ModeReg.vidcfg |= (1 << 11); + if(pPriv->filterQuality) pTDFX->ModeReg.vidcfg |= (3 << 16); + pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg); + + pTDFX->writeLong(pTDFX, VIDOVERLAYSTARTCOORDS, dstBox->x1 | (dstBox->y1 << 12)); + pTDFX->writeLong(pTDFX, VIDOVERLAYENDSCREENCOORDS, (dstBox->x2 - 1) | ((dstBox->y2 - 1) << 12)); + pTDFX->writeLong(pTDFX, VIDOVERLAYDUDX, dudx); + pTDFX->writeLong(pTDFX, VIDOVERLAYDUDXOFFSETSRCWIDTH, left | (src_w << 20)); + pTDFX->writeLong(pTDFX, VIDOVERLAYDVDY, dvdy); + pTDFX->writeLong(pTDFX, VIDOVERLAYDVDYOFFSET, (top & 0x0000ffff) << 3); + + pTDFX->ModeReg.stride &= 0x0000ffff; + pTDFX->ModeReg.stride |= pitch << 16; + pTDFX->writeLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE, pTDFX->ModeReg.stride); + pTDFX->writeLong(pTDFX, SST_3D_LEFTOVERLAYBUF, offset & ~3); + pTDFX->writeLong(pTDFX, VIDINADDR0, offset & ~3); +} + + +static int +TDFXPutImageOverlay( + ScrnInfoPtr pScrn, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + int id, unsigned char* buf, + short width, short height, + Bool Sync, + RegionPtr clipBoxes, pointer data +){ + TDFXPtr pTDFX = TDFXPTR(pScrn); + TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data; + INT32 xa, xb, ya, yb; + unsigned char *dst_start; + int pitch, new_size, offset; + int s2offset = 0, s3offset = 0; + int srcPitch = 0, srcPitch2 = 0; + int dstPitch; + int top, left, npixels, nlines, bpp; + BoxRec dstBox; + CARD32 tmp; + + /* + * s2offset, s3offset - byte offsets into U and V plane of the + * source where copying starts. Y plane is + * done by editing "buf". + * + * offset - byte offset to the first line of the destination. + * + * dst_start - byte address to the first displayed pel. + * + */ + + if(src_w > drw_w) drw_w = src_w; + if(src_h > drw_h) drw_h = src_h; + + /* Clip */ + xa = src_x; + xb = src_x + src_w; + ya = src_y; + yb = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if(!TDFXClipVideo(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height)) + return Success; + + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + + bpp = pScrn->bitsPerPixel >> 3; + pitch = bpp * pScrn->displayWidth; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + dstPitch = ((width << 1) + 3) & ~3; + new_size = ((dstPitch * height) + bpp - 1) / bpp; + srcPitch = (width + 3) & ~3; + s2offset = srcPitch * height; + srcPitch2 = ((width >> 1) + 3) & ~3; + s3offset = (srcPitch2 * (height >> 1)) + s2offset; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + dstPitch = ((width << 1) + 3) & ~3; + new_size = ((dstPitch * height) + bpp - 1) / bpp; + srcPitch = (width << 1); + break; } - return Success; + + if(!(pTDFX->overlayBuffer = TDFXAllocateMemoryLinear(pScrn, pTDFX->overlayBuffer, new_size))) + return BadAlloc; + + /* copy data */ + top = ya >> 16; + left = (xa >> 16) & ~1; + npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left; + + offset = (pTDFX->overlayBuffer->offset * bpp) + (top * dstPitch) + pTDFX->fbOffset; + dst_start = pTDFX->FbBase + offset; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + top &= ~1; + dst_start += left << 1; + tmp = ((top >> 1) * srcPitch2) + (left >> 1); + s2offset += tmp; + s3offset += tmp; + if(id == FOURCC_I420) { + tmp = s2offset; + s2offset = s3offset; + s3offset = tmp; + } + nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top; + TDFXCopyMungedData(buf + (top * srcPitch) + left, buf + s2offset, + buf + s3offset, dst_start, srcPitch, srcPitch2, + dstPitch, nlines, npixels); + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + left <<= 1; + buf += (top * srcPitch) + left; + nlines = ((yb + 0xffff) >> 16) - top; + dst_start += left; + TDFXCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels << 1); + break; + } + + if(!RegionsEqual(&pPriv->clip, clipBoxes)) { + REGION_COPY(pScreen, &pPriv->clip, clipBoxes); + (*pTDFX->AccelInfoRec->FillSolidRects)(pScrn, pPriv->colorKey, + GXcopy, ~0, + REGION_NUM_RECTS(clipBoxes), + REGION_RECTS(clipBoxes)); + } + + TDFXDisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); + + pPriv->videoStatus = CLIENT_VIDEO_ON; + + pTDFX->VideoTimerCallback = TDFXVideoTimerCallback; + + return Success; } -#endif static void -TDFXDeallocateOffscreenBuffer (ScrnInfoPtr pScrn, int id) +TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time) { - TDFXPtr pTDFX = TDFXPTR(pScrn); - - /* There is only one buffer so just deallocate it */ - if (pTDFX->offscreenYUVBuf) - xf86FreeOffscreenArea (pTDFX->offscreenYUVBuf); + TDFXPtr pTDFX = TDFXPTR(pScrn); + TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr; + + if(pPriv->videoStatus & TIMER_MASK) { + if(pPriv->videoStatus & OFF_TIMER) { + if(pPriv->offTime < time) { + pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK; + pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg); + pPriv->videoStatus = FREE_TIMER; + pPriv->freeTime = time + FREE_DELAY; + } + } else + if(pPriv->videoStatus & FREE_TIMER) { + if(pPriv->freeTime < time) { + if(pTDFX->overlayBuffer) { + xf86FreeOffscreenLinear(pTDFX->overlayBuffer); + pTDFX->overlayBuffer = NULL; + } + pPriv->videoStatus = 0; + pTDFX->VideoTimerCallback = NULL; + } + } + } else /* shouldn't get here */ + pTDFX->VideoTimerCallback = NULL; } + +/* + * MEMORY MANAGEMENT + */ + + static FBAreaPtr -TDFXAllocateOffscreenBuffer (ScrnInfoPtr pScrn, int id, int width, int height) +TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height) { - int myWidth; TDFXPtr pTDFX = TDFXPTR(pScrn); + ScreenPtr pScreen; + FBAreaPtr new_area; - if (!pTDFX) - return NULL; - - /* We tweak the width slightly */ - myWidth = width; - /* We tweak the width slightly */ - myWidth = width; - - /* width is measured in pixels. The pixels in the YUV image are alway - * 8 bit YUV data. But, the xf86 offscreen manager allocates in terms of - * desktop pixels, so we adjust. */ - myWidth = myWidth / pTDFX->cpp; - if (width % pTDFX->cpp) - myWidth++; - - /* If we are putting up a subimage then we need an extra column of data - * if the source width is odd, instead of checkin the width just always - * allocate an extra column. */ - /* XXX is this really necessary? */ - myWidth++; - - if (pTDFX->offscreenYUVBuf != NULL && - myWidth == pTDFX->offscreenYUVBufWidth && - height == pTDFX->offscreenYUVBufHeight) - { - /* we already have a buffer, don't do anything. */ - return pTDFX->offscreenYUVBuf; - } - - /* We have a buffer, but its not the right size so resize it */ - if (pTDFX->offscreenYUVBuf != NULL) - { - if (!xf86ResizeOffscreenArea (pTDFX->offscreenYUVBuf, - myWidth, - height)) - { - return (NULL); - } + if (area) { + if ((area->box.x2 - area->box.x1 >= width) && + (area->box.y2 - area->box.y1 >= height)) + return area; + + if (xf86ResizeOffscreenArea(area, width, height)) + return area; + + xf86FreeOffscreenArea(area); } - else - { - /* Allocate a brand new buffer */ - pTDFX->offscreenYUVBuf = - xf86AllocateOffscreenArea (pScrn->pScreen, - myWidth, - height, - 0, - NULL, NULL, NULL); + + pScreen = screenInfo.screens[pScrn->scrnIndex]; + + new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL); + + if (!new_area) { + int max_width, max_height; + + xf86QueryLargestOffscreenArea(pScreen, &max_width, &max_height, pTDFX->cpp, 0, PRIORITY_EXTREME); + + if (max_width < width || max_height < height) + return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL); } - /* Return the buffer */ - pTDFX->offscreenYUVBufWidth = myWidth; - pTDFX->offscreenYUVBufHeight = height; - return (pTDFX->offscreenYUVBuf); + return new_area; } -static int -TDFXQueryImageAttributes( - ScrnInfoPtr pScrn, - int id, - unsigned short *w, unsigned short *h, - int *pitches, int *offsets) +static FBLinearPtr +TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size) { + ScreenPtr pScreen; + FBLinearPtr new_linear; - int size; - TDFXPtr pTDFX = TDFXPTR(pScrn); + if(linear) { + if(linear->size >= size) + return linear; - /* The Maximum size for 3dfx YUV planar space - * but our temporary buffer has to fit in the pixmap region which - * is the same width as the desktop and pTDFX->pixmapCacheLines - * pixels high. - */ - if(*w > 1024) *w = 1024; - if (*w > pTDFX->stride) *w = pTDFX->stride; - if(*h > pTDFX->pixmapCacheLines) *h = pTDFX->pixmapCacheLines; + if(xf86ResizeOffscreenLinear(linear, size)) + return linear; + xf86FreeOffscreenLinear(linear); + } + pScreen = screenInfo.screens[pScrn->scrnIndex]; - if (offsets) offsets[0] = 0; - switch(id) { - case FOURCC_YV12: - case FOURCC_I420: - if (pitches) pitches[0] = *w; - /* Size of Y plane plus the size of U and V planes */ - size = *w * *h; - if (offsets) offsets[1] = size; - size += ((*w >> 1) * (*h >> 1)); - if (offsets) offsets[2] = size; - size += ((*w >> 1) * (*h >> 1)); - break; - case FOURCC_UYVY: - case FOURCC_YUY2: - default: - size = *w << 1; - if(pitches) pitches[0] = size; - size *= *h; - break; - } - return size; + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL); + + if(!new_linear) { + int max_size; + + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, PRIORITY_EXTREME); + + if(max_size < size) + return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL); + } + + return new_linear; } #endif /* !XvExtension */ diff --git a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfxdefs.h b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfxdefs.h index c77566b78..a925b22ca 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfxdefs.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfxdefs.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfxdefs.h,v 1.9 2000/12/15 15:19:35 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfxdefs.h,v 1.8 2000/12/01 14:29:00 dawes Exp $ */ /* Voodoo Banshee driver version 1.0.1 @@ -47,8 +47,10 @@ #define SST_DESKTOP_CLUT_BYPASS BIT(10) #define SST_HALF_MODE BIT(4) #define SST_CURSOR_EN BIT(27) +#define SST_FBI_BUSY BIT(7) #define SST_BUSY BIT(9) #define SST_RETRACE BIT(6) +#define SST_COMMANDEXTRA_VSYNC BIT(2) #define MEM_TYPE_SGRAM 0 #define MEM_TYPE_SDRAM 1 @@ -198,9 +200,11 @@ #define SST_3D_COMMAND SST_3D_OFFSET+0x120 #define SST_3D_SLICTRL SST_3D_OFFSET+0x20C #define SST_3D_AACTRL SST_3D_OFFSET+0x210 -#define SST_3D_CHIPMASK SST_3D_OFFSET+0x214 +#define SST_3D_LEFTOVERLAYBUF SST_3D_OFFSET+0x250 +#define SST_3D_RIGHTOVERLAYBUF SST_3D_OFFSET+0x254 /* NAPALM REGISTERS */ +#define CFG_PCI_COMMAND 4 #define CFG_MEM0BASE 16 #define CFG_MEM1BASE 20 #define CFG_INIT_ENABLE 64 |