diff --git a/configure.ac b/configure.ac index 6c9acb1..96fe4a0 100644 --- a/configure.ac +++ b/configure.ac @@ -69,7 +69,7 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto) XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto) # Obtain compiler/linker options for the driver dependencies -PKG_CHECK_MODULES(XORG, [xorg-server >= 1.18.0 xproto fontsproto $REQUIRED_MODULES]) +PKG_CHECK_MODULES(XORG, [xorg-server >= 1.1.0 xproto fontsproto $REQUIRED_MODULES]) sdkdir=`$PKG_CONFIG --variable=sdkdir xorg-server` # Checks for libraries. @@ -121,6 +121,27 @@ fi AM_CONDITIONAL(XSERVER_LIBPCIACCESS, test "x$XSERVER_LIBPCIACCESS" = xyes) +AC_ARG_ENABLE(xaa, + AS_HELP_STRING([--enable-xaa], + [Enable legacy X Acceleration Architecture (XAA) [default=auto]]), + [XAA="$enableval"], + [XAA=auto]) +if test "x$XAA" != xno; then + save_CFLAGS=$CFLAGS + save_CPPFLAGS=$CPPFLAGS + CFLAGS=$XORG_CFLAGS + CPPFLAGS="$XORG_CFLAGS" + AC_CHECK_HEADERS([xaa.h], XAA=yes, XAA=no) + CFLAGS=$save_CFLAGS + CPPFLAGS=$save_CPPFLAGS +fi +AC_MSG_CHECKING([whether to include XAA support]) +AM_CONDITIONAL(XAA, test "x$XAA" = xyes) +AC_MSG_RESULT([$XAA]) +if test "x$XAA" = xyes; then + AC_DEFINE(USE_XAA, 1, [Build support for XAA]) +fi + # Properly handle EXA. AC_MSG_CHECKING([whether to enable EXA support]) if test "x$EXA" = xyes; then diff --git a/src/Makefile.am b/src/Makefile.am index a7910d2..b5a086a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -65,3 +65,8 @@ if USE_EXA mga_drv_la_SOURCES += \ mga_exa.c endif + +if XAA +mga_drv_la_SOURCES += \ + mga_arc.c +endif diff --git a/src/mga.h b/src/mga.h index 36eb714..4ff8088 100644 --- a/src/mga.h +++ b/src/mga.h @@ -20,6 +20,9 @@ #include #include "compiler.h" +#ifdef HAVE_XAA_H +#include "xaa.h" +#endif #include "xf86fbman.h" #include "exa.h" #include "xf86Cursor.h" @@ -556,6 +559,9 @@ typedef struct { CARD32 MAccess; int FifoSize; int StyleLen; +#ifdef USE_XAA + XAAInfoRecPtr AccelInfoRec; +#endif xf86CursorInfoPtr CursorInfoRec; DGAModePtr DGAModes; int numDGAModes; @@ -718,10 +724,12 @@ void MGAAdjustGranularity(ScrnInfoPtr pScrn, int* x, int* y); void MGA2064SetupFuncs(ScrnInfoPtr pScrn); void MGAGSetupFuncs(ScrnInfoPtr pScrn); +/*#ifdef USE_XAA */ void MGAStormSync(ScrnInfoPtr pScrn); void MGAStormEngineInit(ScrnInfoPtr pScrn); Bool MGAStormAccelInit(ScreenPtr pScreen); Bool mgaAccelInit(ScreenPtr pScreen); +/* #endif */ #ifdef USE_EXA Bool mgaExaInit(ScreenPtr pScreen); @@ -729,6 +737,10 @@ Bool mgaExaInit(ScreenPtr pScreen); Bool MGAHWCursorInit(ScreenPtr pScreen); +#ifdef USE_XAA +void MGAPolyArcThinSolid(DrawablePtr, GCPtr, int, xArc*); +#endif /* USE_XAA */ + Bool MGADGAInit(ScreenPtr pScreen); void MGARefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); @@ -804,6 +816,10 @@ MGA_MARK_SYNC(MGAPtr pMga, ScrnInfoPtr pScrn) if (pMga->Exa) exaMarkSync(pScrn->pScreen); #endif +#ifdef USE_XAA + if (!pMga->Exa) + SET_SYNC_FLAG(pMga->AccelInfoRec); +#endif } static __inline__ void @@ -813,6 +829,10 @@ MGA_SYNC(MGAPtr pMga, ScrnInfoPtr pScrn) if (pMga->Exa) exaWaitSync(pScrn->pScreen); #endif +#ifdef USE_XAA + if (!pMga->Exa && pMga->AccelInfoRec && pMga->AccelInfoRec->NeedToSync) + pMga->AccelInfoRec->Sync(pScrn); +#endif } #endif diff --git a/src/mga_dga.c b/src/mga_dga.c index e90cec5..585572c 100644 --- a/src/mga_dga.c +++ b/src/mga_dga.c @@ -15,6 +15,12 @@ static Bool MGA_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, static Bool MGA_SetMode(ScrnInfoPtr, DGAModePtr); static int MGA_GetViewport(ScrnInfoPtr); static void MGA_SetViewport(ScrnInfoPtr, int, int, int); +#ifdef USE_XAA +static void MGA_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); +static void MGA_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); +static void MGA_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, + unsigned long); +#endif static DGAFunctionRec MGA_DGAFuncs = { @@ -24,7 +30,13 @@ DGAFunctionRec MGA_DGAFuncs = { MGA_SetViewport, MGA_GetViewport, MGAStormSync, +#ifdef USE_XAA + MGA_FillRect, + MGA_BlitRect, + MGA_BlitTransRect +#else NULL, NULL, NULL +#endif }; @@ -112,6 +124,13 @@ SECOND_PASS: mode->flags = DGA_CONCURRENT_ACCESS; if(pixmap) mode->flags |= DGA_PIXMAP_AVAILABLE; +#ifdef USE_XAA + if(!pMga->NoAccel) { + mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT; + if((Bpp != 3) && (pMga->Chipset != PCI_CHIP_MGA2064)) + mode->flags |= DGA_BLIT_RECT_TRANS; + } +#endif if(pMode->Flags & V_DBLSCAN) mode->flags |= DGA_DOUBLESCAN; if(pMode->Flags & V_INTERLACE) @@ -346,6 +365,74 @@ MGA_SetViewport( pMga->DGAViewportStatus = 0; /* MGAAdjustFrame loops until finished */ } +#ifdef USE_XAA +static void +MGA_FillRect ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned long color +){ + MGAPtr pMga = MGAPTR(pScrn); + + if(!pMga->AccelInfoRec) return; + + mgaDoSetupForSolidFill(pScrn, color, GXcopy, ~0, + pMga->CurrentLayout.bitsPerPixel); + (*pMga->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); + + SET_SYNC_FLAG(pMga->AccelInfoRec); +} + +static void +MGA_BlitRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty +){ + MGAPtr pMga = MGAPTR(pScrn); + int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; + int ydir = (srcy < dsty) ? -1 : 1; + + if(!pMga->AccelInfoRec) return; + + mgaDoSetupForScreenToScreenCopy( pScrn, xdir, ydir, GXcopy, ~0, -1, + pMga->CurrentLayout.bitsPerPixel ); + + (*pMga->AccelInfoRec->SubsequentScreenToScreenCopy)( + pScrn, srcx, srcy, dstx, dsty, w, h); + + SET_SYNC_FLAG(pMga->AccelInfoRec); +} + + +static void MGA_BlitTransRect( ScrnInfoPtr pScrn, int srcx, int srcy, + int w, int h, int dstx, int dsty, + unsigned long color ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + if( (pMga->AccelInfoRec != NULL) + && (pMga->CurrentLayout.bitsPerPixel != 24) + && (pMga->Chipset != PCI_CHIP_MGA2064) ) { + const int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; + const int ydir = (srcy < dsty) ? -1 : 1; + + pMga->DrawTransparent = TRUE; + + mgaDoSetupForScreenToScreenCopy( pScrn, xdir, ydir, GXcopy, ~0, color, + pMga->CurrentLayout.bitsPerPixel ); + + pMga->DrawTransparent = FALSE; + + (*pMga->AccelInfoRec->SubsequentScreenToScreenCopy)( + pScrn, srcx, srcy, dstx, dsty, w, h); + + SET_SYNC_FLAG(pMga->AccelInfoRec); + } +} +#endif + static Bool MGA_OpenFramebuffer( ScrnInfoPtr pScrn, diff --git a/src/mga_dri.c b/src/mga_dri.c index e5b15d9..a30c567 100644 --- a/src/mga_dri.c +++ b/src/mga_dri.c @@ -121,6 +121,9 @@ static void MGAWaitForIdleDMA( ScrnInfoPtr pScrn ) void MGAGetQuiescence( ScrnInfoPtr pScrn ) { MGAPtr pMga = MGAPTR(pScrn); +#ifdef USE_XAA + MGAFBLayout *pLayout = &pMga->CurrentLayout; +#endif /* USE_XAA */ pMga->haveQuiescense = 1; @@ -128,6 +131,31 @@ void MGAGetQuiescence( ScrnInfoPtr pScrn ) MGAWaitForIdleDMA( pScrn ); /* FIXME what about EXA? */ +#ifdef USE_XAA + if (!pMga->Exa && pMga->AccelInfoRec) { + WAITFIFO( 11 ); + OUTREG( MGAREG_MACCESS, pMga->MAccess ); + OUTREG( MGAREG_PITCH, pLayout->displayWidth ); + + pMga->PlaneMask = ~0; + OUTREG( MGAREG_PLNWT, pMga->PlaneMask ); + + pMga->BgColor = 0; + pMga->FgColor = 0; + OUTREG( MGAREG_BCOL, pMga->BgColor ); + OUTREG( MGAREG_FCOL, pMga->FgColor ); + OUTREG( MGAREG_SRCORG, pMga->realSrcOrg ); + + pMga->SrcOrg = 0; + OUTREG( MGAREG_DSTORG, pMga->DstOrg ); + OUTREG( MGAREG_OPMODE, MGAOPM_DMA_BLIT ); + OUTREG( MGAREG_CXBNDRY, 0xFFFF0000 ); /* (maxX << 16) | minX */ + OUTREG( MGAREG_YTOP, 0x00000000 ); /* minPixelPointer */ + OUTREG( MGAREG_YBOT, 0x007FFFFF ); /* maxPixelPointer */ + + pMga->AccelFlags &= ~CLIPPER_ON; + } +#endif } } @@ -145,6 +173,10 @@ void MGAGetQuiescenceShared( ScrnInfoPtr pScrn ) MGAWaitForIdleDMA( pMGAEnt->pScrn_1 ); /* FIXME what about EXA? */ +#ifdef USE_XAA + if (!pMga->Exa && pMga->AccelInfoRec) + pMga->RestoreAccelState( pScrn ); +#endif xf86SetLastScrnFlag( pScrn->entityList[0], pScrn->scrnIndex ); } } @@ -635,12 +667,191 @@ 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 = xf86ScreenToScrn(pScreen); + 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 + static void MGADRIInitBuffersEXA(WindowPtr pWin, RegionPtr prgn, CARD32 index) { /* FIXME */ } +#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 = xf86ScreenToScrn(pScreen); + 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; + pptNew2 = 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)malloc(sizeof(BoxRec)*nbox); + if (!pboxNew1) return; + pptNew1 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox); + if (!pptNew1) { + free(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)malloc(sizeof(BoxRec)*nbox); + pptNew2 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox); + if (!pboxNew2 || !pptNew2) { + free(pptNew2); + free(pboxNew2); + if (pboxNew1) { + free(pptNew1); + free(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) { + free(pptNew2); + free(pboxNew2); + } + if (pboxNew1) { + free(pptNew1); + free(pboxNew1); + } + + pMga->AccelInfoRec->NeedToSync = TRUE; + +} +#endif + static void MGADRIMoveBuffersEXA(WindowPtr pParent, DDXPointRec ptOldOrg, RegionPtr prgnSrc, CARD32 index) { @@ -790,6 +1001,19 @@ Bool MGADRIScreenInit( ScreenPtr pScreen ) pDRIInfo->InitBuffers = MGADRIInitBuffersEXA; pDRIInfo->MoveBuffers = MGADRIMoveBuffersEXA; +#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 be0b3bc..6105413 100644 --- a/src/mga_driver.c +++ b/src/mga_driver.c @@ -54,6 +54,11 @@ #include "xf86Modes.h" +#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 +#include "xf86Resources.h" +#include "xf86RAC.h" +#endif + /* All drivers need this */ #include "compiler.h" @@ -80,6 +85,10 @@ #include "mga_macros.h" #include "mga_maven.h" +#ifdef USE_XAA +#include "xaa.h" +#endif + #include "xf86cmap.h" #include "shadowfb.h" #include "fbdevhw.h" @@ -1957,14 +1966,16 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags) pMga->NoAccel = FALSE; pMga->Exa = FALSE; #ifdef USE_EXA +#ifndef USE_XAA pMga->Exa = TRUE; +#endif if (!xf86NameCmp(s, "EXA")) { pMga->Exa = TRUE; from = X_CONFIG; } #endif xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration\n", - pMga->Exa ? "EXA" : "no"); + pMga->Exa ? "EXA" : "XAA"); } if (xf86ReturnOptValBool(pMga->Options, OPTION_PCI_RETRY, FALSE)) { pMga->UsePCIRetry = TRUE; @@ -2053,7 +2064,7 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags) } } - /* Load EXA if needed */ + /* Load XAA if needed */ if (!pMga->NoAccel) { #ifdef USE_EXA if (pMga->Exa) { @@ -2065,10 +2076,14 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags) } } else { #endif - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Falling back to shadowfb\n"); - pMga->ShadowFB = TRUE; - pMga->NoAccel = TRUE; +#ifdef USE_XAA + if (!xf86LoadSubModule(pScrn, "xaa")) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Falling back to shadowfb\n"); + pMga->ShadowFB = TRUE; + pMga->NoAccel = TRUE; + } +#endif #ifdef USE_EXA } #endif @@ -3126,6 +3141,13 @@ MGACrtc2FillStrip(ScrnInfoPtr pScrn) (pScrn->bitsPerPixel >> 3) * pScrn->displayWidth * pScrn->virtualY); } else { xf86SetLastScrnFlag(pScrn->entityList[0], pScrn->scrnIndex); +#ifdef USE_XAA + pMga->RestoreAccelState(pScrn); + pMga->SetupForSolidFill(pScrn, 0, GXcopy, 0xFFFFFFFF); + pMga->SubsequentSolidFillRect(pScrn, pScrn->virtualX, 0, + pScrn->displayWidth - pScrn->virtualX, + pScrn->virtualY); +#endif MGAStormSync(pScrn); } } @@ -3768,6 +3790,10 @@ MGACloseScreen(CLOSE_SCREEN_ARGS_DECL) pMgaEnt->refCount--; } +#ifdef USE_XAA + if (pMga->AccelInfoRec) + XAADestroyInfoRec(pMga->AccelInfoRec); +#endif #ifdef USE_EXA if (pMga->ExaDriver) { exaDriverFini(pScreen); diff --git a/src/mga_storm.c b/src/mga_storm.c index 0a12c68..59cf64f 100644 --- a/src/mga_storm.c +++ b/src/mga_storm.c @@ -14,6 +14,11 @@ /* Drivers that need to access the PCI config space directly need this */ #include "xf86Pci.h" +/* Drivers that use XAA need this */ +#ifdef HAVE_XAA_H +#include "xaa.h" +#include "xaalocal.h" +#endif #include "xf86fbman.h" #include "miline.h" #include "servermd.h" @@ -46,18 +51,553 @@ } +#define MGAMoveDWORDS(d,s,c) \ +do { \ + write_mem_barrier(); \ + XAAMoveDWORDS((d),(s),(c)); \ +} while (0) + +#ifdef USE_XAA +static void mgaSetupForSolidFill( ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask ); + +static void mgaSetupForScreenToScreenCopy( ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, unsigned int planemask, int trans ); + +static void mgaSubsequentScreenToScreenCopy( ScrnInfoPtr pScrn, + int srcX, int srcY, int dstX, int dstY, int w, int h ); + +static void mgaSubsequentScreenToScreenCopy_FastBlit( ScrnInfoPtr pScrn, + int srcX, int srcY, int dstX, int dstY, int w, int h ); + +static void mgaSetupForScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn, + int fg, int bg, int rop, unsigned int planemask ); + +static void mgaSubsequentScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft ); + +static void mgaSubsequentColorExpandScanline( ScrnInfoPtr pScrn, int bufno ); + +static void mgaSubsequentColorExpandScanlineIndirect( ScrnInfoPtr pScrn, + int bufno ); + +static void mgaSubsequentSolidFillRect( ScrnInfoPtr pScrn, int x, int y, + int w, int h ); + +static void mgaSubsequentSolidFillTrap( ScrnInfoPtr pScrn, int y, int h, + int left, int dxL, int dyL, int eL, int right, int dxR, int dyR, int eR ); + +static void mgaSubsequentSolidHorVertLine( ScrnInfoPtr pScrn, int x, int y, + int len, int dir ); + +static void mgaSubsequentSolidTwoPointLine( ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int flags ); + +static void mgaSetupForMono8x8PatternFill( ScrnInfoPtr pScrn, + int patx, int paty, int fg, int bg, int rop, unsigned int planemask ); + +static void mgaSubsequentMono8x8PatternFillRect( ScrnInfoPtr pScrn, + int patx, int paty, int x, int y, int w, int h ); + +static void mgaSubsequentMono8x8PatternFillRect_Additional( ScrnInfoPtr pScrn, + int patx, int paty, int x, int y, int w, int h ); + +static void mgaSubsequentMono8x8PatternFillTrap( ScrnInfoPtr pScrn, + int patx, int paty, int y, int h, int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR ); + +static void mgaSetupForScanlineImageWrite( ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int transparency_color, int bpp, int depth ); + +static void mgaSubsequentScanlineImageWriteRect( ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft ); + +static void mgaSubsequentImageWriteScanline( ScrnInfoPtr pScrn, int num ); + +static void mgaSetupForPlanarScreenToScreenColorExpandFill( ScrnInfoPtr pScrn, + int fg, int bg, int rop, unsigned int planemask ); + +static void mgaSubsequentPlanarScreenToScreenColorExpandFill( ScrnInfoPtr pScrn, + int x, int y, int w, int h, int srcx, int srcy, int skipleft ); + +static void mgaSetupForScreenToScreenColorExpandFill( ScrnInfoPtr pScrn, + int fg, int bg, int rop, unsigned int planemask ); + +static void mgaSubsequentScreenToScreenColorExpandFill( ScrnInfoPtr pScrn, + int x, int y, int w, int h, int srcx, int srcy, int skipleft ); + +#if X_BYTE_ORDER == X_LITTLE_ENDIAN +static void mgaSetupForDashedLine( ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned int planemask, int length, unsigned char *pattern ); + +static void mgaSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, int flags, int phase ); +#endif + +static void mgaRestoreAccelState( ScrnInfoPtr pScrn ); + +static void MGASetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2); +static void MGADisableClipping(ScrnInfoPtr pScrn); +static void MGAFillSolidRectsDMA(ScrnInfoPtr pScrn, int fg, int rop, + unsigned int planemask, int nBox, BoxPtr pBox); +static void MGAFillSolidSpansDMA(ScrnInfoPtr pScrn, int fg, int rop, + unsigned int planemask, int n, DDXPointPtr ppt, + int *pwidth, int fSorted); +static void MGAFillMono8x8PatternRectsTwoPass(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned int planemask, int nBox, + BoxPtr pBox, int pattern0, int pattern1, + int xorigin, int yorigin); +static void MGAValidatePolyArc(GCPtr, unsigned long, DrawablePtr); +static void MGAValidatePolyPoint(GCPtr, unsigned long, DrawablePtr); +static void MGAFillCacheBltRects(ScrnInfoPtr, int, unsigned int, int, BoxPtr, + int, int, XAACacheInfoPtr); + + +static __inline__ void +common_replicate_colors_and_mask( unsigned int fg, unsigned int bg, + unsigned int pm, + unsigned int bpp, + unsigned int * rep_fg, + unsigned int * rep_bg, + unsigned int * rep_pm ) +{ + switch( bpp ) { + case 8: + *rep_fg = REPLICATE_8( fg ); + *rep_bg = REPLICATE_8( bg ); + *rep_pm = REPLICATE_8( pm ); + break; + case 16: + *rep_fg = REPLICATE_16( fg ); + *rep_bg = REPLICATE_16( bg ); + *rep_pm = REPLICATE_16( pm ); + break; + case 24: + *rep_fg = REPLICATE_24( fg ); + *rep_bg = REPLICATE_24( bg ); + *rep_pm = REPLICATE_24( pm ); + break; + case 32: + *rep_fg = REPLICATE_32( fg ); + *rep_bg = REPLICATE_32( bg ); + *rep_pm = REPLICATE_32( pm ); + break; + } +} + + +#ifdef RENDER + +static Bool MGASetupForCPUToScreenAlphaTexture(ScrnInfoPtr pScrn, int op, + CARD16 red, CARD16 green, CARD16 blue, CARD16 alpha, int alphaType, + CARD8 *alphaPtr, int alphaPitch, int width, int height, int flags); + +static Bool MGASetupForCPUToScreenAlphaTextureFaked(ScrnInfoPtr Scrn, int op, + CARD16 red, CARD16 green, CARD16 blue, CARD16 alpha, int alphaType, + CARD8 *alphaPtr, int alphaPitch, int width, int height, int flags); + +static Bool MGASetupForCPUToScreenTexture(ScrnInfoPtr pScrn, int op, + int texType, CARD8 *texPtr, int texPitch, int width, int height, + int flags); + +static void MGASubsequentCPUToScreenTexture(ScrnInfoPtr pScrn, int dstx, + int dsty, int srcx, int srcy, int width, int height); + +#include "mipict.h" +#include "dixstruct.h" + +static CARD32 MGAAlphaTextureFormats[2] = {PICT_a8, 0}; +static CARD32 MGATextureFormats[2] = {PICT_a8r8g8b8, 0}; + +static void +RemoveLinear (FBLinearPtr linear) +{ + MGAPtr pMga = (MGAPtr)(linear->devPrivate.ptr); + + pMga->LinearScratch = NULL; /* just lost our scratch */ +} + +static void +RenderCallback (ScrnInfoPtr pScrn) +{ + MGAPtr pMga = MGAPTR(pScrn); + + if((currentTime.milliseconds > pMga->RenderTime) && pMga->LinearScratch) { + xf86FreeOffscreenLinear(pMga->LinearScratch); + pMga->LinearScratch = NULL; + } + + if(!pMga->LinearScratch) + pMga->RenderCallback = NULL; +} + +#define RENDER_DELAY 15000 + +static Bool +AllocateLinear ( + ScrnInfoPtr pScrn, + int sizeNeeded +){ + MGAPtr pMga = MGAPTR(pScrn); + + pMga->RenderTime = currentTime.milliseconds + RENDER_DELAY; + pMga->RenderCallback = RenderCallback; + + if(pMga->LinearScratch) { + if(pMga->LinearScratch->size >= sizeNeeded) + return TRUE; + else { + if(xf86ResizeOffscreenLinear(pMga->LinearScratch, sizeNeeded)) + return TRUE; + + xf86FreeOffscreenLinear(pMga->LinearScratch); + pMga->LinearScratch = NULL; + } + } + + pMga->LinearScratch = xf86AllocateOffscreenLinear( + pScrn->pScreen, sizeNeeded, 32, + NULL, RemoveLinear, pMga); + + return (pMga->LinearScratch != NULL); +} + +static int +GetPowerOfTwo(int w) +{ + int Pof2 = 0; + int i = 12; + + while(--i) { + if(w & (1 << i)) { + Pof2 = i; + if(w & ((1 << i) - 1)) + Pof2++; + break; + } + } + return Pof2; +} + + +static int tex_padw, tex_padh; + +Bool MGASetupForCPUToScreenAlphaTextureFaked( ScrnInfoPtr pScrn, int op, + CARD16 red, CARD16 green, + CARD16 blue, CARD16 alpha, + int alphaType, CARD8 *alphaPtr, + int alphaPitch, int width, + int height, int flags ) +{ + int log2w, log2h, pitch, sizeNeeded, offset; + unsigned int texctl, dwgctl, alphactrl; + MGAPtr pMga = MGAPTR(pScrn); + + if(op != PictOpOver) /* only one tested */ + return FALSE; + + if((width > 2048) || (height > 2048)) + return FALSE; + + log2w = GetPowerOfTwo(width); + log2h = GetPowerOfTwo(height); + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + pitch = (width + 15) & ~15; + sizeNeeded = pitch * height; + if(pScrn->bitsPerPixel == 16) + sizeNeeded <<= 1; + + if(!AllocateLinear(pScrn, sizeNeeded)) + return FALSE; + + offset = pMga->LinearScratch->offset << 1; + if(pScrn->bitsPerPixel == 32) + offset <<= 1; + + if(pMga->AccelInfoRec->NeedToSync) + MGAStormSync(pScrn); + + XAA_888_plus_PICT_a8_to_8888( + (blue >> 8) | (green & 0xff00) | ((red & 0xff00) << 8), + alphaPtr, alphaPitch, (CARD32*)(pMga->FbStart + offset), + pitch, width, height); + + tex_padw = 1 << log2w; + tex_padh = 1 << log2h; + + WAITFIFO(15); + OUTREG(MGAREG_TMR0, (1 << 20) / tex_padw); /* sx inc */ + OUTREG(MGAREG_TMR1, 0); /* sy inc */ + OUTREG(MGAREG_TMR2, 0); /* tx inc */ + OUTREG(MGAREG_TMR3, (1 << 20) / tex_padh); /* ty inc */ + OUTREG(MGAREG_TMR4, 0x00000000); + OUTREG(MGAREG_TMR5, 0x00000000); + OUTREG(MGAREG_TMR8, 0x00010000); + OUTREG(MGAREG_TEXORG, offset); + OUTREG(MGAREG_TEXWIDTH, log2w | (((8 - log2w) & 63) << 9) | + ((width - 1) << 18)); + OUTREG(MGAREG_TEXHEIGHT, log2h | (((8 - log2h) & 63) << 9) | + ((height - 1) << 18)); + + texctl = MGA_TW32 | MGA_PITCHLIN | MGA_TAKEY | MGA_CLAMPUV | + ((pitch & 0x07FF) << 9); + dwgctl = MGADWG_TEXTURE_TRAP | MGADWG_I | MGADWG_ARZERO | + MGADWG_SGNZERO | MGADWG_SHIFTZERO | 0xc0000; + alphactrl = MGA_SRC_ALPHA | MGA_DST_ONE_MINUS_SRC_ALPHA | + MGA_ALPHACHANNEL; + + OUTREG(MGAREG_TEXCTL, texctl); + OUTREG(MGAREG_TEXCTL2, MGA_TC2_DECALDIS | MGA_TC2_CKSTRANSDIS); + OUTREG(MGAREG_DWGCTL, dwgctl); + OUTREG(MGAREG_TEXFILTER, ((0x1e << 20) | MGA_MAG_BILIN)); + OUTREG(MGAREG_ALPHACTRL, alphactrl); + + return TRUE; +} + +Bool +MGASetupForCPUToScreenAlphaTexture ( + ScrnInfoPtr pScrn, + int op, + CARD16 red, + CARD16 green, + CARD16 blue, + CARD16 alpha, + int alphaType, + CARD8 *alphaPtr, + int alphaPitch, + int width, + int height, + int flags +){ + int log2w, log2h, i, pitch, sizeNeeded, offset; + unsigned int texctl, dwgctl, alphactrl; + CARD8 *dst; + MGAPtr pMga = MGAPTR(pScrn); + + if(op != PictOpOver) /* only one tested */ + return FALSE; + + if((width > 2048) || (height > 2048)) + return FALSE; + + log2w = GetPowerOfTwo(width); + log2h = GetPowerOfTwo(height); + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + pitch = (width + 15) & ~15; + sizeNeeded = (pitch * height) >> 1; + if(pScrn->bitsPerPixel == 32) + sizeNeeded >>= 1; + + if(!AllocateLinear(pScrn, sizeNeeded)) + return FALSE; + + offset = pMga->LinearScratch->offset << 1; + if(pScrn->bitsPerPixel == 32) + offset <<= 1; + + if(pMga->AccelInfoRec->NeedToSync) + MGAStormSync(pScrn); + + i = height; + dst = pMga->FbStart + offset; + while(i--) { + memcpy(dst, alphaPtr, width); + dst += pitch; + alphaPtr += alphaPitch; + } + + tex_padw = 1 << log2w; + tex_padh = 1 << log2h; + + + WAITFIFO(12); + OUTREG(MGAREG_DR4, red << 7); /* red start */ + OUTREG(MGAREG_DR6, 0); + OUTREG(MGAREG_DR7, 0); + OUTREG(MGAREG_DR8, green << 7); /* green start */ + OUTREG(MGAREG_DR10, 0); + OUTREG(MGAREG_DR11, 0); + OUTREG(MGAREG_DR12, blue << 7); /* blue start */ + OUTREG(MGAREG_DR14, 0); + OUTREG(MGAREG_DR15, 0); + OUTREG(MGAREG_ALPHASTART, alpha << 7); /* alpha start */ + OUTREG(MGAREG_ALPHAXINC, 0); + OUTREG(MGAREG_ALPHAYINC, 0); + + WAITFIFO(15); + OUTREG(MGAREG_TMR0, (1 << 20) / tex_padw); /* sx inc */ + OUTREG(MGAREG_TMR1, 0); /* sy inc */ + OUTREG(MGAREG_TMR2, 0); /* tx inc */ + OUTREG(MGAREG_TMR3, (1 << 20) / tex_padh); /* ty inc */ + OUTREG(MGAREG_TMR4, 0x00000000); + OUTREG(MGAREG_TMR5, 0x00000000); + OUTREG(MGAREG_TMR8, 0x00010000); + OUTREG(MGAREG_TEXORG, offset); + OUTREG(MGAREG_TEXWIDTH, log2w | (((8 - log2w) & 63) << 9) | + ((width - 1) << 18)); + OUTREG(MGAREG_TEXHEIGHT, log2h | (((8 - log2h) & 63) << 9) | + ((height - 1) << 18)); + + texctl = MGA_TW8A | MGA_PITCHLIN | MGA_TAKEY | MGA_CLAMPUV | + MGA_TEXMODULATE | + ((pitch & 0x07FF) << 9); + dwgctl = MGADWG_TEXTURE_TRAP | MGADWG_I | MGADWG_ARZERO | + MGADWG_SGNZERO | MGADWG_SHIFTZERO | 0xc0000; + alphactrl = MGA_SRC_ONE | MGA_DST_ONE_MINUS_SRC_ALPHA | + MGA_ALPHACHANNEL | MGA_MODULATEDALPHA; + + OUTREG(MGAREG_TEXCTL, texctl); + OUTREG(MGAREG_TEXCTL2, MGA_TC2_DECALDIS | MGA_TC2_CKSTRANSDIS); + OUTREG(MGAREG_DWGCTL, dwgctl); + OUTREG(MGAREG_TEXFILTER, ((0x1e << 20) | MGA_MAG_BILIN)); + OUTREG(MGAREG_ALPHACTRL, alphactrl); + + return TRUE; +} + + +Bool +MGASetupForCPUToScreenTexture ( + ScrnInfoPtr pScrn, + int op, + int texType, + CARD8 *texPtr, + int texPitch, + int width, + int height, + int flags +){ + int log2w, log2h, i, pitch, sizeNeeded, offset; + unsigned int texctl, dwgctl, alphactrl; + MGAPtr pMga = MGAPTR(pScrn); + + if(op != PictOpOver) /* only one tested */ + return FALSE; + + if((width > 2048) || (height > 2048)) + return FALSE; + + log2w = GetPowerOfTwo(width); + log2h = GetPowerOfTwo(height); + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + pitch = (width + 15) & ~15; + sizeNeeded = pitch * height; + if(pScrn->bitsPerPixel == 16) + sizeNeeded <<= 1; + + if(!AllocateLinear(pScrn, sizeNeeded)) + return FALSE; + + offset = pMga->LinearScratch->offset << 1; + if(pScrn->bitsPerPixel == 32) + offset <<= 1; + + if(pMga->AccelInfoRec->NeedToSync) + MGAStormSync(pScrn); + + { + CARD8 *dst = (CARD8*)(pMga->FbStart + offset); + i = height; + while(i--) { + memcpy(dst, texPtr, width << 2); + texPtr += texPitch; + dst += pitch << 2; + } + } + + tex_padw = 1 << log2w; + tex_padh = 1 << log2h; + + WAITFIFO(15); + OUTREG(MGAREG_TMR0, (1 << 20) / tex_padw); /* sx inc */ + OUTREG(MGAREG_TMR1, 0); /* sy inc */ + OUTREG(MGAREG_TMR2, 0); /* tx inc */ + OUTREG(MGAREG_TMR3, (1 << 20) / tex_padh); /* ty inc */ + OUTREG(MGAREG_TMR4, 0x00000000); + OUTREG(MGAREG_TMR5, 0x00000000); + OUTREG(MGAREG_TMR8, 0x00010000); + OUTREG(MGAREG_TEXORG, offset); + OUTREG(MGAREG_TEXWIDTH, log2w | (((8 - log2w) & 63) << 9) | + ((width - 1) << 18)); + OUTREG(MGAREG_TEXHEIGHT, log2h | (((8 - log2h) & 63) << 9) | + ((height - 1) << 18)); + + texctl = MGA_TW32 | MGA_PITCHLIN | MGA_TAKEY | MGA_CLAMPUV | + ((pitch & 0x07FF) << 9); + dwgctl = MGADWG_TEXTURE_TRAP | MGADWG_I | MGADWG_ARZERO | + MGADWG_SGNZERO | MGADWG_SHIFTZERO | 0xc0000; + alphactrl = MGA_SRC_ONE | MGA_DST_ONE_MINUS_SRC_ALPHA | + MGA_ALPHACHANNEL; + + OUTREG(MGAREG_TEXCTL, texctl); + OUTREG(MGAREG_TEXCTL2, MGA_TC2_DECALDIS | MGA_TC2_CKSTRANSDIS); + OUTREG(MGAREG_DWGCTL, dwgctl); + OUTREG(MGAREG_TEXFILTER, ((0x1e << 20) | MGA_MAG_BILIN)); + OUTREG(MGAREG_ALPHACTRL, alphactrl); + + return TRUE; +} +void +MGASubsequentCPUToScreenTexture ( + ScrnInfoPtr pScrn, + int dstx, + int dsty, + int srcx, + int srcy, + int width, + int height +){ + MGAPtr pMga = MGAPTR(pScrn); + + WAITFIFO(4); + OUTREG(MGAREG_TMR6, (srcx << 20) / tex_padw); + OUTREG(MGAREG_TMR7, (srcy << 20) / tex_padh); + OUTREG(MGAREG_FXBNDRY, ((dstx + width) << 16) | (dstx & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dsty << 16) | height); + + pMga->AccelInfoRec->NeedToSync = TRUE; +} + + +#endif /* defined(RENDER) */ +#endif + Bool mgaAccelInit( ScreenPtr pScreen ) { +#ifdef USE_XAA + XAAInfoRecPtr infoPtr; +#endif ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); MGAPtr pMga = MGAPTR(pScrn); // int maxFastBlitMem, maxlines; +#ifdef USE_XAA + int maxFastBlitMem; +#endif /* USE_XAA */ int maxlines; +#if defined(USE_XAA) && defined(RENDER) + Bool doRender = FALSE; +#endif /* defined(USE_XAA) && defined(RENDER) */ BoxRec AvailFBArea; +#ifdef USE_XAA + int i; +#endif /* USE_XAA */ pMga->ScratchBuffer = malloc(((pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel) + 127) >> 3); if(!pMga->ScratchBuffer) return FALSE; +#ifdef USE_XAA + pMga->AccelInfoRec = infoPtr = XAACreateInfoRec(); + if(!infoPtr) return FALSE; +#endif pMga->RenderTime = 0; pMga->LinearScratch = 0; @@ -90,6 +630,178 @@ Bool mgaAccelInit( ScreenPtr pScreen ) pMga->AtypeNoBLK = MGAAtypeNoBLK; } +#ifdef USE_XAA + /* fill out infoPtr here */ + infoPtr->Flags = PIXMAP_CACHE | + OFFSCREEN_PIXMAPS | + LINEAR_FRAMEBUFFER | + MICROSOFT_ZERO_LINE_BIAS; + + /* sync */ + infoPtr->Sync = MGAStormSync; + + /* screen to screen copy */ + infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY; + infoPtr->SetupForScreenToScreenCopy = + mgaSetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = mgaSubsequentScreenToScreenCopy; + + if(pMga->HasFBitBlt) { + infoPtr->FillCacheBltRects = MGAFillCacheBltRects; + infoPtr->FillCacheBltRectsFlags = NO_TRANSPARENCY; + } + /* solid fills */ + infoPtr->SetupForSolidFill = mgaSetupForSolidFill; + infoPtr->SubsequentSolidFillRect = mgaSubsequentSolidFillRect; + infoPtr->SubsequentSolidFillTrap = mgaSubsequentSolidFillTrap; + + /* solid lines */ + infoPtr->SetupForSolidLine = infoPtr->SetupForSolidFill; + infoPtr->SubsequentSolidHorVertLine = mgaSubsequentSolidHorVertLine; + infoPtr->SubsequentSolidTwoPointLine = mgaSubsequentSolidTwoPointLine; + + /* clipping */ + infoPtr->SetClippingRectangle = MGASetClippingRectangle; + infoPtr->DisableClipping = MGADisableClipping; + infoPtr->ClippingFlags = HARDWARE_CLIP_SOLID_LINE | + HARDWARE_CLIP_DASHED_LINE | + HARDWARE_CLIP_SOLID_FILL | + HARDWARE_CLIP_MONO_8x8_FILL; + +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + /* dashed lines */ + infoPtr->DashedLineFlags = LINE_PATTERN_MSBFIRST_LSBJUSTIFIED; + infoPtr->SetupForDashedLine = mgaSetupForDashedLine; + infoPtr->SubsequentDashedTwoPointLine = mgaSubsequentDashedTwoPointLine; + infoPtr->DashPatternMaxLength = 128; +#endif + + /* 8x8 mono patterns */ + infoPtr->Mono8x8PatternFillFlags = HARDWARE_PATTERN_PROGRAMMED_BITS | + HARDWARE_PATTERN_PROGRAMMED_ORIGIN | + HARDWARE_PATTERN_SCREEN_ORIGIN | + BIT_ORDER_IN_BYTE_MSBFIRST; + infoPtr->SetupForMono8x8PatternFill = mgaSetupForMono8x8PatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = + mgaSubsequentMono8x8PatternFillRect; + infoPtr->SubsequentMono8x8PatternFillTrap = + mgaSubsequentMono8x8PatternFillTrap; + + /* cpu to screen color expansion */ + infoPtr->ScanlineCPUToScreenColorExpandFillFlags = + CPU_TRANSFER_PAD_DWORD | + SCANLINE_PAD_DWORD | +#if X_BYTE_ORDER == X_BIG_ENDIAN + BIT_ORDER_IN_BYTE_MSBFIRST | +#else + BIT_ORDER_IN_BYTE_LSBFIRST | +#endif + LEFT_EDGE_CLIPPING | + LEFT_EDGE_CLIPPING_NEGATIVE_X; + + if(pMga->ILOADBase) { + pMga->ColorExpandBase = pMga->ILOADBase; + } else { + pMga->ColorExpandBase = pMga->IOBase; + } + infoPtr->SetupForScanlineCPUToScreenColorExpandFill = + mgaSetupForScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = + mgaSubsequentScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentColorExpandScanline = mgaSubsequentColorExpandScanline; + infoPtr->NumScanlineColorExpandBuffers = 1; + infoPtr->ScanlineColorExpandBuffers = &(pMga->ColorExpandBase); + + /* screen to screen color expansion */ + if(pMga->AccelFlags & USE_LINEAR_EXPANSION) { + infoPtr->ScreenToScreenColorExpandFillFlags = +#if X_BYTE_ORDER == X_BIG_ENDIAN + BIT_ORDER_IN_BYTE_MSBFIRST; +#else + BIT_ORDER_IN_BYTE_LSBFIRST; +#endif + infoPtr->SetupForScreenToScreenColorExpandFill = + mgaSetupForScreenToScreenColorExpandFill; + infoPtr->SubsequentScreenToScreenColorExpandFill = + mgaSubsequentScreenToScreenColorExpandFill; + } + else if ( pMga->CurrentLayout.bitsPerPixel != 24 ) { + /* Alternate (but slower) planar expansions */ + infoPtr->SetupForScreenToScreenColorExpandFill = + mgaSetupForPlanarScreenToScreenColorExpandFill; + infoPtr->SubsequentScreenToScreenColorExpandFill = + mgaSubsequentPlanarScreenToScreenColorExpandFill; + infoPtr->CacheColorExpandDensity = pMga->CurrentLayout.bitsPerPixel; + infoPtr->CacheMonoStipple = XAAGetCachePlanarMonoStipple(); + + /* It's faster to blit the stipples if you have fastbilt + */ + if(pMga->HasFBitBlt) + infoPtr->ScreenToScreenColorExpandFillFlags = TRANSPARENCY_ONLY; + } + + /* image writes */ + infoPtr->ScanlineImageWriteFlags = CPU_TRANSFER_PAD_DWORD | + SCANLINE_PAD_DWORD | + LEFT_EDGE_CLIPPING | + LEFT_EDGE_CLIPPING_NEGATIVE_X | + NO_TRANSPARENCY | + NO_GXCOPY; + + infoPtr->SetupForScanlineImageWrite = mgaSetupForScanlineImageWrite; + infoPtr->SubsequentScanlineImageWriteRect = + mgaSubsequentScanlineImageWriteRect; + infoPtr->SubsequentImageWriteScanline = mgaSubsequentImageWriteScanline; + infoPtr->NumScanlineImageWriteBuffers = 1; + infoPtr->ScanlineImageWriteBuffers = &(pMga->ScratchBuffer); + + + /* midrange replacements */ + + if(pMga->ILOADBase && pMga->UsePCIRetry && infoPtr->SetupForSolidFill) { + infoPtr->FillSolidRects = MGAFillSolidRectsDMA; + infoPtr->FillSolidSpans = MGAFillSolidSpansDMA; + } + + if(pMga->AccelFlags & TWO_PASS_COLOR_EXPAND) { + if(infoPtr->SetupForMono8x8PatternFill) + infoPtr->FillMono8x8PatternRects = + MGAFillMono8x8PatternRectsTwoPass; + } + + if(infoPtr->SetupForSolidFill) { + infoPtr->ValidatePolyArc = MGAValidatePolyArc; + infoPtr->PolyArcMask = GCFunction | GCLineWidth | GCPlaneMask | + GCLineStyle | GCFillStyle; + infoPtr->ValidatePolyPoint = MGAValidatePolyPoint; + infoPtr->PolyPointMask = GCFunction | GCPlaneMask; + } + if(pMga->AccelFlags & MGA_NO_PLANEMASK) { + infoPtr->ScanlineImageWriteFlags |= NO_PLANEMASK; + infoPtr->ScreenToScreenCopyFlags |= NO_PLANEMASK; + infoPtr->ScanlineCPUToScreenColorExpandFillFlags |= NO_PLANEMASK; + infoPtr->SolidFillFlags |= NO_PLANEMASK; + infoPtr->SolidLineFlags |= NO_PLANEMASK; +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + infoPtr->DashedLineFlags |= NO_PLANEMASK; +#endif + infoPtr->Mono8x8PatternFillFlags |= NO_PLANEMASK; + infoPtr->ScreenToScreenColorExpandFillFlags |= NO_PLANEMASK; + infoPtr->FillSolidRectsFlags |= NO_PLANEMASK; + infoPtr->FillSolidSpansFlags |= NO_PLANEMASK; + infoPtr->FillMono8x8PatternRectsFlags |= NO_PLANEMASK; + infoPtr->FillCacheBltRectsFlags |= NO_PLANEMASK; + } + + + maxFastBlitMem = (pMga->Interleave ? 4096 : 2048) * 1024; + + if(pMga->FbMapSize > maxFastBlitMem) { + pMga->MaxFastBlitY = maxFastBlitMem / (pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel / 8); + } + +#endif + switch (pMga->Chipset) { case PCI_CHIP_MGAG200_SE_A_PCI: case PCI_CHIP_MGAG200_SE_B_PCI: @@ -225,10 +937,90 @@ Bool mgaAccelInit( ScreenPtr pScreen ) } +#ifdef USE_XAA + for (i = 0; i < pScrn->numEntities; i++) { + if (xf86IsEntityShared(pScrn->entityList[i])) { + infoPtr->RestoreAccelState = mgaRestoreAccelState; + break; + } + } + +#ifdef RENDER + if(doRender && ((pScrn->bitsPerPixel == 32) || (pScrn->bitsPerPixel == 16))) + { + if(pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550) { + infoPtr->CPUToScreenAlphaTextureFlags = XAA_RENDER_NO_TILE; + infoPtr->SetupForCPUToScreenAlphaTexture = + MGASetupForCPUToScreenAlphaTexture; + } else { + infoPtr->CPUToScreenAlphaTextureFlags = XAA_RENDER_NO_TILE | + XAA_RENDER_NO_SRC_ALPHA; + infoPtr->SetupForCPUToScreenAlphaTexture = + MGASetupForCPUToScreenAlphaTextureFaked; + } + infoPtr->SubsequentCPUToScreenAlphaTexture = + MGASubsequentCPUToScreenTexture; + infoPtr->CPUToScreenAlphaTextureFormats = MGAAlphaTextureFormats; + + infoPtr->SetupForCPUToScreenTexture = MGASetupForCPUToScreenTexture; + infoPtr->SubsequentCPUToScreenTexture = MGASubsequentCPUToScreenTexture; + infoPtr->CPUToScreenTextureFlags = XAA_RENDER_NO_TILE; + infoPtr->CPUToScreenTextureFormats = MGATextureFormats; + } +#endif /* defined(RENDER) */ + + return(XAAInit(pScreen, infoPtr)); +#else return TRUE; +#endif } +#ifdef USE_XAA +/* Support for multiscreen */ +static void mgaRestoreAccelState(ScrnInfoPtr pScrn) +{ + MGAPtr pMga = MGAPTR(pScrn); + MGAFBLayout *pLayout = &pMga->CurrentLayout; + unsigned int replicate_fg = 0; + unsigned int replicate_bg = 0; + unsigned int replicate_pm = 0; + + MGAStormSync(pScrn); + WAITFIFO(12); + pMga->SrcOrg = 0; + OUTREG(MGAREG_MACCESS, pMga->MAccess); + OUTREG(MGAREG_PITCH, pLayout->displayWidth); + OUTREG(MGAREG_YDSTORG, pMga->YDstOrg); + + + common_replicate_colors_and_mask( pMga->FgColor, pMga->BgColor, + pMga->PlaneMask, pLayout->bitsPerPixel, + & replicate_fg, & replicate_bg, + & replicate_pm ); + + if( (pLayout->bitsPerPixel != 24) + && ((pMga->AccelFlags & MGA_NO_PLANEMASK) == 0) ) { + OUTREG( MGAREG_PLNWT, replicate_pm ); + } + + OUTREG( MGAREG_BCOL, replicate_bg ); + OUTREG( MGAREG_FCOL, replicate_fg ); + + OUTREG(MGAREG_SRCORG, pMga->realSrcOrg); + OUTREG(MGAREG_DSTORG, pMga->DstOrg); +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT ); +#else + OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT | 0x10000); +#endif + OUTREG(MGAREG_CXBNDRY, 0xFFFF0000); /* (maxX << 16) | minX */ + OUTREG(MGAREG_YTOP, 0x00000000); /* minPixelPointer */ + OUTREG(MGAREG_YBOT, 0x007FFFFF); /* maxPixelPointer */ + pMga->AccelFlags &= ~CLIPPER_ON; +} +#endif + CARD32 MGAAtype[16] = { MGADWG_RPL | 0x00000000, MGADWG_RSTR | 0x00080000, MGADWG_RSTR | 0x00040000, MGADWG_BLK | 0x000c0000, @@ -313,6 +1105,13 @@ void MGAStormEngineInit( ScrnInfoPtr pScrn ) opmode &= ~0x30000; #endif +#ifdef USE_XAA + pMga->SetupForSolidFill = mgaSetupForSolidFill; + pMga->SubsequentSolidFillRect = mgaSubsequentSolidFillRect; + pMga->RestoreAccelState = mgaRestoreAccelState; +#endif + + pMga->fifoCount = 0; while(MGAISBUSY()); @@ -383,3 +1182,1386 @@ void MGAStormEngineInit( ScrnInfoPtr pScrn ) xf86SetLastScrnFlag(pScrn->entityList[0], pScrn->scrnIndex); } + + +#ifdef USE_XAA +static void +MGASetClippingRectangle( + ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2 +){ + MGAPtr pMga = MGAPTR(pScrn); + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + WAITFIFO(3); + OUTREG(MGAREG_CXBNDRY,(x2 << 16) | x1); + OUTREG(MGAREG_YTOP, (y1 * pScrn->displayWidth) + pMga->YDstOrg); + OUTREG(MGAREG_YBOT, (y2 * pScrn->displayWidth) + pMga->YDstOrg); + pMga->AccelFlags |= CLIPPER_ON; +} + +static void +MGADisableClipping(ScrnInfoPtr pScrn) +{ + MGAPtr pMga = MGAPTR(pScrn); + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + WAITFIFO(3); + OUTREG(MGAREG_CXBNDRY, 0xFFFF0000); /* (maxX << 16) | minX */ + OUTREG(MGAREG_YTOP, 0x00000000); /* minPixelPointer */ + OUTREG(MGAREG_YBOT, 0x007FFFFF); /* maxPixelPointer */ + pMga->AccelFlags &= ~CLIPPER_ON; +} + + +static CARD32 +common_setup_for_pattern_fill( MGAPtr pMga, int fg, int bg, int rop, + int planemask, + CARD32 * reg_data, unsigned int count, + CARD32 cmd ) +{ + unsigned int replicate_fg = 0; + unsigned int replicate_bg = 0; + unsigned int replicate_pm = 0; + unsigned int i; + + + common_replicate_colors_and_mask( fg, bg, planemask, + pMga->CurrentLayout.bitsPerPixel, + & replicate_fg, & replicate_bg, + & replicate_pm ); + + + if( bg == -1 ) { + if ( (pMga->CurrentLayout.bitsPerPixel == 24) && !RGBEQUAL(fg) ) { + cmd |= MGADWG_TRANSC | pMga->AtypeNoBLK[rop]; + } + else { + cmd |= MGADWG_TRANSC | pMga->Atype[rop]; + } + + WAITFIFO( count + 3 ); + } + else { + /* (Packed) 24-bit is a funky mode. We only use the Atype table in + * 24-bit if the components of the foreground color and the components + * of the background color are the same (e.g., fg = 0xf8f8f8 and bg = + * 0x131313). + */ + + if( ((pMga->AccelFlags & BLK_OPAQUE_EXPANSION) != 0) + && ((pMga->CurrentLayout.bitsPerPixel != 24) + || (RGBEQUAL(fg) && RGBEQUAL(bg))) ) { + cmd |= pMga->Atype[rop]; + } + else { + cmd |= pMga->AtypeNoBLK[rop]; + } + + WAITFIFO( count + 4 ); + SET_BACKGROUND_REPLICATED( bg, replicate_bg ); + } + + SET_FOREGROUND_REPLICATED( fg, replicate_fg ); + SET_PLANEMASK_REPLICATED( planemask, replicate_pm, + pMga->CurrentLayout.bitsPerPixel ); + + /* FIXME: Is this the right order? */ + + for ( i = 0 ; i < count ; i++ ) { + OUTREG( reg_data[0], reg_data[1] ); + reg_data += 2; + } + + OUTREG(MGAREG_DWGCTL, cmd); + + return cmd; +} + + + /*********************************************\ + | Screen-to-Screen Copy | + \*********************************************/ + +#define BLIT_LEFT 1 +#define BLIT_UP 4 + +void mgaDoSetupForScreenToScreenCopy( ScrnInfoPtr pScrn, int xdir, int ydir, + int rop, unsigned int planemask, + int trans, unsigned bpp ) +{ + MGAPtr pMga = MGAPTR(pScrn); + CARD32 dwgctl = pMga->AtypeNoBLK[rop] | MGADWG_SHIFTZERO | + MGADWG_BITBLT | MGADWG_BFCOL; + unsigned int tmp; + unsigned int replicated_trans = 0; + unsigned int replicated_mask = 0; + + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + pMga->AccelInfoRec->SubsequentScreenToScreenCopy = + mgaSubsequentScreenToScreenCopy; + + pMga->BltScanDirection = 0; + if(ydir == -1) pMga->BltScanDirection |= BLIT_UP; + if(xdir == -1) + pMga->BltScanDirection |= BLIT_LEFT; + else if(pMga->HasFBitBlt && (rop == GXcopy) && !pMga->DrawTransparent) + pMga->AccelInfoRec->SubsequentScreenToScreenCopy = + mgaSubsequentScreenToScreenCopy_FastBlit; + + + common_replicate_colors_and_mask( trans, 0, planemask, bpp, + & replicated_trans, & tmp, + & replicated_mask ); + + if(pMga->DrawTransparent) { + dwgctl |= MGADWG_TRANSC; + WAITFIFO(2); + + SET_FOREGROUND_REPLICATED( trans, replicated_trans ); + SET_BACKGROUND_REPLICATED( ~0, ~0 ); + } + + WAITFIFO(4); + OUTREG(MGAREG_DWGCTL, dwgctl); + OUTREG(MGAREG_SGN, pMga->BltScanDirection); + + SET_PLANEMASK_REPLICATED( planemask, replicated_mask, bpp ); + OUTREG(MGAREG_AR5, ydir * pMga->CurrentLayout.displayWidth); +} + + +void mgaSetupForScreenToScreenCopy( ScrnInfoPtr pScrn, int xdir, int ydir, + int rop, unsigned int planemask, + int trans ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + mgaDoSetupForScreenToScreenCopy( pScrn, xdir, ydir, rop, planemask, trans, + pMga->CurrentLayout.bitsPerPixel ); +} + + +void mgaSubsequentScreenToScreenCopy( ScrnInfoPtr pScrn, + int srcX, int srcY, int dstX, int dstY, + int w, int h ) +{ + int start, end, SrcOrg = 0, DstOrg = 0; + MGAPtr pMga = MGAPTR(pScrn); + + if (pMga->AccelFlags & LARGE_ADDRESSES) { + const unsigned int display_bit_width = + (pMga->CurrentLayout.displayWidth * pMga->CurrentLayout.bitsPerPixel); + + SrcOrg = ((srcY & ~1023) * display_bit_width) >> 9; + DstOrg = ((dstY & ~1023) * display_bit_width) >> 9; + dstY &= 1023; + } + + if(pMga->BltScanDirection & BLIT_UP) { + srcY += h - 1; + dstY += h - 1; + } + + w--; + start = end = XYADDRESS(srcX, srcY); + + if(pMga->BltScanDirection & BLIT_LEFT) start += w; + else end += w; + + if (pMga->AccelFlags & LARGE_ADDRESSES) { + WAITFIFO(7); + if(DstOrg) + OUTREG(MGAREG_DSTORG, (DstOrg << 6) + pMga->DstOrg); + if(SrcOrg != pMga->SrcOrg) { + pMga->SrcOrg = SrcOrg; + OUTREG(MGAREG_SRCORG, (SrcOrg << 6) + pMga->realSrcOrg); + } + if(SrcOrg) { + SrcOrg = (SrcOrg << 9) / pMga->CurrentLayout.bitsPerPixel; + end -= SrcOrg; + start -= SrcOrg; + } + OUTREG(MGAREG_AR0, end); + OUTREG(MGAREG_AR3, start); + OUTREG(MGAREG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h); + if(DstOrg) + OUTREG(MGAREG_DSTORG, pMga->DstOrg); + } else { + WAITFIFO(4); + OUTREG(MGAREG_AR0, end); + OUTREG(MGAREG_AR3, start); + OUTREG(MGAREG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h); + } +} + + +void mgaSubsequentScreenToScreenCopy_FastBlit( ScrnInfoPtr pScrn, + int srcX, int srcY, + int dstX, int dstY, + int w, int h ) +{ + int start, end; + MGAPtr pMga = MGAPTR(pScrn); + static const unsigned int masks[5] = { + 0, 0x07f, 0x03f, 0x7f, 0x1f + }; + + if(pMga->BltScanDirection & BLIT_UP) { + srcY += h - 1; + dstY += h - 1; + } + + w--; + start = XYADDRESS(srcX, srcY); + end = start + w; + + /* we assume the driver asserts screen pitches such that + we can always use fastblit for scrolling */ + if(((srcX ^ dstX) & masks[ pMga->CurrentLayout.bitsPerPixel / 8 ]) == 0) { + if(pMga->MaxFastBlitY) { + if(pMga->BltScanDirection & BLIT_UP) { + if((srcY >= pMga->MaxFastBlitY) || + (dstY >= pMga->MaxFastBlitY)) + goto FASTBLIT_BAILOUT; + } else { + if(((srcY + h) > pMga->MaxFastBlitY) || + ((dstY + h) > pMga->MaxFastBlitY)) + goto FASTBLIT_BAILOUT; + } + } + + /* Millennium 1 fastblit bug fix */ + if(pMga->AccelFlags & FASTBLT_BUG) { + int fxright = dstX + w; + int tmp_dstX = dstX; + int tmp_fxright = fxright; + static const unsigned shift_tab[5] = { + 0, 6, 5, 6, 4 + }; + const unsigned shift = shift_tab[pMga->CurrentLayout.bitsPerPixel / 8]; + + if (pMga->CurrentLayout.bitsPerPixel == 24) { + tmp_dstX *= 3; + tmp_fxright = fxright * 3 + 2; + } + + if( (tmp_dstX & (1 << shift)) + && (((tmp_fxright >> shift) - (tmp_dstX >> shift)) & 7) == 7) { + fxright = (tmp_fxright | (1 << shift)); + if (pMga->CurrentLayout.bitsPerPixel == 24) { + fxright /= 3; + } + + WAITFIFO(8); + OUTREG(MGAREG_CXRIGHT, dstX + w); + OUTREG(MGAREG_DWGCTL, 0x040A400C); + OUTREG(MGAREG_AR0, end); + OUTREG(MGAREG_AR3, start); + OUTREG(MGAREG_FXBNDRY, (fxright << 16) | (dstX & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h); + OUTREG(MGAREG_DWGCTL, pMga->AtypeNoBLK[GXcopy] | + MGADWG_SHIFTZERO | MGADWG_BITBLT | MGADWG_BFCOL); + OUTREG(MGAREG_CXRIGHT, 0xFFFF); + return; + } + } + + WAITFIFO(6); + OUTREG(MGAREG_DWGCTL, 0x040A400C); + OUTREG(MGAREG_AR0, end); + OUTREG(MGAREG_AR3, start); + OUTREG(MGAREG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h); + OUTREG(MGAREG_DWGCTL, pMga->AtypeNoBLK[GXcopy] | MGADWG_SHIFTZERO | + MGADWG_BITBLT | MGADWG_BFCOL); + return; + } + +FASTBLIT_BAILOUT: + + WAITFIFO(4); + OUTREG(MGAREG_AR0, end); + OUTREG(MGAREG_AR3, start); + OUTREG(MGAREG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h); +} + + /******************\ + | Solid Fills | + \******************/ + +void mgaDoSetupForSolidFill( ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask, unsigned int bpp ) +{ + MGAPtr pMga = MGAPTR(pScrn); + unsigned int tmp; + unsigned int replicated_color = 0; + unsigned int replicated_planemask = 0; + + common_replicate_colors_and_mask( color, 0, planemask, bpp, + & replicated_color, & tmp, + & replicated_planemask ); + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + if ( (bpp == 24) && !RGBEQUAL(color) ) { + pMga->FilledRectCMD = MGADWG_TRAP | MGADWG_SOLID | MGADWG_ARZERO | + MGADWG_SGNZERO | MGADWG_SHIFTZERO | + MGADWG_BMONOLEF | pMga->AtypeNoBLK[rop]; + } + else { + pMga->FilledRectCMD = MGADWG_TRAP | MGADWG_SOLID | MGADWG_ARZERO | + MGADWG_SGNZERO | MGADWG_SHIFTZERO | + MGADWG_BMONOLEF | pMga->Atype[rop]; + } + + pMga->SolidLineCMD = MGADWG_SOLID | MGADWG_SHIFTZERO | MGADWG_BFCOL | + pMga->AtypeNoBLK[rop]; + + if(pMga->AccelFlags & TRANSC_SOLID_FILL) + pMga->FilledRectCMD |= MGADWG_TRANSC; + + WAITFIFO(3); + if ( color != pMga->FgColor ) { + pMga->FgColor = color; + OUTREG( MGAREG_FCOL, replicated_color ); + } + + if ( (bpp != 24) + && !(pMga->AccelFlags & MGA_NO_PLANEMASK) + && (planemask != pMga->PlaneMask) ) { + pMga->PlaneMask = planemask; + OUTREG( MGAREG_PLNWT, replicated_planemask ); + } + + OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD); +} + +void mgaSetupForSolidFill( ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + mgaDoSetupForSolidFill( pScrn, color, rop, planemask, + pMga->CurrentLayout.bitsPerPixel ); +} + +void mgaSubsequentSolidFillRect( ScrnInfoPtr pScrn, + int x, int y, int w, int h ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + WAITFIFO(2); + OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h); +} + +void mgaSubsequentSolidFillTrap( ScrnInfoPtr pScrn, int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR ) +{ + MGAPtr pMga = MGAPTR(pScrn); + int sdxl = (dxL < 0); + int ar2 = sdxl? dxL : -dxL; + int sdxr = (dxR < 0); + int ar5 = sdxr? dxR : -dxR; + + WAITFIFO(11); + OUTREG(MGAREG_DWGCTL, + pMga->FilledRectCMD & ~(MGADWG_ARZERO | MGADWG_SGNZERO)); + OUTREG(MGAREG_AR0, dyL); + OUTREG(MGAREG_AR1, ar2 - eL); + OUTREG(MGAREG_AR2, ar2); + OUTREG(MGAREG_AR4, ar5 - eR); + OUTREG(MGAREG_AR5, ar5); + OUTREG(MGAREG_AR6, dyR); + OUTREG(MGAREG_SGN, (sdxl << 1) | (sdxr << 5)); + OUTREG(MGAREG_FXBNDRY, ((right + 1) << 16) | (left & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h); + OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD); +} + + + /***************\ + | Solid Lines | + \***************/ + +void mgaSubsequentSolidHorVertLine( ScrnInfoPtr pScrn, int x, int y, + int len, int dir ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + if(dir == DEGREES_0) { + WAITFIFO(2); + OUTREG(MGAREG_FXBNDRY, ((x + len) << 16) | (x & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | 1); + } else if(pMga->AccelFlags & USE_RECTS_FOR_LINES) { + WAITFIFO(2); + OUTREG(MGAREG_FXBNDRY, ((x + 1) << 16) | (x & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | len); + } else { + WAITFIFO(4); + OUTREG(MGAREG_DWGCTL, pMga->SolidLineCMD | MGADWG_AUTOLINE_OPEN); + OUTREG(MGAREG_XYSTRT, (y << 16) | (x & 0xffff)); + OUTREG(MGAREG_XYEND + MGAREG_EXEC, ((y + len) << 16) | (x & 0xffff)); + OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD); + } +} + + +void mgaSubsequentSolidTwoPointLine( ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int flags ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + WAITFIFO(4); + OUTREG(MGAREG_DWGCTL, pMga->SolidLineCMD | + ((flags & OMIT_LAST) ? MGADWG_AUTOLINE_OPEN : MGADWG_AUTOLINE_CLOSE)); + OUTREG(MGAREG_XYSTRT, (y1 << 16) | (x1 & 0xFFFF)); + OUTREG(MGAREG_XYEND + MGAREG_EXEC, (y2 << 16) | (x2 & 0xFFFF)); + OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD); +} + + + /***************************\ + | 8x8 Mono Pattern Fills | + \***************************/ + + +void mgaSetupForMono8x8PatternFill( ScrnInfoPtr pScrn, + int patx, int paty, int fg, int bg, + int rop, unsigned int planemask ) +{ + MGAPtr pMga = MGAPTR(pScrn); + XAAInfoRecPtr infoRec = pMga->AccelInfoRec; + CARD32 regs[4]; + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + infoRec->SubsequentMono8x8PatternFillRect = + mgaSubsequentMono8x8PatternFillRect; + + regs[0] = MGAREG_PAT0; + regs[1] = patx; + regs[2] = MGAREG_PAT1; + regs[3] = paty; + + pMga->PatternRectCMD = common_setup_for_pattern_fill( pMga, fg, bg, rop, + planemask, regs, 2, + (MGADWG_TRAP + | MGADWG_ARZERO + | MGADWG_SGNZERO + | MGADWG_BMONOLEF) ); +} + + +void mgaSubsequentMono8x8PatternFillRect( ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, int w, int h ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + WAITFIFO(3); + OUTREG(MGAREG_SHIFT, (paty << 4) | patx); + OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h); + pMga->AccelInfoRec->SubsequentMono8x8PatternFillRect = + mgaSubsequentMono8x8PatternFillRect_Additional; +} + +static void mgaSubsequentMono8x8PatternFillRect_Additional( ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, + int w, int h ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + WAITFIFO(2); + OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h); +} + + +void mgaSubsequentMono8x8PatternFillTrap( ScrnInfoPtr pScrn, + int patx, int paty, + int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + int sdxl = (dxL < 0) ? (1<<1) : 0; + int ar2 = sdxl? dxL : -dxL; + int sdxr = (dxR < 0) ? (1<<5) : 0; + int ar5 = sdxr? dxR : -dxR; + + WAITFIFO(12); + OUTREG(MGAREG_SHIFT, (paty << 4) | patx); + OUTREG(MGAREG_DWGCTL, + pMga->PatternRectCMD & ~(MGADWG_ARZERO | MGADWG_SGNZERO)); + OUTREG(MGAREG_AR0, dyL); + OUTREG(MGAREG_AR1, ar2 - eL); + OUTREG(MGAREG_AR2, ar2); + OUTREG(MGAREG_AR4, ar5 - eR); + OUTREG(MGAREG_AR5, ar5); + OUTREG(MGAREG_AR6, dyR); + OUTREG(MGAREG_SGN, sdxl | sdxr); + OUTREG(MGAREG_FXBNDRY, ((right + 1) << 16) | (left & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h); + OUTREG(MGAREG_DWGCTL, pMga->PatternRectCMD); +} + + /***********************\ + | Color Expand Rect | + \***********************/ + + +void mgaSetupForScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + (void) common_setup_for_pattern_fill( pMga, fg, bg, rop, + planemask, NULL, 0, + MGADWG_ILOAD | MGADWG_LINEAR + | MGADWG_SGNZERO | MGADWG_SHIFTZERO + | MGADWG_BMONOLEF ); +} + + +void mgaSubsequentScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + pMga->AccelFlags |= CLIPPER_ON; + pMga->expandDWORDs = (w + 31) >> 5; + if((pMga->expandDWORDs * h) > pMga->MaxBlitDWORDS) { + pMga->expandHeight = pMga->MaxBlitDWORDS / pMga->expandDWORDs; + pMga->expandRemaining = h / pMga->expandHeight; + if(!(h = h % pMga->expandHeight)) { + pMga->expandRemaining--; + h = pMga->expandHeight; + } + pMga->expandY = y + h; + } else + pMga->expandRemaining = 0; + pMga->expandRows = h; + + WAITFIFO(5); + OUTREG(MGAREG_CXBNDRY, ((x + w - 1) << 16) | ((x + skipleft) & 0xFFFF)); + w = pMga->expandDWORDs << 5; /* source is dword padded */ + OUTREG(MGAREG_AR0, (w * h) - 1); + OUTREG(MGAREG_AR3, 0); /* crashes occasionally without this */ + OUTREG(MGAREG_FXBNDRY, ((x + w - 1) << 16) | (x & 0xFFFF)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h); + +#if defined(__alpha__) + if(1) /* force indirect always on Alpha */ +#else + if(pMga->expandDWORDs > pMga->FifoSize) +#endif + { + pMga->AccelInfoRec->SubsequentColorExpandScanline = + mgaSubsequentColorExpandScanlineIndirect; + pMga->AccelInfoRec->ScanlineColorExpandBuffers = + (unsigned char**)(&pMga->ScratchBuffer); + } else { + pMga->AccelInfoRec->SubsequentColorExpandScanline = + mgaSubsequentColorExpandScanline; + pMga->AccelInfoRec->ScanlineColorExpandBuffers = + (unsigned char**)(&pMga->ColorExpandBase); + WAITFIFO(pMga->expandDWORDs); + } +} + + +void mgaSubsequentColorExpandScanlineIndirect( ScrnInfoPtr pScrn, + int bufno ) +{ + MGAPtr pMga = MGAPTR(pScrn); + int dwords = pMga->expandDWORDs; + CARD32 *src = (CARD32*)(pMga->ScratchBuffer); + + while(dwords > pMga->FifoSize) { + WAITFIFO(pMga->FifoSize); + MGAMoveDWORDS((CARD32*)(pMga->ColorExpandBase), src, pMga->FifoSize); + src += pMga->FifoSize; + dwords -= pMga->FifoSize; + } + + WAITFIFO(dwords); + MGAMoveDWORDS((CARD32*)(pMga->ColorExpandBase), src, dwords); + + if(!(--pMga->expandRows)) { + if(pMga->expandRemaining) { + WAITFIFO(3); + OUTREG(MGAREG_AR0,((pMga->expandDWORDs<< 5)*pMga->expandHeight)-1); + OUTREG(MGAREG_AR3, 0); /* crashes occasionally without this */ + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (pMga->expandY << 16) | + pMga->expandHeight); + pMga->expandY += pMga->expandHeight; + pMga->expandRows = pMga->expandHeight; + pMga->expandRemaining--; + } else { + DISABLE_CLIP(); + } + } +} + + +void mgaSubsequentColorExpandScanline( ScrnInfoPtr pScrn, + int bufno ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + if(--pMga->expandRows) { + WAITFIFO(pMga->expandDWORDs); + } else if(pMga->expandRemaining) { + WAITFIFO(3); + OUTREG(MGAREG_AR0,((pMga->expandDWORDs<<5)*pMga->expandHeight)-1); + OUTREG(MGAREG_AR3, 0); /* crashes occasionally without this */ + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (pMga->expandY << 16) | + pMga->expandHeight); + pMga->expandY += pMga->expandHeight; + pMga->expandRows = pMga->expandHeight; + pMga->expandRemaining--; + WAITFIFO(pMga->expandDWORDs); + } else { + DISABLE_CLIP(); + } +} + + + /*******************\ + | Image Writes | + \*******************/ + + +void mgaSetupForScanlineImageWrite( ScrnInfoPtr pScrn, int rop, + unsigned int planemask, + int transparency_color, + int bpp, int depth ) +{ + MGAPtr pMga = MGAPTR(pScrn); + unsigned int replicate_pm = 0; + + switch( pMga->CurrentLayout.bitsPerPixel ) { + case 8: + replicate_pm = REPLICATE_8( planemask ); + break; + case 16: + replicate_pm = REPLICATE_16( planemask ); + break; + case 24: + replicate_pm = REPLICATE_24( planemask ); + break; + case 32: + replicate_pm = REPLICATE_32( planemask ); + break; + } + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + WAITFIFO(3); + OUTREG(MGAREG_AR5, 0); + SET_PLANEMASK_REPLICATED( planemask, replicate_pm, + pMga->CurrentLayout.bitsPerPixel ); + OUTREG(MGAREG_DWGCTL, MGADWG_ILOAD | MGADWG_BFCOL | MGADWG_SHIFTZERO | + MGADWG_SGNZERO | pMga->AtypeNoBLK[rop]); +} + + +void mgaSubsequentScanlineImageWriteRect( ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + pMga->AccelFlags |= CLIPPER_ON; + pMga->expandRows = h; + pMga->expandDWORDs = ((w * pMga->CurrentLayout.bitsPerPixel) + 31) >> 5; + + WAITFIFO(5); + OUTREG(MGAREG_CXBNDRY, 0xFFFF0000 | ((x + skipleft) & 0xFFFF)); + OUTREG(MGAREG_AR0, w - 1); + OUTREG(MGAREG_AR3, 0); + OUTREG(MGAREG_FXBNDRY, ((x + w - 1) << 16) | (x & 0xFFFF)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h); +} + + +void mgaSubsequentImageWriteScanline( ScrnInfoPtr pScrn, int bufno ) +{ + MGAPtr pMga = MGAPTR(pScrn); + int dwords = pMga->expandDWORDs; + CARD32 *src = (CARD32*)(pMga->ScratchBuffer); + + while(dwords > pMga->FifoSize) { + WAITFIFO(pMga->FifoSize); + MGAMoveDWORDS((CARD32*)(pMga->ColorExpandBase), src, pMga->FifoSize); + src += pMga->FifoSize; + dwords -= pMga->FifoSize; + } + + WAITFIFO(dwords); + MGAMoveDWORDS((CARD32*)(pMga->ColorExpandBase), src, dwords); + + if(!(--pMga->expandRows)) { + DISABLE_CLIP(); + } +} + + +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + + /***************************\ + | Dashed Lines | + \***************************/ + +void mgaSetupForDashedLine( ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, int length, + unsigned char *pattern ) +{ + MGAPtr pMga = MGAPTR(pScrn); + CARD32 *DashPattern = (CARD32*)pattern; + CARD32 NiceDashPattern = DashPattern[0]; + int dwords = (length + 31) >> 5; + unsigned int replicate_fg = 0; + unsigned int replicate_bg = 0; + unsigned int replicate_pm = 0; + + + common_replicate_colors_and_mask( fg, bg, planemask, + pMga->CurrentLayout.bitsPerPixel, + & replicate_fg, & replicate_bg, + & replicate_pm ); + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + pMga->DashCMD = MGADWG_BFCOL | pMga->AtypeNoBLK[rop]; + pMga->StyleLen = length - 1; + + if(bg == -1) { + pMga->DashCMD |= MGADWG_TRANSC; + WAITFIFO(dwords + 2); + } else { + WAITFIFO(dwords + 3); + SET_BACKGROUND_REPLICATED( bg, replicate_bg ); + } + + SET_PLANEMASK_REPLICATED( planemask, replicate_pm, + pMga->CurrentLayout.bitsPerPixel ); + SET_FOREGROUND_REPLICATED( fg, replicate_fg ); + + + /* We see if we can draw horizontal lines as 8x8 pattern fills. This is + * worthwhile since the pattern fills can use block mode and the default X + * pattern is 8 pixels long. The forward pattern is the top scanline, the + * backwards pattern is the next one. + */ + switch(length) { + case 2: NiceDashPattern |= NiceDashPattern << 2; + case 4: NiceDashPattern |= NiceDashPattern << 4; + case 8: { + NiceDashPattern |= byte_reversed[NiceDashPattern] << 16; + NiceDashPattern |= NiceDashPattern << 8; + pMga->NiceDashCMD = MGADWG_TRAP | MGADWG_ARZERO | + MGADWG_SGNZERO | MGADWG_BMONOLEF; + pMga->AccelFlags |= NICE_DASH_PATTERN; + + if( bg == -1 ) { + if ( (pMga->CurrentLayout.bitsPerPixel == 24) && !RGBEQUAL(fg) ) { + pMga->NiceDashCMD |= MGADWG_TRANSC | pMga->AtypeNoBLK[rop]; + } + else { + pMga->NiceDashCMD |= MGADWG_TRANSC | pMga->Atype[rop]; + } + } + else { + /* (Packed) 24-bit is a funky mode. We only use the Atype table + * in 24-bit if the components of the foreground color and the + * components of the background color are the same (e.g., fg = + * 0xf8f8f8 and bg = 0x131313). + */ + + if( ((pMga->AccelFlags & BLK_OPAQUE_EXPANSION) != 0) + && ((pMga->CurrentLayout.bitsPerPixel != 24) + || (RGBEQUAL(fg) && RGBEQUAL(bg))) ) { + pMga->NiceDashCMD |= pMga->Atype[rop]; + } + else { + pMga->NiceDashCMD |= pMga->AtypeNoBLK[rop]; + } + } + OUTREG(MGAREG_SRC0, NiceDashPattern); + break; + } + default: { + pMga->AccelFlags &= ~NICE_DASH_PATTERN; + switch (dwords) { + case 4: OUTREG(MGAREG_SRC3, DashPattern[3]); + case 3: OUTREG(MGAREG_SRC2, DashPattern[2]); + case 2: OUTREG(MGAREG_SRC1, DashPattern[1]); + default: OUTREG(MGAREG_SRC0, DashPattern[0]); + } + } + } +} + + +void mgaSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, + int flags, int phase ) +{ + MGAPtr pMga = MGAPTR(pScrn); + + WAITFIFO(4); + if((pMga->AccelFlags & NICE_DASH_PATTERN) && (y1 == y2)) { + OUTREG(MGAREG_DWGCTL, pMga->NiceDashCMD); + if(x2 < x1) { + if(flags & OMIT_LAST) x2++; + OUTREG(MGAREG_SHIFT, ((-y1 & 0x07) << 4) | + ((7 - phase - x1) & 0x07)); + OUTREG(MGAREG_FXBNDRY, ((x1 + 1) << 16) | (x2 & 0xffff)); + } else { + if(!flags) x2++; + OUTREG(MGAREG_SHIFT, (((1 - y1) & 0x07) << 4) | + ((phase - x1) & 0x07)); + OUTREG(MGAREG_FXBNDRY, (x2 << 16) | (x1 & 0xffff)); + } + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y1 << 16) | 1); + } else { + OUTREG(MGAREG_SHIFT, (pMga->StyleLen << 16 ) | + (pMga->StyleLen - phase)); + OUTREG(MGAREG_DWGCTL, pMga->DashCMD | ((flags & OMIT_LAST) ? + MGADWG_AUTOLINE_OPEN : MGADWG_AUTOLINE_CLOSE)); + OUTREG(MGAREG_XYSTRT, (y1 << 16) | (x1 & 0xFFFF)); + OUTREG(MGAREG_XYEND + MGAREG_EXEC, (y2 << 16) | (x2 & 0xFFFF)); + } +} +#endif /* X_BYTE_ORDER == X_LITTLE_ENDIAN */ + + + /******************************************\ + | Planar Screen to Screen Color Expansion | + \******************************************/ + +void mgaSetupForPlanarScreenToScreenColorExpandFill( ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask ) +{ + MGAPtr pMga = MGAPTR(pScrn); + CARD32 mgaCMD = pMga->AtypeNoBLK[rop] | MGADWG_BITBLT | + MGADWG_SGNZERO | MGADWG_BPLAN; + CARD32 regs[2]; + + + regs[0] = MGAREG_AR5; + regs[1] = pScrn->displayWidth; + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + (void) common_setup_for_pattern_fill( pMga, fg, bg, 0, planemask, regs, 1, + mgaCMD ); +} + + +void mgaSubsequentPlanarScreenToScreenColorExpandFill( ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int srcx, int srcy, + int skipleft ) +{ + MGAPtr pMga = MGAPTR(pScrn); + int start, end; + + w--; + start = XYADDRESS(srcx, srcy) + skipleft; + end = start + w; + + WAITFIFO(4); + OUTREG(MGAREG_AR3, start); + OUTREG(MGAREG_AR0, end); + OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h); +} + + + /***********************************\ + | Screen to Screen Color Expansion | + \***********************************/ + +void mgaSetupForScreenToScreenColorExpandFill( ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask ) +{ + MGAPtr pMga = MGAPTR(pScrn); + CARD32 regs[2]; + + regs[0] = MGAREG_AR5; + regs[1] = pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel; + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + (void) common_setup_for_pattern_fill( pMga, fg, bg, rop, planemask, + regs, 1, + MGADWG_BITBLT | MGADWG_SGNZERO + | MGADWG_SHIFTZERO ); +} + + +void mgaSubsequentScreenToScreenColorExpandFill( ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int srcx, int srcy, + int skipleft ) +{ + MGAPtr pMga = MGAPTR(pScrn); + const unsigned int display_bit_width = + (pMga->CurrentLayout.displayWidth * pMga->CurrentLayout.bitsPerPixel); + int start, end, next, num; + Bool resetDstOrg = FALSE; + + if (pMga->AccelFlags & LARGE_ADDRESSES) { + const int DstOrg = ((y & ~1023) * display_bit_width) >> 9; + const int SrcOrg = ((srcy & ~1023) * display_bit_width) >> 9; + + y &= 1023; + srcy &= 1023; + + WAITFIFO(2); + if(DstOrg) { + OUTREG(MGAREG_DSTORG, (DstOrg << 6) + pMga->DstOrg); + resetDstOrg = TRUE; + } + if(SrcOrg != pMga->SrcOrg) { + pMga->SrcOrg = SrcOrg; + OUTREG(MGAREG_SRCORG, (SrcOrg << 6) + pMga->realSrcOrg); + } + } + + w--; + start = (XYADDRESS(srcx, srcy) * pMga->CurrentLayout.bitsPerPixel) + + skipleft; + end = start + w + (display_bit_width * (h - 1)); + + /* src cannot split a 2 Meg boundary from SrcOrg */ + if(!((start ^ end) & 0xff000000)) { + WAITFIFO(4); + OUTREG(MGAREG_AR3, start); + OUTREG(MGAREG_AR0, start + w); + OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h); + } else { + while(h) { + next = (start + 0x00ffffff) & 0xff000000; + if(next <= (start + w)) { + num = next - start - 1; + + WAITFIFO(7); + OUTREG(MGAREG_AR3, start); + OUTREG(MGAREG_AR0, start + num); + OUTREG(MGAREG_FXBNDRY, ((x + num) << 16) | (x & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | 1); + + OUTREG(MGAREG_AR3, next); + OUTREG(MGAREG_AR0, start + w ); + OUTREG(MGAREG_FXBNDRY + MGAREG_EXEC, ((x + w) << 16) | + ((x + num + 1) & 0xffff)); + start += display_bit_width; + h--; y++; + } else { + num = ((next - start - w)/display_bit_width) + 1; + if(num > h) num = h; + + WAITFIFO(4); + OUTREG(MGAREG_AR3, start); + OUTREG(MGAREG_AR0, start + w); + OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | num); + + start += num * display_bit_width; + h -= num; y += num; + } + } + } + + if(resetDstOrg) { + WAITFIFO(1); + OUTREG(MGAREG_DSTORG, pMga->DstOrg); + } +} + + +static void +MGAFillSolidRectsDMA( + ScrnInfoPtr pScrn, + int fg, int rop, + unsigned int planemask, + int nBox, /* number of rectangles to fill */ + BoxPtr pBox /* Pointer to first rectangle to fill */ +){ + MGAPtr pMga = MGAPTR(pScrn); + XAAInfoRecPtr infoRec = pMga->AccelInfoRec; + CARD32 *base = (CARD32*)pMga->ILOADBase; + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + SET_SYNC_FLAG(infoRec); + (*infoRec->SetupForSolidFill)(pScrn, fg, rop, planemask); + + if(nBox & 1) { + OUTREG(MGAREG_FXBNDRY, ((pBox->x2) << 16) | (pBox->x1 & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, + (pBox->y1 << 16) | (pBox->y2 - pBox->y1)); + nBox--; pBox++; + } + + if(!nBox) return; + + OUTREG(MGAREG_OPMODE, MGAOPM_DMA_GENERAL); + while(nBox) { + base[0] = DMAINDICES(MGAREG_FXBNDRY, MGAREG_YDSTLEN + MGAREG_EXEC, + MGAREG_FXBNDRY, MGAREG_YDSTLEN + MGAREG_EXEC); + base[1] = ((pBox->x2) << 16) | (pBox->x1 & 0xffff); + base[2] = (pBox->y1 << 16) | (pBox->y2 - pBox->y1); + pBox++; + base[3] = ((pBox->x2) << 16) | (pBox->x1 & 0xffff); + base[4] = (pBox->y1 << 16) | (pBox->y2 - pBox->y1); + pBox++; + base += 5; nBox -= 2; + } + OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT); +} + +static void +MGAFillSolidSpansDMA( + ScrnInfoPtr pScrn, + int fg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted +){ + MGAPtr pMga = MGAPTR(pScrn); + XAAInfoRecPtr infoRec = pMga->AccelInfoRec; + CARD32 *base = (CARD32*)pMga->ILOADBase; + + CHECK_DMA_QUIESCENT(pMga, pScrn); + SET_SYNC_FLAG(infoRec); + + if(infoRec->ClipBox) { + OUTREG(MGAREG_CXBNDRY, + ((infoRec->ClipBox->x2 - 1) << 16) | infoRec->ClipBox->x1); + OUTREG(MGAREG_YTOP, + (infoRec->ClipBox->y1 * pScrn->displayWidth) + pMga->YDstOrg); + OUTREG(MGAREG_YBOT, + ((infoRec->ClipBox->y2 - 1) * pScrn->displayWidth) + pMga->YDstOrg); + } + + (*infoRec->SetupForSolidFill)(pScrn, fg, rop, planemask); + + if(n & 1) { + OUTREG(MGAREG_FXBNDRY, ((ppt->x + *pwidth) << 16) | (ppt->x & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (ppt->y << 16) | 1); + ppt++; pwidth++; n--; + } + + if(n) { + if(n > 838860) n = 838860; /* maximum number we have room for */ + + OUTREG(MGAREG_OPMODE, MGAOPM_DMA_GENERAL); + while(n) { + base[0] = DMAINDICES(MGAREG_FXBNDRY, MGAREG_YDSTLEN + MGAREG_EXEC, + MGAREG_FXBNDRY, MGAREG_YDSTLEN + MGAREG_EXEC); + base[1] = ((ppt->x + *(pwidth++)) << 16) | (ppt->x & 0xffff); + base[2] = (ppt->y << 16) | 1; + ppt++; + base[3] = ((ppt->x + *(pwidth++)) << 16) | (ppt->x & 0xffff); + base[4] = (ppt->y << 16) | 1; + ppt++; + base += 5; n -= 2; + } + OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT); + } + + if(infoRec->ClipBox) { + OUTREG(MGAREG_CXBNDRY, 0xFFFF0000); /* (maxX << 16) | minX */ + OUTREG(MGAREG_YTOP, 0x00000000); /* minPixelPointer */ + OUTREG(MGAREG_YBOT, 0x007FFFFF); /* maxPixelPointer */ + } +} + + +static void +MGAFillMono8x8PatternRectsTwoPass( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBoxInit, + BoxPtr pBoxInit, + int pattern0, int pattern1, + int xorg, int yorg +){ + MGAPtr pMga = MGAPTR(pScrn); + XAAInfoRecPtr infoRec = pMga->AccelInfoRec; + int nBox, SecondPassColor; + BoxPtr pBox; + + CHECK_DMA_QUIESCENT(pMga, pScrn); + + if((rop == GXcopy) && (bg != -1)) { + SecondPassColor = bg; + bg = -1; + } else SecondPassColor = -1; + + WAITFIFO(1); + OUTREG(MGAREG_SHIFT, (((-yorg) & 0x07) << 4) | ((-xorg) & 0x07)); + +SECOND_PASS: + + nBox = nBoxInit; + pBox = pBoxInit; + + (*infoRec->SetupForMono8x8PatternFill)(pScrn, pattern0, pattern1, + fg, bg, rop, planemask); + + while(nBox--) { + WAITFIFO(2); + OUTREG(MGAREG_FXBNDRY, ((pBox->x2) << 16) | (pBox->x1 & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, + (pBox->y1 << 16) | (pBox->y2 - pBox->y1)); + pBox++; + } + + if(SecondPassColor != -1) { + fg = SecondPassColor; + SecondPassColor = -1; + pattern0 = ~pattern0; + pattern1 = ~pattern1; + goto SECOND_PASS; + } + + SET_SYNC_FLAG(infoRec); +} + + +static void +MGAValidatePolyArc( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +){ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pGC->pScreen); + MGAPtr pMga = MGAPTR(pScrn); + Bool fullPlanemask = TRUE; + + if((pGC->planemask & pMga->AccelInfoRec->FullPlanemask) != + pMga->AccelInfoRec->FullPlanemask) + { + if(pMga->AccelFlags & MGA_NO_PLANEMASK) return; + fullPlanemask = FALSE; + } + + if(!pGC->lineWidth && + (pGC->fillStyle == FillSolid) && + (pGC->lineStyle == LineSolid) && + ((pGC->alu != GXcopy) || !fullPlanemask)) + { + pGC->ops->PolyArc = MGAPolyArcThinSolid; + } +} + +static void +MGAPolyPoint ( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + xPoint *ppt +){ + int numRects = REGION_NUM_RECTS(pGC->pCompositeClip); + XAAInfoRecPtr infoRec; + BoxPtr pbox; + MGAPtr pMga; + int xorg, yorg; + ScrnInfoPtr pScrn; + + if(!numRects) return; + + if(numRects != 1) { + XAAGetFallbackOps()->PolyPoint(pDraw, pGC, mode, npt, ppt); + return; + } + + infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + pScrn = infoRec->pScrn; + pMga = MGAPTR(pScrn); + xorg = pDraw->x; + yorg = pDraw->y; + + pbox = REGION_RECTS(pGC->pCompositeClip); + + (*infoRec->SetClippingRectangle)(infoRec->pScrn, + pbox->x1, pbox->y1, pbox->x2 - 1, pbox->y2 - 1); + (*infoRec->SetupForSolidFill)(infoRec->pScrn, pGC->fgPixel, pGC->alu, + pGC->planemask); + + if(mode == CoordModePrevious) { + while(npt--) { + xorg += ppt->x; + yorg += ppt->y; + WAITFIFO(2); + OUTREG(MGAREG_FXBNDRY, ((xorg + 1) << 16) | (xorg & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (yorg << 16) | 1); + ppt++; + } + } else { + int x; + while(npt--) { + x = ppt->x + xorg; + WAITFIFO(2); + OUTREG(MGAREG_FXBNDRY, ((x + 1) << 16) | (x & 0xffff)); + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, ((ppt->y + yorg) << 16) | 1); + ppt++; + } + } + + (*infoRec->DisableClipping)(infoRec->pScrn); + + SET_SYNC_FLAG(infoRec); +} + + +static void +MGAValidatePolyPoint( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +){ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pGC->pScreen); + MGAPtr pMga = MGAPTR(pScrn); + Bool fullPlanemask = TRUE; + + pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint; + + if((pGC->planemask & pMga->AccelInfoRec->FullPlanemask) != + pMga->AccelInfoRec->FullPlanemask) + { + if(pMga->AccelFlags & MGA_NO_PLANEMASK) return; + fullPlanemask = FALSE; + } + + if((pGC->alu != GXcopy) || !fullPlanemask) + pGC->ops->PolyPoint = MGAPolyPoint; +} + + +static void +MGAFillCacheBltRects( + ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + XAACacheInfoPtr pCache +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int x, y, phaseY, phaseX, skipleft, height, width, w, blit_w, blit_h, start; + + CHECK_DMA_QUIESCENT(MGAPTR(pScrn), pScrn); + + (*infoRec->SetupForScreenToScreenCopy)(pScrn, 1, 1, rop, planemask, + pCache->trans_color); + + while(nBox--) { + y = pBox->y1; + phaseY = (y - yorg) % pCache->orig_h; + if(phaseY < 0) phaseY += pCache->orig_h; + phaseX = (pBox->x1 - xorg) % pCache->orig_w; + if(phaseX < 0) phaseX += pCache->orig_w; + height = pBox->y2 - y; + width = pBox->x2 - pBox->x1; + start = phaseY ? (pCache->orig_h - phaseY) : 0; + + /* This is optimized for WRAM */ + + if ((rop == GXcopy) && (height >= (pCache->orig_h + start))) { + w = width; skipleft = phaseX; x = pBox->x1; + blit_h = pCache->orig_h; + + while(1) { + blit_w = pCache->w - skipleft; + if(blit_w > w) blit_w = w; + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, + pCache->x + skipleft, pCache->y, + x, y + start, blit_w, blit_h); + w -= blit_w; + if(!w) break; + x += blit_w; + skipleft = (skipleft + blit_w) % pCache->orig_w; + } + height -= blit_h; + + if(start) { + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, + pBox->x1, y + blit_h, pBox->x1, y, width, start); + height -= start; + y += start; + } + start = blit_h; + + while(height) { + if(blit_h > height) blit_h = height; + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, + pBox->x1, y, + pBox->x1, y + start, width, blit_h); + height -= blit_h; + start += blit_h; + blit_h <<= 1; + } + } else { + while(1) { + w = width; skipleft = phaseX; x = pBox->x1; + blit_h = pCache->h - phaseY; + if(blit_h > height) blit_h = height; + + while(1) { + blit_w = pCache->w - skipleft; + if(blit_w > w) blit_w = w; + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, + pCache->x + skipleft, pCache->y + phaseY, + x, y, blit_w, blit_h); + w -= blit_w; + if(!w) break; + x += blit_w; + skipleft = (skipleft + blit_w) % pCache->orig_w; + } + height -= blit_h; + if(!height) break; + y += blit_h; + phaseY = (phaseY + blit_h) % pCache->orig_h; + } + } + pBox++; + } + + SET_SYNC_FLAG(infoRec); +} +#endif diff --git a/src/mga_video.c b/src/mga_video.c index 4a36e54..32f5e9f 100644 --- a/src/mga_video.c +++ b/src/mga_video.c @@ -15,6 +15,11 @@ #include "xf86xv.h" #include +#ifdef USE_XAA +#include "xaa.h" +#include "xaalocal.h" +#endif + #include "dixstruct.h" #include "fourcc.h" @@ -560,11 +565,15 @@ MGAAllocateMemory( void **mem_struct, int size ){ +#if defined(USE_XAA) || defined(USE_EXA) + MGAPtr pMga = MGAPTR(pScrn); +#endif /* defined(USE_XAA) || defined(USE_EXA) */ +#ifdef USE_XAA + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); +#endif /* USE_XAA */ int offset = 0; #ifdef USE_EXA - MGAPtr pMga = MGAPTR(pScrn); - if (pMga->Exa) { ExaOffscreenArea *area = *mem_struct; @@ -585,6 +594,53 @@ MGAAllocateMemory( offset = area->offset; } #endif /* USE_EXA */ +#ifdef USE_XAA + FBLinearPtr linear = *mem_struct; + int cpp = pMga->CurrentLayout.bitsPerPixel / 8; + + /* XAA allocates in units of pixels at the screen bpp, so adjust size + * appropriately. + */ + size = (size + cpp - 1) / cpp; + + if (!pMga->Exa) { + if (linear) { + if (linear->size >= size) + return linear->offset * cpp; + + if (xf86ResizeOffscreenLinear(linear, size)) + return linear->offset * cpp; + + xf86FreeOffscreenLinear(linear); + } + + + linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + NULL, NULL, NULL); + *mem_struct = linear; + + if (!linear) { + int max_size; + + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, + PRIORITY_EXTREME); + + if (max_size < size) + return 0; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + + linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + NULL, NULL, NULL); + *mem_struct = linear; + + if (!linear) + return 0; + } + + offset = linear->offset * cpp; + } +#endif /* USE_XAA */ return offset; } @@ -592,9 +648,11 @@ MGAAllocateMemory( static void MGAFreeMemory(ScrnInfoPtr pScrn, void *mem_struct) { -#ifdef USE_EXA +#if defined(USE_XAA) || defined(USE_EXA) MGAPtr pMga = MGAPTR(pScrn); +#endif /* defined(USE_XAA) || defined(USE_EXA) */ +#ifdef USE_EXA if (pMga->Exa) { ExaOffscreenArea *area = mem_struct; @@ -602,6 +660,14 @@ MGAFreeMemory(ScrnInfoPtr pScrn, void *mem_struct) exaOffscreenFree(pScrn->pScreen, area); } #endif /* USE_EXA */ +#ifdef USE_XAA + if (!pMga->Exa) { + FBLinearPtr linear = mem_struct; + + if (linear) + xf86FreeOffscreenLinear(linear); + } +#endif /* USE_XAA */ } static void @@ -1939,6 +2005,12 @@ MGAPutImageILOAD( clipBoxes, width, height)) return Success; +#ifdef USE_XAA + if( pMga->AccelInfoRec->NeedToSync && ((long)data != pPriv->lastPort) ) { + MGAStormSync(pScrn); + } +#endif + pPriv->lastPort = (long)data; nbox=REGION_NUM_RECTS(clipBoxes); pbox=REGION_RECTS(clipBoxes); @@ -1967,6 +2039,9 @@ MGAPutImageILOAD( pbox++; } +#ifdef USE_XAA + pMga->AccelInfoRec->NeedToSync = TRUE; +#endif pPriv->videoStatus = FREE_TIMER; pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; pMga->VideoTimerCallback = MGAVideoTimerCallback; --- /dev//null 2026-02-11 11:03:04.442000280 +0100 +++ xf86-video-mga/src/mga_arc.c 2026-02-12 20:56:25.767939853 +0100 @@ -0,0 +1,225 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include +#include "regionstr.h" +#include "mizerarc.h" +#include "mi.h" +#include "scrnintstr.h" +#ifdef HAVE_XAA_H +#include "xaa.h" +#include "xaalocal.h" +#endif +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "xf86Pci.h" + +#include "mga.h" +#include "mga_reg.h" +#include "mga_macros.h" + + +#define DRAW_POINT(x, y) { \ + tmp = x; \ + OUTREG(MGAREG_FXBNDRY, (tmp) | (((tmp) + 1) << 16)); \ + OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, ((y) << 16) | 1); \ +} + +#ifdef USE_XAA +static void +MGAZeroArc( + DrawablePtr pDraw, + GCPtr pGC, + xArc *arc +){ + int yoffset, dyoffset, x, y, a, b, d, mask, k1, k3, dx, dy, tmp; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + ScrnInfoPtr pScrn = infoRec->pScrn; + MGAPtr pMga = MGAPTR(pScrn); + miZeroArcRec info; + Bool do360; + DDXPointRec org, orgo; + + CHECK_DMA_QUIESCENT( pMga, infoRec->pScrn ); + + (*infoRec->SetupForSolidFill)(infoRec->pScrn, pGC->fgPixel, + pGC->alu, pGC->planemask); + + do360 = miZeroArcSetup(arc, &info, TRUE); + org.y = info.yorg + pDraw->y; + org.x = 0; + orgo.y = info.yorgo + pDraw->y; + orgo.x = 0; + info.xorg += pDraw->x; + info.xorgo += pDraw->x; + + MIARCSETUP(); + yoffset = y ? 1 : 0; + dyoffset = 0; + mask = info.initialMask; + if (!(arc->width & 1)) { + WAITFIFO(4); + if (mask & 2) + DRAW_POINT(info.xorgo, org.y); + if (mask & 8) + DRAW_POINT(info.xorgo, orgo.y); + } + if (!info.end.x || !info.end.y) { + mask = info.end.mask; + info.end = info.altend; + } + if (do360 && (arc->width == arc->height) && !(arc->width & 1)) { + int xoffset = 1; + DDXPointRec orghb, orgohb; + + orghb.y = org.y + info.h; + orghb.x = org.x + info.xorg; + orgohb.y = orghb.y; + orgohb.x = orghb.x - info.h; + + org.x += info.xorg; + orgo.x += info.xorg; + orghb.x += info.h; + while (1) { + WAITFIFO(16); + DRAW_POINT(org.x + x, org.y + yoffset); + DRAW_POINT(org.x - x, org.y + yoffset); + DRAW_POINT(orgo.x - x, orgo.y - yoffset); + DRAW_POINT(orgo.x + x, orgo.y - yoffset); + if (a < 0) break; + DRAW_POINT(orghb.x - y, orghb.y - xoffset); + DRAW_POINT(orgohb.x + y, orgohb.y - xoffset); + DRAW_POINT(orgohb.x + y, orgohb.y + xoffset); + DRAW_POINT(orghb.x - y, orghb.y + xoffset); + xoffset ++; + MIARCCIRCLESTEP(yoffset ++;); + } + org.x -= info.xorg; + orgo.x -= info.xorg; + x = info.w; + yoffset = info.h; + } + else if (do360) { + while (y < info.h || x < info.w) { + MIARCOCTANTSHIFT(dyoffset = 1;); + WAITFIFO(8); + DRAW_POINT(org.x + info.xorg + x, org.y + yoffset); + DRAW_POINT(org.x + info.xorgo - x, org.y + yoffset); + DRAW_POINT(orgo.x + info.xorgo - x, orgo.y - yoffset); + DRAW_POINT(orgo.x + info.xorg + x, orgo.y - yoffset); + MIARCSTEP(yoffset += dyoffset;, yoffset++;); + } + } + else { + while (y < info.h || x < info.w) { + MIARCOCTANTSHIFT(dyoffset = 1;); + if ((x == info.start.x) || (y == info.start.y)) { + mask = info.start.mask; + info.start = info.altstart; + } + WAITFIFO(8); + if (mask & 1) + DRAW_POINT(org.x + info.xorg + x, org.y + yoffset); + if (mask & 2) + DRAW_POINT(org.x + info.xorgo - x, org.y + yoffset); + if (mask & 4) + DRAW_POINT(orgo.x + info.xorgo - x, orgo.y - yoffset); + if (mask & 8) + DRAW_POINT(orgo.x + info.xorg + x, orgo.y - yoffset); + if ((x == info.end.x) || (y == info.end.y)) { + mask = info.end.mask; + info.end = info.altend; + } + MIARCSTEP(yoffset += dyoffset;, yoffset++;); + } + } + if ((x == info.start.x) || (y == info.start.y)) + mask = info.start.mask; + + WAITFIFO(4); + if (mask & 1) + DRAW_POINT(org.x + info.xorg + x, org.y + yoffset); + if (mask & 4) + DRAW_POINT(orgo.x + info.xorgo - x, orgo.y - yoffset); + if (arc->height & 1) { + WAITFIFO(4); + if (mask & 2) + DRAW_POINT(org.x + info.xorgo - x, org.y + yoffset); + if (mask & 8) + DRAW_POINT(orgo.x + info.xorg + x, orgo.y - yoffset); + } + + SET_SYNC_FLAG(infoRec); +} + +void +MGAPolyArcThinSolid ( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs +){ + xArc *arc; + BoxRec box; + int i, x2, y2; + RegionPtr cclip; + + cclip = pGC->pCompositeClip; + + if(!REGION_NUM_RECTS(cclip)) + return; + + for (arc = parcs, i = narcs; --i >= 0; arc++) { + if (miCanZeroArc(arc)) { + box.x1 = arc->x + pDraw->x; + box.y1 = arc->y + pDraw->y; + x2 = box.x1 + (int)arc->width + 1; + box.x2 = x2; + y2 = box.y1 + (int)arc->height + 1; + box.y2 = y2; + if ( (x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) && + (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) ) + MGAZeroArc (pDraw, pGC, arc); + else + miZeroPolyArc(pDraw, pGC, 1, arc); + } + else + miPolyArc(pDraw, pGC, 1, arc); + } +} +#endif /* USE_XAA */ +