diff options
author | Ian Romanick <idr@us.ibm.com> | 2007-08-20 15:20:39 -0700 |
---|---|---|
committer | Ian Romanick <idr@us.ibm.com> | 2007-08-20 15:20:39 -0700 |
commit | 707d3adbc7d9ee918d6c70083f51ad851ce68852 (patch) | |
tree | ca70f5609de3d2aa2311e3cc0fecf638707c0de8 | |
parent | 741c50c162986a14647301c2c5f8e080a7664efd (diff) | |
parent | 489e007a29de63716ab550eacb3e98a91975d1d5 (diff) |
Merge branch 'master' of git+ssh://git.freedesktop.org/git/xorg/driver/xf86-video-mga into pci-rework
-rw-r--r-- | mga_PInS.txt | 28 | ||||
-rw-r--r-- | src/mga.h | 29 | ||||
-rw-r--r-- | src/mga_dacG.c | 13 | ||||
-rw-r--r-- | src/mga_dri.c | 219 | ||||
-rw-r--r-- | src/mga_driver.c | 91 | ||||
-rw-r--r-- | src/mga_exa.c | 133 | ||||
-rw-r--r-- | src/mga_storm.c | 182 | ||||
-rw-r--r-- | src/mga_vga.c | 207 | ||||
-rw-r--r-- | src/mga_video.c | 780 | ||||
-rw-r--r-- | util/stormdwg.c | 10 |
10 files changed, 1423 insertions, 269 deletions
diff --git a/mga_PInS.txt b/mga_PInS.txt index bd2ec80..eda6cf9 100644 --- a/mga_PInS.txt +++ b/mga_PInS.txt @@ -221,7 +221,33 @@ Offset Type Description 9 Has DLL? 10 Core uses MCTLWTST? 11 - 15 MCTLWTST values for core? -116 char[5] Unknown? +116 uint16_t Display Info. + Bits Meaning + 0-3 Primary display info (see below) + 4-7 Secondary display info (see below) + 8-10 Primary modes (see below) + 13 Default output + 0 = default output is secondary connector + 1 = default output is primary connector + 12-14 Secondary modes (see below) + 15 Primary hardware dectect + 0 = hardware detection is off + 1 = use hardware detection to determine main output + + Display info values: + 0000 None + 0001 HD15 + 0010 DVI + 0011 TV + x1xx Reserved + 1xxx Reserved + + Modes values: + xx1 Analog + x1x Digital + 1xx TV + +118 char[3] Unknown? 121 uint8_t VCO min for system PLL. Stored using standard clock encoding (see above). 122 uint8_t VCO min for video PLL. Stored using standard clock @@ -148,6 +148,32 @@ void MGAdbg_outreg32(ScrnInfoPtr, int,int, char*); outMGAdreg(MGA1064_DATA, tmp | (val)); \ } while (0) +#define MGAWAITVSYNC() \ + do { \ + unsigned int count = 0; \ + unsigned int status = 0; \ + do { \ + status = INREG( MGAREG_Status ); \ + count++; \ + } while( ( status & 0x08 ) && (count < 250000) );\ + count = 0; \ + status = 0; \ + do { \ + status = INREG( MGAREG_Status ); \ + count++; \ + } while( !( status & 0x08 ) && (count < 250000) );\ + } while (0) + +#define MGAWAITBUSY() \ + do { \ + unsigned int count = 0; \ + unsigned int status = 0; \ + do { \ + status = INREG8( MGAREG_Status + 2 ); \ + count++; \ + } while( ( status & 0x01 ) && (count < 500000) ); \ + } while (0) + #define PORT_OFFSET (0x1F00 - 0x300) #define MGA_VERSION 4000 @@ -730,6 +756,9 @@ long MGAG450SavePLLFreq(ScrnInfoPtr pScrn); void MGAprintDac(ScrnInfoPtr pScrn); void MGAG200SESaveFonts(ScrnInfoPtr, vgaRegPtr); void MGAG200SERestoreFonts(ScrnInfoPtr, vgaRegPtr); +void MGAG200SESaveMode(ScrnInfoPtr, vgaRegPtr); +void MGAG200SERestoreMode(ScrnInfoPtr, vgaRegPtr); +void MGAG200SEHWProtect(ScrnInfoPtr, Bool); #ifdef USEMGAHAL /************ ESC Call Definition ***************/ diff --git a/src/mga_dacG.c b/src/mga_dacG.c index cd68cb1..350c160 100644 --- a/src/mga_dacG.c +++ b/src/mga_dacG.c @@ -416,11 +416,9 @@ MGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode) MGA1064_MISC_CTL_VGA8 | MGA1064_MISC_CTL_DAC_RAM_CS; - if(pMga->HasSDRAM) - pReg->Option = 0x40499121; - else - pReg->Option = 0x4049cd21; - pReg->Option2 = 0x00008000; + if (pMga->HasSDRAM) + pReg->Option = 0x40049120; + pReg->Option2 = 0x00008000; break; case PCI_CHIP_MGAG200: case PCI_CHIP_MGAG200_PCI: @@ -810,7 +808,7 @@ MGA_NOT_HAL( /* This handles restoring the generic VGA registers. */ if (pMga->is_G200SE) { - vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE); + MGAG200SERestoreMode(pScrn, vgaReg); if (restoreFonts) MGAG200SERestoreFonts(pScrn, vgaReg); } else { @@ -910,7 +908,7 @@ MGAGSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, * in the generic VGA portion. */ if (pMga->is_G200SE) { - vgaHWSave(pScrn, vgaReg, VGA_SR_MODE); + MGAG200SESaveMode(pScrn, vgaReg); if (saveFonts) MGAG200SESaveFonts(pScrn, vgaReg); } else { @@ -965,6 +963,7 @@ MGAGSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, OUTREG8(MGAREG_CRTCEXT_INDEX, i); mgaReg->ExtVga[i] = INREG8(MGAREG_CRTCEXT_DATA); } + #ifdef DEBUG ErrorF("Saved values:\nDAC:"); for (i=0; i<DACREGSIZE; i++) { diff --git a/src/mga_dri.c b/src/mga_dri.c index dd0c2fd..bb2cc39 100644 --- a/src/mga_dri.c +++ b/src/mga_dri.c @@ -76,13 +76,6 @@ static char MGAKernelDriverName[] = "mga"; static char MGAClientDriverName[] = "mga"; -/* DRI buffer management - */ -extern void mgaDRIInitBuffers( WindowPtr pWin, RegionPtr prgn, CARD32 index ); -extern void mgaDRIMoveBuffers( WindowPtr pParent, DDXPointRec ptOldOrg, - RegionPtr prgnSrc, CARD32 index ); - - /* Initialize the visual configs that are supported by the hardware. * These are combined with the visual configs that the indirect * rendering core supports, and the intersection is exported to the @@ -496,7 +489,6 @@ MGADRISwapContextShared( ScreenPtr pScreen, DRISyncType syncType, } } -#ifdef USE_XAA void MGASelectBuffer( ScrnInfoPtr pScrn, int which ) { MGAPtr pMga = MGAPTR(pScrn); @@ -518,8 +510,6 @@ void MGASelectBuffer( ScrnInfoPtr pScrn, int which ) break; } } -#endif - static unsigned int mylog2( unsigned int n ) { @@ -903,6 +893,200 @@ static Bool MGADRIBuffersInit( ScreenPtr pScreen ) return TRUE; } +#ifdef USE_XAA +static void MGADRIInitBuffersXAA(WindowPtr pWin, RegionPtr prgn, + CARD32 index) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + MGAPtr pMga = MGAPTR(pScrn); + BoxPtr pbox = REGION_RECTS(prgn); + int nbox = REGION_NUM_RECTS(prgn); + XAAInfoRecPtr xaa = pMga->AccelInfoRec; + + CHECK_DMA_QUIESCENT(MGAPTR(pScrn), pScrn); + + xaa->SetupForSolidFill(pScrn, 0, GXcopy, -1); + + while (nbox--) { + MGASelectBuffer(pScrn, MGA_BACK); + xaa->SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, + pbox->x2-pbox->x1, pbox->y2-pbox->y1); + MGASelectBuffer(pScrn, MGA_DEPTH); + xaa->SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, + pbox->x2-pbox->x1, pbox->y2-pbox->y1); + pbox++; + } + + MGASelectBuffer(pScrn, MGA_FRONT); + + pMga->AccelInfoRec->NeedToSync = TRUE; +} +#endif + +#ifdef USE_EXA +static void MGADRIInitBuffersEXA(WindowPtr pWin, RegionPtr prgn, + CARD32 index) +{ + /* FIXME */ +} +#endif + +#ifdef USE_XAA +/* + This routine is a modified form of XAADoBitBlt with the calls to + ScreenToScreenBitBlt built in. My routine has the prgnSrc as source + instead of destination. My origin is upside down so the ydir cases + are reversed. +*/ +static void MGADRIMoveBuffersXAA(WindowPtr pParent, DDXPointRec ptOldOrg, + RegionPtr prgnSrc, CARD32 index) +{ + ScreenPtr pScreen = pParent->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + MGAPtr pMga = MGAPTR(pScrn); + int nbox; + BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2; + DDXPointPtr pptTmp, pptNew1, pptNew2; + int xdir, ydir; + int dx, dy; + DDXPointPtr pptSrc; + int screenwidth = pScrn->virtualX; + int screenheight = pScrn->virtualY; + XAAInfoRecPtr xaa = pMga->AccelInfoRec; + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + pbox = REGION_RECTS(prgnSrc); + nbox = REGION_NUM_RECTS(prgnSrc); + pboxNew1 = 0; + pptNew1 = 0; + pboxNew2 = 0; + pboxNew2 = 0; + pptSrc = &ptOldOrg; + + dx = pParent->drawable.x - ptOldOrg.x; + dy = pParent->drawable.y - ptOldOrg.y; + + /* If the copy will overlap in Y, reverse the order */ + if (dy>0) { + ydir = -1; + + if (nbox>1) { + /* Keep ordering in each band, reverse order of bands */ + pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox); + if (!pboxNew1) return; + pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox); + if (!pptNew1) { + DEALLOCATE_LOCAL(pboxNew1); + return; + } + pboxBase = pboxNext = pbox+nbox-1; + while (pboxBase >= pbox) { + while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) + pboxNext--; + pboxTmp = pboxNext+1; + pptTmp = pptSrc + (pboxTmp - pbox); + while (pboxTmp <= pboxBase) { + *pboxNew1++ = *pboxTmp++; + *pptNew1++ = *pptTmp++; + } + pboxBase = pboxNext; + } + pboxNew1 -= nbox; + pbox = pboxNew1; + pptNew1 -= nbox; + pptSrc = pptNew1; + } + } else { + /* No changes required */ + ydir = 1; + } + + /* If the regions will overlap in X, reverse the order */ + if (dx>0) { + xdir = -1; + + if (nbox > 1) { + /*reverse orderof rects in each band */ + pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox); + pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox); + if (!pboxNew2 || !pptNew2) { + if (pptNew2) DEALLOCATE_LOCAL(pptNew2); + if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2); + if (pboxNew1) { + DEALLOCATE_LOCAL(pptNew1); + DEALLOCATE_LOCAL(pboxNew1); + } + return; + } + pboxBase = pboxNext = pbox; + while (pboxBase < pbox+nbox) { + while ((pboxNext < pbox+nbox) && + (pboxNext->y1 == pboxBase->y1)) + pboxNext++; + pboxTmp = pboxNext; + pptTmp = pptSrc + (pboxTmp - pbox); + while (pboxTmp != pboxBase) { + *pboxNew2++ = *--pboxTmp; + *pptNew2++ = *--pptTmp; + } + pboxBase = pboxNext; + } + pboxNew2 -= nbox; + pbox = pboxNew2; + pptNew2 -= nbox; + pptSrc = pptNew2; + } + } else { + /* No changes are needed */ + xdir = 1; + } + + xaa->SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1); + for ( ; nbox-- ; pbox++) { + int x1 = pbox->x1; + int y1 = pbox->y1; + int destx = x1 + dx; + int desty = y1 + dy; + int w = pbox->x2 - x1 + 1; + int h = pbox->y2 - y1 + 1; + + if ( destx < 0 ) x1 -= destx, w += destx, destx = 0; + if ( desty < 0 ) y1 -= desty, h += desty, desty = 0; + if ( destx + w > screenwidth ) w = screenwidth - destx; + if ( desty + h > screenheight ) h = screenheight - desty; + if ( w <= 0 ) continue; + if ( h <= 0 ) continue; + + MGASelectBuffer(pScrn, MGA_BACK); + xaa->SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); + MGASelectBuffer(pScrn, MGA_DEPTH); + xaa->SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); + } + MGASelectBuffer(pScrn, MGA_FRONT); + + if (pboxNew2) { + DEALLOCATE_LOCAL(pptNew2); + DEALLOCATE_LOCAL(pboxNew2); + } + if (pboxNew1) { + DEALLOCATE_LOCAL(pptNew1); + DEALLOCATE_LOCAL(pboxNew1); + } + + pMga->AccelInfoRec->NeedToSync = TRUE; + +} +#endif + +#ifdef USE_EXA +static void MGADRIMoveBuffersEXA(WindowPtr pParent, DDXPointRec ptOldOrg, + RegionPtr prgnSrc, CARD32 index) +{ + /* FIXME */ +} +#endif Bool MGADRIScreenInit( ScreenPtr pScreen ) { @@ -1044,8 +1228,19 @@ Bool MGADRIScreenInit( ScreenPtr pScreen ) pDRIInfo->SwapContext = MGADRISwapContext; } - pDRIInfo->InitBuffers = mgaDRIInitBuffers; - pDRIInfo->MoveBuffers = mgaDRIMoveBuffers; +#ifdef USE_EXA + if (pMga->Exa) { + pDRIInfo->InitBuffers = MGADRIInitBuffersEXA; + pDRIInfo->MoveBuffers = MGADRIMoveBuffersEXA; + } else { +#endif +#ifdef USE_XAA + pDRIInfo->InitBuffers = MGADRIInitBuffersXAA; + pDRIInfo->MoveBuffers = MGADRIMoveBuffersXAA; +#endif +#ifdef USE_EXA + } +#endif pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; diff --git a/src/mga_driver.c b/src/mga_driver.c index 866e46a..2c9c6ef 100644 --- a/src/mga_driver.c +++ b/src/mga_driver.c @@ -755,6 +755,7 @@ MGACountRam(ScrnInfoPtr pScrn) int ProbeSize = 8192; int SizeFound = 2048; CARD32 biosInfo = 0; + CARD8 seq1; #if 0 /* This isn't correct. It looks like this can have arbitrary @@ -832,6 +833,16 @@ MGACountRam(ScrnInfoPtr pScrn) base = pMga->FbBase; + if (pMga->is_G200SE) { + OUTREG8(MGAREG_SEQ_INDEX, 0x01); + seq1 = INREG8(MGAREG_SEQ_DATA); + seq1 |= 0x20; + MGAWAITVSYNC(); + MGAWAITBUSY(); + OUTREG8(MGAREG_SEQ_DATA, seq1); + usleep(20000); + } + /* turn MGA mode on - enable linear frame buffer (CRTCEXT3) */ OUTREG8(MGAREG_CRTCEXT_INDEX, 3); tmp = INREG8(MGAREG_CRTCEXT_DATA); @@ -852,7 +863,7 @@ MGACountRam(ScrnInfoPtr pScrn) base[1] = 0; for (Offset = 0x100000; Offset < (ProbeSize * 1024); - Offset += 0x1000) { + Offset += 0x1000) { FirstMemoryVal1 = base[Offset]; FirstMemoryVal2 = base[Offset+1]; SecondMemoryVal1 = base[Offset+0x100]; @@ -907,8 +918,17 @@ MGACountRam(ScrnInfoPtr pScrn) OUTREG8(MGAREG_CRTCEXT_INDEX, 3); OUTREG8(MGAREG_CRTCEXT_DATA, tmp); + if (pMga->is_G200SE) { + OUTREG8(MGAREG_SEQ_INDEX, 0x01); + seq1 = INREG8(MGAREG_SEQ_DATA); + seq1 &= ~0x20; + MGAWAITVSYNC(); + MGAWAITBUSY(); + OUTREG8(MGAREG_SEQ_DATA, seq1); + usleep(20000); + } MGAUnmapMem(pScrn); - } + } return SizeFound; } @@ -1409,6 +1429,9 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags) if (pMga->SecondCrtc) flags24 = Support32bppFb; + if (pMga->is_G200SE) + pScrn->confScreen->defaultdepth = 16; + if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) { return FALSE; } else { @@ -1459,6 +1482,14 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags) memcpy(pMga->Options, MGAOptions, sizeof(MGAOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pMga->Options); + if (pMga->is_G200SE) { + /* Disable MTRR support on PCIe systems */ + CARD32 temp = pciReadLong(pMga->PciTag, 0xDC); + if ((temp & 0x0000FF00) != 0x0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling MTRR support.\n"); + pScrn->options = xf86ReplaceBoolOption(pScrn->options, "MTRR", FALSE); + } + } #if !defined(__powerpc__) pMga->softbooted = FALSE; @@ -1890,6 +1921,21 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags) pScrn->monitor->DDC = MGAdoDDC(pScrn); #endif /* !__powerpc__ */ + if (!pScrn->monitor->DDC && pMga->is_G200SE) { + /* Jam in ranges big enough for 1024x768 */ + if (!pScrn->monitor->nHsync) { + pScrn->monitor->nHsync = 1; + pScrn->monitor->hsync[0].lo = 31.5; + pScrn->monitor->hsync[0].hi = 48.0; + } + if (!pScrn->monitor->nVrefresh) { + pScrn->monitor->nVrefresh = 1; + pScrn->monitor->vrefresh[0].lo = 56.0; + pScrn->monitor->vrefresh[0].hi = 75.0; + } + } + + /* * If the driver can do gamma correction, it should call xf86SetGamma() * here. @@ -1907,7 +1953,7 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags) /* XXX Set HW cursor use */ /* Set the min pixel clock */ - pMga->MinClock = 12000; /* XXX Guess, need to check this */ + pMga->MinClock = 17750; xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", pMga->MinClock / 1000); /* @@ -2686,7 +2732,11 @@ MGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) return FALSE; /* Program the registers */ - vgaHWProtect(pScrn, TRUE); + if (pMga->is_G200SE) { + MGAG200SEHWProtect(pScrn, TRUE); + } else { + vgaHWProtect(pScrn, TRUE); + } vgaReg = &hwp->ModeReg; mgaReg = &pMga->ModeReg; #ifdef USEMGAHAL @@ -2790,7 +2840,11 @@ MGA_HAL( MGAStormSync(pScrn); MGAStormEngineInit(pScrn); - vgaHWProtect(pScrn, FALSE); + if (pMga->is_G200SE) { + MGAG200SEHWProtect(pScrn,FALSE); + } else { + vgaHWProtect(pScrn, FALSE); + } if (xf86IsPc98()) { if (pMga->Chipset == PCI_CHIP_MGA2064) @@ -2799,6 +2853,13 @@ MGA_HAL( outb(0xfac, 0x02); } + MGA_NOT_HAL( + if (pMga->is_G200SE) { + OUTREG8(0x1FDE, 0x06); + OUTREG8(0x1FDF, 0x14); + } + ); + pMga->CurrentLayout.mode = mode; if(pMga->MergedFB && mode->Private && (mode->PrivSize == 0)) { @@ -2895,7 +2956,11 @@ MGARestore(ScrnInfoPtr pScrn) } /* Only restore text mode fonts/text for the primary card */ - vgaHWProtect(pScrn, TRUE); + if (pMga->is_G200SE) { + MGAG200SEHWProtect(pScrn,TRUE); + } else { + vgaHWProtect(pScrn, TRUE); + } if (pMga->Primary) { #ifdef USEMGAHAL MGA_HAL( @@ -2909,7 +2974,12 @@ MGARestore(ScrnInfoPtr pScrn) } else { vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE); } - vgaHWProtect(pScrn, FALSE); + + if (pMga->is_G200SE) { + MGAG200SEHWProtect(pScrn,FALSE); + } else { + vgaHWProtect(pScrn,FALSE); + } } @@ -3202,8 +3272,7 @@ MGAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) * InitGLXVisuals call back. * The DRI does not work when textured video is enabled at this time. */ - if ((pMga->Chipset == PCI_CHIP_MGAG200_SE_A_PCI) || - (pMga->Chipset == PCI_CHIP_MGAG200_SE_B_PCI)) { + if (pMga->is_G200SE) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Not supported by hardware, not initializing the DRI\n"); pMga->directRenderingEnabled = FALSE; @@ -3933,10 +4002,14 @@ MGADisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, crtcext1 = 0x30; break; } + /* XXX Prefer an implementation that doesn't depend on VGA specifics */ OUTREG8(MGAREG_SEQ_INDEX, 0x01); /* Select SEQ1 */ seq1 |= INREG8(MGAREG_SEQ_DATA) & ~0x20; + MGAWAITVSYNC(); + MGAWAITBUSY(); OUTREG8(MGAREG_SEQ_DATA, seq1); + usleep(20000); OUTREG8(MGAREG_CRTCEXT_INDEX, 0x01); /* Select CRTCEXT1 */ crtcext1 |= INREG8(MGAREG_CRTCEXT_DATA) & ~0x30; OUTREG8(MGAREG_CRTCEXT_DATA, crtcext1); diff --git a/src/mga_exa.c b/src/mga_exa.c index 17618f5..bfb78e7 100644 --- a/src/mga_exa.c +++ b/src/mga_exa.c @@ -227,11 +227,6 @@ mgaPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int xdir, int ydir, int alu, */ QUIESCE_DMA(pSrc); - DEBUG_MSG(("s: %x@%x d: %x@%x xdir %d ydir %d alu %d pm %d\n", - exaGetPixmapOffset(pSrc), exaGetPixmapPitch(pSrc), - exaGetPixmapOffset(pDst), exaGetPixmapPitch(pDst), - xdir, ydir, alu, planemask)); - if (xdir < 0) blit_direction |= BLIT_LEFT; @@ -261,8 +256,6 @@ mgaCopy(PixmapPtr pDst, int srcx, int srcy, int dstx, int dsty, int w, int h) PMGA(pDst); int start, end; - DEBUG_MSG((" %d,%d -> %d,%d %dx%d\n", srcx, srcy, dstx,dsty, w, h)); - w--; if (pMga->BltScanDirection & BLIT_UP) { @@ -277,9 +270,6 @@ mgaCopy(PixmapPtr pDst, int srcx, int srcy, int dstx, int dsty, int w, int h) else end += w; - DEBUG_MSG((" end %d start %d dstx %d dsty %d w %d h %d\n", - end, start, dstx, dsty, w, h)); - WAITFIFO(4); OUTREG(MGAREG_AR0, end); OUTREG(MGAREG_AR3, start); @@ -360,6 +350,8 @@ static Bool mgaCheckComposite(int op, PicturePtr pSrcPict, PicturePtr pMaskPict, PicturePtr pDstPict) { + MGAPtr pMga = xf86Screens[pSrcPict->pDrawable->pScreen->myNum]->driverPrivate; + if (op >= sizeof(mgaBlendOp) / sizeof(mgaBlendOp[0])) { DEBUG_MSG(("unsupported op %x\n", op)); return FALSE; @@ -383,10 +375,9 @@ mgaCheckComposite(int op, PicturePtr pSrcPict, PicturePtr pMaskPict, return FALSE; } - /* FIXME - * Doing this operation in hardware is broken atm :/ - */ - if (op == PictOpAdd && pSrcPict->format == PICT_a8 && + /* Only the G550 can perform Add on A8 textures, it seems. */ + if (pMga->Chipset != PCI_CHIP_MGAG550 && + op == PictOpAdd && pSrcPict->format == PICT_a8 && pDstPict->format == PICT_a8) return FALSE; @@ -594,15 +585,6 @@ mgaPrepareComposite(int op, PicturePtr pSrcPict, PicturePtr pMaskPict, blendcntl = (blendcntl & ~MGA_SRC_BLEND_MASK) | MGA_SRC_ZERO; } - if (!PICT_FORMAT_A(pSrcPict->format) && mgaBlendOp[op].src_alpha) { - int dblend = blendcntl & MGA_DST_BLEND_MASK; - - if (dblend == MGA_DST_SRC_ALPHA) - blendcntl = (blendcntl & ~MGA_DST_BLEND_MASK) | MGA_DST_ONE; - else if (dblend == MGA_DST_ONE_MINUS_SRC_ALPHA) - blendcntl = (blendcntl & ~MGA_DST_BLEND_MASK) | MGA_DST_ZERO; - } - WAITFIFO(5); OUTREG(MGAREG_FCOL, fcol); OUTREG(MGAREG_TDUALSTAGE0, ds0); @@ -732,6 +714,33 @@ mgaUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, src += src_pitch; } + exaMarkSync(pDst->drawable.pScreen); + + return TRUE; +} + +static Bool +mgaDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, + char *dst, int dst_pitch) +{ + PMGA(pSrc); + + char *src = pSrc->devPrivate.ptr; + int src_pitch = exaGetPixmapPitch(pSrc); + + int cpp = (pSrc->drawable.bitsPerPixel + 7) / 8; + int bytes = w * cpp; + + src += y * src_pitch + x * cpp; + + QUIESCE_DMA(pSrc); + + while (h--) { + memcpy (dst, src, bytes); + src += src_pitch; + dst += dst_pitch; + } + return TRUE; } @@ -749,6 +758,80 @@ mgaWaitMarker(ScreenPtr pScreen, int marker) while (INREG (MGAREG_Status) & 0x10000); } +static void +init_dri(ScrnInfoPtr pScrn) +{ + MGAPtr pMga = MGAPTR(pScrn); + MGADRIServerPrivatePtr dri = pMga->DRIServerInfo; + int cpp = pScrn->bitsPerPixel / 8; + int widthBytes = pScrn->displayWidth * cpp; + int bufferSize = ((pScrn->virtualY * widthBytes + MGA_BUFFER_ALIGN) + & ~MGA_BUFFER_ALIGN); + int maxlines, mb; + + switch (pMga->Chipset) { + case PCI_CHIP_MGAG200_SE_A_PCI: + case PCI_CHIP_MGAG200_SE_B_PCI: + mb = 1; + break; + default: + mb = 16; + break; + } + + maxlines = (min(pMga->FbUsableSize, mb * 1024 * 1024)) / + (pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel / 8); + + dri->frontOffset = 0; + dri->frontPitch = widthBytes; + + /* Try for front, back, depth, and two framebuffers worth of + * pixmap cache. Should be enough for a fullscreen background + * image plus some leftovers. + */ + dri->textureSize = pMga->FbMapSize - 5 * bufferSize; + + /* If that gives us less than half the available memory, let's + * be greedy and grab some more. Sorry, I care more about 3D + * performance than playing nicely, and you'll get around a full + * framebuffer's worth of pixmap cache anyway. + */ + if (dri->textureSize < (int)pMga->FbMapSize / 2) { + dri->textureSize = pMga->FbMapSize - 4 * bufferSize; + } + + /* Check to see if there is more room available after the maximum + * scanline for textures. + */ + if ((int) pMga->FbMapSize - maxlines * widthBytes - bufferSize * 2 + > dri->textureSize) { + dri->textureSize = pMga->FbMapSize - maxlines * widthBytes - + bufferSize * 2; + } + + /* Set a minimum usable local texture heap size. This will fit + * two 256x256x32bpp textures. + */ + if (dri->textureSize < 512 * 1024) { + dri->textureOffset = 0; + dri->textureSize = 0; + } + + /* Reserve space for textures */ + dri->textureOffset = (pMga->FbMapSize - dri->textureSize + + MGA_BUFFER_ALIGN) & ~MGA_BUFFER_ALIGN; + + /* Reserve space for the shared depth buffer */ + dri->depthOffset = (dri->textureOffset - bufferSize + + MGA_BUFFER_ALIGN) & ~MGA_BUFFER_ALIGN; + dri->depthPitch = widthBytes; + + /* Reserve space for the shared back buffer */ + dri->backOffset = (dri->depthOffset - bufferSize + + MGA_BUFFER_ALIGN) & ~MGA_BUFFER_ALIGN; + dri->backPitch = widthBytes; +} + Bool mgaExaInit(ScreenPtr pScreen) { @@ -806,6 +889,10 @@ mgaExaInit(ScreenPtr pScreen) } pExa->UploadToScreen = mgaUploadToScreen; + pExa->DownloadFromScreen = mgaDownloadFromScreen; + + if (pMga->directRenderingEnabled) + init_dri(pScrn); return exaDriverInit(pScreen, pExa); } diff --git a/src/mga_storm.c b/src/mga_storm.c index 23801ac..dfdebeb 100644 --- a/src/mga_storm.c +++ b/src/mga_storm.c @@ -143,12 +143,6 @@ static void mgaSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn, static void mgaRestoreAccelState( ScrnInfoPtr pScrn ); -#ifdef XF86DRI -void mgaDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index); -void mgaDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, - RegionPtr prgnSrc, CARD32 index); -#endif - static void MGASetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2); static void MGADisableClipping(ScrnInfoPtr pScrn); @@ -2543,179 +2537,3 @@ MGAFillCacheBltRects( SET_SYNC_FLAG(infoRec); } - - -#if defined(XF86DRI) -void -mgaDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - MGAPtr pMga = MGAPTR(pScrn); - BoxPtr pbox = REGION_RECTS(prgn); - int nbox = REGION_NUM_RECTS(prgn); - - CHECK_DMA_QUIESCENT(MGAPTR(pScrn), pScrn); - - mgaSetupForSolidFill(pScrn, 0, GXcopy, -1); - while (nbox--) { - MGASelectBuffer(pScrn, MGA_BACK); - mgaSubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, - pbox->x2-pbox->x1, pbox->y2-pbox->y1); - MGASelectBuffer(pScrn, MGA_DEPTH); - mgaSubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, - pbox->x2-pbox->x1, pbox->y2-pbox->y1); - pbox++; - } - MGASelectBuffer(pScrn, MGA_FRONT); - - pMga->AccelInfoRec->NeedToSync = TRUE; -} - -/* - This routine is a modified form of XAADoBitBlt with the calls to - ScreenToScreenBitBlt built in. My routine has the prgnSrc as source - instead of destination. My origin is upside down so the ydir cases - are reversed. -*/ - -void -mgaDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, - RegionPtr prgnSrc, CARD32 index) -{ - ScreenPtr pScreen = pParent->drawable.pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - MGAPtr pMga = MGAPTR(pScrn); - int nbox; - BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2; - DDXPointPtr pptTmp, pptNew1, pptNew2; - int xdir, ydir; - int dx, dy; - DDXPointPtr pptSrc; - int screenwidth = pScrn->virtualX; - int screenheight = pScrn->virtualY; - - CHECK_DMA_QUIESCENT(MGAPTR(pScrn), pScrn); - - pbox = REGION_RECTS(prgnSrc); - nbox = REGION_NUM_RECTS(prgnSrc); - pboxNew1 = 0; - pptNew1 = 0; - pboxNew2 = 0; - pboxNew2 = 0; - pptSrc = &ptOldOrg; - - dx = pParent->drawable.x - ptOldOrg.x; - dy = pParent->drawable.y - ptOldOrg.y; - - /* If the copy will overlap in Y, reverse the order */ - if (dy>0) { - ydir = -1; - - if (nbox>1) { - /* Keep ordering in each band, reverse order of bands */ - pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox); - if (!pboxNew1) return; - pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox); - if (!pptNew1) { - DEALLOCATE_LOCAL(pboxNew1); - return; - } - pboxBase = pboxNext = pbox+nbox-1; - while (pboxBase >= pbox) { - while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) - pboxNext--; - pboxTmp = pboxNext+1; - pptTmp = pptSrc + (pboxTmp - pbox); - while (pboxTmp <= pboxBase) { - *pboxNew1++ = *pboxTmp++; - *pptNew1++ = *pptTmp++; - } - pboxBase = pboxNext; - } - pboxNew1 -= nbox; - pbox = pboxNew1; - pptNew1 -= nbox; - pptSrc = pptNew1; - } - } else { - /* No changes required */ - ydir = 1; - } - - /* If the regions will overlap in X, reverse the order */ - if (dx>0) { - xdir = -1; - - if (nbox > 1) { - /*reverse orderof rects in each band */ - pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox); - pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox); - if (!pboxNew2 || !pptNew2) { - if (pptNew2) DEALLOCATE_LOCAL(pptNew2); - if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2); - if (pboxNew1) { - DEALLOCATE_LOCAL(pptNew1); - DEALLOCATE_LOCAL(pboxNew1); - } - return; - } - pboxBase = pboxNext = pbox; - while (pboxBase < pbox+nbox) { - while ((pboxNext < pbox+nbox) && - (pboxNext->y1 == pboxBase->y1)) - pboxNext++; - pboxTmp = pboxNext; - pptTmp = pptSrc + (pboxTmp - pbox); - while (pboxTmp != pboxBase) { - *pboxNew2++ = *--pboxTmp; - *pptNew2++ = *--pptTmp; - } - pboxBase = pboxNext; - } - pboxNew2 -= nbox; - pbox = pboxNew2; - pptNew2 -= nbox; - pptSrc = pptNew2; - } - } else { - /* No changes are needed */ - xdir = 1; - } - - mgaSetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1); - for ( ; nbox-- ; pbox++) { - int x1 = pbox->x1; - int y1 = pbox->y1; - int destx = x1 + dx; - int desty = y1 + dy; - int w = pbox->x2 - x1 + 1; - int h = pbox->y2 - y1 + 1; - - if ( destx < 0 ) x1 -= destx, w += destx, destx = 0; - if ( desty < 0 ) y1 -= desty, h += desty, desty = 0; - if ( destx + w > screenwidth ) w = screenwidth - destx; - if ( desty + h > screenheight ) h = screenheight - desty; - if ( w <= 0 ) continue; - if ( h <= 0 ) continue; - - MGASelectBuffer(pScrn, MGA_BACK); - mgaSubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); - MGASelectBuffer(pScrn, MGA_DEPTH); - mgaSubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); - } - MGASelectBuffer(pScrn, MGA_FRONT); - - if (pboxNew2) { - DEALLOCATE_LOCAL(pptNew2); - DEALLOCATE_LOCAL(pboxNew2); - } - if (pboxNew1) { - DEALLOCATE_LOCAL(pptNew1); - DEALLOCATE_LOCAL(pboxNew1); - } - - pMga->AccelInfoRec->NeedToSync = TRUE; -} - -#endif /* XF86DRI */ diff --git a/src/mga_vga.c b/src/mga_vga.c index fbbfc60..8dfc08f 100644 --- a/src/mga_vga.c +++ b/src/mga_vga.c @@ -4,6 +4,8 @@ #include "vgaHW.h" #include "compiler.h" #include "xf86cmap.h" +#include "mga.h" +#include "mga_reg.h" #define TEXT_AMOUNT 16384 #define FONT_AMOUNT (8*8192) @@ -12,9 +14,11 @@ void MGAG200SERestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore) { vgaHWPtr hwp = VGAHWPTR(scrninfp); + MGAPtr pMga = MGAPTR(scrninfp); int savedIOBase; unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4; Bool doMap = FALSE; + unsigned char scrn; /* If nothing to do, return now */ if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo) @@ -48,7 +52,14 @@ MGAG200SERestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore) /* Force into colour mode */ hwp->writeMiscOut(hwp, miscOut | 0x01); - vgaHWBlankScreen(scrninfp, FALSE); + scrn = hwp->readSeq(hwp, 0x01); + scrn |= 0x20;/* blank screen */ + vgaHWSeqReset(hwp, TRUE); + MGAWAITVSYNC(); + MGAWAITBUSY(); + hwp->writeSeq(hwp, 0x01, scrn);/* change mode */ + usleep(20000); + vgaHWSeqReset(hwp, FALSE); /* * here we temporarily switch to 16 colour planar mode, to simply @@ -66,36 +77,28 @@ MGAG200SERestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore) hwp->writeGr(hwp, 0x01, 0x00); /* all planes come from CPU */ } + hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ + hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ + hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ + if (hwp->FontInfo1) { hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */ - hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */ - hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ - hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ slowbcopy_tobus(hwp->FontInfo1, hwp->Base, FONT_AMOUNT); } if (hwp->FontInfo2) { hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */ - hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */ - hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ - hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ slowbcopy_tobus(hwp->FontInfo2, hwp->Base, FONT_AMOUNT); } if (hwp->TextInfo) { hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */ - hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */ - hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ - hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ slowbcopy_tobus(hwp->TextInfo, hwp->Base, TEXT_AMOUNT); hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */ - hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ hwp->writeGr(hwp, 0x04, 0x01); /* read plane 1 */ - hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ - hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ slowbcopy_tobus((unsigned char *)hwp->TextInfo + TEXT_AMOUNT, hwp->Base, TEXT_AMOUNT); } @@ -113,7 +116,14 @@ MGAG200SERestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore) hwp->writeSeq(hwp, 0x04, seq4); hwp->IOBase = savedIOBase; - vgaHWBlankScreen(scrninfp, TRUE); + scrn = hwp->readSeq(hwp, 0x01); + scrn &= ~0x20;/* enable screen */ + vgaHWSeqReset(hwp, TRUE); + MGAWAITVSYNC(); + MGAWAITBUSY(); + hwp->writeSeq(hwp, 0x01, scrn);/* change mode */ + usleep(20000); + vgaHWSeqReset(hwp, FALSE); if (doMap) vgaHWUnmapMem(scrninfp); @@ -124,9 +134,11 @@ void MGAG200SESaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save) { vgaHWPtr hwp = VGAHWPTR(scrninfp); + MGAPtr pMga = MGAPTR(scrninfp); int savedIOBase; unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4; Bool doMap = FALSE; + unsigned char scrn; if (hwp->Base == NULL) { doMap = TRUE; @@ -157,7 +169,14 @@ MGAG200SESaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save) /* Force into colour mode */ hwp->writeMiscOut(hwp, miscOut | 0x01); - vgaHWBlankScreen(scrninfp, FALSE); + scrn = hwp->readSeq(hwp, 0x01); + scrn |= 0x20;/* blank screen */ + vgaHWSeqReset(hwp, TRUE); + MGAWAITVSYNC(); + MGAWAITBUSY(); + hwp->writeSeq(hwp, 0x01, scrn);/* change mode */ + usleep(20000); + vgaHWSeqReset(hwp, FALSE); /* * get the character sets, and text screen if required @@ -171,34 +190,25 @@ MGAG200SESaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save) #if 0 hwp->writeAttr(hwp, 0x10, 0x01); /* graphics mode */ #endif + hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ + hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ + hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ if (hwp->FontInfo1 || (hwp->FontInfo1 = xalloc(FONT_AMOUNT))) { hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */ - hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */ - hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ - hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ slowbcopy_frombus(hwp->Base, hwp->FontInfo1, FONT_AMOUNT); } if (hwp->FontInfo2 || (hwp->FontInfo2 = xalloc(FONT_AMOUNT))) { hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */ - hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */ - hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ - hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ slowbcopy_frombus(hwp->Base, hwp->FontInfo2, FONT_AMOUNT); } if (hwp->TextInfo || (hwp->TextInfo = xalloc(2 * TEXT_AMOUNT))) { hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */ - hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */ - hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ - hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ slowbcopy_frombus(hwp->Base, hwp->TextInfo, TEXT_AMOUNT); hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */ - hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ hwp->writeGr(hwp, 0x04, 0x01); /* read plane 1 */ - hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ - hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ slowbcopy_frombus(hwp->Base, (unsigned char *)hwp->TextInfo + TEXT_AMOUNT, TEXT_AMOUNT); } @@ -213,8 +223,149 @@ MGAG200SESaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save) hwp->writeMiscOut(hwp, miscOut); hwp->IOBase = savedIOBase; - vgaHWBlankScreen(scrninfp, TRUE); + scrn = hwp->readSeq(hwp, 0x01); + scrn &= ~0x20;/* enable screen */ + vgaHWSeqReset(hwp, TRUE); + MGAWAITVSYNC(); + MGAWAITBUSY(); + hwp->writeSeq(hwp, 0x01, scrn);/* change mode */ + usleep(20000); + vgaHWSeqReset(hwp, FALSE); if (doMap) vgaHWUnmapMem(scrninfp); } + +void +MGAG200SERestoreMode(ScrnInfoPtr scrninfp, vgaRegPtr restore) +{ + vgaHWPtr hwp = VGAHWPTR(scrninfp); + MGAPtr pMga = MGAPTR(scrninfp); + int i; + unsigned char scrn; + + if (restore->MiscOutReg & 0x01) + hwp->IOBase = VGA_IOBASE_COLOR; + else + hwp->IOBase = VGA_IOBASE_MONO; + + hwp->writeMiscOut(hwp, restore->MiscOutReg); + + + for (i = 1; i < restore->numSequencer; i++) + { + MGAWAITVSYNC(); + MGAWAITBUSY(); + hwp->writeSeq(hwp, i, restore->Sequencer[i]); + usleep(20000); + } + + scrn = hwp->readSeq(hwp, 0x01); + scrn |= 0x20;/* blank screen */ + vgaHWSeqReset(hwp, TRUE); + MGAWAITVSYNC(); + MGAWAITBUSY(); + hwp->writeSeq(hwp, 0x01, scrn);/* change mode */ + usleep(20000); + + /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */ + hwp->writeCrtc(hwp, 17, restore->CRTC[17] & ~0x80); + + for (i = 0; i < restore->numCRTC; i++) + hwp->writeCrtc(hwp, i, restore->CRTC[i]); + + for (i = 0; i < restore->numGraphics; i++) + hwp->writeGr(hwp, i, restore->Graphics[i]); + + hwp->enablePalette(hwp); + for (i = 0; i < restore->numAttribute; i++) + hwp->writeAttr(hwp, i, restore->Attribute[i]); + hwp->disablePalette(hwp); + + MGAWAITVSYNC(); + MGAWAITBUSY(); + hwp->writeSeq(hwp, 1, restore->Sequencer[1]); + usleep(20000); +} + +void +MGAG200SESaveMode(ScrnInfoPtr scrninfp, vgaRegPtr save) +{ + vgaHWPtr hwp = VGAHWPTR(scrninfp); + int i; + + save->MiscOutReg = hwp->readMiscOut(hwp); + if (save->MiscOutReg & 0x01) + hwp->IOBase = VGA_IOBASE_COLOR; + else + hwp->IOBase = VGA_IOBASE_MONO; + + for (i = 0; i < save->numCRTC; i++) { + save->CRTC[i] = hwp->readCrtc(hwp, i); +#ifdef DEBUG + ErrorF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]); +#endif + } + + hwp->enablePalette(hwp); + for (i = 0; i < save->numAttribute; i++) { + save->Attribute[i] = hwp->readAttr(hwp, i); +#ifdef DEBUG + ErrorF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]); +#endif + } + hwp->disablePalette(hwp); + + for (i = 0; i < save->numGraphics; i++) { + save->Graphics[i] = hwp->readGr(hwp, i); +#ifdef DEBUG + ErrorF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]); +#endif + } + + for (i = 1; i < save->numSequencer; i++) { + save->Sequencer[i] = hwp->readSeq(hwp, i); +#ifdef DEBUG + ErrorF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]); +#endif + } +} + +void +MGAG200SEHWProtect(ScrnInfoPtr pScrn, Bool on) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + MGAPtr pMga = MGAPTR(pScrn); + + unsigned char tmp; + + if (pScrn->vtSema) { + if (on) { + /* + * Turn off screen and disable sequencer. + */ + tmp = hwp->readSeq(hwp, 0x01); + + vgaHWSeqReset(hwp, TRUE); /* start synchronous reset */ + MGAWAITVSYNC(); + MGAWAITBUSY(); + hwp->writeSeq(hwp, 0x01, tmp | 0x20); /* disable the display */ + usleep(20000); + hwp->enablePalette(hwp); + } else { + /* + * Reenable sequencer, then turn on screen. + */ + + tmp = hwp->readSeq(hwp, 0x01); + + MGAWAITVSYNC(); + MGAWAITBUSY(); + hwp->writeSeq(hwp, 0x01, tmp & ~0x20); /* reenable display */ + usleep(20000); + vgaHWSeqReset(hwp, FALSE); /* clear synchronousreset */ + + hwp->disablePalette(hwp); + } + } +} diff --git a/src/mga_video.c b/src/mga_video.c index 30ae6fc..a2d7979 100644 --- a/src/mga_video.c +++ b/src/mga_video.c @@ -63,6 +63,10 @@ static void MGAResetVideoOverlay(ScrnInfoPtr); static void MGAVideoTimerCallback(ScrnInfoPtr pScrn, Time time); +static XF86VideoAdaptorPtr MGASetupImageVideoILOAD(ScreenPtr); +static int MGAPutImageILOAD(ScrnInfoPtr, short, short, short, short, short, + short, short, short, int, unsigned char*, short, + short, Bool, RegionPtr, pointer, DrawablePtr); #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) @@ -91,12 +95,27 @@ void MGAInitVideo(ScreenPtr pScreen) if((pScrn->bitsPerPixel != 8) && !pMga->NoAccel && (pMga->SecondCrtc == FALSE) && - ((pMga->Chipset == PCI_CHIP_MGAG200) || + ((pMga->Chipset == PCI_CHIP_MGA2164) || + (pMga->Chipset == PCI_CHIP_MGA2164_AGP) || +/* (pMga->Chipset == PCI_CHIP_MGA2064) || */ + (pMga->Chipset == PCI_CHIP_MGAG200) || (pMga->Chipset == PCI_CHIP_MGAG200_PCI) || (pMga->Chipset == PCI_CHIP_MGAG400) || (pMga->Chipset == PCI_CHIP_MGAG550))) { - if((pMga->Overlay8Plus24 || pMga->TexturedVideo) && + if( (pMga->Chipset == PCI_CHIP_MGA2164) || +/* (pMga->Chipset == PCI_CHIP_MGA2064) || */ + (pMga->Chipset == PCI_CHIP_MGA2164_AGP) + ) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using MGA 2164W ILOAD video\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "This is an experimental driver and may not work on your machine.\n"); + + newAdaptor = MGASetupImageVideoILOAD(pScreen); + pMga->TexturedVideo = TRUE; + /* ^^^ this is not really true but the ILOAD scaler shares + much more code with the textured video than the overlay */ + } else if((pMga->Overlay8Plus24 || pMga->TexturedVideo) && (pScrn->bitsPerPixel != 24)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using texture video\n"); @@ -1258,3 +1277,760 @@ MGAInitOffscreenImages(ScreenPtr pScreen) xf86XVRegisterOffscreenImages(pScreen, offscreenImages, num); } + + +/* Matrox MGA 2164W Xv extension support. +* The extension is implemented as a HOST->FB image load in YUV format. +* I decided not to use real hardware overlay since on the Millennium II +* it would limit the size of the frame buffer to 4Mb (even on a 16Mb +* card) due to an hardware limitation. +* Author: Gabriele Gorla (gorlik@yahoo.com) +* Based on the MGA-Gxxx Xv extension by: Mark Vojkovich + */ + +/* This code is still in alpha stage. Only YUV->RGB conversion + and horizontal scaling are hardware accelerated. + All 4 FOURCC formats supported by X should be supported. + It has been tested only on my DEC XP1000 at 1024x768x32 under + linux 2.6.18 with X.org 7.1.1 (debian alpha) + + Bug reports and success/failure stories are greatly appreciated. +*/ + +/* #define DEBUG_MGA2164 */ +/* #define CUSTOM_MEMCOPY */ +#define MGA2164_SWFILTER + + +static XF86VideoAdaptorPtr +MGASetupImageVideoILOAD(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86VideoAdaptorPtr adapt; + MGAPtr pMga = MGAPTR(pScrn); + + adapt = MGAAllocAdaptor(pScrn, FALSE); + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = 0; + adapt->name = "Matrox Millennium II ILOAD Video Engine"; + adapt->nEncodings = 1; + adapt->pEncodings = &DummyEncoding[1]; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = MGA_MAX_PORTS; + adapt->pAttributes = NULL; + adapt->nAttributes = 0; + + /* number of supported color formats */ + adapt->pImages = Images; + adapt->nImages = 4; + + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = MGAStopVideo; + + adapt->SetPortAttribute = MGASetPortAttributeTexture; + adapt->GetPortAttribute = MGAGetPortAttributeTexture; + adapt->QueryBestSize = MGAQueryBestSize; + adapt->PutImage = MGAPutImageILOAD; + adapt->QueryImageAttributes = MGAQueryImageAttributes; + + REGION_INIT(pScreen, &(pMga->portPrivate->clip), NullBox, 0); + + return adapt; +} + +/* this function is optimized for alpha. It might be better also for +other load/store risc architectures but I never tested on anything else +than my ev56 */ +static void CopyMungedScanline_AXP(CARD32 *fb_ptr, short src_w, + CARD32 *tsp, CARD32 *tpu, CARD32 *tpv) +{ + CARD32 k,y0,y1,u,v; + + for(k=src_w/8;k;k--) { + y0=*tsp; + y1=*(tsp+1); + u=*tpu; + v=*tpv; + + *(fb_ptr)=(y1&0x000000ff)|((y1&0x0000ff00)<<8) | + (v&0x00ff0000)<<8 | (u&0x00ff0000)>>8; + *(fb_ptr+1)=(y1&0x000000ff)|((y1&0x0000ff00)<<8) | + (v&0x00ff0000)<<8 | (u&0x00ff0000)>>8; + + *(fb_ptr+2)=(y0&0x000000ff)|((y0&0x0000ff00)<<8) | + (v&0x000000ff)<<24 | (u&0x000000ff)<<8; + *(fb_ptr+3)=(y0&0x000000ff)|((y0&0x0000ff00)<<8) | + (v&0x000000ff)<<24 | (u&0x000000ff)<<8; + + /*correct below*/ + /* *(fb_ptr)=(y0&0x000000ff)|((y0&0x0000ff00)<<8) | + (v&0x000000ff)<<24 | (u&0x000000ff)<<8; + *(fb_ptr+1)=((y0&0x00ff0000)>>16)|((y0&0xff000000)>>8) | + (v&0x0000ff00)<<16 | (u&0x0000ff00); + *(fb_ptr+2)=(y1&0x000000ff)|((y1&0x0000ff00)<<8) | + (v&0x00ff0000)<<8 | (u&0x00ff0000)>>8; + *(fb_ptr+3)=((y1&0x00ff0000)>>16)|((y1&0xff000000)>>8) | + (v&0xff000000) | (u&0xff000000)>>16; */ + + tsp+=2; tpu++; tpv++; + fb_ptr+=4; + } +} + +static void CopyMungedScanline_AXP2(CARD32 *fb_ptr, short src_w, + CARD32 *tsp, CARD32 *tpu, CARD32 *tpv) +{ + CARD8 *y, *u, *v; + int k; + y=(CARD8 *)tsp; + u=(CARD8 *)tpu; + v=(CARD8 *)tpv; + + for(k=src_w/8;k;k--) { + fb_ptr[0]=y[0] | y[1]<<16 | v[0]<<24 | u[0]<<8; + fb_ptr[1]=y[2] | y[3]<<16 | v[1]<<24 | u[1]<<8; + fb_ptr[2]=y[4] | y[5]<<16 | v[2]<<24 | u[2]<<8; + fb_ptr[3]=y[6] | y[7]<<16 | v[3]<<24 | u[3]<<8; + + y+=8; u+=4; v+=4; + fb_ptr+=4; + } +} + + +static void CopyMungedScanlineFilter_AXP(CARD32 *fb_ptr, short src_w, + CARD32 *tsp1, CARD32 *tpu1, CARD32 *tpv1, + CARD32 *tsp2, CARD32 *tpu2, CARD32 *tpv2, + int beta, int xds ) +{ + unsigned int k,y0_1,y1_1,y0_2,y1_2,u,v; + int yf[8], uf[4], vf[4]; + int oneminbeta = 0xff - beta; + + for(k=xds*src_w/8;k;k--) { + y0_1=*tsp1; + y1_1=*(tsp1+1); + y0_2=*tsp2; + y1_2=*(tsp2+1); + u=*tpu1; + v=*tpv1; + + tsp1+=2; tsp2+=2; tpu1++; tpv1++; + yf[0] = ((y0_1&0x000000ff)*oneminbeta + (y0_2&0x000000ff)*beta )>>8; + yf[1] = (((y0_1&0x0000ff00)>>8)*oneminbeta + ((y0_2&0x0000ff00)>>8)*beta )>>8; + yf[2] = (((y0_1&0x00ff0000)>>16)*oneminbeta + ((y0_2&0x00ff0000)>>16)*beta )>>8; + yf[3] = (((y0_1&0xff000000)>>24)*oneminbeta + ((y0_2&0xff000000)>>24)*beta )>>8; + yf[4] = ((y1_1&0x000000ff)*oneminbeta + (y1_2&0x000000ff)*beta )>>8; + yf[5] = (((y1_1&0x0000ff00)>>8)*oneminbeta + ((y1_2&0x0000ff00)>>8)*beta )>>8; + yf[6] = (((y1_1&0x00ff0000)>>16)*oneminbeta + ((y1_2&0x00ff0000)>>16)*beta )>>8; + yf[7] = (((y1_1&0xff000000)>>24)*oneminbeta + ((y1_2&0xff000000)>>24)*beta )>>8; + + /* FIXME: there is still no filtering on u and v */ + uf[0]=(u&0x000000ff); + uf[1]=(u&0x0000ff00)>>8; + uf[2]=(u&0x00ff0000)>>16; + uf[3]=(u&0xff000000)>>24; + + vf[0]=(v&0x000000ff); + vf[1]=(v&0x0000ff00)>>8; + vf[2]=(v&0x00ff0000)>>16; + vf[3]=(v&0xff000000)>>24; + + switch(xds) { + case 1: + *(fb_ptr)=(yf[0]) | (yf[1]<<16) | + vf[0]<<24 | uf[0]<<8; + *(fb_ptr+1)=(yf[2]) | (yf[3]<<16) | + vf[1]<<24 | uf[1]<<8; + *(fb_ptr+2)=(yf[4]) | (yf[5]<<16) | + vf[2]<<24 | uf[2]<<8; + *(fb_ptr+3)=(yf[6]) | (yf[7]<<16) | + vf[3]<<24 | uf[3]<<8; + fb_ptr+=4; + break; + + case 2: + *(fb_ptr)=(yf[0]+yf[1])/2 | (((yf[2]+yf[3])/2)<<16) | + ((vf[0]+vf[1])/2 )<<24 | ((uf[0]+uf[1])/2)<<8; + *(fb_ptr+1)=(yf[4]+yf[5])/2 | ( ((yf[6]+yf[7])/2) <<16) | + ((vf[2]+vf[3])/2 )<<24 | ((uf[2]+uf[3])/2)<<8; + fb_ptr+=2; + break; + + case 4: + *(fb_ptr)=(yf[0]+yf[1]+yf[2]+yf[3])/4 | (((yf[4]+yf[5]+yf[6]+yf[7])/4)<<16) | + ((vf[0]+vf[1]+vf[2]+vf[3])/4 )<<24 | ((uf[0]+uf[1]+uf[2]+uf[3])/4)<<8; + fb_ptr+=1; + break; + + default: + break; + } + } +} + +static void CopyMungedScanlineFilterDown_AXP(CARD32 *fb_ptr, short src_w, + CARD32 *tsp1, CARD32 *tpu1, CARD32 *tpv1, + CARD32 *tsp2, CARD32 *tpu2, CARD32 *tpv2, + int beta , int xds) +{ + unsigned int k,y0_1,y1_1,y0_2,y1_2,u,v; + int yf[8], uf[4], vf[4]; + + for(k=src_w/8;k;k--) { + y0_1=*tsp1; + y1_1=*(tsp1+1); + y0_2=*tsp2; + y1_2=*(tsp2+1); + u=*tpu1; + v=*tpv1; + + tsp1+=2; tsp2+=2; tpu1++; tpv1++; + yf[0] = ((y0_1&0x000000ff) + (y0_2&0x000000ff))>>8; + yf[1] = (((y0_1&0x0000ff00)>>8) + ((y0_2&0x0000ff00)>>8))>>8; + yf[2] = (((y0_1&0x00ff0000)>>16) + ((y0_2&0x00ff0000)>>16))>>8; + yf[3] = (((y0_1&0x000000ff)>>24) + ((y0_2&0x000000ff)>>24))>>8; + yf[4] = ((y1_1&0x000000ff) + (y1_2&0x000000ff))>>8; + yf[5] = (((y1_1&0x0000ff00)>>8) + ((y1_2&0x0000ff00)>>8))>>8; + yf[6] = (((y1_1&0x00ff0000)>>16) + ((y1_2&0x00ff0000)>>16))>>8; + yf[7] = (((y1_1&0x000000ff)>>24) + ((y1_2&0x000000ff)>>24))>>8; + + *(fb_ptr)=(yf[0]) | (yf[1]<<16) | + (v&0x000000ff)<<24 | (u&0x000000ff)<<8; + *(fb_ptr+1)=(yf[2]) | (yf[3]<<16) | + (v&0x0000ff00)<<16 | (u&0x0000ff00); + *(fb_ptr+2)=(yf[4]) | (yf[5]<<16) | + (v&0x00ff0000)<<8 | (u&0x00ff0000)>>8; + *(fb_ptr+3)=(yf[6]) | (yf[7]<<16) | + (v&0xff000000) | (u&0xff000000)>>16; + + fb_ptr+=4; + } +} + +static void MGACopyScaledILOAD( + ScrnInfoPtr pScrn, + int id, unsigned char *buf, + BoxPtr pbox, + int width, int height, int pitch, + short src_x, short src_y, + short src_w, short src_h, + short drw_x, short drw_y, + short drw_w, short drw_h + ) +{ + MGAPtr pMga = MGAPTR(pScrn); + CARD32 *fb_ptr; + unsigned char *ubuf, *vbuf, *tbuf; + CARD32 *pu, *pv; + int k,l, pl, dl, xds, yds; + short box_h; + short scr_pitch = ( pScrn->virtualX + 15) & ~15; + +#ifdef DEBUG_MGA2164 + char sbuf[255]; + + sprintf(sbuf,"---- PBOX: x1=%d y1=%d w=%d h=%d (x2=%d y2=%d)\n", + pbox->x1,pbox->y1,pbox->x2-pbox->x1,pbox->y2-pbox->y1, + pbox->x2,pbox->y2); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); + + sprintf(sbuf,"in src: src_x=%d src_y=%d src_w=%d src_h=%d\n", + src_x,src_y,src_w,src_h); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); + sprintf(sbuf,"in drw: drw_x=%d drw_y=%d drw_w=%d drw_h=%d\n", + drw_x,drw_y,drw_w,drw_h); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); +#endif + + /* scaling yuv->rgb */ + + /* hack to force width and src image to be 8 pixel aligned */ + src_x&=~0x7; + src_w&=~0x7; + + box_h=pbox->y2-pbox->y1; + + /* compute X down scaling factor */ + if(src_w>drw_w) { + if(src_w/2<drw_w) { + xds=2; + } else if(src_w/4<drw_w) { + xds=4; + } else { xds=8; } + } else xds = 1; + + /* prevent crashing when dragging window outside left boundary of screen */ + /* FIXME: need to implement per pixel left start to avoid undesired + effects when dragging window outside left screen boundary */ + + if(drw_x<0) { + src_x=( -(drw_x*src_w)/drw_w + 0x7)&~0x7; + src_w-=src_x; + drw_w+=drw_x; + drw_x=0; + } + + src_w/=xds; + + /* compute X down scaling factor */ + if(src_h>drw_h) { + if(src_h/2<drw_h) { + yds=2; + } else if(src_h/4<drw_h) { + yds=4; + } else { yds=8; } + } else yds = 1; + + +#ifdef DEBUG_MGA2164 + char sbuf[255]; + + sprintf(sbuf,"---- xds = %d\n", + xds); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); +#endif + + +#ifdef DEBUG_MGA2164 + sprintf(sbuf,"out src: src_x=%d src_y=%d src_w=%d src_h=%d\n", + src_x,src_y,src_w,src_h); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); + sprintf(sbuf,"out drw: drw_x=%d drw_y=%d drw_w=%d drw_h=%d\n", + drw_x,drw_y,drw_w,drw_h); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); +#endif + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + /* scaling ILOAD */ + + vbuf=buf+width*height; + ubuf=vbuf+width*height/4; + pu = (CARD32 *)(ubuf+(src_y/2)*(width/2)); + pv = (CARD32 *)(vbuf+(src_y/2)*(width/2)); + + for(pl=-1,dl=0;dl<box_h;dl++) { + int beta; + l=(dl+(pbox->y1-drw_y))*src_h/drw_h; + /* FIXME: check the math */ + beta = ((dl+(pbox->y1-drw_y))*src_h*0xff/drw_h) - ((dl+(pbox->y1-drw_y))*src_h/drw_h*0xff); + +#ifdef MGA2164_BLIT_DUP + if(l!=pl) +#else + if(1) +#endif + { + + /* + #ifdef DEBUG_MGA2164 + sprintf(sbuf,"new line: scr_dst %d img_src %d prev %d\n", + dl,l,pl); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); + #endif + */ + + OUTREG(MGAREG_DWGCTL, MGADWG_ILOAD_HIQH | MGADWG_BUYUV | MGADWG_SHIFTZERO + | MGADWG_SGNZERO | 0xc0000); + + OUTREG(MGAREG_AR0, pbox->x1 + drw_w -1); /* SRC LINE END why -1 ? */ + OUTREG(MGAREG_AR2, ( ( (src_w-1)<<16) / (drw_w-1)) + 1 ); /* ((SRC_X_DIM -1)<<16) / (DST_X_DIM-1) +1 */ + OUTREG(MGAREG_AR3, pbox->x1 ); /* SRC LINE START*/ + OUTREG(MGAREG_AR5, scr_pitch); /* DST_Y_INCR = PITCH? */ + OUTREG(MGAREG_AR6, ((src_w-drw_w)<<16) / (drw_w-1) ); /* */ + OUTREG(MGAREG_FXBNDRY, drw_x|((drw_x+drw_w-1)<<16) ); /* why -1 ? */ + OUTREG(MGAREG_CXBNDRY, pbox->x1 | ((pbox->x2-1)<<16 ) ); + OUTREG(MGAREG_YDST , pbox->y1+dl ); /* Y_START_POS */ + OUTREG(MGAREG_LEN + MGAREG_EXEC , 1); /* # of LINES */ + + /* xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Data finished\n"); */ + + fb_ptr=(CARD32 *)pMga->ILOADBase; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + tbuf=buf+(l+src_y)*width; + { + CARD32 *tpu=pu+src_x/8+l/2*width/8; + CARD32 *tpv=pv+src_x/8+l/2*width/8; + CARD32 *tsp=(CARD32 *)(tbuf+src_x), *tsp2; + + if((l+src_y)<(src_h-1)) + tsp2=(CARD32 *)(tbuf+src_x+width); + else + tsp2=(CARD32 *)(tbuf+src_x); + + /* it is not clear if waiting is actually good for performance */ + /* WAITFIFO(pMga->FifoSize);*/ + /* should try to get MGACopyMunged data to work here */ + /* CopyMungedScanline_AXP(fb_ptr,src_w,tsp,tpu,tpv); */ + + /* Filter does not work yet */ + CopyMungedScanlineFilter_AXP(fb_ptr,src_w,tsp,tpu,tpv,tsp2,tpu,tpv, beta, xds); + /* if(l&1) { + pu+=width/8; + pv+=width/8; + } */ + } + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + tbuf=buf+(l+src_y)*width*2; + +#ifndef MGA2164_SWFILTER + WAITFIFO(pMga->FifoSize/2); + memcpy(fb_ptr, tbuf+src_x*2, src_w*2); + fb_ptr+=src_w*2; /* pointer in the pseudo dma window */ +#else + { + CARD32 *tsp=(CARD32 *)(tbuf+src_x*2), *tsp2; + + if((l+src_y)<(src_h-1)) + tsp2=(CARD32 *)(tbuf+src_x*2+width*2); + else + tsp2=(CARD32 *)(tbuf+src_x*2); + /* { + char sbuf [256]; + sprintf(sbuf,"dst line: %d src_line: %d beta: %x\n", + dl, l, beta ); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); + } */ + + WAITFIFO(pMga->FifoSize/4); + for(k=xds*src_w/8;k;k--) { + int oneminbeta = 0xff-beta; + int y[8], u[4], v[4], ya[4], ua[2], va[2], p; + + switch(yds) { + case 1: + /* upscale y filter */ + for(p=0;p<4;p++) { + y[2*p]=(((*(tsp+p)&0x000000ff))*oneminbeta+((*(tsp2+p)&0x000000ff))*beta)>>8; + y[2*p+1]=(((*(tsp+p)&0x00ff0000)>>16)*oneminbeta+((*(tsp2+p)&0x00ff0000)>>16)*beta)>>8; + u[p]=(((*(tsp+p)&0x0000ff00)>>8)*oneminbeta+((*(tsp2+p)&0x0000ff00)>>8)*beta)>>8; + v[p]=(((*(tsp+p)&0xff000000)>>24)*oneminbeta+((*(tsp2+p)&0xff000000)>>24)*beta)>>8; + } + break; + /* downscale y filter */ + case 2: + case 3: + case 4: + default: + for(p=0;p<4;p++) { + y[2*p]=(((*(tsp+p)&0x000000ff))); + y[2*p+1]=(((*(tsp+p)&0x00ff0000)>>16)); + u[p]=(((*(tsp+p)&0x0000ff00)>>8)); + v[p]=(((*(tsp+p)&0xff000000)>>24)); + } + break; + } + + switch (xds) { + case 1: /* simple copy */ + *(fb_ptr++)=y[0]|y[1]<<16|u[0]<<8|v[0]<<24; + *(fb_ptr++)=y[2]|y[3]<<16|u[1]<<8|v[1]<<24; + *(fb_ptr++)=y[4]|y[5]<<16|u[2]<<8|v[2]<<24; + *(fb_ptr++)=y[6]|y[7]<<16|u[3]<<8|v[3]<<24; + break; + case 2: /* dowscale by 2 */ + ya[0]=(y[0]+y[1])>>1; + ya[1]=(y[2]+y[3])>>1; + ya[2]=(y[4]+y[5])>>1; + ya[3]=(y[6]+y[7])>>1; + ua[0]=(u[0]+u[1])>>1; + ua[1]=(u[2]+u[3])>>1; + va[0]=(v[0]+v[1])>>1; + va[1]=(v[2]+v[3])>>1; + *(fb_ptr++)=ya[0]|ya[1]<<16|ua[0]<<8|va[0]<<24; + *(fb_ptr++)=ya[2]|ya[3]<<16|ua[1]<<8|va[1]<<24; + break; + case 4: /* downscale by 4 */ + ya[0]=(y[0]+y[1]+y[2]+y[3])>>2; + ya[1]=(y[4]+y[5]+y[6]+y[7])>>2; + ua[0]=(u[0]+u[1]+u[2]+u[3])>>2; + va[0]=(v[0]+v[1]+v[2]+v[3])>>2; + *(fb_ptr++)=ya[0]|ya[1]<<16|ua[0]<<8|va[0]<<24; + break; + case 8: + default: + break; + } + + /* fb_ptr+=4; */ + tsp+=4; tsp2+=4; + } + } +#endif /* MGA2164_SWFILTER */ + break; + default: + break; + } + pl=l; + } else { + /* dup lines */ + +#ifdef DEBUG_MGA2164 + sprintf(sbuf,"dup line: scr_src %d scr_dst %d\n", + dl-1,dl); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); +#endif + + OUTREG(MGAREG_DWGCTL, 0x040C6008); + OUTREG(MGAREG_FXBNDRY, pbox->x1|((pbox->x2-1)<<16) ); /* why -1 ? */ + OUTREG(MGAREG_AR3, (pbox->y1+dl-1)*scr_pitch+pbox->x1 ); /* SRC LINE START*/ + OUTREG(MGAREG_AR0, (pbox->y1+dl-1)*scr_pitch+pbox->x2 -1); /* SRC LINE END why -1 ? */ + OUTREG(MGAREG_AR5, scr_pitch); /* DST_Y_INCR = PITCH? */ + OUTREG(MGAREG_YDST , pbox->y1+dl); /* Y_START_POS */ + OUTREG(MGAREG_LEN + MGAREG_EXEC , 1); /* # of LINES */ + } + } + OUTREG(MGAREG_CXBNDRY, 0xFFFF0000); +} + +static void MGACopyILOAD( + ScrnInfoPtr pScrn, + int id, unsigned char *buf, + BoxPtr pbox, + int width, int height, int pitch, + short src_x, short src_y, + short src_w, short src_h, + short drw_x, short drw_y, + short drw_w, short drw_h + ) +{ + MGAPtr pMga = MGAPTR(pScrn); + CARD32 *fb_ptr; + CARD8 *ubuf, *vbuf; + CARD32 *pu, *pv; + int k,l; + short clip_x1, clip_x2, tmp_w; + +#ifdef DEBUG_MGA2164 + char sbuf[255]; + + sprintf(sbuf,"---- PBOX: x1=%d y1=%d w=%d h=%d (x2=%d y2=%d)\n", + pbox->x1,pbox->y1,pbox->x2-pbox->x1,pbox->y2-pbox->y1, + pbox->x2,pbox->y2); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); + + sprintf(sbuf,"in src: src_x=%d src_y=%d src_w=%d src_h=%d\n", + src_x,src_y,src_w,src_h); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); + sprintf(sbuf,"in drw: drw_x=%d drw_y=%d drw_w=%d drw_h=%d\n", + drw_x,drw_y,drw_w,drw_h); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); +#endif + + /* non-scaling yuv->rgb */ + + /* hack to force width and src image to be 8 pixel aligned */ + src_x&=~0x7; + src_w&=~0x7; + drw_w&=~0x7; + tmp_w=drw_w; + clip_x1=drw_x; + clip_x2=drw_x+drw_w; + + /* hack for clipping in non scaling version */ + /* this works only if no scaling */ + if(pbox->x1 > drw_x) { /* left side X clipping*/ + src_x+=((pbox->x1-drw_x)&~0x7); + src_w-=((pbox->x1-drw_x)&~0x7); + clip_x1=pbox->x1; + drw_x+=src_x; + drw_w=src_w; + } + + if( (pbox->x2) < (drw_x+drw_w) ) { /* right side X clipping */ + tmp_w=( (pbox->x2) - drw_x ); + drw_w= tmp_w & (~0x7); + if(drw_w!=tmp_w) drw_w+=8; + clip_x2=drw_x+tmp_w-1; /* not sure why needs -1 */ + src_w=drw_w; + } + + if(pbox->y1 > drw_y) { /* top side Y clipping */ + src_y+=(pbox->y1-drw_y); + src_h-=(pbox->y1-drw_y); + drw_y+=src_y; + drw_h=src_h; + } + if((pbox->y2)<(drw_y+drw_h)) { /* bottom side Y clipping */ + drw_h=(pbox->y2)-drw_y; + src_h=drw_h; + } + + if(drw_x<0) drw_x=0; + +#ifdef DEBUG_MGA2164 + sprintf(sbuf,"out src: src_x=%d src_y=%d src_w=%d src_h=%d\n", + src_x,src_y,src_w,src_h); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); + sprintf(sbuf,"out drw: drw_x=%d drw_y=%d drw_w=%d drw_h=%d\n", + drw_x,drw_y,drw_w,drw_h); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); +#endif + + /* ready to draw */ + if(drw_w==0||drw_h==0) return; + + if(drw_w<0||drw_h<0) { + /* actually until scaling is working this might happen + during normal operation */ + /* sprintf(sbuf,"drw_w or drw_h are negative (this should never + happen)\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, sbuf); */ + return; + } + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + /* non scaling ILOAD */ + WAITFIFO(6); + OUTREG(MGAREG_AR5, 0); + OUTREG(MGAREG_DWGCTL, MGADWG_ILOAD | MGADWG_BUYUV | MGADWG_SHIFTZERO + | MGADWG_SGNZERO | 0xc0000); + OUTREG(MGAREG_AR0, (drw_w)-1 ); + OUTREG(MGAREG_AR3, 0); + OUTREG(MGAREG_CXBNDRY, clip_x1|(clip_x2<<16)); + OUTREG(MGAREG_FXBNDRY, drw_x|((drw_x+drw_w-1)<<16)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC , (drw_y<<16)|drw_h); + + fb_ptr=(CARD32 *)pMga->ILOADBase; + vbuf=buf+width*height; + ubuf=vbuf+width*height/4; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + pu = (CARD32 *)(ubuf+(src_y/2)*(width/2)); + pv = (CARD32 *)(vbuf+(src_y/2)*(width/2)); + buf+=src_y*width; + + for(l=0;l<drw_h;l++) { + CARD32 *tpu=pu+src_x/8; + CARD32 *tpv=pv+src_x/8; + CARD32 *tsp=(CARD32 *)(buf+src_x); + + /* it is not clear if waiting is actually good for performance */ + /* WAITFIFO(pMga->FifoSize);*/ + /* should try to get MGACopyMunged data to work here */ + CopyMungedScanline_AXP(fb_ptr,src_w,tsp,tpu,tpv); + buf+=width; + if(l&1) { + pu+=width/8; + pv+=width/8; + } + } + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + buf+=src_y*width*2; + for(l=0;l<drw_h;l++) { + +#ifndef CUSTOM_MEMCOPY + WAITFIFO(pMga->FifoSize/2); /* not sure what's the value for best performance */ + memcpy(fb_ptr, buf+src_x*2, src_w*2); + fb_ptr+=src_w*2; +#else + CARD32 *tsp=(CARD32 *)(buf+src_x*2); + WAITFIFO(pMga->FifoSize/4); + for(k=src_w/8;k;k--) { + *(fb_ptr)=*(tsp); + *(fb_ptr+1)=*(tsp+1); + *(fb_ptr+2)=*(tsp+2); + *(fb_ptr+3)=*(tsp+3); + fb_ptr+=4; tsp+=4; + } +#endif /* CUSTOM_MEMCOPY */ + buf+=width*2; + } + break; + default: + break; + } + OUTREG(MGAREG_CXBNDRY, 0xFFFF0000); /* put clipping back to normal */ +} + +static int +MGAPutImageILOAD( + 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, + DrawablePtr pDraw + ){ + MGAPtr pMga = MGAPTR(pScrn); + MGAPortPrivPtr pPriv = pMga->portPrivate; + INT32 x1, x2, y1, y2; + int dstPitch = 0; + int bpp; + BoxRec dstBox; + int nbox; + BoxPtr pbox; + + /* Clip */ + x1 = src_x; x2 = src_x + src_w; + y1 = src_y; y2 = 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(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, + clipBoxes, width, height)) + return Success; + + bpp = pScrn->bitsPerPixel >> 3; + + if( pMga->AccelInfoRec->NeedToSync && ((long)data != pPriv->lastPort) ) { + MGAStormSync(pScrn); + } + + pPriv->lastPort = (long)data; + nbox=REGION_NUM_RECTS(clipBoxes); + pbox=REGION_RECTS(clipBoxes); + + while(nbox--) { + + if ( (drw_w==src_w) && (drw_h==src_h) && (drw_x >= 0 ) ) { + /* special case 1: non scaling optimization */ + MGACopyILOAD(pScrn,id,buf,pbox, + width, height, dstPitch, src_x, src_y, src_w, src_h, + drw_x, drw_y, drw_w, drw_h); +#if 0 + } else if ( (drw_w>src_w) && (drw_h>src_h) && (drw_x >= 0 ) ) { + /* special case 2: upscaling for full screen apps */ + /* FIXME: to do */ + MGACopyScaledILOAD(pScrn,id,buf,pbox, + width, height, dstPitch, src_x, src_y, src_w, src_h, + drw_x, drw_y, drw_w, drw_h); + +#endif + } else /* generic fallback case */ + MGACopyScaledILOAD(pScrn,id,buf,pbox, + width, height, dstPitch, src_x, src_y, src_w, src_h, + drw_x, drw_y, drw_w, drw_h); + /* FIXME: when the generic is perfect I will enable the optimizations */ + pbox++; + } + + + pMga->AccelInfoRec->NeedToSync = TRUE; + pPriv->videoStatus = FREE_TIMER; + pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + pMga->VideoTimerCallback = MGAVideoTimerCallback; + + return Success; +} diff --git a/util/stormdwg.c b/util/stormdwg.c index 8f04e0e..99f76cc 100644 --- a/util/stormdwg.c +++ b/util/stormdwg.c @@ -7,7 +7,7 @@ #include <stdio.h> #include <stdlib.h> -char *opcodes[] = { +const char *opcodes[] = { "line_open", /* 0000 */ "autoline_open", /* 0001 */ "line_close", /* 0010 */ @@ -29,7 +29,7 @@ char *opcodes[] = { "iload filter" /* 1111 */ }; -char *atype[] = { +const char *atype[] = { "rpl - Write (Replace)", /* 000 */ "rstr - read-modify-write (raster)", /* 001 */ "reserved", /* 010 */ @@ -40,7 +40,7 @@ char *atype[] = { "I - Gouraud (with depth compare)" /* 111 */ }; -char *zmode[] = { +const char *zmode[] = { "NOZCMP - always", /* 000 */ "reserved", /* 001 */ "ZE - depth =", /* 010 */ @@ -51,7 +51,7 @@ char *zmode[] = { "zgte" /* 111 */ }; -char *bop[] = { +const char *bop[] = { "0", /* 0000 */ "~(D|S)", /* 0001 */ "D & ~S", /* 0010 */ @@ -73,7 +73,7 @@ char *bop[] = { "1" /* 1111 */ }; -char *bitmod[] = { +const char *bitmod[] = { "BMONOLEF - Source is mono, or if iload, source is little endian", /* 0000 */ "BPLAN - source is mono from one plane", /* 0001 */ "BFCOL - source is colour, and is formatted from host", /* 0010 */ |