summaryrefslogtreecommitdiff
path: root/src/mga_storm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mga_storm.c')
-rw-r--r--src/mga_storm.c2703
1 files changed, 2703 insertions, 0 deletions
diff --git a/src/mga_storm.c b/src/mga_storm.c
new file mode 100644
index 0000000..ff083ac
--- /dev/null
+++ b/src/mga_storm.c
@@ -0,0 +1,2703 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_storm.c,v 1.98 2003/01/16 16:09:10 eich Exp $ */
+
+
+/* All drivers should typically include these */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+
+/* For correct __inline__ usage */
+#include "compiler.h"
+
+/* Drivers that need to access the PCI config space directly need this */
+#include "xf86Pci.h"
+
+/* Drivers for PCI hardware need this */
+#include "xf86PciInfo.h"
+
+/* Drivers that use XAA need this */
+#include "xaa.h"
+#include "xaalocal.h"
+#include "xf86fbman.h"
+#include "miline.h"
+#include "servermd.h"
+
+#ifdef XF86DRI
+#include "cfb.h"
+#include "GL/glxtokens.h"
+#endif
+
+#include "mga_bios.h"
+#include "mga.h"
+#include "mga_reg.h"
+#include "mga_map.h"
+#include "mga_macros.h"
+
+#ifdef XF86DRI
+#include "mga_dri.h"
+#endif
+
+#define MGAMoveDWORDS(d,s,c) \
+do { \
+ write_mem_barrier(); \
+ XAAMoveDWORDS((d),(s),(c)); \
+} while (0)
+
+static void MGANAME(SubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn,
+ int srcX, int srcY, int dstX, int dstY,
+ int w, int h);
+static void MGANAME(SubsequentScreenToScreenCopy_FastBlit)(ScrnInfoPtr pScrn,
+ int srcX, int srcY, int dstX, int dstY,
+ int w, int h);
+static void MGANAME(SetupForScanlineCPUToScreenColorExpandFill)(
+ ScrnInfoPtr pScrn, int fg,
+ int bg, int rop, unsigned int planemask);
+static void MGANAME(SubsequentScanlineCPUToScreenColorExpandFill)(
+ ScrnInfoPtr pScrn,
+ int x, int y, int w, int h, int skipleft);
+static void MGANAME(SubsequentColorExpandScanline)(ScrnInfoPtr pScrn,
+ int bufno);
+static void MGANAME(SubsequentColorExpandScanlineIndirect)(ScrnInfoPtr pScrn,
+ int bufno);
+static void MGANAME(SubsequentSolidFillRect)(ScrnInfoPtr pScrn,
+ int x, int y, int w, int h);
+static void MGANAME(SubsequentSolidFillTrap)(ScrnInfoPtr pScrn, int y, int h,
+ int left, int dxL, int dyL, int eL,
+ int right, int dxR, int dyR, int eR);
+static void MGANAME(SubsequentSolidHorVertLine) (ScrnInfoPtr pScrn,
+ int x, int y, int len, int dir);
+static void MGANAME(SubsequentSolidTwoPointLine)(ScrnInfoPtr pScrn,
+ int x1, int y1, int x2, int y2, int flags);
+static void MGANAME(SetupForMono8x8PatternFill)(ScrnInfoPtr pScrn,
+ int patx, int paty, int fg, int bg,
+ int rop, unsigned int planemask);
+static void MGANAME(SubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int x, int y, int w, int h );
+static void MGANAME(SubsequentMono8x8PatternFillRect_Additional)(
+ ScrnInfoPtr pScrn, int patx, int paty,
+ int x, int y, int w, int h );
+static void MGANAME(SubsequentMono8x8PatternFillTrap)( 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 MGANAME(SetupForScanlineImageWrite)(ScrnInfoPtr pScrn, int rop,
+ unsigned int planemask,
+ int transparency_color, int bpp, int depth);
+static void MGANAME(SubsequentScanlineImageWriteRect)(ScrnInfoPtr pScrn,
+ int x, int y, int w, int h, int skipleft);
+static void MGANAME(SubsequentImageWriteScanline)(ScrnInfoPtr pScrn, int num);
+#if PSZ != 24
+static void MGANAME(SetupForPlanarScreenToScreenColorExpandFill)(
+ ScrnInfoPtr pScrn, int fg, int bg, int rop,
+ unsigned int planemask);
+static void MGANAME(SubsequentPlanarScreenToScreenColorExpandFill)(
+ ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ int srcx, int srcy, int skipleft);
+#endif
+static void MGANAME(SetupForScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn,
+ int fg, int bg, int rop,
+ unsigned int planemask);
+static void MGANAME(SubsequentScreenToScreenColorExpandFill)(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 MGANAME(SetupForDashedLine)(ScrnInfoPtr pScrn, int fg, int bg,
+ int rop, unsigned int planemask, int length,
+ unsigned char *pattern);
+static void MGANAME(SubsequentDashedTwoPointLine)(ScrnInfoPtr pScrn,
+ int x1, int y1, int x2, int y2,
+ int flags, int phase);
+#endif
+void MGANAME(RestoreAccelState)(ScrnInfoPtr pScrn);
+#if PSZ == 8
+void Mga16RestoreAccelState(ScrnInfoPtr pScrn);
+void Mga24RestoreAccelState(ScrnInfoPtr pScrn);
+void Mga32RestoreAccelState(ScrnInfoPtr pScrn);
+#endif
+
+#ifdef XF86DRI
+void MGANAME(DRIInitBuffers)(WindowPtr pWin,
+ RegionPtr prgn, CARD32 index);
+void MGANAME(DRIMoveBuffers)(WindowPtr pParent, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 index);
+
+#endif
+
+extern void MGASetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2);
+extern void MGADisableClipping(ScrnInfoPtr pScrn);
+extern void MGAFillSolidRectsDMA(ScrnInfoPtr pScrn, int fg, int rop,
+ unsigned int planemask, int nBox, BoxPtr pBox);
+extern void MGAFillSolidSpansDMA(ScrnInfoPtr pScrn, int fg, int rop,
+ unsigned int planemask, int n, DDXPointPtr ppt,
+ int *pwidth, int fSorted);
+extern 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);
+extern void MGAValidatePolyArc(GCPtr, unsigned long, DrawablePtr);
+extern void MGAValidatePolyPoint(GCPtr, unsigned long, DrawablePtr);
+extern void MGAFillCacheBltRects(ScrnInfoPtr, int, unsigned int, int, BoxPtr,
+ int, int, XAACacheInfoPtr);
+
+#ifdef RENDER
+
+extern 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
+);
+
+extern 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
+);
+
+
+extern Bool
+MGASetupForCPUToScreenTexture (
+ ScrnInfoPtr pScrn,
+ int op,
+ int texType,
+ CARD8 *texPtr,
+ int texPitch,
+ int width,
+ int height,
+ int flags
+);
+
+extern void
+MGASubsequentCPUToScreenTexture (
+ ScrnInfoPtr pScrn,
+ int dstx,
+ int dsty,
+ int srcx,
+ int srcy,
+ int width,
+ int height
+);
+
+extern CARD32 MGAAlphaTextureFormats[2];
+extern CARD32 MGATextureFormats[2];
+
+#if PSZ == 8
+#include "mipict.h"
+#include "dixstruct.h"
+
+CARD32 MGAAlphaTextureFormats[2] = {PICT_a8, 0};
+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, i, pitch, sizeNeeded, offset;
+ 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);
+
+ if(pMga->Overlay8Plus24) {
+ i = 0x00ffffff;
+ WAITFIFO(1);
+ SET_PLANEMASK(i);
+ }
+
+ 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));
+ OUTREG(MGAREG_TEXCTL, 0x1A000106 | ((pitch & 0x07FF) << 9));
+ OUTREG(MGAREG_TEXCTL2, 0x00000014);
+ OUTREG(MGAREG_DWGCTL, 0x000c7076);
+ OUTREG(MGAREG_TEXFILTER, 0x01e00020);
+ OUTREG(MGAREG_ALPHACTRL, 0x00000154);
+
+ 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;
+ 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);
+
+ if(pMga->Overlay8Plus24) {
+ i = 0x00ffffff;
+ WAITFIFO(1);
+ SET_PLANEMASK(i);
+ }
+
+ 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));
+ OUTREG(MGAREG_TEXCTL, 0x3A000107 | ((pitch & 0x07FF) << 9));
+ OUTREG(MGAREG_TEXCTL2, 0x00000014);
+ OUTREG(MGAREG_DWGCTL, 0x000c7076);
+ OUTREG(MGAREG_TEXFILTER, 0x01e00020);
+ OUTREG(MGAREG_ALPHACTRL, 0x02000151);
+
+ 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;
+ 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);
+
+ if(pMga->Overlay8Plus24) {
+ i = 0x00ffffff;
+ WAITFIFO(1);
+ SET_PLANEMASK(i);
+ }
+
+ 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));
+ OUTREG(MGAREG_TEXCTL, 0x1A000106 | ((pitch & 0x07FF) << 9));
+ OUTREG(MGAREG_TEXCTL2, 0x00000014);
+ OUTREG(MGAREG_DWGCTL, 0x000c7076);
+ OUTREG(MGAREG_TEXFILTER, 0x01e00020);
+ OUTREG(MGAREG_ALPHACTRL, 0x00000151);
+
+ 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
+#endif
+
+Bool
+MGANAME(AccelInit)(ScreenPtr pScreen)
+{
+ XAAInfoRecPtr infoPtr;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ MGAPtr pMga = MGAPTR(pScrn);
+ int maxFastBlitMem, maxlines;
+ Bool doRender = FALSE;
+ BoxRec AvailFBArea;
+
+ pMga->ScratchBuffer = xalloc(((pScrn->displayWidth * PSZ) + 127) >> 3);
+ if(!pMga->ScratchBuffer) return FALSE;
+
+ pMga->AccelInfoRec = infoPtr = XAACreateInfoRec();
+ if(!infoPtr) return FALSE;
+
+ pMga->RenderTime = 0;
+ pMga->LinearScratch = 0;
+
+ pMga->MaxFastBlitY = 0;
+ pMga->MaxBlitDWORDS = 0x40000 >> 5;
+
+ switch (pMga->Chipset) {
+ case PCI_CHIP_MGA2064:
+ pMga->AccelFlags = BLK_OPAQUE_EXPANSION | FASTBLT_BUG;
+ break;
+ case PCI_CHIP_MGA2164:
+ case PCI_CHIP_MGA2164_AGP:
+ pMga->AccelFlags = BLK_OPAQUE_EXPANSION |
+ TRANSC_SOLID_FILL |
+ USE_RECTS_FOR_LINES;
+ break;
+ case PCI_CHIP_MGAG400:
+ case PCI_CHIP_MGAG550:
+ if(pMga->SecondCrtc == TRUE) {
+ pMga->HasFBitBlt = FALSE;
+ }
+ pMga->MaxBlitDWORDS = 0x400000 >> 5;
+ /* fallthrough */
+ case PCI_CHIP_MGAG200:
+ case PCI_CHIP_MGAG200_PCI:
+ doRender = FALSE;
+ pMga->AccelFlags = TRANSC_SOLID_FILL |
+ TWO_PASS_COLOR_EXPAND;
+
+#if 1
+ if((pMga->FbMapSize > 8*1024*1024) && (pScrn->depth == 8))
+ pMga->AccelFlags |= LARGE_ADDRESSES;
+#endif
+ break;
+ case PCI_CHIP_MGA1064:
+ pMga->AccelFlags = 0;
+ break;
+ case PCI_CHIP_MGAG100:
+ case PCI_CHIP_MGAG100_PCI:
+ default:
+ pMga->AccelFlags = MGA_NO_PLANEMASK;
+ break;
+ }
+
+ /* all should be able to use this now with the bug fixes */
+ pMga->AccelFlags |= USE_LINEAR_EXPANSION;
+
+#if PSZ == 24
+ pMga->AccelFlags |= MGA_NO_PLANEMASK;
+#endif
+
+ if(pMga->HasSDRAM) {
+ pMga->Atype = pMga->AtypeNoBLK = MGAAtypeNoBLK;
+ pMga->AccelFlags &= ~TWO_PASS_COLOR_EXPAND;
+ } else {
+ pMga->Atype = MGAAtype;
+ pMga->AtypeNoBLK = MGAAtypeNoBLK;
+ }
+
+ /* 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 =
+ MGANAME(SetupForScreenToScreenCopy);
+ infoPtr->SubsequentScreenToScreenCopy =
+ MGANAME(SubsequentScreenToScreenCopy);
+
+ if(pMga->HasFBitBlt) {
+ infoPtr->FillCacheBltRects = MGAFillCacheBltRects;
+ infoPtr->FillCacheBltRectsFlags = NO_TRANSPARENCY;
+ }
+ /* solid fills */
+ infoPtr->SetupForSolidFill = MGANAME(SetupForSolidFill);
+ infoPtr->SubsequentSolidFillRect = MGANAME(SubsequentSolidFillRect);
+ infoPtr->SubsequentSolidFillTrap = MGANAME(SubsequentSolidFillTrap);
+
+ /* solid lines */
+ infoPtr->SetupForSolidLine = infoPtr->SetupForSolidFill;
+ infoPtr->SubsequentSolidHorVertLine =
+ MGANAME(SubsequentSolidHorVertLine);
+ infoPtr->SubsequentSolidTwoPointLine =
+ MGANAME(SubsequentSolidTwoPointLine);
+
+ /* 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 = MGANAME(SetupForDashedLine);
+ infoPtr->SubsequentDashedTwoPointLine =
+ MGANAME(SubsequentDashedTwoPointLine);
+ 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 = MGANAME(SetupForMono8x8PatternFill);
+ infoPtr->SubsequentMono8x8PatternFillRect =
+ MGANAME(SubsequentMono8x8PatternFillRect);
+ infoPtr->SubsequentMono8x8PatternFillTrap =
+ MGANAME(SubsequentMono8x8PatternFillTrap);
+
+ /* 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 =
+ MGANAME(SetupForScanlineCPUToScreenColorExpandFill);
+ infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
+ MGANAME(SubsequentScanlineCPUToScreenColorExpandFill);
+ infoPtr->SubsequentColorExpandScanline =
+ MGANAME(SubsequentColorExpandScanline);
+ infoPtr->NumScanlineColorExpandBuffers = 1;
+ infoPtr->ScanlineColorExpandBuffers = &(pMga->ColorExpandBase);
+
+ /* screen to screen color expansion */
+ if(pMga->AccelFlags & USE_LINEAR_EXPANSION) {
+ infoPtr->ScreenToScreenColorExpandFillFlags =
+ BIT_ORDER_IN_BYTE_LSBFIRST;
+ infoPtr->SetupForScreenToScreenColorExpandFill =
+ MGANAME(SetupForScreenToScreenColorExpandFill);
+ infoPtr->SubsequentScreenToScreenColorExpandFill =
+ MGANAME(SubsequentScreenToScreenColorExpandFill);
+ } else {
+#if PSZ != 24
+ /* Alternate (but slower) planar expansions */
+ infoPtr->SetupForScreenToScreenColorExpandFill =
+ MGANAME(SetupForPlanarScreenToScreenColorExpandFill);
+ infoPtr->SubsequentScreenToScreenColorExpandFill =
+ MGANAME(SubsequentPlanarScreenToScreenColorExpandFill);
+ infoPtr->CacheColorExpandDensity = PSZ;
+ infoPtr->CacheMonoStipple = XAACachePlanarMonoStipple;
+ /* It's faster to blit the stipples if you have fastbilt */
+ if(pMga->HasFBitBlt)
+ infoPtr->ScreenToScreenColorExpandFillFlags = TRANSPARENCY_ONLY;
+#endif
+ }
+
+ /* 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 =
+ MGANAME(SetupForScanlineImageWrite);
+ infoPtr->SubsequentScanlineImageWriteRect =
+ MGANAME(SubsequentScanlineImageWriteRect);
+ infoPtr->SubsequentImageWriteScanline =
+ MGANAME(SubsequentImageWriteScanline);
+ 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 * PSZ / 8);
+ }
+
+ maxlines = (min(pMga->FbUsableSize, 16*1024*1024)) /
+ (pScrn->displayWidth * PSZ / 8);
+
+#ifdef XF86DRI
+ if ( pMga->directRenderingEnabled ) {
+ MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
+ BoxRec MemBox;
+ int cpp = pScrn->bitsPerPixel / 8;
+ int widthBytes = pScrn->displayWidth * cpp;
+ int bufferSize = ((pScrn->virtualY * widthBytes + MGA_BUFFER_ALIGN)
+ & ~MGA_BUFFER_ALIGN);
+ int scanlines;
+
+ pMGADRIServer->frontOffset = 0;
+ pMGADRIServer->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.
+ */
+ pMGADRIServer->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 ( pMGADRIServer->textureSize < (int)pMga->FbMapSize / 2 ) {
+ pMGADRIServer->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
+ > pMGADRIServer->textureSize ) {
+ pMGADRIServer->textureSize = (pMga->FbMapSize -
+ maxlines * widthBytes -
+ bufferSize * 2);
+ }
+
+ /* Set a minimum usable local texture heap size. This will fit
+ * two 256x256x32bpp textures.
+ */
+ if ( pMGADRIServer->textureSize < 512 * 1024 ) {
+ pMGADRIServer->textureOffset = 0;
+ pMGADRIServer->textureSize = 0;
+ }
+
+ /* Reserve space for textures */
+ pMGADRIServer->textureOffset = (pMga->FbMapSize -
+ pMGADRIServer->textureSize +
+ MGA_BUFFER_ALIGN) & ~MGA_BUFFER_ALIGN;
+
+ /* Reserve space for the shared depth buffer */
+ pMGADRIServer->depthOffset = (pMGADRIServer->textureOffset -
+ bufferSize +
+ MGA_BUFFER_ALIGN) & ~MGA_BUFFER_ALIGN;
+ pMGADRIServer->depthPitch = widthBytes;
+
+ /* Reserve space for the shared back buffer */
+ pMGADRIServer->backOffset = (pMGADRIServer->depthOffset - bufferSize +
+ MGA_BUFFER_ALIGN) & ~MGA_BUFFER_ALIGN;
+ pMGADRIServer->backPitch = widthBytes;
+
+ scanlines = pMGADRIServer->backOffset / widthBytes - 1;
+ if ( scanlines > maxlines ) scanlines = maxlines;
+
+ MemBox.x1 = 0;
+ MemBox.y1 = 0;
+ MemBox.x2 = pScrn->displayWidth;
+ MemBox.y2 = scanlines;
+
+ if ( !xf86InitFBManager( pScreen, &MemBox ) ) {
+ xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
+ "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
+ MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2 );
+ return FALSE;
+ } else {
+ int width, height;
+
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO,
+ "Memory manager initialized to (%d,%d) (%d,%d)\n",
+ MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2 );
+
+ if ( xf86QueryLargestOffscreenArea( pScreen, &width,
+ &height, 0, 0, 0 ) ) {
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO,
+ "Largest offscreen area available: %d x %d\n",
+ width, height );
+ }
+ }
+
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO,
+ "Reserved back buffer at offset 0x%x\n",
+ pMGADRIServer->backOffset );
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO,
+ "Reserved depth buffer at offset 0x%x\n",
+ pMGADRIServer->depthOffset );
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO,
+ "Reserved %d kb for textures at offset 0x%x\n",
+ pMGADRIServer->textureSize/1024,
+ pMGADRIServer->textureOffset );
+ }
+ else
+#endif
+ {
+ AvailFBArea.x1 = 0;
+ AvailFBArea.x2 = pScrn->displayWidth;
+ AvailFBArea.y1 = 0;
+ AvailFBArea.y2 = maxlines;
+
+ /*
+ * Need to keep a strip of memory to the right of screen to workaround
+ * a display problem with the second CRTC.
+ */
+ if (pMga->SecondCrtc)
+ AvailFBArea.x2 = pScrn->virtualX;
+
+ xf86InitFBManager(pScreen, &AvailFBArea);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %d lines for offscreen "
+ "memory.\n",
+ maxlines - pScrn->virtualY);
+
+ }
+
+ {
+ Bool shared_accel = FALSE;
+ int i;
+
+ for(i = 0; i < pScrn->numEntities; i++) {
+ if(xf86IsEntityShared(pScrn->entityList[i]))
+ shared_accel = TRUE;
+ }
+ if(shared_accel == TRUE)
+ infoPtr->RestoreAccelState = MGANAME(RestoreAccelState);
+ }
+
+#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
+
+ return(XAAInit(pScreen, infoPtr));
+}
+
+void
+MGANAME(InitSolidFillRectFuncs)(MGAPtr pMga)
+{
+ pMga->SetupForSolidFill = MGANAME(SetupForSolidFill);
+ pMga->SubsequentSolidFillRect = MGANAME(SubsequentSolidFillRect);
+}
+
+/* Support for multiscreen */
+void
+MGANAME(RestoreAccelState)(ScrnInfoPtr pScrn)
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+ MGAFBLayout *pLayout = &pMga->CurrentLayout;
+ CARD32 tmp;
+
+ MGAStormSync(pScrn);
+ WAITFIFO(12);
+ pMga->SrcOrg = 0;
+ OUTREG(MGAREG_MACCESS, pMga->MAccess);
+ OUTREG(MGAREG_PITCH, pLayout->displayWidth);
+ OUTREG(MGAREG_YDSTORG, pMga->YDstOrg);
+ tmp = pMga->PlaneMask;
+ pMga->PlaneMask = ~tmp;
+ SET_PLANEMASK(tmp);
+ tmp = pMga->BgColor;
+ pMga->BgColor = ~tmp;
+ SET_BACKGROUND(tmp);
+ tmp = pMga->FgColor;
+ pMga->FgColor = ~tmp;
+ SET_FOREGROUND(tmp);
+ 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;
+}
+
+#if PSZ == 8
+
+CARD32 MGAAtype[16] = {
+ MGADWG_RPL | 0x00000000, MGADWG_RSTR | 0x00080000,
+ MGADWG_RSTR | 0x00040000, MGADWG_BLK | 0x000c0000,
+ MGADWG_RSTR | 0x00020000, MGADWG_RSTR | 0x000a0000,
+ MGADWG_RSTR | 0x00060000, MGADWG_RSTR | 0x000e0000,
+ MGADWG_RSTR | 0x00010000, MGADWG_RSTR | 0x00090000,
+ MGADWG_RSTR | 0x00050000, MGADWG_RSTR | 0x000d0000,
+ MGADWG_RPL | 0x00030000, MGADWG_RSTR | 0x000b0000,
+ MGADWG_RSTR | 0x00070000, MGADWG_RPL | 0x000f0000
+};
+
+
+CARD32 MGAAtypeNoBLK[16] = {
+ MGADWG_RPL | 0x00000000, MGADWG_RSTR | 0x00080000,
+ MGADWG_RSTR | 0x00040000, MGADWG_RPL | 0x000c0000,
+ MGADWG_RSTR | 0x00020000, MGADWG_RSTR | 0x000a0000,
+ MGADWG_RSTR | 0x00060000, MGADWG_RSTR | 0x000e0000,
+ MGADWG_RSTR | 0x00010000, MGADWG_RSTR | 0x00090000,
+ MGADWG_RSTR | 0x00050000, MGADWG_RSTR | 0x000d0000,
+ MGADWG_RPL | 0x00030000, MGADWG_RSTR | 0x000b0000,
+ MGADWG_RSTR | 0x00070000, MGADWG_RPL | 0x000f0000
+};
+
+
+Bool
+MGAStormAccelInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ switch( pScrn->bitsPerPixel )
+ {
+ case 8:
+ return Mga8AccelInit(pScreen);
+ case 16:
+ return Mga16AccelInit(pScreen);
+ case 24:
+ return Mga24AccelInit(pScreen);
+ case 32:
+ return Mga32AccelInit(pScreen);
+ }
+ return FALSE;
+}
+
+
+
+void
+MGAStormSync(ScrnInfoPtr pScrn)
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ CHECK_DMA_QUIESCENT(pMga, pScrn);
+
+ while(MGAISBUSY());
+ /* flush cache before a read (mga-1064g 5.1.6) */
+ OUTREG8(MGAREG_CRTC_INDEX, 0);
+ if(pMga->AccelFlags & CLIPPER_ON) {
+ pMga->AccelFlags &= ~CLIPPER_ON;
+ OUTREG(MGAREG_CXBNDRY, 0xFFFF0000);
+ }
+}
+
+void
+MGAStormEngineInit(ScrnInfoPtr pScrn)
+{
+ long maccess = 0;
+ MGAPtr pMga = MGAPTR(pScrn);
+ MGAFBLayout *pLayout = &pMga->CurrentLayout;
+ CARD32 opmode;
+
+ CHECK_DMA_QUIESCENT(pMga, pScrn);
+
+ if ((pMga->Chipset == PCI_CHIP_MGAG100)
+ || (pMga->Chipset == PCI_CHIP_MGAG100_PCI))
+ maccess = 1 << 14;
+
+ opmode = INREG(MGAREG_OPMODE);
+
+ switch( pLayout->bitsPerPixel )
+ {
+ case 8:
+ pMga->RestoreAccelState = Mga8RestoreAccelState;
+ break;
+ case 16:
+ maccess |= 1;
+ if(pLayout->depth == 15)
+ maccess |= (1 << 31);
+ Mga16InitSolidFillRectFuncs(pMga);
+ pMga->RestoreAccelState = Mga16RestoreAccelState;
+ opmode |= 0x10000;
+ break;
+ case 24:
+ maccess |= 3;
+ Mga24InitSolidFillRectFuncs(pMga);
+ pMga->RestoreAccelState = Mga24RestoreAccelState;
+ opmode |= 0x20000;
+ break;
+ case 32:
+ maccess |= 2;
+ Mga32InitSolidFillRectFuncs(pMga);
+ pMga->RestoreAccelState = Mga32RestoreAccelState;
+ opmode |= 0x20000;
+ break;
+ }
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ opmode &= ~0x30000;
+#endif
+
+ pMga->fifoCount = 0;
+
+ while(MGAISBUSY());
+
+ if(!pMga->FifoSize) {
+ pMga->FifoSize = INREG8(MGAREG_FIFOSTATUS);
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%i DWORD fifo\n",
+ pMga->FifoSize);
+ }
+
+ OUTREG(MGAREG_PITCH, pLayout->displayWidth);
+ OUTREG(MGAREG_YDSTORG, pMga->YDstOrg);
+ OUTREG(MGAREG_MACCESS, maccess);
+ pMga->MAccess = maccess;
+ pMga->PlaneMask = ~0;
+ /* looks like this doesn't apply to mga g100 pci */
+
+ if ((pMga->Chipset != PCI_CHIP_MGAG100)
+ && (pMga->Chipset != PCI_CHIP_MGAG100_PCI))
+ OUTREG(MGAREG_PLNWT, pMga->PlaneMask);
+
+ pMga->FgColor = 0;
+ OUTREG(MGAREG_FCOL, pMga->FgColor);
+ pMga->BgColor = 0;
+ OUTREG(MGAREG_BCOL, pMga->BgColor);
+ OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT | opmode);
+
+ /* put clipping in a known state */
+ OUTREG(MGAREG_CXBNDRY, 0xFFFF0000); /* (maxX << 16) | minX */
+ OUTREG(MGAREG_YTOP, 0x00000000); /* minPixelPointer */
+ OUTREG(MGAREG_YBOT, 0x007FFFFF); /* maxPixelPointer */
+ pMga->AccelFlags &= ~CLIPPER_ON;
+
+ switch(pMga->Chipset) {
+ case PCI_CHIP_MGAG550:
+ case PCI_CHIP_MGAG400:
+ case PCI_CHIP_MGAG200:
+ case PCI_CHIP_MGAG200_PCI:
+ pMga->SrcOrg = 0;
+ OUTREG(MGAREG_SRCORG, pMga->realSrcOrg);
+ OUTREG(MGAREG_DSTORG, pMga->DstOrg);
+ break;
+ default:
+ break;
+ }
+ xf86SetLastScrnFlag(pScrn->entityList[0], pScrn->scrnIndex);
+
+}
+
+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;
+}
+
+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;
+}
+
+#endif
+
+
+ /*********************************************\
+ | Screen-to-Screen Copy |
+ \*********************************************/
+
+#define BLIT_LEFT 1
+#define BLIT_UP 4
+
+void
+MGANAME(SetupForScreenToScreenCopy)(
+ ScrnInfoPtr pScrn,
+ int xdir, int ydir,
+ int rop,
+ unsigned int planemask,
+ int trans
+){
+ MGAPtr pMga = MGAPTR(pScrn);
+ CARD32 dwgctl = pMga->AtypeNoBLK[rop] | MGADWG_SHIFTZERO |
+ MGADWG_BITBLT | MGADWG_BFCOL;
+
+ CHECK_DMA_QUIESCENT(pMga, pScrn);
+
+ pMga->AccelInfoRec->SubsequentScreenToScreenCopy =
+ MGANAME(SubsequentScreenToScreenCopy);
+
+ 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 =
+ MGANAME(SubsequentScreenToScreenCopy_FastBlit);
+
+ if(pMga->DrawTransparent) {
+ dwgctl |= MGADWG_TRANSC;
+ WAITFIFO(2);
+ SET_FOREGROUND(trans);
+ trans = ~0;
+ SET_BACKGROUND(trans);
+ }
+
+ WAITFIFO(4);
+ OUTREG(MGAREG_DWGCTL, dwgctl);
+ OUTREG(MGAREG_SGN, pMga->BltScanDirection);
+ SET_PLANEMASK(planemask);
+ OUTREG(MGAREG_AR5, ydir * pMga->CurrentLayout.displayWidth);
+}
+
+
+static void
+MGANAME(SubsequentScreenToScreenCopy)(
+ 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) {
+ SrcOrg = ((srcY & ~1023) * pMga->CurrentLayout.displayWidth * PSZ) >> 9;
+ DstOrg = ((dstY & ~1023) * pMga->CurrentLayout.displayWidth * PSZ) >> 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) / PSZ;
+ 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);
+ }
+}
+
+
+static void
+MGANAME(SubsequentScreenToScreenCopy_FastBlit)(
+ ScrnInfoPtr pScrn,
+ int srcX, int srcY, int dstX, int dstY, int w, int h
+)
+{
+ int start, end;
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ 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(
+#if PSZ == 32
+ !((srcX ^ dstX) & 31)
+#elif PSZ == 16
+ !((srcX ^ dstX) & 63)
+#else
+ !((srcX ^ dstX) & 127)
+#endif
+ ) {
+ 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;
+#if PSZ == 8
+ if((dstX & (1 << 6)) && (((fxright >> 6) - (dstX >> 6)) & 7) == 7) {
+ fxright |= 1 << 6;
+#elif PSZ == 16
+ if((dstX & (1 << 5)) && (((fxright >> 5) - (dstX >> 5)) & 7) == 7) {
+ fxright |= 1 << 5;
+#elif PSZ == 24
+ if(((dstX * 3) & (1 << 6)) &&
+ ((((fxright * 3 + 2) >> 6) - ((dstX * 3) >> 6)) & 7) == 7) {
+ fxright = ((fxright * 3 + 2) | (1 << 6)) / 3;
+#elif PSZ == 32
+ if((dstX & (1 << 4)) && (((fxright >> 4) - (dstX >> 4)) & 7) == 7) {
+ fxright |= 1 << 4;
+#endif
+ 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;
+ } /* } } } (preserve pairs for pair matching) */
+ }
+
+ 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
+MGANAME(SetupForSolidFill)(
+ ScrnInfoPtr pScrn,
+ int color,
+ int rop,
+ unsigned int planemask )
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ CHECK_DMA_QUIESCENT(pMga, pScrn);
+
+#if PSZ == 24
+ if(!RGBEQUAL(color))
+ pMga->FilledRectCMD = MGADWG_TRAP | MGADWG_SOLID | MGADWG_ARZERO |
+ MGADWG_SGNZERO | MGADWG_SHIFTZERO |
+ MGADWG_BMONOLEF | pMga->AtypeNoBLK[rop];
+ else
+#endif
+ 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);
+ SET_FOREGROUND(color);
+ SET_PLANEMASK(planemask);
+ OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD);
+}
+
+static void
+MGANAME(SubsequentSolidFillRect)(
+ 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);
+}
+
+static void
+MGANAME(SubsequentSolidFillTrap)(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 |
+ \***************/
+
+
+static void
+MGANAME(SubsequentSolidHorVertLine) (
+ 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);
+ }
+}
+
+
+static void
+MGANAME(SubsequentSolidTwoPointLine)(
+ 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 |
+ \***************************/
+
+
+static void
+MGANAME(SetupForMono8x8PatternFill)(
+ ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int fg, int bg,
+ int rop,
+ unsigned int planemask )
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+ XAAInfoRecPtr infoRec = pMga->AccelInfoRec;
+
+ CHECK_DMA_QUIESCENT(pMga, pScrn);
+
+ pMga->PatternRectCMD = MGADWG_TRAP | MGADWG_ARZERO | MGADWG_SGNZERO |
+ MGADWG_BMONOLEF;
+
+ infoRec->SubsequentMono8x8PatternFillRect =
+ MGANAME(SubsequentMono8x8PatternFillRect);
+
+ if(bg == -1) {
+#if PSZ == 24
+ if(!RGBEQUAL(fg))
+ pMga->PatternRectCMD |= MGADWG_TRANSC | pMga->AtypeNoBLK[rop];
+ else
+#endif
+ pMga->PatternRectCMD |= MGADWG_TRANSC | pMga->Atype[rop];
+
+ WAITFIFO(5);
+ } else {
+#if PSZ == 24
+ if((pMga->AccelFlags & BLK_OPAQUE_EXPANSION) && RGBEQUAL(fg) && RGBEQUAL(bg))
+#else
+ if(pMga->AccelFlags & BLK_OPAQUE_EXPANSION)
+#endif
+ pMga->PatternRectCMD |= pMga->Atype[rop];
+ else
+ pMga->PatternRectCMD |= pMga->AtypeNoBLK[rop];
+ WAITFIFO(6);
+ SET_BACKGROUND(bg);
+ }
+
+ SET_FOREGROUND(fg);
+ SET_PLANEMASK(planemask);
+ OUTREG(MGAREG_DWGCTL, pMga->PatternRectCMD);
+ OUTREG(MGAREG_PAT0, patx);
+ OUTREG(MGAREG_PAT1, paty);
+}
+
+
+
+static void
+MGANAME(SubsequentMono8x8PatternFillRect)(
+ 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 =
+ MGANAME(SubsequentMono8x8PatternFillRect_Additional);
+}
+
+static void
+MGANAME(SubsequentMono8x8PatternFillRect_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);
+}
+
+
+static void
+MGANAME(SubsequentMono8x8PatternFillTrap)(
+ 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 |
+ \***********************/
+
+
+static void
+MGANAME(SetupForScanlineCPUToScreenColorExpandFill)(
+ ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop,
+ unsigned int planemask )
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+ CARD32 mgaCMD = MGADWG_ILOAD | MGADWG_LINEAR | MGADWG_SGNZERO |
+ MGADWG_SHIFTZERO | MGADWG_BMONOLEF;
+
+ CHECK_DMA_QUIESCENT(pMga, pScrn);
+
+ if(bg == -1) {
+#if PSZ == 24
+ if(!RGBEQUAL(fg))
+ mgaCMD |= MGADWG_TRANSC | pMga->AtypeNoBLK[rop];
+ else
+#endif
+ mgaCMD |= MGADWG_TRANSC | pMga->Atype[rop];
+
+ WAITFIFO(3);
+ } else {
+#if PSZ == 24
+ if((pMga->AccelFlags & BLK_OPAQUE_EXPANSION) &&
+ RGBEQUAL(fg) && RGBEQUAL(bg))
+#else
+ if(pMga->AccelFlags & BLK_OPAQUE_EXPANSION)
+#endif
+ mgaCMD |= pMga->Atype[rop];
+ else
+ mgaCMD |= pMga->AtypeNoBLK[rop];
+ WAITFIFO(4);
+ SET_BACKGROUND(bg);
+ }
+
+ SET_FOREGROUND(fg);
+ SET_PLANEMASK(planemask);
+ OUTREG(MGAREG_DWGCTL, mgaCMD);
+}
+
+static void
+MGANAME(SubsequentScanlineCPUToScreenColorExpandFill)(
+ 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 =
+ MGANAME(SubsequentColorExpandScanlineIndirect);
+ pMga->AccelInfoRec->ScanlineColorExpandBuffers =
+ (unsigned char**)(&pMga->ScratchBuffer);
+ } else {
+ pMga->AccelInfoRec->SubsequentColorExpandScanline =
+ MGANAME(SubsequentColorExpandScanline);
+ pMga->AccelInfoRec->ScanlineColorExpandBuffers =
+ (unsigned char**)(&pMga->ColorExpandBase);
+ WAITFIFO(pMga->expandDWORDs);
+ }
+}
+
+static void
+MGANAME(SubsequentColorExpandScanlineIndirect)(
+ 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();
+ }
+ }
+}
+
+static void
+MGANAME(SubsequentColorExpandScanline)(
+ 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 |
+ \*******************/
+
+
+static void MGANAME(SetupForScanlineImageWrite)(
+ ScrnInfoPtr pScrn,
+ int rop,
+ unsigned int planemask,
+ int transparency_color,
+ int bpp, int depth
+){
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ CHECK_DMA_QUIESCENT(pMga, pScrn);
+
+ WAITFIFO(3);
+ OUTREG(MGAREG_AR5, 0);
+ SET_PLANEMASK(planemask);
+ OUTREG(MGAREG_DWGCTL, MGADWG_ILOAD | MGADWG_BFCOL | MGADWG_SHIFTZERO |
+ MGADWG_SGNZERO | pMga->AtypeNoBLK[rop]);
+}
+
+
+static void MGANAME(SubsequentScanlineImageWriteRect)(
+ 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 * PSZ) + 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);
+}
+
+static void MGANAME(SubsequentImageWriteScanline)(
+ 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
+MGANAME(SetupForDashedLine)(
+ 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;
+
+ 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(bg);
+ }
+ SET_PLANEMASK(planemask);
+ SET_FOREGROUND(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 PSZ == 24
+ if(!RGBEQUAL(fg))
+ pMga->NiceDashCMD |= MGADWG_TRANSC | pMga->AtypeNoBLK[rop];
+ else
+#endif
+ pMga->NiceDashCMD |= MGADWG_TRANSC | pMga->Atype[rop];
+ } else {
+#if PSZ == 24
+ if((pMga->AccelFlags & BLK_OPAQUE_EXPANSION) &&
+ RGBEQUAL(fg) && RGBEQUAL(bg))
+#else
+ if(pMga->AccelFlags & BLK_OPAQUE_EXPANSION)
+#endif
+ 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
+MGANAME(SubsequentDashedTwoPointLine)(
+ 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 */
+
+#if PSZ != 24
+
+ /******************************************\
+ | Planar Screen to Screen Color Expansion |
+ \******************************************/
+
+static void
+MGANAME(SetupForPlanarScreenToScreenColorExpandFill)(
+ 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;
+
+ CHECK_DMA_QUIESCENT(pMga, pScrn);
+
+ if(bg == -1) {
+ mgaCMD |= MGADWG_TRANSC;
+ WAITFIFO(4);
+ } else {
+ WAITFIFO(5);
+ SET_BACKGROUND(bg);
+ }
+
+ SET_FOREGROUND(fg);
+ SET_PLANEMASK(planemask);
+ OUTREG(MGAREG_AR5, pScrn->displayWidth);
+ OUTREG(MGAREG_DWGCTL, mgaCMD);
+}
+
+static void
+MGANAME(SubsequentPlanarScreenToScreenColorExpandFill)(
+ 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);
+}
+
+#endif
+
+ /***********************************\
+ | Screen to Screen Color Expansion |
+ \***********************************/
+
+static void
+MGANAME(SetupForScreenToScreenColorExpandFill)(
+ ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop,
+ unsigned int planemask
+){
+ MGAPtr pMga = MGAPTR(pScrn);
+ CARD32 mgaCMD = MGADWG_BITBLT | MGADWG_SGNZERO | MGADWG_SHIFTZERO;
+
+ CHECK_DMA_QUIESCENT(pMga, pScrn);
+
+ if(bg == -1) {
+#if PSZ == 24
+ if(!RGBEQUAL(fg))
+ mgaCMD |= MGADWG_TRANSC | pMga->AtypeNoBLK[rop];
+ else
+#endif
+ mgaCMD |= MGADWG_TRANSC | pMga->Atype[rop];
+
+ WAITFIFO(4);
+ } else {
+#if PSZ == 24
+ if((pMga->AccelFlags & BLK_OPAQUE_EXPANSION) &&
+ RGBEQUAL(fg) && RGBEQUAL(bg))
+#else
+ if((pMga->AccelFlags & BLK_OPAQUE_EXPANSION))
+#endif
+ mgaCMD |= pMga->Atype[rop];
+ else
+ mgaCMD |= pMga->AtypeNoBLK[rop];
+ WAITFIFO(5);
+ SET_BACKGROUND(bg);
+ }
+
+ SET_FOREGROUND(fg);
+ SET_PLANEMASK(planemask);
+ OUTREG(MGAREG_AR5, pScrn->displayWidth * PSZ);
+ OUTREG(MGAREG_DWGCTL, mgaCMD);
+
+}
+
+static void
+MGANAME(SubsequentScreenToScreenColorExpandFill)(
+ ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ int srcx, int srcy,
+ int skipleft
+){
+ MGAPtr pMga = MGAPTR(pScrn);
+ int pitch = pScrn->displayWidth * PSZ;
+ int start, end, next, num;
+ Bool resetDstOrg = FALSE;
+
+ if (pMga->AccelFlags & LARGE_ADDRESSES) {
+ int DstOrg = ((y & ~1023) * pScrn->displayWidth * PSZ) >> 9;
+ int SrcOrg = ((srcy & ~1023) * pScrn->displayWidth * PSZ) >> 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) * PSZ) + skipleft;
+ end = start + w + (pitch * (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 += pitch;
+ h--; y++;
+ } else {
+ num = ((next - start - w)/pitch) + 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 * pitch;
+ h -= num; y += num;
+ }
+ }
+ }
+
+ if(resetDstOrg) {
+ WAITFIFO(1);
+ OUTREG(MGAREG_DSTORG, pMga->DstOrg);
+ }
+}
+
+
+
+#if PSZ == 8
+
+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);
+}
+
+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 */
+ }
+}
+
+
+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);
+}
+
+
+void
+MGAValidatePolyArc(
+ GCPtr pGC,
+ unsigned long changes,
+ DrawablePtr pDraw
+){
+ ScrnInfoPtr pScrn = xf86Screens[pGC->pScreen->myNum];
+ 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;
+
+ if(!numRects) return;
+
+ if(numRects != 1) {
+ XAAFallbackOps.PolyPoint(pDraw, pGC, mode, npt, ppt);
+ return;
+ }
+
+ infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
+ pMga = MGAPTR(infoRec->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);
+}
+
+
+void
+MGAValidatePolyPoint(
+ GCPtr pGC,
+ unsigned long changes,
+ DrawablePtr pDraw
+){
+ ScrnInfoPtr pScrn = xf86Screens[pGC->pScreen->myNum];
+ MGAPtr pMga = MGAPTR(pScrn);
+ Bool fullPlanemask = TRUE;
+
+ pGC->ops->PolyPoint = XAAFallbackOps.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;
+}
+
+
+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
+
+#ifdef XF86DRI
+void
+MGANAME(DRIInitBuffers)(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);
+
+ MGANAME(SetupForSolidFill)(pScrn, 0, GXcopy, -1);
+ while (nbox--) {
+ MGASelectBuffer(pScrn, MGA_BACK);
+ MGANAME(SubsequentSolidFillRect)(pScrn, pbox->x1, pbox->y1,
+ pbox->x2-pbox->x1, pbox->y2-pbox->y1);
+ MGASelectBuffer(pScrn, MGA_DEPTH);
+ MGANAME(SubsequentSolidFillRect)(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
+MGANAME(DRIMoveBuffers)(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;
+ }
+
+ MGANAME(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);
+ MGANAME(SubsequentScreenToScreenCopy)(pScrn, x1, y1,
+ destx,desty, w, h);
+ MGASelectBuffer(pScrn, MGA_DEPTH);
+ MGANAME(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 /* XF86DRI */