mga_storm.c revision a31a186a
1#define PSZ 8
2
3#ifdef HAVE_CONFIG_H
4#include "config.h"
5#endif
6
7/* All drivers should typically include these */
8#include "xf86.h"
9#include "xf86_OSproc.h"
10
11/* For correct __inline__ usage */
12#include "compiler.h"
13
14/* Drivers that need to access the PCI config space directly need this */
15#include "xf86Pci.h"
16
17/* Drivers for PCI hardware need this */
18#include "xf86PciInfo.h"
19
20/* Drivers that use XAA need this */
21#include "xaa.h"
22#include "xaalocal.h"
23#include "xf86fbman.h"
24#include "miline.h"
25#include "servermd.h"
26
27#ifdef XF86DRI
28#include "GL/glxtokens.h"
29#endif
30
31#include "mga.h"
32#include "mga_reg.h"
33#include "mga_macros.h"
34
35#ifdef XF86DRI
36#include "mga_dri.h"
37#endif
38
39#define REPLICATE_8(r)  (((r) & 0x0ff) | (((r) & 0x0ff) << 8) \
40			 | (((r) & 0x0ff) << 16) | (((r) & 0x0ff) << 24))
41#define REPLICATE_16(r) (((r) & 0x0000ffff) | (((r) & 0x0000ffff) << 16))
42#define REPLICATE_24(r) (((r) & 0x00ffffff) | (((r) & 0x00ffffff) << 24))
43#define REPLICATE_32(r) (r)
44
45
46#define SET_FOREGROUND_REPLICATED(c, rep_c) \
47	if((c) != pMga->FgColor) { \
48	   pMga->FgColor = (c); \
49	   OUTREG(MGAREG_FCOL,(rep_c)); \
50	}
51
52#define SET_BACKGROUND_REPLICATED(c, rep_c) \
53	if((c) != pMga->BgColor) { \
54	   pMga->BgColor = (c); \
55	   OUTREG(MGAREG_BCOL,(rep_c)); \
56	}
57
58
59#define MGAMoveDWORDS(d,s,c) \
60do { \
61  write_mem_barrier(); \
62  XAAMoveDWORDS((d),(s),(c)); \
63} while (0)
64
65static void mgaSetupForSolidFill( ScrnInfoPtr pScrn, int color,
66    int rop, unsigned int planemask );
67
68static void mgaSetupForScreenToScreenCopy( ScrnInfoPtr pScrn,
69    int xdir, int ydir, int rop, unsigned int planemask, int trans );
70
71static void mgaSubsequentScreenToScreenCopy( ScrnInfoPtr pScrn,
72    int srcX, int srcY, int dstX, int dstY, int w, int h );
73
74static void mgaSubsequentScreenToScreenCopy_FastBlit( ScrnInfoPtr pScrn,
75    int srcX, int srcY, int dstX, int dstY, int w, int h );
76
77static void mgaSetupForScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn,
78    int fg, int bg, int rop, unsigned int planemask );
79
80static void mgaSubsequentScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn,
81    int x, int y, int w, int h, int skipleft );
82
83static void mgaSubsequentColorExpandScanline( ScrnInfoPtr pScrn, int bufno );
84
85static void mgaSubsequentColorExpandScanlineIndirect( ScrnInfoPtr pScrn,
86    int bufno );
87
88static void mgaSubsequentSolidFillRect( ScrnInfoPtr pScrn, int x, int y,
89    int w, int h );
90
91static void mgaSubsequentSolidFillTrap( ScrnInfoPtr pScrn, int y, int h,
92    int left, int dxL, int dyL, int eL,	int right, int dxR, int dyR, int eR );
93
94static void mgaSubsequentSolidHorVertLine( ScrnInfoPtr pScrn, int x, int y,
95    int len, int dir );
96
97static void mgaSubsequentSolidTwoPointLine( ScrnInfoPtr pScrn,	int x1, int y1,
98    int x2, int y2, int flags );
99
100static void mgaSetupForMono8x8PatternFill( ScrnInfoPtr pScrn,
101    int patx, int paty, int fg, int bg, int rop, unsigned int planemask );
102
103static void mgaSubsequentMono8x8PatternFillRect( ScrnInfoPtr pScrn,
104    int patx, int paty,	int x, int y, int w, int h );
105
106static void mgaSubsequentMono8x8PatternFillRect_Additional( ScrnInfoPtr pScrn,
107    int patx, int paty, int x, int y, int w, int h );
108
109static void mgaSubsequentMono8x8PatternFillTrap( ScrnInfoPtr pScrn,
110    int patx, int paty, int y, int h, int left, int dxL, int dyL, int eL,
111    int right, int dxR, int dyR, int eR );
112
113static void mgaSetupForScanlineImageWrite( ScrnInfoPtr pScrn, int rop,
114    unsigned int planemask, int transparency_color, int bpp, int depth );
115
116static void mgaSubsequentScanlineImageWriteRect( ScrnInfoPtr pScrn,
117    int x, int y, int w, int h, int skipleft );
118
119static void mgaSubsequentImageWriteScanline( ScrnInfoPtr pScrn, int num );
120
121static void mgaSetupForPlanarScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
122    int fg, int bg, int rop, unsigned int planemask );
123
124static void mgaSubsequentPlanarScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
125    int x, int y, int w, int h,	int srcx, int srcy, int skipleft );
126
127static void mgaSetupForScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
128    int fg, int bg, int rop, unsigned int planemask );
129
130static void mgaSubsequentScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
131    int x, int y, int w, int h, int srcx, int srcy, int skipleft );
132
133#if X_BYTE_ORDER == X_LITTLE_ENDIAN
134static void mgaSetupForDashedLine( ScrnInfoPtr pScrn, int fg, int bg,
135    int rop, unsigned int planemask, int length, unsigned char *pattern );
136
137static void mgaSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn,
138    int x1, int y1, int x2, int y2, int flags, int phase );
139#endif
140
141static void mgaRestoreAccelState( ScrnInfoPtr pScrn );
142
143static void MGASetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1,
144				int x2, int y2);
145static void MGADisableClipping(ScrnInfoPtr pScrn);
146static void MGAFillSolidRectsDMA(ScrnInfoPtr pScrn, int fg, int rop,
147				unsigned int planemask, int nBox, BoxPtr pBox);
148static void MGAFillSolidSpansDMA(ScrnInfoPtr pScrn, int fg, int rop,
149				unsigned int planemask, int n, DDXPointPtr ppt,
150 				int *pwidth, int fSorted);
151static void MGAFillMono8x8PatternRectsTwoPass(ScrnInfoPtr pScrn, int fg, int bg,
152 				int rop, unsigned int planemask, int nBox,
153 				BoxPtr pBox, int pattern0, int pattern1,
154				int xorigin, int yorigin);
155static void MGAValidatePolyArc(GCPtr, unsigned long, DrawablePtr);
156static void MGAValidatePolyPoint(GCPtr, unsigned long, DrawablePtr);
157static void MGAFillCacheBltRects(ScrnInfoPtr, int, unsigned int, int, BoxPtr,
158				int, int, XAACacheInfoPtr);
159
160
161static __inline__ void
162common_replicate_colors_and_mask( unsigned int fg, unsigned int bg,
163				  unsigned int pm,
164				  unsigned int bpp,
165				  unsigned int * rep_fg,
166				  unsigned int * rep_bg,
167				  unsigned int * rep_pm )
168{
169    switch( bpp ) {
170    case 8:
171	*rep_fg = REPLICATE_8( fg );
172	*rep_bg = REPLICATE_8( bg );
173	*rep_pm = REPLICATE_8( pm );
174	break;
175    case 16:
176	*rep_fg = REPLICATE_16( fg );
177	*rep_bg = REPLICATE_16( bg );
178	*rep_pm = REPLICATE_16( pm );
179	break;
180    case 24:
181	*rep_fg = REPLICATE_24( fg );
182	*rep_bg = REPLICATE_24( bg );
183	*rep_pm = REPLICATE_24( pm );
184	break;
185    case 32:
186	*rep_fg = REPLICATE_32( fg );
187	*rep_bg = REPLICATE_32( bg );
188	*rep_pm = REPLICATE_32( pm );
189	break;
190    }
191}
192
193
194#ifdef RENDER
195
196static Bool MGASetupForCPUToScreenAlphaTexture(ScrnInfoPtr pScrn, int op,
197    CARD16 red, CARD16 green, CARD16 blue, CARD16 alpha, int alphaType,
198    CARD8 *alphaPtr, int alphaPitch, int width, int height, int flags);
199
200static Bool MGASetupForCPUToScreenAlphaTextureFaked(ScrnInfoPtr Scrn, int op,
201    CARD16 red, CARD16 green, CARD16 blue, CARD16 alpha, int alphaType,
202    CARD8 *alphaPtr, int alphaPitch, int width, int height, int flags);
203
204static Bool MGASetupForCPUToScreenTexture(ScrnInfoPtr pScrn, int op,
205    int texType, CARD8 *texPtr, int texPitch, int width, int height,
206    int flags);
207
208static void MGASubsequentCPUToScreenTexture(ScrnInfoPtr pScrn, int dstx,
209    int dsty, int srcx, int srcy, int width, int height);
210
211#include "mipict.h"
212#include "dixstruct.h"
213
214static CARD32 MGAAlphaTextureFormats[2] = {PICT_a8, 0};
215static CARD32 MGATextureFormats[2] = {PICT_a8r8g8b8, 0};
216
217static void
218RemoveLinear (FBLinearPtr linear)
219{
220   MGAPtr pMga = (MGAPtr)(linear->devPrivate.ptr);
221
222   pMga->LinearScratch = NULL;  /* just lost our scratch */
223}
224
225static void
226RenderCallback (ScrnInfoPtr pScrn)
227{
228    MGAPtr pMga = MGAPTR(pScrn);
229
230    if((currentTime.milliseconds > pMga->RenderTime) && pMga->LinearScratch) {
231	xf86FreeOffscreenLinear(pMga->LinearScratch);
232	pMga->LinearScratch = NULL;
233    }
234
235    if(!pMga->LinearScratch)
236	pMga->RenderCallback = NULL;
237}
238
239#define RENDER_DELAY	15000
240
241static Bool
242AllocateLinear (
243   ScrnInfoPtr pScrn,
244   int sizeNeeded
245){
246   MGAPtr pMga = MGAPTR(pScrn);
247
248   pMga->RenderTime = currentTime.milliseconds + RENDER_DELAY;
249   pMga->RenderCallback = RenderCallback;
250
251   if(pMga->LinearScratch) {
252	if(pMga->LinearScratch->size >= sizeNeeded)
253	   return TRUE;
254	else {
255	   if(xf86ResizeOffscreenLinear(pMga->LinearScratch, sizeNeeded))
256		return TRUE;
257
258	   xf86FreeOffscreenLinear(pMga->LinearScratch);
259	   pMga->LinearScratch = NULL;
260	}
261   }
262
263   pMga->LinearScratch = xf86AllocateOffscreenLinear(
264				pScrn->pScreen, sizeNeeded, 32,
265				NULL, RemoveLinear, pMga);
266
267   return (pMga->LinearScratch != NULL);
268}
269
270static int
271GetPowerOfTwo(int w)
272{
273    int Pof2 = 0;
274    int i = 12;
275
276    while(--i) {
277        if(w & (1 << i)) {
278            Pof2 = i;
279            if(w & ((1 << i) - 1))
280                Pof2++;
281            break;
282        }
283    }
284    return Pof2;
285}
286
287
288static int tex_padw, tex_padh;
289
290Bool MGASetupForCPUToScreenAlphaTextureFaked( ScrnInfoPtr pScrn, int op,
291					      CARD16 red, CARD16 green,
292					      CARD16 blue, CARD16 alpha,
293					      int alphaType, CARD8 *alphaPtr,
294					      int alphaPitch, int width,
295					      int height, int flags )
296{
297    int log2w, log2h, pitch, sizeNeeded, offset;
298    unsigned int texctl, dwgctl, alphactrl;
299    MGAPtr pMga = MGAPTR(pScrn);
300
301    if(op != PictOpOver)  /* only one tested */
302	return FALSE;
303
304    if((width > 2048) || (height > 2048))
305	return FALSE;
306
307    log2w = GetPowerOfTwo(width);
308    log2h = GetPowerOfTwo(height);
309
310    CHECK_DMA_QUIESCENT(pMga, pScrn);
311
312    pitch = (width + 15) & ~15;
313    sizeNeeded = pitch * height;
314    if(pScrn->bitsPerPixel == 16)
315	sizeNeeded <<= 1;
316
317    if(!AllocateLinear(pScrn, sizeNeeded))
318	return FALSE;
319
320    offset = pMga->LinearScratch->offset << 1;
321    if(pScrn->bitsPerPixel == 32)
322        offset <<= 1;
323
324    if(pMga->AccelInfoRec->NeedToSync)
325	MGAStormSync(pScrn);
326
327    XAA_888_plus_PICT_a8_to_8888(
328	(blue >> 8) | (green & 0xff00) | ((red & 0xff00) << 8),
329	alphaPtr, alphaPitch, (CARD32*)(pMga->FbStart + offset),
330        pitch, width, height);
331
332    tex_padw = 1 << log2w;
333    tex_padh = 1 << log2h;
334
335    WAITFIFO(15);
336    OUTREG(MGAREG_TMR0, (1 << 20) / tex_padw);  /* sx inc */
337    OUTREG(MGAREG_TMR1, 0);  /* sy inc */
338    OUTREG(MGAREG_TMR2, 0);  /* tx inc */
339    OUTREG(MGAREG_TMR3, (1 << 20) / tex_padh);  /* ty inc */
340    OUTREG(MGAREG_TMR4, 0x00000000);
341    OUTREG(MGAREG_TMR5, 0x00000000);
342    OUTREG(MGAREG_TMR8, 0x00010000);
343    OUTREG(MGAREG_TEXORG, offset);
344    OUTREG(MGAREG_TEXWIDTH,  log2w | (((8 - log2w) & 63) << 9) |
345                                ((width - 1) << 18));
346    OUTREG(MGAREG_TEXHEIGHT, log2h | (((8 - log2h) & 63) << 9) |
347                                ((height - 1) << 18));
348
349    texctl = MGA_TW32 | MGA_PITCHLIN | MGA_TAKEY | MGA_CLAMPUV |
350             ((pitch & 0x07FF) << 9);
351    dwgctl = MGADWG_TEXTURE_TRAP | MGADWG_I | MGADWG_ARZERO |
352             MGADWG_SGNZERO | MGADWG_SHIFTZERO | 0xc0000;
353    alphactrl = MGA_SRC_ALPHA | MGA_DST_ONE_MINUS_SRC_ALPHA |
354                MGA_ALPHACHANNEL;
355
356    OUTREG(MGAREG_TEXCTL, texctl);
357    OUTREG(MGAREG_TEXCTL2, MGA_TC2_DECALDIS | MGA_TC2_CKSTRANSDIS);
358    OUTREG(MGAREG_DWGCTL, dwgctl);
359    OUTREG(MGAREG_TEXFILTER, ((0x1e << 20) | MGA_MAG_BILIN));
360    OUTREG(MGAREG_ALPHACTRL, alphactrl);
361
362    return TRUE;
363}
364
365Bool
366MGASetupForCPUToScreenAlphaTexture (
367   ScrnInfoPtr	pScrn,
368   int		op,
369   CARD16	red,
370   CARD16	green,
371   CARD16	blue,
372   CARD16	alpha,
373   int		alphaType,
374   CARD8	*alphaPtr,
375   int		alphaPitch,
376   int		width,
377   int		height,
378   int		flags
379){
380    int log2w, log2h, i, pitch, sizeNeeded, offset;
381    unsigned int texctl, dwgctl, alphactrl;
382    CARD8 *dst;
383    MGAPtr pMga = MGAPTR(pScrn);
384
385    if(op != PictOpOver)  /* only one tested */
386	return FALSE;
387
388    if((width > 2048) || (height > 2048))
389	return FALSE;
390
391    log2w = GetPowerOfTwo(width);
392    log2h = GetPowerOfTwo(height);
393
394    CHECK_DMA_QUIESCENT(pMga, pScrn);
395
396    pitch = (width + 15) & ~15;
397    sizeNeeded = (pitch * height) >> 1;
398    if(pScrn->bitsPerPixel == 32)
399	sizeNeeded >>= 1;
400
401    if(!AllocateLinear(pScrn, sizeNeeded))
402	return FALSE;
403
404    offset = pMga->LinearScratch->offset << 1;
405    if(pScrn->bitsPerPixel == 32)
406        offset <<= 1;
407
408    if(pMga->AccelInfoRec->NeedToSync)
409	MGAStormSync(pScrn);
410
411    i = height;
412    dst = pMga->FbStart + offset;
413    while(i--) {
414	memcpy(dst, alphaPtr, width);
415	dst += pitch;
416	alphaPtr += alphaPitch;
417    }
418
419    tex_padw = 1 << log2w;
420    tex_padh = 1 << log2h;
421
422
423    WAITFIFO(12);
424    OUTREG(MGAREG_DR4, red << 7);  /* red start */
425    OUTREG(MGAREG_DR6, 0);
426    OUTREG(MGAREG_DR7, 0);
427    OUTREG(MGAREG_DR8, green << 7);  /* green start */
428    OUTREG(MGAREG_DR10, 0);
429    OUTREG(MGAREG_DR11, 0);
430    OUTREG(MGAREG_DR12, blue << 7);  /* blue start */
431    OUTREG(MGAREG_DR14, 0);
432    OUTREG(MGAREG_DR15, 0);
433    OUTREG(MGAREG_ALPHASTART, alpha << 7);  /* alpha start */
434    OUTREG(MGAREG_ALPHAXINC, 0);
435    OUTREG(MGAREG_ALPHAYINC, 0);
436
437    WAITFIFO(15);
438    OUTREG(MGAREG_TMR0, (1 << 20) / tex_padw);  /* sx inc */
439    OUTREG(MGAREG_TMR1, 0);  /* sy inc */
440    OUTREG(MGAREG_TMR2, 0);  /* tx inc */
441    OUTREG(MGAREG_TMR3, (1 << 20) / tex_padh);  /* ty inc */
442    OUTREG(MGAREG_TMR4, 0x00000000);
443    OUTREG(MGAREG_TMR5, 0x00000000);
444    OUTREG(MGAREG_TMR8, 0x00010000);
445    OUTREG(MGAREG_TEXORG, offset);
446    OUTREG(MGAREG_TEXWIDTH,  log2w | (((8 - log2w) & 63) << 9) |
447                                ((width - 1) << 18));
448    OUTREG(MGAREG_TEXHEIGHT, log2h | (((8 - log2h) & 63) << 9) |
449                                ((height - 1) << 18));
450
451    texctl = MGA_TW8A | MGA_PITCHLIN | MGA_TAKEY | MGA_CLAMPUV |
452             MGA_TEXMODULATE |
453             ((pitch & 0x07FF) << 9);
454    dwgctl = MGADWG_TEXTURE_TRAP | MGADWG_I | MGADWG_ARZERO |
455             MGADWG_SGNZERO | MGADWG_SHIFTZERO | 0xc0000;
456    alphactrl = MGA_SRC_ONE | MGA_DST_ONE_MINUS_SRC_ALPHA |
457                MGA_ALPHACHANNEL | MGA_MODULATEDALPHA;
458
459    OUTREG(MGAREG_TEXCTL, texctl);
460    OUTREG(MGAREG_TEXCTL2, MGA_TC2_DECALDIS | MGA_TC2_CKSTRANSDIS);
461    OUTREG(MGAREG_DWGCTL, dwgctl);
462    OUTREG(MGAREG_TEXFILTER, ((0x1e << 20) | MGA_MAG_BILIN));
463    OUTREG(MGAREG_ALPHACTRL, alphactrl);
464
465    return TRUE;
466}
467
468
469Bool
470MGASetupForCPUToScreenTexture (
471   ScrnInfoPtr	pScrn,
472   int		op,
473   int		texType,
474   CARD8	*texPtr,
475   int		texPitch,
476   int		width,
477   int		height,
478   int		flags
479){
480    int log2w, log2h, i, pitch, sizeNeeded, offset;
481    unsigned int texctl, dwgctl, alphactrl;
482    MGAPtr pMga = MGAPTR(pScrn);
483
484    if(op != PictOpOver)  /* only one tested */
485	return FALSE;
486
487    if((width > 2048) || (height > 2048))
488	return FALSE;
489
490    log2w = GetPowerOfTwo(width);
491    log2h = GetPowerOfTwo(height);
492
493    CHECK_DMA_QUIESCENT(pMga, pScrn);
494
495    pitch = (width + 15) & ~15;
496    sizeNeeded = pitch * height;
497    if(pScrn->bitsPerPixel == 16)
498	sizeNeeded <<= 1;
499
500    if(!AllocateLinear(pScrn, sizeNeeded))
501	return FALSE;
502
503    offset = pMga->LinearScratch->offset << 1;
504    if(pScrn->bitsPerPixel == 32)
505        offset <<= 1;
506
507    if(pMga->AccelInfoRec->NeedToSync)
508	MGAStormSync(pScrn);
509
510    {
511	CARD8 *dst = (CARD8*)(pMga->FbStart + offset);
512	i = height;
513	while(i--) {
514            memcpy(dst, texPtr, width << 2);
515	    texPtr += texPitch;
516	    dst += pitch << 2;
517	}
518    }
519
520    tex_padw = 1 << log2w;
521    tex_padh = 1 << log2h;
522
523    WAITFIFO(15);
524    OUTREG(MGAREG_TMR0, (1 << 20) / tex_padw);  /* sx inc */
525    OUTREG(MGAREG_TMR1, 0);  /* sy inc */
526    OUTREG(MGAREG_TMR2, 0);  /* tx inc */
527    OUTREG(MGAREG_TMR3, (1 << 20) / tex_padh);  /* ty inc */
528    OUTREG(MGAREG_TMR4, 0x00000000);
529    OUTREG(MGAREG_TMR5, 0x00000000);
530    OUTREG(MGAREG_TMR8, 0x00010000);
531    OUTREG(MGAREG_TEXORG, offset);
532    OUTREG(MGAREG_TEXWIDTH,  log2w | (((8 - log2w) & 63) << 9) |
533                                ((width - 1) << 18));
534    OUTREG(MGAREG_TEXHEIGHT, log2h | (((8 - log2h) & 63) << 9) |
535                                ((height - 1) << 18));
536
537    texctl = MGA_TW32 | MGA_PITCHLIN | MGA_TAKEY | MGA_CLAMPUV |
538             ((pitch & 0x07FF) << 9);
539    dwgctl = MGADWG_TEXTURE_TRAP | MGADWG_I | MGADWG_ARZERO |
540             MGADWG_SGNZERO | MGADWG_SHIFTZERO | 0xc0000;
541    alphactrl = MGA_SRC_ONE | MGA_DST_ONE_MINUS_SRC_ALPHA |
542                MGA_ALPHACHANNEL;
543
544    OUTREG(MGAREG_TEXCTL, texctl);
545    OUTREG(MGAREG_TEXCTL2, MGA_TC2_DECALDIS | MGA_TC2_CKSTRANSDIS);
546    OUTREG(MGAREG_DWGCTL, dwgctl);
547    OUTREG(MGAREG_TEXFILTER, ((0x1e << 20) | MGA_MAG_BILIN));
548    OUTREG(MGAREG_ALPHACTRL, alphactrl);
549
550    return TRUE;
551}
552void
553MGASubsequentCPUToScreenTexture (
554    ScrnInfoPtr	pScrn,
555    int		dstx,
556    int		dsty,
557    int		srcx,
558    int		srcy,
559    int		width,
560    int		height
561){
562    MGAPtr pMga = MGAPTR(pScrn);
563
564    WAITFIFO(4);
565    OUTREG(MGAREG_TMR6, (srcx << 20) / tex_padw);
566    OUTREG(MGAREG_TMR7, (srcy << 20) / tex_padh);
567    OUTREG(MGAREG_FXBNDRY, ((dstx + width) << 16) | (dstx & 0xffff));
568    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dsty << 16) | height);
569
570    pMga->AccelInfoRec->NeedToSync = TRUE;
571}
572
573
574#endif /* defined(RENDER) */
575
576Bool mgaAccelInit( ScreenPtr pScreen )
577{
578    XAAInfoRecPtr infoPtr;
579    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
580    MGAPtr pMga = MGAPTR(pScrn);
581    int maxFastBlitMem, maxlines;
582    Bool doRender = FALSE;
583    BoxRec AvailFBArea;
584    int i;
585
586    pMga->ScratchBuffer = xalloc(((pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel) + 127) >> 3);
587    if(!pMga->ScratchBuffer) return FALSE;
588
589    pMga->AccelInfoRec = infoPtr = XAACreateInfoRec();
590    if(!infoPtr) return FALSE;
591
592    pMga->RenderTime = 0;
593    pMga->LinearScratch = 0;
594
595    pMga->MaxFastBlitY = 0;
596    pMga->MaxBlitDWORDS = 0x40000 >> 5;
597
598
599    /* Set initial acceleration flags.
600     */
601    pMga->AccelFlags = pMga->chip_attribs->accel_flags;
602
603    if ((pMga->FbMapSize > 8*1024*1024) && (pScrn->depth == 8)) {
604	pMga->AccelFlags |= LARGE_ADDRESSES;
605    }
606
607    if (pMga->CurrentLayout.bitsPerPixel == 24) {
608	pMga->AccelFlags |= MGA_NO_PLANEMASK;
609    }
610
611    if (pMga->SecondCrtc) {
612	pMga->HasFBitBlt = FALSE;
613    }
614
615    if(pMga->HasSDRAM) {
616	pMga->Atype = pMga->AtypeNoBLK = MGAAtypeNoBLK;
617	pMga->AccelFlags &= ~TWO_PASS_COLOR_EXPAND;
618    } else {
619	pMga->Atype = MGAAtype;
620	pMga->AtypeNoBLK = MGAAtypeNoBLK;
621    }
622
623    /* fill out infoPtr here */
624    infoPtr->Flags = 	PIXMAP_CACHE |
625			OFFSCREEN_PIXMAPS |
626			LINEAR_FRAMEBUFFER |
627			MICROSOFT_ZERO_LINE_BIAS;
628
629    /* sync */
630    infoPtr->Sync = MGAStormSync;
631
632    /* screen to screen copy */
633    infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
634    infoPtr->SetupForScreenToScreenCopy =
635        	mgaSetupForScreenToScreenCopy;
636    infoPtr->SubsequentScreenToScreenCopy = mgaSubsequentScreenToScreenCopy;
637
638    if(pMga->HasFBitBlt) {
639	infoPtr->FillCacheBltRects = MGAFillCacheBltRects;
640	infoPtr->FillCacheBltRectsFlags = NO_TRANSPARENCY;
641    }
642    /* solid fills */
643    infoPtr->SetupForSolidFill = mgaSetupForSolidFill;
644    infoPtr->SubsequentSolidFillRect = mgaSubsequentSolidFillRect;
645    infoPtr->SubsequentSolidFillTrap = mgaSubsequentSolidFillTrap;
646
647    /* solid lines */
648    infoPtr->SetupForSolidLine = infoPtr->SetupForSolidFill;
649    infoPtr->SubsequentSolidHorVertLine = mgaSubsequentSolidHorVertLine;
650    infoPtr->SubsequentSolidTwoPointLine = mgaSubsequentSolidTwoPointLine;
651
652    /* clipping */
653    infoPtr->SetClippingRectangle = MGASetClippingRectangle;
654    infoPtr->DisableClipping = MGADisableClipping;
655    infoPtr->ClippingFlags = 	HARDWARE_CLIP_SOLID_LINE  |
656				HARDWARE_CLIP_DASHED_LINE |
657				HARDWARE_CLIP_SOLID_FILL  |
658				HARDWARE_CLIP_MONO_8x8_FILL;
659
660#if X_BYTE_ORDER == X_LITTLE_ENDIAN
661    /* dashed lines */
662    infoPtr->DashedLineFlags = LINE_PATTERN_MSBFIRST_LSBJUSTIFIED;
663    infoPtr->SetupForDashedLine = mgaSetupForDashedLine;
664    infoPtr->SubsequentDashedTwoPointLine = mgaSubsequentDashedTwoPointLine;
665    infoPtr->DashPatternMaxLength = 128;
666#endif
667
668    /* 8x8 mono patterns */
669    infoPtr->Mono8x8PatternFillFlags = HARDWARE_PATTERN_PROGRAMMED_BITS |
670					HARDWARE_PATTERN_PROGRAMMED_ORIGIN |
671					HARDWARE_PATTERN_SCREEN_ORIGIN |
672					BIT_ORDER_IN_BYTE_MSBFIRST;
673    infoPtr->SetupForMono8x8PatternFill = mgaSetupForMono8x8PatternFill;
674    infoPtr->SubsequentMono8x8PatternFillRect =
675		mgaSubsequentMono8x8PatternFillRect;
676    infoPtr->SubsequentMono8x8PatternFillTrap =
677		mgaSubsequentMono8x8PatternFillTrap;
678
679    /* cpu to screen color expansion */
680    infoPtr->ScanlineCPUToScreenColorExpandFillFlags =
681					CPU_TRANSFER_PAD_DWORD |
682					SCANLINE_PAD_DWORD |
683#if X_BYTE_ORDER == X_BIG_ENDIAN
684					BIT_ORDER_IN_BYTE_MSBFIRST |
685#else
686					BIT_ORDER_IN_BYTE_LSBFIRST |
687#endif
688					LEFT_EDGE_CLIPPING |
689					LEFT_EDGE_CLIPPING_NEGATIVE_X;
690
691    if(pMga->ILOADBase) {
692	pMga->ColorExpandBase = pMga->ILOADBase;
693    } else {
694	pMga->ColorExpandBase = pMga->IOBase;
695    }
696    infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
697		mgaSetupForScanlineCPUToScreenColorExpandFill;
698    infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
699		mgaSubsequentScanlineCPUToScreenColorExpandFill;
700    infoPtr->SubsequentColorExpandScanline = mgaSubsequentColorExpandScanline;
701    infoPtr->NumScanlineColorExpandBuffers = 1;
702    infoPtr->ScanlineColorExpandBuffers = &(pMga->ColorExpandBase);
703
704    /* screen to screen color expansion */
705    if(pMga->AccelFlags & USE_LINEAR_EXPANSION) {
706	infoPtr->ScreenToScreenColorExpandFillFlags =
707						BIT_ORDER_IN_BYTE_LSBFIRST;
708	infoPtr->SetupForScreenToScreenColorExpandFill =
709		mgaSetupForScreenToScreenColorExpandFill;
710	infoPtr->SubsequentScreenToScreenColorExpandFill =
711		mgaSubsequentScreenToScreenColorExpandFill;
712    }
713    else if ( pMga->CurrentLayout.bitsPerPixel != 24 ) {
714	/* Alternate (but slower) planar expansions */
715	infoPtr->SetupForScreenToScreenColorExpandFill =
716	  mgaSetupForPlanarScreenToScreenColorExpandFill;
717	infoPtr->SubsequentScreenToScreenColorExpandFill =
718	  mgaSubsequentPlanarScreenToScreenColorExpandFill;
719	infoPtr->CacheColorExpandDensity = pMga->CurrentLayout.bitsPerPixel;
720	infoPtr->CacheMonoStipple = XAAGetCachePlanarMonoStipple();
721
722	/* It's faster to blit the stipples if you have fastbilt
723	 */
724	if(pMga->HasFBitBlt)
725	    infoPtr->ScreenToScreenColorExpandFillFlags = TRANSPARENCY_ONLY;
726    }
727
728    /* image writes */
729    infoPtr->ScanlineImageWriteFlags = 	CPU_TRANSFER_PAD_DWORD |
730					SCANLINE_PAD_DWORD |
731					LEFT_EDGE_CLIPPING |
732					LEFT_EDGE_CLIPPING_NEGATIVE_X |
733					NO_TRANSPARENCY |
734					NO_GXCOPY;
735
736    infoPtr->SetupForScanlineImageWrite = mgaSetupForScanlineImageWrite;
737    infoPtr->SubsequentScanlineImageWriteRect =
738      mgaSubsequentScanlineImageWriteRect;
739    infoPtr->SubsequentImageWriteScanline = mgaSubsequentImageWriteScanline;
740    infoPtr->NumScanlineImageWriteBuffers = 1;
741    infoPtr->ScanlineImageWriteBuffers = &(pMga->ScratchBuffer);
742
743
744    /* midrange replacements */
745
746    if(pMga->ILOADBase && pMga->UsePCIRetry && infoPtr->SetupForSolidFill) {
747	infoPtr->FillSolidRects = MGAFillSolidRectsDMA;
748	infoPtr->FillSolidSpans = MGAFillSolidSpansDMA;
749    }
750
751    if(pMga->AccelFlags & TWO_PASS_COLOR_EXPAND) {
752	if(infoPtr->SetupForMono8x8PatternFill)
753	    infoPtr->FillMono8x8PatternRects =
754				MGAFillMono8x8PatternRectsTwoPass;
755    }
756
757    if(infoPtr->SetupForSolidFill) {
758	infoPtr->ValidatePolyArc = MGAValidatePolyArc;
759	infoPtr->PolyArcMask = GCFunction | GCLineWidth | GCPlaneMask |
760				GCLineStyle | GCFillStyle;
761	infoPtr->ValidatePolyPoint = MGAValidatePolyPoint;
762	infoPtr->PolyPointMask = GCFunction | GCPlaneMask;
763    }
764    if(pMga->AccelFlags & MGA_NO_PLANEMASK) {
765	infoPtr->ScanlineImageWriteFlags |= NO_PLANEMASK;
766	infoPtr->ScreenToScreenCopyFlags |= NO_PLANEMASK;
767	infoPtr->ScanlineCPUToScreenColorExpandFillFlags |= NO_PLANEMASK;
768	infoPtr->SolidFillFlags |= NO_PLANEMASK;
769	infoPtr->SolidLineFlags |= NO_PLANEMASK;
770#if X_BYTE_ORDER == X_LITTLE_ENDIAN
771	infoPtr->DashedLineFlags |= NO_PLANEMASK;
772#endif
773	infoPtr->Mono8x8PatternFillFlags |= NO_PLANEMASK;
774	infoPtr->ScreenToScreenColorExpandFillFlags |= NO_PLANEMASK;
775	infoPtr->FillSolidRectsFlags |= NO_PLANEMASK;
776	infoPtr->FillSolidSpansFlags |= NO_PLANEMASK;
777	infoPtr->FillMono8x8PatternRectsFlags |= NO_PLANEMASK;
778	infoPtr->FillCacheBltRectsFlags |= NO_PLANEMASK;
779    }
780
781
782    maxFastBlitMem = (pMga->Interleave ? 4096 : 2048) * 1024;
783
784    if(pMga->FbMapSize > maxFastBlitMem) {
785	pMga->MaxFastBlitY = maxFastBlitMem / (pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel / 8);
786    }
787
788    switch (pMga->Chipset) {
789    case PCI_CHIP_MGAG200_SE_A_PCI:
790    case PCI_CHIP_MGAG200_SE_B_PCI:
791	maxlines = (min(pMga->FbUsableSize, 1*1024*1024)) /
792		   (pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel / 8);
793	break;
794    default:
795	maxlines = (min(pMga->FbUsableSize, 16*1024*1024)) /
796		   (pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel / 8);
797	break;
798    }
799
800#ifdef XF86DRI
801    if ( pMga->directRenderingEnabled ) {
802       MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
803       BoxRec MemBox;
804       int cpp = pScrn->bitsPerPixel / 8;
805       int widthBytes = pScrn->displayWidth * cpp;
806       int bufferSize = ((pScrn->virtualY * widthBytes + MGA_BUFFER_ALIGN)
807			 & ~MGA_BUFFER_ALIGN);
808       int scanlines;
809
810       pMGADRIServer->frontOffset = 0;
811       pMGADRIServer->frontPitch = widthBytes;
812
813       /* Try for front, back, depth, and two framebuffers worth of
814	* pixmap cache.  Should be enough for a fullscreen background
815	* image plus some leftovers.
816	*/
817       pMGADRIServer->textureSize = pMga->FbMapSize - 5 * bufferSize;
818
819       /* If that gives us less than half the available memory, let's
820	* be greedy and grab some more.  Sorry, I care more about 3D
821	* performance than playing nicely, and you'll get around a full
822	* framebuffer's worth of pixmap cache anyway.
823	*/
824       if ( pMGADRIServer->textureSize < (int)pMga->FbMapSize / 2 ) {
825	  pMGADRIServer->textureSize = pMga->FbMapSize - 4 * bufferSize;
826       }
827
828       /* Check to see if there is more room available after the maximum
829	* scanline for textures.
830	*/
831       if ( (int)pMga->FbMapSize - maxlines * widthBytes - bufferSize * 2
832	    > pMGADRIServer->textureSize ) {
833	  pMGADRIServer->textureSize = (pMga->FbMapSize -
834					maxlines * widthBytes -
835					bufferSize * 2);
836       }
837
838       /* Set a minimum usable local texture heap size.  This will fit
839	* two 256x256x32bpp textures.
840	*/
841       if ( pMGADRIServer->textureSize < 512 * 1024 ) {
842	  pMGADRIServer->textureOffset = 0;
843	  pMGADRIServer->textureSize = 0;
844       }
845
846       /* Reserve space for textures */
847       pMGADRIServer->textureOffset = (pMga->FbMapSize -
848				       pMGADRIServer->textureSize +
849				       MGA_BUFFER_ALIGN) & ~MGA_BUFFER_ALIGN;
850
851       /* Reserve space for the shared depth buffer */
852       pMGADRIServer->depthOffset = (pMGADRIServer->textureOffset -
853				     bufferSize +
854				     MGA_BUFFER_ALIGN) & ~MGA_BUFFER_ALIGN;
855       pMGADRIServer->depthPitch = widthBytes;
856
857       /* Reserve space for the shared back buffer */
858       pMGADRIServer->backOffset = (pMGADRIServer->depthOffset - bufferSize +
859				    MGA_BUFFER_ALIGN) & ~MGA_BUFFER_ALIGN;
860       pMGADRIServer->backPitch = widthBytes;
861
862       scanlines = pMGADRIServer->backOffset / widthBytes - 1;
863       if ( scanlines > maxlines ) scanlines = maxlines;
864
865       MemBox.x1 = 0;
866       MemBox.y1 = 0;
867       MemBox.x2 = pScrn->displayWidth;
868       MemBox.y2 = scanlines;
869
870       if ( !xf86InitFBManager( pScreen, &MemBox ) ) {
871	  xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
872		      "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
873		      MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2 );
874	  return FALSE;
875       } else {
876	  int width, height;
877
878	  xf86DrvMsg( pScrn->scrnIndex, X_INFO,
879		      "Memory manager initialized to (%d,%d) (%d,%d)\n",
880		      MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2 );
881
882	  if ( xf86QueryLargestOffscreenArea( pScreen, &width,
883					      &height, 0, 0, 0 ) ) {
884	     xf86DrvMsg( pScrn->scrnIndex, X_INFO,
885			 "Largest offscreen area available: %d x %d\n",
886			 width, height );
887	  }
888       }
889
890       xf86DrvMsg( pScrn->scrnIndex, X_INFO,
891		   "Reserved back buffer at offset 0x%x\n",
892		   pMGADRIServer->backOffset );
893       xf86DrvMsg( pScrn->scrnIndex, X_INFO,
894		   "Reserved depth buffer at offset 0x%x\n",
895		   pMGADRIServer->depthOffset );
896       xf86DrvMsg( pScrn->scrnIndex, X_INFO,
897		   "Reserved %d kb for textures at offset 0x%x\n",
898		   pMGADRIServer->textureSize/1024,
899		   pMGADRIServer->textureOffset );
900    }
901    else
902#endif /* defined(XF86DRI) */
903    {
904       AvailFBArea.x1 = 0;
905       AvailFBArea.x2 = pScrn->displayWidth;
906       AvailFBArea.y1 = 0;
907       AvailFBArea.y2 = maxlines;
908
909       /*
910	* Need to keep a strip of memory to the right of screen to workaround
911	* a display problem with the second CRTC.
912	*/
913       if (pMga->SecondCrtc)
914	  AvailFBArea.x2 = pScrn->virtualX;
915
916       xf86InitFBManager(pScreen, &AvailFBArea);
917       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %d lines for offscreen "
918		  "memory.\n",
919		  maxlines - pScrn->virtualY);
920
921    }
922
923    for (i = 0; i < pScrn->numEntities; i++) {
924	if (xf86IsEntityShared(pScrn->entityList[i])) {
925	    infoPtr->RestoreAccelState = mgaRestoreAccelState;
926	    break;
927	}
928    }
929
930#ifdef RENDER
931   if(doRender && ((pScrn->bitsPerPixel == 32) || (pScrn->bitsPerPixel == 16)))
932   {
933       if(pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550) {
934           infoPtr->CPUToScreenAlphaTextureFlags = XAA_RENDER_NO_TILE;
935           infoPtr->SetupForCPUToScreenAlphaTexture =
936				MGASetupForCPUToScreenAlphaTexture;
937       } else {
938           infoPtr->CPUToScreenAlphaTextureFlags = XAA_RENDER_NO_TILE |
939					       XAA_RENDER_NO_SRC_ALPHA;
940           infoPtr->SetupForCPUToScreenAlphaTexture =
941				MGASetupForCPUToScreenAlphaTextureFaked;
942       }
943       infoPtr->SubsequentCPUToScreenAlphaTexture =
944				MGASubsequentCPUToScreenTexture;
945       infoPtr->CPUToScreenAlphaTextureFormats = MGAAlphaTextureFormats;
946
947       infoPtr->SetupForCPUToScreenTexture = MGASetupForCPUToScreenTexture;
948       infoPtr->SubsequentCPUToScreenTexture = MGASubsequentCPUToScreenTexture;
949       infoPtr->CPUToScreenTextureFlags = XAA_RENDER_NO_TILE;
950       infoPtr->CPUToScreenTextureFormats = MGATextureFormats;
951    }
952#endif /* defined(RENDER) */
953
954    return(XAAInit(pScreen, infoPtr));
955}
956
957
958/* Support for multiscreen */
959static void mgaRestoreAccelState(ScrnInfoPtr pScrn)
960{
961   MGAPtr pMga = MGAPTR(pScrn);
962   MGAFBLayout *pLayout = &pMga->CurrentLayout;
963    unsigned int replicate_fg = 0;
964    unsigned int replicate_bg = 0;
965    unsigned int replicate_pm = 0;
966
967   MGAStormSync(pScrn);
968   WAITFIFO(12);
969   pMga->SrcOrg = 0;
970   OUTREG(MGAREG_MACCESS, pMga->MAccess);
971   OUTREG(MGAREG_PITCH, pLayout->displayWidth);
972   OUTREG(MGAREG_YDSTORG, pMga->YDstOrg);
973
974
975    common_replicate_colors_and_mask( pMga->FgColor, pMga->BgColor,
976				      pMga->PlaneMask, pLayout->bitsPerPixel,
977				      & replicate_fg, & replicate_bg,
978				      & replicate_pm );
979
980    if( (pLayout->bitsPerPixel != 24)
981	&& ((pMga->AccelFlags & MGA_NO_PLANEMASK) == 0) ) {
982	OUTREG( MGAREG_PLNWT, replicate_pm );
983    }
984
985    OUTREG( MGAREG_BCOL, replicate_bg );
986    OUTREG( MGAREG_FCOL, replicate_fg );
987
988   OUTREG(MGAREG_SRCORG, pMga->realSrcOrg);
989   OUTREG(MGAREG_DSTORG, pMga->DstOrg);
990#if X_BYTE_ORDER == X_LITTLE_ENDIAN
991   OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT );
992#else
993   OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT | 0x10000);
994#endif
995   OUTREG(MGAREG_CXBNDRY, 0xFFFF0000); /* (maxX << 16) | minX */
996   OUTREG(MGAREG_YTOP, 0x00000000);    /* minPixelPointer */
997   OUTREG(MGAREG_YBOT, 0x007FFFFF);    /* maxPixelPointer */
998   pMga->AccelFlags &= ~CLIPPER_ON;
999}
1000
1001
1002CARD32 MGAAtype[16] = {
1003   MGADWG_RPL  | 0x00000000, MGADWG_RSTR | 0x00080000,
1004   MGADWG_RSTR | 0x00040000, MGADWG_BLK  | 0x000c0000,
1005   MGADWG_RSTR | 0x00020000, MGADWG_RSTR | 0x000a0000,
1006   MGADWG_RSTR | 0x00060000, MGADWG_RSTR | 0x000e0000,
1007   MGADWG_RSTR | 0x00010000, MGADWG_RSTR | 0x00090000,
1008   MGADWG_RSTR | 0x00050000, MGADWG_RSTR | 0x000d0000,
1009   MGADWG_RPL  | 0x00030000, MGADWG_RSTR | 0x000b0000,
1010   MGADWG_RSTR | 0x00070000, MGADWG_RPL  | 0x000f0000
1011};
1012
1013
1014CARD32 MGAAtypeNoBLK[16] = {
1015   MGADWG_RPL  | 0x00000000, MGADWG_RSTR | 0x00080000,
1016   MGADWG_RSTR | 0x00040000, MGADWG_RPL  | 0x000c0000,
1017   MGADWG_RSTR | 0x00020000, MGADWG_RSTR | 0x000a0000,
1018   MGADWG_RSTR | 0x00060000, MGADWG_RSTR | 0x000e0000,
1019   MGADWG_RSTR | 0x00010000, MGADWG_RSTR | 0x00090000,
1020   MGADWG_RSTR | 0x00050000, MGADWG_RSTR | 0x000d0000,
1021   MGADWG_RPL  | 0x00030000, MGADWG_RSTR | 0x000b0000,
1022   MGADWG_RSTR | 0x00070000, MGADWG_RPL  | 0x000f0000
1023};
1024
1025
1026Bool
1027MGAStormAccelInit(ScreenPtr pScreen)
1028{
1029    return mgaAccelInit( pScreen );
1030}
1031
1032
1033
1034void
1035MGAStormSync(ScrnInfoPtr pScrn)
1036{
1037    MGAPtr pMga = MGAPTR(pScrn);
1038
1039    CHECK_DMA_QUIESCENT(pMga, pScrn);
1040
1041    /* MGAISBUSY() reportedly causes a freeze for Mystique revisions 0 and 1 */
1042    if (!(pMga->Chipset == PCI_CHIP_MGA1064 && (pMga->ChipRev >= 0 && pMga->ChipRev <= 1)))
1043	while(MGAISBUSY());
1044    /* flush cache before a read (mga-1064g 5.1.6) */
1045    OUTREG8(MGAREG_CRTC_INDEX, 0);
1046    if(pMga->AccelFlags & CLIPPER_ON) {
1047        pMga->AccelFlags &= ~CLIPPER_ON;
1048        OUTREG(MGAREG_CXBNDRY, 0xFFFF0000);
1049    }
1050}
1051
1052
1053void MGAStormEngineInit( ScrnInfoPtr pScrn )
1054{
1055    long maccess = 0;
1056    MGAPtr pMga = MGAPTR(pScrn);
1057    MGAFBLayout *pLayout = &pMga->CurrentLayout;
1058    CARD32 opmode;
1059    static const unsigned int maccess_table[5] = {
1060   /* bpp:  8  16  24  32 */
1061	0,  0,  1,  3,  2
1062    };
1063    static const unsigned int opmode_table[5] = {
1064        /* bpp:        8       16       24       32 */
1065	0x00000, 0x00000, 0x10000, 0x20000, 0x20000
1066    };
1067
1068    CHECK_DMA_QUIESCENT(pMga, pScrn);
1069
1070    if ((pMga->Chipset == PCI_CHIP_MGAG100)
1071	|| (pMga->Chipset == PCI_CHIP_MGAG100_PCI))
1072    	maccess = 1 << 14;
1073
1074    opmode = INREG(MGAREG_OPMODE);
1075
1076    maccess |= maccess_table[ pLayout->bitsPerPixel / 8 ];
1077    if ( pLayout->depth == 15 ) {
1078        maccess |= (1 << 31);
1079    }
1080
1081    opmode |= opmode_table[ pLayout->bitsPerPixel / 8 ];
1082#if X_BYTE_ORDER == X_LITTLE_ENDIAN
1083    opmode &= ~0x30000;
1084#endif
1085
1086    pMga->SetupForSolidFill = mgaSetupForSolidFill;
1087    pMga->SubsequentSolidFillRect = mgaSubsequentSolidFillRect;
1088    pMga->RestoreAccelState = mgaRestoreAccelState;
1089
1090
1091    pMga->fifoCount = 0;
1092
1093    while(MGAISBUSY());
1094
1095    if(!pMga->FifoSize) {
1096	pMga->FifoSize = INREG8(MGAREG_FIFOSTATUS);
1097	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%i DWORD fifo\n",
1098						pMga->FifoSize);
1099    }
1100
1101    OUTREG(MGAREG_PITCH, pLayout->displayWidth);
1102    OUTREG(MGAREG_YDSTORG, pMga->YDstOrg);
1103    OUTREG(MGAREG_MACCESS, maccess);
1104    pMga->MAccess = maccess;
1105    pMga->PlaneMask = ~0;
1106    /* looks like this doesn't apply to mga g100 pci */
1107
1108    if ((pMga->Chipset != PCI_CHIP_MGAG100)
1109	&& (pMga->Chipset != PCI_CHIP_MGAG100_PCI))
1110        OUTREG(MGAREG_PLNWT, pMga->PlaneMask);
1111
1112    pMga->FgColor = 0;
1113    OUTREG(MGAREG_FCOL, pMga->FgColor);
1114    pMga->BgColor = 0;
1115    OUTREG(MGAREG_BCOL, pMga->BgColor);
1116    OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT | opmode);
1117
1118    /* put clipping in a known state */
1119    OUTREG(MGAREG_CXBNDRY, 0xFFFF0000);	/* (maxX << 16) | minX */
1120    OUTREG(MGAREG_YTOP, 0x00000000);	/* minPixelPointer */
1121    OUTREG(MGAREG_YBOT, 0x007FFFFF);	/* maxPixelPointer */
1122    pMga->AccelFlags &= ~CLIPPER_ON;
1123
1124    switch(pMga->Chipset) {
1125    case PCI_CHIP_MGAG550:
1126    case PCI_CHIP_MGAG400:
1127    case PCI_CHIP_MGAG200:
1128    case PCI_CHIP_MGAG200_PCI:
1129    case PCI_CHIP_MGAG200_SE_A_PCI:
1130    case PCI_CHIP_MGAG200_SE_B_PCI:
1131    case PCI_CHIP_MGAG200_WINBOND_PCI:
1132    case PCI_CHIP_MGAG200_EV_PCI:
1133    case PCI_CHIP_MGAG200_EH_PCI:
1134	pMga->SrcOrg = 0;
1135	OUTREG(MGAREG_SRCORG, pMga->realSrcOrg);
1136	OUTREG(MGAREG_DSTORG, pMga->DstOrg);
1137	break;
1138    default:
1139	break;
1140    }
1141
1142    if (pMga->is_G200WB)
1143    {
1144        CARD32 dwgctl = MGADWG_RSTR | 0x00060000 | MGADWG_SHIFTZERO |
1145			MGADWG_BITBLT | MGADWG_BFCOL;
1146        WAITFIFO(7);
1147        OUTREG(MGAREG_DWGCTL, dwgctl);
1148        OUTREG(MGAREG_SGN, 0);
1149        OUTREG(MGAREG_AR5, 1);
1150        OUTREG(MGAREG_AR0, 1);
1151        OUTREG(MGAREG_AR3, 0);
1152        OUTREG(MGAREG_FXBNDRY, (1 << 16) | (1 & 0xffff));
1153        OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (1 << 16) | 1);
1154    }
1155
1156    xf86SetLastScrnFlag(pScrn->entityList[0], pScrn->scrnIndex);
1157}
1158
1159
1160static void
1161MGASetClippingRectangle(
1162   ScrnInfoPtr pScrn,
1163   int x1, int y1, int x2, int y2
1164){
1165    MGAPtr pMga = MGAPTR(pScrn);
1166
1167    CHECK_DMA_QUIESCENT(pMga, pScrn);
1168
1169    WAITFIFO(3);
1170    OUTREG(MGAREG_CXBNDRY,(x2 << 16) | x1);
1171    OUTREG(MGAREG_YTOP, (y1 * pScrn->displayWidth) + pMga->YDstOrg);
1172    OUTREG(MGAREG_YBOT, (y2 * pScrn->displayWidth) + pMga->YDstOrg);
1173    pMga->AccelFlags |= CLIPPER_ON;
1174}
1175
1176static void
1177MGADisableClipping(ScrnInfoPtr pScrn)
1178{
1179    MGAPtr pMga = MGAPTR(pScrn);
1180
1181    CHECK_DMA_QUIESCENT(pMga, pScrn);
1182
1183    WAITFIFO(3);
1184    OUTREG(MGAREG_CXBNDRY, 0xFFFF0000);     /* (maxX << 16) | minX */
1185    OUTREG(MGAREG_YTOP, 0x00000000);        /* minPixelPointer */
1186    OUTREG(MGAREG_YBOT, 0x007FFFFF);        /* maxPixelPointer */
1187    pMga->AccelFlags &= ~CLIPPER_ON;
1188}
1189
1190
1191static CARD32
1192common_setup_for_pattern_fill( MGAPtr pMga, int fg, int bg, int rop,
1193			       int planemask,
1194			       CARD32 * reg_data, unsigned int count,
1195			       CARD32 cmd )
1196{
1197    unsigned int replicate_fg = 0;
1198    unsigned int replicate_bg = 0;
1199    unsigned int replicate_pm = 0;
1200    unsigned int i;
1201
1202
1203    common_replicate_colors_and_mask( fg, bg, planemask,
1204				      pMga->CurrentLayout.bitsPerPixel,
1205				      & replicate_fg, & replicate_bg,
1206				      & replicate_pm );
1207
1208
1209    if( bg == -1 ) {
1210    	if ( (pMga->CurrentLayout.bitsPerPixel == 24) && !RGBEQUAL(fg) ) {
1211            cmd |= MGADWG_TRANSC | pMga->AtypeNoBLK[rop];
1212	}
1213	else {
1214            cmd |= MGADWG_TRANSC | pMga->Atype[rop];
1215	}
1216
1217	WAITFIFO( count + 3 );
1218    }
1219    else {
1220	/* (Packed) 24-bit is a funky mode.  We only use the Atype table in
1221	 * 24-bit if the components of the foreground color and the components
1222	 * of the background color are the same (e.g., fg = 0xf8f8f8 and bg =
1223	 * 0x131313).
1224	 */
1225
1226	if( ((pMga->AccelFlags & BLK_OPAQUE_EXPANSION) != 0)
1227	    && ((pMga->CurrentLayout.bitsPerPixel != 24)
1228		|| (RGBEQUAL(fg) && RGBEQUAL(bg))) ) {
1229	    cmd |= pMga->Atype[rop];
1230	}
1231	else {
1232	    cmd |= pMga->AtypeNoBLK[rop];
1233	}
1234
1235	WAITFIFO( count + 4 );
1236	SET_BACKGROUND_REPLICATED( bg, replicate_bg );
1237    }
1238
1239    SET_FOREGROUND_REPLICATED( fg, replicate_fg );
1240    SET_PLANEMASK_REPLICATED( planemask, replicate_pm,
1241			      pMga->CurrentLayout.bitsPerPixel );
1242
1243    /* FIXME: Is this the right order? */
1244
1245    for ( i = 0 ; i < count ; i++ ) {
1246	OUTREG( reg_data[0], reg_data[1] );
1247	reg_data += 2;
1248    }
1249
1250    OUTREG(MGAREG_DWGCTL, cmd);
1251
1252    return cmd;
1253}
1254
1255
1256	/*********************************************\
1257	|            Screen-to-Screen Copy            |
1258	\*********************************************/
1259
1260#define BLIT_LEFT	1
1261#define BLIT_UP		4
1262
1263void mgaDoSetupForScreenToScreenCopy( ScrnInfoPtr pScrn, int xdir, int ydir,
1264				      int rop, unsigned int planemask,
1265				      int trans, unsigned bpp )
1266{
1267    MGAPtr pMga = MGAPTR(pScrn);
1268    CARD32 dwgctl = pMga->AtypeNoBLK[rop] | MGADWG_SHIFTZERO |
1269			MGADWG_BITBLT | MGADWG_BFCOL;
1270    unsigned int tmp;
1271    unsigned int replicated_trans = 0;
1272    unsigned int replicated_mask = 0;
1273
1274
1275    CHECK_DMA_QUIESCENT(pMga, pScrn);
1276
1277    pMga->AccelInfoRec->SubsequentScreenToScreenCopy =
1278      mgaSubsequentScreenToScreenCopy;
1279
1280    pMga->BltScanDirection = 0;
1281    if(ydir == -1) pMga->BltScanDirection |= BLIT_UP;
1282    if(xdir == -1)
1283	pMga->BltScanDirection |= BLIT_LEFT;
1284    else if(pMga->HasFBitBlt && (rop == GXcopy) && !pMga->DrawTransparent)
1285	pMga->AccelInfoRec->SubsequentScreenToScreenCopy =
1286		mgaSubsequentScreenToScreenCopy_FastBlit;
1287
1288
1289    common_replicate_colors_and_mask( trans, 0, planemask, bpp,
1290				      & replicated_trans, & tmp,
1291				      & replicated_mask );
1292
1293    if(pMga->DrawTransparent) {
1294	dwgctl |= MGADWG_TRANSC;
1295	WAITFIFO(2);
1296
1297	SET_FOREGROUND_REPLICATED( trans, replicated_trans );
1298	SET_BACKGROUND_REPLICATED( ~0, ~0 );
1299    }
1300
1301    WAITFIFO(4);
1302    OUTREG(MGAREG_DWGCTL, dwgctl);
1303    OUTREG(MGAREG_SGN, pMga->BltScanDirection);
1304
1305    SET_PLANEMASK_REPLICATED( planemask, replicated_mask, bpp );
1306    OUTREG(MGAREG_AR5, ydir * pMga->CurrentLayout.displayWidth);
1307}
1308
1309
1310void mgaSetupForScreenToScreenCopy( ScrnInfoPtr pScrn, int xdir, int ydir,
1311				    int rop, unsigned int planemask,
1312				    int trans )
1313{
1314    MGAPtr pMga = MGAPTR(pScrn);
1315
1316    mgaDoSetupForScreenToScreenCopy( pScrn, xdir, ydir, rop, planemask, trans,
1317				     pMga->CurrentLayout.bitsPerPixel );
1318}
1319
1320
1321void mgaSubsequentScreenToScreenCopy( ScrnInfoPtr pScrn,
1322				      int srcX, int srcY, int dstX, int dstY,
1323				      int w, int h )
1324{
1325    int start, end, SrcOrg = 0, DstOrg = 0;
1326    MGAPtr pMga = MGAPTR(pScrn);
1327
1328    if (pMga->AccelFlags & LARGE_ADDRESSES) {
1329	const unsigned int display_bit_width =
1330	  (pMga->CurrentLayout.displayWidth * pMga->CurrentLayout.bitsPerPixel);
1331
1332	SrcOrg = ((srcY & ~1023) * display_bit_width) >> 9;
1333	DstOrg = ((dstY & ~1023) * display_bit_width) >> 9;
1334        dstY &= 1023;
1335    }
1336
1337    if(pMga->BltScanDirection & BLIT_UP) {
1338	srcY += h - 1;
1339	dstY += h - 1;
1340    }
1341
1342    w--;
1343    start = end = XYADDRESS(srcX, srcY);
1344
1345    if(pMga->BltScanDirection & BLIT_LEFT) start += w;
1346    else end += w;
1347
1348    if (pMga->AccelFlags & LARGE_ADDRESSES) {
1349	WAITFIFO(7);
1350	if(DstOrg)
1351	    OUTREG(MGAREG_DSTORG, (DstOrg << 6) + pMga->DstOrg);
1352	if(SrcOrg != pMga->SrcOrg) {
1353	    pMga->SrcOrg = SrcOrg;
1354	    OUTREG(MGAREG_SRCORG, (SrcOrg << 6) + pMga->realSrcOrg);
1355 	}
1356	if(SrcOrg) {
1357	    SrcOrg = (SrcOrg << 9) / pMga->CurrentLayout.bitsPerPixel;
1358	    end -= SrcOrg;
1359	    start -= SrcOrg;
1360	}
1361	OUTREG(MGAREG_AR0, end);
1362	OUTREG(MGAREG_AR3, start);
1363	OUTREG(MGAREG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff));
1364	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h);
1365	if(DstOrg)
1366	   OUTREG(MGAREG_DSTORG, pMga->DstOrg);
1367    } else {
1368	WAITFIFO(4);
1369	OUTREG(MGAREG_AR0, end);
1370	OUTREG(MGAREG_AR3, start);
1371	OUTREG(MGAREG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff));
1372	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h);
1373    }
1374}
1375
1376
1377void mgaSubsequentScreenToScreenCopy_FastBlit( ScrnInfoPtr pScrn,
1378					       int srcX, int srcY,
1379					       int dstX, int dstY,
1380					       int w, int h )
1381{
1382    int start, end;
1383    MGAPtr pMga = MGAPTR(pScrn);
1384    static const unsigned int masks[5] = {
1385	0, 0x07f, 0x03f, 0x7f, 0x1f
1386    };
1387
1388    if(pMga->BltScanDirection & BLIT_UP) {
1389	srcY += h - 1;
1390	dstY += h - 1;
1391    }
1392
1393    w--;
1394    start = XYADDRESS(srcX, srcY);
1395    end = start + w;
1396
1397    /* we assume the driver asserts screen pitches such that
1398	we can always use fastblit for scrolling */
1399    if(((srcX ^ dstX) & masks[ pMga->CurrentLayout.bitsPerPixel / 8 ]) == 0) {
1400	if(pMga->MaxFastBlitY) {
1401	   if(pMga->BltScanDirection & BLIT_UP) {
1402		if((srcY >= pMga->MaxFastBlitY) ||
1403				(dstY >= pMga->MaxFastBlitY))
1404			goto FASTBLIT_BAILOUT;
1405	   } else {
1406		if(((srcY + h) > pMga->MaxFastBlitY) ||
1407				((dstY + h) > pMga->MaxFastBlitY))
1408			goto FASTBLIT_BAILOUT;
1409	   }
1410	}
1411
1412	/* Millennium 1 fastblit bug fix */
1413        if(pMga->AccelFlags & FASTBLT_BUG) {
1414	    int fxright = dstX + w;
1415	    int tmp_dstX = dstX;
1416	    int tmp_fxright = fxright;
1417	    static const unsigned shift_tab[5] = {
1418		0, 6, 5, 6, 4
1419	    };
1420	    const unsigned shift = shift_tab[pMga->CurrentLayout.bitsPerPixel / 8];
1421
1422	   if (pMga->CurrentLayout.bitsPerPixel == 24) {
1423	       tmp_dstX *= 3;
1424	       tmp_fxright = fxright * 3 + 2;
1425	   }
1426
1427           if( (tmp_dstX & (1 << shift))
1428	       && (((tmp_fxright >> shift) - (tmp_dstX >> shift)) & 7) == 7) {
1429	       fxright = (tmp_fxright | (1 << shift));
1430	       if (pMga->CurrentLayout.bitsPerPixel == 24) {
1431		   fxright /= 3;
1432	       }
1433
1434	       WAITFIFO(8);
1435	       OUTREG(MGAREG_CXRIGHT, dstX + w);
1436	       OUTREG(MGAREG_DWGCTL, 0x040A400C);
1437	       OUTREG(MGAREG_AR0, end);
1438	       OUTREG(MGAREG_AR3, start);
1439	       OUTREG(MGAREG_FXBNDRY, (fxright << 16) | (dstX & 0xffff));
1440	       OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h);
1441	       OUTREG(MGAREG_DWGCTL, pMga->AtypeNoBLK[GXcopy] |
1442		      MGADWG_SHIFTZERO | MGADWG_BITBLT | MGADWG_BFCOL);
1443	       OUTREG(MGAREG_CXRIGHT, 0xFFFF);
1444	       return;
1445	    }
1446	}
1447
1448   	WAITFIFO(6);
1449    	OUTREG(MGAREG_DWGCTL, 0x040A400C);
1450    	OUTREG(MGAREG_AR0, end);
1451    	OUTREG(MGAREG_AR3, start);
1452    	OUTREG(MGAREG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff));
1453    	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h);
1454    	OUTREG(MGAREG_DWGCTL, pMga->AtypeNoBLK[GXcopy] | MGADWG_SHIFTZERO |
1455			MGADWG_BITBLT | MGADWG_BFCOL);
1456	return;
1457    }
1458
1459FASTBLIT_BAILOUT:
1460
1461    WAITFIFO(4);
1462    OUTREG(MGAREG_AR0, end);
1463    OUTREG(MGAREG_AR3, start);
1464    OUTREG(MGAREG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff));
1465    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h);
1466}
1467
1468        /******************\
1469	|   Solid Fills    |
1470	\******************/
1471
1472void mgaDoSetupForSolidFill( ScrnInfoPtr pScrn, int color, int rop,
1473			     unsigned int planemask, unsigned int bpp )
1474{
1475    MGAPtr pMga = MGAPTR(pScrn);
1476    unsigned int tmp;
1477    unsigned int replicated_color = 0;
1478    unsigned int replicated_planemask = 0;
1479
1480    common_replicate_colors_and_mask( color, 0, planemask, bpp,
1481				      & replicated_color, & tmp,
1482				      & replicated_planemask );
1483
1484    CHECK_DMA_QUIESCENT(pMga, pScrn);
1485
1486    if ( (bpp == 24) && !RGBEQUAL(color) ) {
1487	pMga->FilledRectCMD = MGADWG_TRAP | MGADWG_SOLID | MGADWG_ARZERO |
1488	  MGADWG_SGNZERO | MGADWG_SHIFTZERO |
1489	  MGADWG_BMONOLEF | pMga->AtypeNoBLK[rop];
1490    }
1491    else {
1492	pMga->FilledRectCMD = MGADWG_TRAP | MGADWG_SOLID | MGADWG_ARZERO |
1493	  MGADWG_SGNZERO | MGADWG_SHIFTZERO |
1494	  MGADWG_BMONOLEF | pMga->Atype[rop];
1495    }
1496
1497    pMga->SolidLineCMD = MGADWG_SOLID | MGADWG_SHIFTZERO | MGADWG_BFCOL |
1498      pMga->AtypeNoBLK[rop];
1499
1500    if(pMga->AccelFlags & TRANSC_SOLID_FILL)
1501	pMga->FilledRectCMD |= MGADWG_TRANSC;
1502
1503    WAITFIFO(3);
1504    if ( color != pMga->FgColor ) {
1505	pMga->FgColor = color;
1506	OUTREG( MGAREG_FCOL, replicated_color );
1507    }
1508
1509    if ( (bpp != 24)
1510	 && !(pMga->AccelFlags & MGA_NO_PLANEMASK)
1511	 && (planemask != pMga->PlaneMask) ) {
1512	pMga->PlaneMask = planemask;
1513	OUTREG( MGAREG_PLNWT, replicated_planemask );
1514    }
1515
1516    OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD);
1517}
1518
1519void mgaSetupForSolidFill( ScrnInfoPtr pScrn, int color, int rop,
1520			   unsigned int planemask )
1521{
1522    MGAPtr pMga = MGAPTR(pScrn);
1523
1524    mgaDoSetupForSolidFill( pScrn, color, rop, planemask,
1525			    pMga->CurrentLayout.bitsPerPixel );
1526}
1527
1528void mgaSubsequentSolidFillRect( ScrnInfoPtr pScrn,
1529				 int x, int y, int w, int h )
1530{
1531    MGAPtr pMga = MGAPTR(pScrn);
1532
1533    WAITFIFO(2);
1534    OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff));
1535    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1536}
1537
1538void mgaSubsequentSolidFillTrap( ScrnInfoPtr pScrn, int y, int h,
1539				 int left, int dxL, int dyL, int eL,
1540				 int right, int dxR, int dyR, int eR )
1541{
1542    MGAPtr pMga = MGAPTR(pScrn);
1543    int sdxl = (dxL < 0);
1544    int ar2 = sdxl? dxL : -dxL;
1545    int sdxr = (dxR < 0);
1546    int ar5 = sdxr? dxR : -dxR;
1547
1548    WAITFIFO(11);
1549    OUTREG(MGAREG_DWGCTL,
1550		pMga->FilledRectCMD & ~(MGADWG_ARZERO | MGADWG_SGNZERO));
1551    OUTREG(MGAREG_AR0, dyL);
1552    OUTREG(MGAREG_AR1, ar2 - eL);
1553    OUTREG(MGAREG_AR2, ar2);
1554    OUTREG(MGAREG_AR4, ar5 - eR);
1555    OUTREG(MGAREG_AR5, ar5);
1556    OUTREG(MGAREG_AR6, dyR);
1557    OUTREG(MGAREG_SGN, (sdxl << 1) | (sdxr << 5));
1558    OUTREG(MGAREG_FXBNDRY, ((right + 1) << 16) | (left & 0xffff));
1559    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1560    OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD);
1561}
1562
1563
1564	/***************\
1565	|  Solid Lines  |
1566	\***************/
1567
1568void mgaSubsequentSolidHorVertLine( ScrnInfoPtr pScrn, int x, int y,
1569				    int len, int dir )
1570{
1571    MGAPtr pMga = MGAPTR(pScrn);
1572
1573    if(dir == DEGREES_0) {
1574	WAITFIFO(2);
1575	OUTREG(MGAREG_FXBNDRY, ((x + len) << 16) | (x & 0xffff));
1576	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | 1);
1577    } else if(pMga->AccelFlags & USE_RECTS_FOR_LINES) {
1578	WAITFIFO(2);
1579	OUTREG(MGAREG_FXBNDRY, ((x + 1) << 16) | (x & 0xffff));
1580	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | len);
1581    } else {
1582	WAITFIFO(4);
1583	OUTREG(MGAREG_DWGCTL, pMga->SolidLineCMD | MGADWG_AUTOLINE_OPEN);
1584	OUTREG(MGAREG_XYSTRT, (y << 16) | (x & 0xffff));
1585	OUTREG(MGAREG_XYEND + MGAREG_EXEC, ((y + len) << 16) | (x & 0xffff));
1586	OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD);
1587    }
1588}
1589
1590
1591void mgaSubsequentSolidTwoPointLine( ScrnInfoPtr pScrn, int x1, int y1,
1592				     int x2, int y2, int flags )
1593{
1594    MGAPtr pMga = MGAPTR(pScrn);
1595
1596    WAITFIFO(4);
1597    OUTREG(MGAREG_DWGCTL, pMga->SolidLineCMD |
1598        ((flags & OMIT_LAST) ? MGADWG_AUTOLINE_OPEN : MGADWG_AUTOLINE_CLOSE));
1599    OUTREG(MGAREG_XYSTRT, (y1 << 16) | (x1 & 0xFFFF));
1600    OUTREG(MGAREG_XYEND + MGAREG_EXEC, (y2 << 16) | (x2 & 0xFFFF));
1601    OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD);
1602}
1603
1604
1605	/***************************\
1606	|   8x8 Mono Pattern Fills  |
1607	\***************************/
1608
1609
1610void mgaSetupForMono8x8PatternFill( ScrnInfoPtr pScrn,
1611				    int patx, int paty, int fg, int bg,
1612				    int rop, unsigned int planemask )
1613{
1614    MGAPtr pMga = MGAPTR(pScrn);
1615    XAAInfoRecPtr infoRec = pMga->AccelInfoRec;
1616    CARD32 regs[4];
1617
1618    CHECK_DMA_QUIESCENT(pMga, pScrn);
1619
1620    infoRec->SubsequentMono8x8PatternFillRect =
1621		mgaSubsequentMono8x8PatternFillRect;
1622
1623    regs[0] = MGAREG_PAT0;
1624    regs[1] = patx;
1625    regs[2] = MGAREG_PAT1;
1626    regs[3] = paty;
1627
1628    pMga->PatternRectCMD = common_setup_for_pattern_fill( pMga, fg, bg, rop,
1629							  planemask, regs, 2,
1630							  (MGADWG_TRAP
1631							   | MGADWG_ARZERO
1632							   | MGADWG_SGNZERO
1633							   | MGADWG_BMONOLEF) );
1634}
1635
1636
1637void mgaSubsequentMono8x8PatternFillRect( ScrnInfoPtr pScrn,
1638					  int patx, int paty,
1639					  int x, int y, int w, int h )
1640{
1641    MGAPtr pMga = MGAPTR(pScrn);
1642
1643    WAITFIFO(3);
1644    OUTREG(MGAREG_SHIFT, (paty << 4) | patx);
1645    OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff));
1646    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1647    pMga->AccelInfoRec->SubsequentMono8x8PatternFillRect =
1648		mgaSubsequentMono8x8PatternFillRect_Additional;
1649}
1650
1651static void mgaSubsequentMono8x8PatternFillRect_Additional( ScrnInfoPtr pScrn,
1652							    int patx, int paty,
1653							    int x, int y,
1654							    int w, int h )
1655{
1656    MGAPtr pMga = MGAPTR(pScrn);
1657
1658    WAITFIFO(2);
1659    OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff));
1660    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1661}
1662
1663
1664void mgaSubsequentMono8x8PatternFillTrap( ScrnInfoPtr pScrn,
1665					  int patx, int paty,
1666					  int y, int h,
1667					  int left, int dxL, int dyL, int eL,
1668					  int right, int dxR, int dyR, int eR )
1669{
1670    MGAPtr pMga = MGAPTR(pScrn);
1671
1672    int sdxl = (dxL < 0) ? (1<<1) : 0;
1673    int ar2 = sdxl? dxL : -dxL;
1674    int sdxr = (dxR < 0) ? (1<<5) : 0;
1675    int ar5 = sdxr? dxR : -dxR;
1676
1677    WAITFIFO(12);
1678    OUTREG(MGAREG_SHIFT, (paty << 4) | patx);
1679    OUTREG(MGAREG_DWGCTL,
1680	pMga->PatternRectCMD & ~(MGADWG_ARZERO | MGADWG_SGNZERO));
1681    OUTREG(MGAREG_AR0, dyL);
1682    OUTREG(MGAREG_AR1, ar2 - eL);
1683    OUTREG(MGAREG_AR2, ar2);
1684    OUTREG(MGAREG_AR4, ar5 - eR);
1685    OUTREG(MGAREG_AR5, ar5);
1686    OUTREG(MGAREG_AR6, dyR);
1687    OUTREG(MGAREG_SGN, sdxl | sdxr);
1688    OUTREG(MGAREG_FXBNDRY, ((right + 1) << 16) | (left & 0xffff));
1689    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1690    OUTREG(MGAREG_DWGCTL, pMga->PatternRectCMD);
1691}
1692
1693	/***********************\
1694	|   Color Expand Rect   |
1695	\***********************/
1696
1697
1698void mgaSetupForScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn,
1699						    int fg, int bg,
1700						    int rop,
1701						    unsigned int planemask )
1702{
1703    MGAPtr pMga = MGAPTR(pScrn);
1704
1705
1706    CHECK_DMA_QUIESCENT(pMga, pScrn);
1707
1708    (void) common_setup_for_pattern_fill( pMga, fg, bg, rop,
1709					  planemask, NULL, 0,
1710					  MGADWG_ILOAD | MGADWG_LINEAR
1711					  | MGADWG_SGNZERO | MGADWG_SHIFTZERO
1712					  | MGADWG_BMONOLEF );
1713}
1714
1715
1716void mgaSubsequentScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn,
1717	int x, int y, int w, int h,
1718	int skipleft )
1719{
1720    MGAPtr pMga = MGAPTR(pScrn);
1721
1722    pMga->AccelFlags |= CLIPPER_ON;
1723    pMga->expandDWORDs = (w + 31) >> 5;
1724    if((pMga->expandDWORDs * h) > pMga->MaxBlitDWORDS) {
1725	pMga->expandHeight = pMga->MaxBlitDWORDS / pMga->expandDWORDs;
1726	pMga->expandRemaining = h / pMga->expandHeight;
1727	if(!(h = h % pMga->expandHeight)) {
1728	   pMga->expandRemaining--;
1729	   h = pMga->expandHeight;
1730	}
1731	pMga->expandY = y + h;
1732    } else
1733	pMga->expandRemaining = 0;
1734    pMga->expandRows = h;
1735
1736    WAITFIFO(5);
1737    OUTREG(MGAREG_CXBNDRY, ((x + w - 1) << 16) | ((x + skipleft) & 0xFFFF));
1738    w = pMga->expandDWORDs << 5;     /* source is dword padded */
1739    OUTREG(MGAREG_AR0, (w * h) - 1);
1740    OUTREG(MGAREG_AR3, 0);  /* crashes occasionally without this */
1741    OUTREG(MGAREG_FXBNDRY, ((x + w - 1) << 16) | (x & 0xFFFF));
1742    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1743
1744#if defined(__alpha__)
1745    if(1) /* force indirect always on Alpha */
1746#else
1747    if(pMga->expandDWORDs > pMga->FifoSize)
1748#endif
1749    {
1750        pMga->AccelInfoRec->SubsequentColorExpandScanline =
1751                mgaSubsequentColorExpandScanlineIndirect;
1752        pMga->AccelInfoRec->ScanlineColorExpandBuffers =
1753                (unsigned char**)(&pMga->ScratchBuffer);
1754    } else {
1755        pMga->AccelInfoRec->SubsequentColorExpandScanline =
1756                mgaSubsequentColorExpandScanline;
1757        pMga->AccelInfoRec->ScanlineColorExpandBuffers =
1758                (unsigned char**)(&pMga->ColorExpandBase);
1759	WAITFIFO(pMga->expandDWORDs);
1760    }
1761}
1762
1763
1764void mgaSubsequentColorExpandScanlineIndirect( ScrnInfoPtr pScrn,
1765					       int bufno )
1766{
1767    MGAPtr pMga = MGAPTR(pScrn);
1768    int dwords = pMga->expandDWORDs;
1769    CARD32 *src = (CARD32*)(pMga->ScratchBuffer);
1770
1771    while(dwords > pMga->FifoSize) {
1772	WAITFIFO(pMga->FifoSize);
1773	MGAMoveDWORDS((CARD32*)(pMga->ColorExpandBase), src, pMga->FifoSize);
1774	src += pMga->FifoSize;
1775	dwords -= pMga->FifoSize;
1776    }
1777
1778    WAITFIFO(dwords);
1779    MGAMoveDWORDS((CARD32*)(pMga->ColorExpandBase), src, dwords);
1780
1781    if(!(--pMga->expandRows)) {
1782	if(pMga->expandRemaining) {
1783	    WAITFIFO(3);
1784	    OUTREG(MGAREG_AR0,((pMga->expandDWORDs<< 5)*pMga->expandHeight)-1);
1785	    OUTREG(MGAREG_AR3, 0);  /* crashes occasionally without this */
1786	    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (pMga->expandY << 16) |
1787	                                      pMga->expandHeight);
1788	    pMga->expandY += pMga->expandHeight;
1789            pMga->expandRows = pMga->expandHeight;
1790	    pMga->expandRemaining--;
1791	} else {
1792            DISABLE_CLIP();
1793	}
1794    }
1795}
1796
1797
1798void mgaSubsequentColorExpandScanline( ScrnInfoPtr pScrn,
1799				       int bufno )
1800{
1801    MGAPtr pMga = MGAPTR(pScrn);
1802
1803    if(--pMga->expandRows) {
1804	WAITFIFO(pMga->expandDWORDs);
1805    } else if(pMga->expandRemaining) {
1806	WAITFIFO(3);
1807	OUTREG(MGAREG_AR0,((pMga->expandDWORDs<<5)*pMga->expandHeight)-1);
1808	OUTREG(MGAREG_AR3, 0);  /* crashes occasionally without this */
1809	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (pMga->expandY << 16) |
1810	                                      pMga->expandHeight);
1811	pMga->expandY += pMga->expandHeight;
1812        pMga->expandRows = pMga->expandHeight;
1813	pMga->expandRemaining--;
1814	WAITFIFO(pMga->expandDWORDs);
1815    } else {
1816        DISABLE_CLIP();
1817    }
1818}
1819
1820
1821	/*******************\
1822	|   Image Writes    |
1823	\*******************/
1824
1825
1826void mgaSetupForScanlineImageWrite( ScrnInfoPtr pScrn, int rop,
1827				    unsigned int planemask,
1828				    int transparency_color,
1829				    int bpp, int depth )
1830{
1831    MGAPtr pMga = MGAPTR(pScrn);
1832    unsigned int replicate_pm = 0;
1833
1834    switch( pMga->CurrentLayout.bitsPerPixel ) {
1835    case 8:
1836	replicate_pm = REPLICATE_8( planemask );
1837	break;
1838    case 16:
1839	replicate_pm = REPLICATE_16( planemask );
1840	break;
1841    case 24:
1842	replicate_pm = REPLICATE_24( planemask );
1843	break;
1844    case 32:
1845	replicate_pm = REPLICATE_32( planemask );
1846	break;
1847    }
1848
1849    CHECK_DMA_QUIESCENT(pMga, pScrn);
1850
1851    WAITFIFO(3);
1852    OUTREG(MGAREG_AR5, 0);
1853    SET_PLANEMASK_REPLICATED( planemask, replicate_pm,
1854			      pMga->CurrentLayout.bitsPerPixel );
1855    OUTREG(MGAREG_DWGCTL, MGADWG_ILOAD | MGADWG_BFCOL | MGADWG_SHIFTZERO |
1856			MGADWG_SGNZERO | pMga->AtypeNoBLK[rop]);
1857}
1858
1859
1860void mgaSubsequentScanlineImageWriteRect( ScrnInfoPtr pScrn,
1861					  int x, int y, int w, int h,
1862					  int skipleft )
1863{
1864    MGAPtr pMga = MGAPTR(pScrn);
1865
1866    pMga->AccelFlags |= CLIPPER_ON;
1867    pMga->expandRows = h;
1868    pMga->expandDWORDs = ((w * pMga->CurrentLayout.bitsPerPixel) + 31) >> 5;
1869
1870    WAITFIFO(5);
1871    OUTREG(MGAREG_CXBNDRY, 0xFFFF0000 | ((x + skipleft) & 0xFFFF));
1872    OUTREG(MGAREG_AR0, w - 1);
1873    OUTREG(MGAREG_AR3, 0);
1874    OUTREG(MGAREG_FXBNDRY, ((x + w - 1) << 16) | (x & 0xFFFF));
1875    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1876}
1877
1878
1879void mgaSubsequentImageWriteScanline( ScrnInfoPtr pScrn, int bufno )
1880{
1881    MGAPtr pMga = MGAPTR(pScrn);
1882    int dwords = pMga->expandDWORDs;
1883    CARD32 *src = (CARD32*)(pMga->ScratchBuffer);
1884
1885    while(dwords > pMga->FifoSize) {
1886	WAITFIFO(pMga->FifoSize);
1887        MGAMoveDWORDS((CARD32*)(pMga->ColorExpandBase), src, pMga->FifoSize);
1888        src += pMga->FifoSize;
1889        dwords -= pMga->FifoSize;
1890    }
1891
1892    WAITFIFO(dwords);
1893    MGAMoveDWORDS((CARD32*)(pMga->ColorExpandBase), src, dwords);
1894
1895    if(!(--pMga->expandRows)) {
1896	DISABLE_CLIP();
1897    }
1898}
1899
1900
1901#if X_BYTE_ORDER == X_LITTLE_ENDIAN
1902
1903	/***************************\
1904	|      Dashed  Lines        |
1905	\***************************/
1906
1907void mgaSetupForDashedLine( ScrnInfoPtr pScrn,
1908			    int fg, int bg, int rop,
1909			    unsigned int planemask, int length,
1910			    unsigned char *pattern )
1911{
1912    MGAPtr pMga = MGAPTR(pScrn);
1913    CARD32 *DashPattern = (CARD32*)pattern;
1914    CARD32 NiceDashPattern = DashPattern[0];
1915    int dwords = (length + 31) >> 5;
1916    unsigned int replicate_fg = 0;
1917    unsigned int replicate_bg = 0;
1918    unsigned int replicate_pm = 0;
1919
1920
1921    common_replicate_colors_and_mask( fg, bg, planemask,
1922				      pMga->CurrentLayout.bitsPerPixel,
1923				      & replicate_fg, & replicate_bg,
1924				      & replicate_pm );
1925
1926    CHECK_DMA_QUIESCENT(pMga, pScrn);
1927
1928    pMga->DashCMD = MGADWG_BFCOL | pMga->AtypeNoBLK[rop];
1929    pMga->StyleLen = length - 1;
1930
1931    if(bg == -1) {
1932        pMga->DashCMD |= MGADWG_TRANSC;
1933	WAITFIFO(dwords + 2);
1934    } else {
1935	WAITFIFO(dwords + 3);
1936	SET_BACKGROUND_REPLICATED( bg, replicate_bg );
1937    }
1938
1939    SET_PLANEMASK_REPLICATED( planemask, replicate_pm,
1940			      pMga->CurrentLayout.bitsPerPixel );
1941    SET_FOREGROUND_REPLICATED( fg, replicate_fg );
1942
1943
1944    /* We see if we can draw horizontal lines as 8x8 pattern fills.  This is
1945     * worthwhile since the pattern fills can use block mode and the default X
1946     * pattern is 8 pixels long.  The forward pattern is the top scanline, the
1947     * backwards pattern is the next one.
1948     */
1949    switch(length) {
1950    case 2:	NiceDashPattern |= NiceDashPattern << 2;
1951    case 4:	NiceDashPattern |= NiceDashPattern << 4;
1952    case 8: {
1953	NiceDashPattern |= byte_reversed[NiceDashPattern] << 16;
1954	NiceDashPattern |= NiceDashPattern << 8;
1955	pMga->NiceDashCMD = MGADWG_TRAP | MGADWG_ARZERO |
1956	  MGADWG_SGNZERO | MGADWG_BMONOLEF;
1957	pMga->AccelFlags |= NICE_DASH_PATTERN;
1958
1959	if( bg == -1 ) {
1960	    if ( (pMga->CurrentLayout.bitsPerPixel == 24) && !RGBEQUAL(fg) ) {
1961		pMga->NiceDashCMD |= MGADWG_TRANSC | pMga->AtypeNoBLK[rop];
1962	    }
1963	    else {
1964		pMga->NiceDashCMD |= MGADWG_TRANSC | pMga->Atype[rop];
1965	    }
1966	}
1967	else {
1968	    /* (Packed) 24-bit is a funky mode.  We only use the Atype table
1969	     * in 24-bit if the components of the foreground color and the
1970	     * components of the background color are the same (e.g., fg =
1971	     * 0xf8f8f8 and bg = 0x131313).
1972	     */
1973
1974	    if( ((pMga->AccelFlags & BLK_OPAQUE_EXPANSION) != 0)
1975		&& ((pMga->CurrentLayout.bitsPerPixel != 24)
1976		    || (RGBEQUAL(fg) && RGBEQUAL(bg))) ) {
1977		pMga->NiceDashCMD |= pMga->Atype[rop];
1978	    }
1979	    else {
1980		pMga->NiceDashCMD |= pMga->AtypeNoBLK[rop];
1981	    }
1982	}
1983	OUTREG(MGAREG_SRC0, NiceDashPattern);
1984	break;
1985    }
1986    default: {
1987	pMga->AccelFlags &= ~NICE_DASH_PATTERN;
1988	switch (dwords) {
1989	case 4:  OUTREG(MGAREG_SRC3, DashPattern[3]);
1990	case 3:  OUTREG(MGAREG_SRC2, DashPattern[2]);
1991	case 2:	 OUTREG(MGAREG_SRC1, DashPattern[1]);
1992	default: OUTREG(MGAREG_SRC0, DashPattern[0]);
1993	}
1994    }
1995    }
1996}
1997
1998
1999void mgaSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn,
2000				      int x1, int y1, int x2, int y2,
2001				      int flags, int phase )
2002{
2003    MGAPtr pMga = MGAPTR(pScrn);
2004
2005    WAITFIFO(4);
2006    if((pMga->AccelFlags & NICE_DASH_PATTERN) && (y1 == y2)) {
2007    	OUTREG(MGAREG_DWGCTL, pMga->NiceDashCMD);
2008	if(x2 < x1) {
2009	   if(flags & OMIT_LAST) x2++;
2010   	   OUTREG(MGAREG_SHIFT, ((-y1 & 0x07) << 4) |
2011				((7 - phase - x1) & 0x07));
2012   	   OUTREG(MGAREG_FXBNDRY, ((x1 + 1) << 16) | (x2 & 0xffff));
2013    	} else {
2014 	   if(!flags) x2++;
2015   	   OUTREG(MGAREG_SHIFT, (((1 - y1) & 0x07) << 4) |
2016				((phase - x1) & 0x07));
2017     	   OUTREG(MGAREG_FXBNDRY, (x2 << 16) | (x1 & 0xffff));
2018	}
2019    	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y1 << 16) | 1);
2020    } else {
2021	OUTREG(MGAREG_SHIFT, (pMga->StyleLen << 16 ) |
2022				(pMga->StyleLen - phase));
2023	OUTREG(MGAREG_DWGCTL, pMga->DashCMD | ((flags & OMIT_LAST) ?
2024			MGADWG_AUTOLINE_OPEN : MGADWG_AUTOLINE_CLOSE));
2025	OUTREG(MGAREG_XYSTRT, (y1 << 16) | (x1 & 0xFFFF));
2026	OUTREG(MGAREG_XYEND + MGAREG_EXEC, (y2 << 16) | (x2 & 0xFFFF));
2027    }
2028}
2029#endif /* X_BYTE_ORDER == X_LITTLE_ENDIAN */
2030
2031
2032	/******************************************\
2033	|  Planar Screen to Screen Color Expansion |
2034	\******************************************/
2035
2036void mgaSetupForPlanarScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
2037						     int fg, int bg,
2038						     int rop,
2039						     unsigned int planemask )
2040{
2041    MGAPtr pMga = MGAPTR(pScrn);
2042    CARD32 mgaCMD = pMga->AtypeNoBLK[rop] | MGADWG_BITBLT |
2043				MGADWG_SGNZERO | MGADWG_BPLAN;
2044    CARD32 regs[2];
2045
2046
2047    regs[0] = MGAREG_AR5;
2048    regs[1] = pScrn->displayWidth;
2049
2050    CHECK_DMA_QUIESCENT(pMga, pScrn);
2051
2052    (void) common_setup_for_pattern_fill( pMga, fg, bg, 0, planemask, regs, 1,
2053					  mgaCMD );
2054}
2055
2056
2057void mgaSubsequentPlanarScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
2058						       int x, int y, int w, int h,
2059						       int srcx, int srcy,
2060						       int skipleft )
2061{
2062    MGAPtr pMga = MGAPTR(pScrn);
2063    int start, end;
2064
2065    w--;
2066    start = XYADDRESS(srcx, srcy) + skipleft;
2067    end = start + w;
2068
2069    WAITFIFO(4);
2070    OUTREG(MGAREG_AR3, start);
2071    OUTREG(MGAREG_AR0, end);
2072    OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff));
2073    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
2074}
2075
2076
2077	/***********************************\
2078	|  Screen to Screen Color Expansion |
2079	\***********************************/
2080
2081void mgaSetupForScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
2082					       int fg, int bg,
2083					       int rop,
2084					       unsigned int planemask )
2085{
2086    MGAPtr pMga = MGAPTR(pScrn);
2087    CARD32 regs[2];
2088
2089    regs[0] = MGAREG_AR5;
2090    regs[1] = pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel;
2091
2092    CHECK_DMA_QUIESCENT(pMga, pScrn);
2093
2094    (void) common_setup_for_pattern_fill( pMga, fg, bg, rop, planemask,
2095					  regs, 1,
2096					  MGADWG_BITBLT | MGADWG_SGNZERO
2097					  | MGADWG_SHIFTZERO );
2098}
2099
2100
2101void mgaSubsequentScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
2102						 int x, int y, int w, int h,
2103						 int srcx, int srcy,
2104						 int skipleft )
2105{
2106    MGAPtr pMga = MGAPTR(pScrn);
2107    const unsigned int display_bit_width =
2108      (pMga->CurrentLayout.displayWidth * pMga->CurrentLayout.bitsPerPixel);
2109    int start, end, next, num;
2110    Bool resetDstOrg = FALSE;
2111
2112    if (pMga->AccelFlags & LARGE_ADDRESSES) {
2113        const int DstOrg = ((y & ~1023) * display_bit_width) >> 9;
2114        const int SrcOrg = ((srcy & ~1023) * display_bit_width) >> 9;
2115
2116	y &= 1023;
2117	srcy &= 1023;
2118
2119	WAITFIFO(2);
2120	if(DstOrg) {
2121            OUTREG(MGAREG_DSTORG, (DstOrg << 6) + pMga->DstOrg);
2122	    resetDstOrg = TRUE;
2123	}
2124        if(SrcOrg != pMga->SrcOrg) {
2125            pMga->SrcOrg = SrcOrg;
2126            OUTREG(MGAREG_SRCORG, (SrcOrg << 6) + pMga->realSrcOrg);
2127        }
2128    }
2129
2130    w--;
2131    start = (XYADDRESS(srcx, srcy) * pMga->CurrentLayout.bitsPerPixel)
2132      + skipleft;
2133    end = start + w + (display_bit_width * (h - 1));
2134
2135    /* src cannot split a 2 Meg boundary from SrcOrg */
2136    if(!((start ^ end) & 0xff000000)) {
2137	WAITFIFO(4);
2138	OUTREG(MGAREG_AR3, start);
2139	OUTREG(MGAREG_AR0, start + w);
2140	OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff));
2141	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
2142    } else {
2143	while(h) {
2144	    next = (start + 0x00ffffff) & 0xff000000;
2145	    if(next <= (start + w)) {
2146		num = next - start - 1;
2147
2148		WAITFIFO(7);
2149		OUTREG(MGAREG_AR3, start);
2150		OUTREG(MGAREG_AR0, start + num);
2151		OUTREG(MGAREG_FXBNDRY, ((x + num) << 16) | (x & 0xffff));
2152		OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | 1);
2153
2154		OUTREG(MGAREG_AR3, next);
2155		OUTREG(MGAREG_AR0, start + w );
2156		OUTREG(MGAREG_FXBNDRY + MGAREG_EXEC, ((x + w) << 16) |
2157                                                     ((x + num + 1) & 0xffff));
2158		start += display_bit_width;
2159		h--; y++;
2160	    } else {
2161		num = ((next - start - w)/display_bit_width) + 1;
2162		if(num > h) num = h;
2163
2164		WAITFIFO(4);
2165		OUTREG(MGAREG_AR3, start);
2166		OUTREG(MGAREG_AR0, start + w);
2167		OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff));
2168		OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | num);
2169
2170		start += num * display_bit_width;
2171		h -= num; y += num;
2172	    }
2173	}
2174    }
2175
2176    if(resetDstOrg) {
2177	WAITFIFO(1);
2178	OUTREG(MGAREG_DSTORG, pMga->DstOrg);
2179    }
2180}
2181
2182
2183static void
2184MGAFillSolidRectsDMA(
2185    ScrnInfoPtr pScrn,
2186    int	fg, int rop,
2187    unsigned int planemask,
2188    int		nBox, 		/* number of rectangles to fill */
2189    BoxPtr	pBox  		/* Pointer to first rectangle to fill */
2190){
2191    MGAPtr pMga = MGAPTR(pScrn);
2192    XAAInfoRecPtr infoRec = pMga->AccelInfoRec;
2193    CARD32 *base = (CARD32*)pMga->ILOADBase;
2194
2195    CHECK_DMA_QUIESCENT(pMga, pScrn);
2196
2197    SET_SYNC_FLAG(infoRec);
2198    (*infoRec->SetupForSolidFill)(pScrn, fg, rop, planemask);
2199
2200    if(nBox & 1) {
2201	OUTREG(MGAREG_FXBNDRY, ((pBox->x2) << 16) | (pBox->x1 & 0xffff));
2202	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC,
2203		(pBox->y1 << 16) | (pBox->y2 - pBox->y1));
2204	nBox--; pBox++;
2205    }
2206
2207    if(!nBox) return;
2208
2209    OUTREG(MGAREG_OPMODE, MGAOPM_DMA_GENERAL);
2210    while(nBox) {
2211	base[0] = DMAINDICES(MGAREG_FXBNDRY, MGAREG_YDSTLEN + MGAREG_EXEC,
2212                MGAREG_FXBNDRY, MGAREG_YDSTLEN + MGAREG_EXEC);
2213	base[1] = ((pBox->x2) << 16) | (pBox->x1 & 0xffff);
2214	base[2] = (pBox->y1 << 16) | (pBox->y2 - pBox->y1);
2215	pBox++;
2216	base[3] = ((pBox->x2) << 16) | (pBox->x1 & 0xffff);
2217	base[4] = (pBox->y1 << 16) | (pBox->y2 - pBox->y1);
2218	pBox++;
2219	base += 5; nBox -= 2;
2220    }
2221    OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT);
2222}
2223
2224static void
2225MGAFillSolidSpansDMA(
2226   ScrnInfoPtr pScrn,
2227   int fg, int rop,
2228   unsigned int planemask,
2229   int n,
2230   DDXPointPtr ppt,
2231   int *pwidth, int fSorted
2232){
2233    MGAPtr pMga = MGAPTR(pScrn);
2234    XAAInfoRecPtr infoRec = pMga->AccelInfoRec;
2235    CARD32 *base = (CARD32*)pMga->ILOADBase;
2236
2237    CHECK_DMA_QUIESCENT(pMga, pScrn);
2238    SET_SYNC_FLAG(infoRec);
2239
2240    if(infoRec->ClipBox) {
2241	OUTREG(MGAREG_CXBNDRY,
2242	   ((infoRec->ClipBox->x2 - 1) << 16) | infoRec->ClipBox->x1);
2243	OUTREG(MGAREG_YTOP,
2244	   (infoRec->ClipBox->y1 * pScrn->displayWidth) + pMga->YDstOrg);
2245	OUTREG(MGAREG_YBOT,
2246	   ((infoRec->ClipBox->y2 - 1) * pScrn->displayWidth) + pMga->YDstOrg);
2247    }
2248
2249    (*infoRec->SetupForSolidFill)(pScrn, fg, rop, planemask);
2250
2251    if(n & 1) {
2252	OUTREG(MGAREG_FXBNDRY, ((ppt->x + *pwidth) << 16) | (ppt->x & 0xffff));
2253	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (ppt->y << 16) | 1);
2254	ppt++; pwidth++; n--;
2255    }
2256
2257    if(n) {
2258	if(n > 838860) n = 838860;  /* maximum number we have room for */
2259
2260	OUTREG(MGAREG_OPMODE, MGAOPM_DMA_GENERAL);
2261	while(n) {
2262	    base[0] = DMAINDICES(MGAREG_FXBNDRY, MGAREG_YDSTLEN + MGAREG_EXEC,
2263                MGAREG_FXBNDRY, MGAREG_YDSTLEN + MGAREG_EXEC);
2264	    base[1] = ((ppt->x + *(pwidth++)) << 16) | (ppt->x & 0xffff);
2265	    base[2] = (ppt->y << 16) | 1;
2266	    ppt++;
2267	    base[3] = ((ppt->x + *(pwidth++)) << 16) | (ppt->x & 0xffff);
2268	    base[4] = (ppt->y << 16) | 1;
2269	    ppt++;
2270	    base += 5; n -= 2;
2271	}
2272	OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT);
2273    }
2274
2275    if(infoRec->ClipBox) {
2276	OUTREG(MGAREG_CXBNDRY, 0xFFFF0000);     /* (maxX << 16) | minX */
2277	OUTREG(MGAREG_YTOP, 0x00000000);        /* minPixelPointer */
2278	OUTREG(MGAREG_YBOT, 0x007FFFFF);        /* maxPixelPointer */
2279    }
2280}
2281
2282
2283static void
2284MGAFillMono8x8PatternRectsTwoPass(
2285    ScrnInfoPtr pScrn,
2286    int	fg, int bg, int rop,
2287    unsigned int planemask,
2288    int	nBoxInit,
2289    BoxPtr pBoxInit,
2290    int pattern0, int pattern1,
2291    int xorg, int yorg
2292){
2293    MGAPtr pMga = MGAPTR(pScrn);
2294    XAAInfoRecPtr infoRec = pMga->AccelInfoRec;
2295    int	nBox, SecondPassColor;
2296    BoxPtr pBox;
2297
2298    CHECK_DMA_QUIESCENT(pMga, pScrn);
2299
2300    if((rop == GXcopy) && (bg != -1)) {
2301	SecondPassColor = bg;
2302	bg = -1;
2303    } else SecondPassColor = -1;
2304
2305    WAITFIFO(1);
2306    OUTREG(MGAREG_SHIFT, (((-yorg) & 0x07) << 4) | ((-xorg) & 0x07));
2307
2308SECOND_PASS:
2309
2310    nBox = nBoxInit;
2311    pBox = pBoxInit;
2312
2313    (*infoRec->SetupForMono8x8PatternFill)(pScrn, pattern0, pattern1,
2314					fg, bg, rop, planemask);
2315
2316    while(nBox--) {
2317	WAITFIFO(2);
2318	OUTREG(MGAREG_FXBNDRY, ((pBox->x2) << 16) | (pBox->x1 & 0xffff));
2319	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC,
2320			(pBox->y1 << 16) | (pBox->y2 - pBox->y1));
2321	pBox++;
2322    }
2323
2324    if(SecondPassColor != -1) {
2325	fg = SecondPassColor;
2326	SecondPassColor = -1;
2327	pattern0 = ~pattern0;
2328	pattern1 = ~pattern1;
2329	goto SECOND_PASS;
2330    }
2331
2332    SET_SYNC_FLAG(infoRec);
2333}
2334
2335
2336static void
2337MGAValidatePolyArc(
2338   GCPtr 	pGC,
2339   unsigned long changes,
2340   DrawablePtr pDraw
2341){
2342   ScrnInfoPtr pScrn = xf86Screens[pGC->pScreen->myNum];
2343   MGAPtr pMga = MGAPTR(pScrn);
2344   Bool fullPlanemask = TRUE;
2345
2346   if((pGC->planemask & pMga->AccelInfoRec->FullPlanemask) !=
2347	pMga->AccelInfoRec->FullPlanemask)
2348   {
2349	if(pMga->AccelFlags & MGA_NO_PLANEMASK) return;
2350	fullPlanemask = FALSE;
2351   }
2352
2353   if(!pGC->lineWidth &&
2354      (pGC->fillStyle == FillSolid) &&
2355      (pGC->lineStyle == LineSolid) &&
2356      ((pGC->alu != GXcopy) || !fullPlanemask))
2357   {
2358	pGC->ops->PolyArc = MGAPolyArcThinSolid;
2359   }
2360}
2361
2362static void
2363MGAPolyPoint (
2364    DrawablePtr pDraw,
2365    GCPtr pGC,
2366    int mode,
2367    int npt,
2368    xPoint *ppt
2369){
2370    int numRects = REGION_NUM_RECTS(pGC->pCompositeClip);
2371    XAAInfoRecPtr infoRec;
2372    BoxPtr pbox;
2373    MGAPtr pMga;
2374    int xorg, yorg;
2375    ScrnInfoPtr pScrn;
2376
2377    if(!numRects) return;
2378
2379    if(numRects != 1) {
2380	XAAGetFallbackOps()->PolyPoint(pDraw, pGC, mode, npt, ppt);
2381	return;
2382    }
2383
2384    infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
2385    pScrn = infoRec->pScrn;
2386    pMga = MGAPTR(pScrn);
2387    xorg = pDraw->x;
2388    yorg = pDraw->y;
2389
2390    pbox = REGION_RECTS(pGC->pCompositeClip);
2391
2392    (*infoRec->SetClippingRectangle)(infoRec->pScrn,
2393                pbox->x1, pbox->y1, pbox->x2 - 1, pbox->y2 - 1);
2394    (*infoRec->SetupForSolidFill)(infoRec->pScrn, pGC->fgPixel, pGC->alu,
2395				   pGC->planemask);
2396
2397    if(mode == CoordModePrevious) {
2398	while(npt--) {
2399	    xorg += ppt->x;
2400	    yorg += ppt->y;
2401	    WAITFIFO(2);
2402	    OUTREG(MGAREG_FXBNDRY, ((xorg + 1) << 16) | (xorg & 0xffff));
2403	    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (yorg << 16) | 1);
2404	    ppt++;
2405	}
2406    } else {
2407	int x;
2408	while(npt--) {
2409	    x = ppt->x + xorg;
2410	    WAITFIFO(2);
2411	    OUTREG(MGAREG_FXBNDRY, ((x + 1) << 16) | (x & 0xffff));
2412	    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, ((ppt->y + yorg) << 16) | 1);
2413	    ppt++;
2414	}
2415    }
2416
2417    (*infoRec->DisableClipping)(infoRec->pScrn);
2418
2419    SET_SYNC_FLAG(infoRec);
2420}
2421
2422
2423static void
2424MGAValidatePolyPoint(
2425   GCPtr 	pGC,
2426   unsigned long changes,
2427   DrawablePtr pDraw
2428){
2429   ScrnInfoPtr pScrn = xf86Screens[pGC->pScreen->myNum];
2430   MGAPtr pMga = MGAPTR(pScrn);
2431   Bool fullPlanemask = TRUE;
2432
2433   pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint;
2434
2435   if((pGC->planemask & pMga->AccelInfoRec->FullPlanemask) !=
2436	pMga->AccelInfoRec->FullPlanemask)
2437   {
2438	if(pMga->AccelFlags & MGA_NO_PLANEMASK) return;
2439	fullPlanemask = FALSE;
2440   }
2441
2442   if((pGC->alu != GXcopy) || !fullPlanemask)
2443	pGC->ops->PolyPoint = MGAPolyPoint;
2444}
2445
2446
2447static void
2448MGAFillCacheBltRects(
2449   ScrnInfoPtr pScrn,
2450   int rop,
2451   unsigned int planemask,
2452   int nBox,
2453   BoxPtr pBox,
2454   int xorg, int yorg,
2455   XAACacheInfoPtr pCache
2456){
2457    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
2458    int x, y, phaseY, phaseX, skipleft, height, width, w, blit_w, blit_h, start;
2459
2460    CHECK_DMA_QUIESCENT(MGAPTR(pScrn), pScrn);
2461
2462    (*infoRec->SetupForScreenToScreenCopy)(pScrn, 1, 1, rop, planemask,
2463		pCache->trans_color);
2464
2465    while(nBox--) {
2466	y = pBox->y1;
2467	phaseY = (y - yorg) % pCache->orig_h;
2468	if(phaseY < 0) phaseY += pCache->orig_h;
2469	phaseX = (pBox->x1 - xorg) % pCache->orig_w;
2470	if(phaseX < 0) phaseX += pCache->orig_w;
2471	height = pBox->y2 - y;
2472	width = pBox->x2 - pBox->x1;
2473	start = phaseY ? (pCache->orig_h - phaseY) : 0;
2474
2475	/* This is optimized for WRAM */
2476
2477	if ((rop == GXcopy) && (height >= (pCache->orig_h + start))) {
2478	    w = width; skipleft = phaseX; x = pBox->x1;
2479	    blit_h = pCache->orig_h;
2480
2481	    while(1) {
2482		blit_w = pCache->w - skipleft;
2483		if(blit_w > w) blit_w = w;
2484		(*infoRec->SubsequentScreenToScreenCopy)(pScrn,
2485			pCache->x + skipleft, pCache->y,
2486			x, y + start, blit_w, blit_h);
2487		w -= blit_w;
2488		if(!w) break;
2489		x += blit_w;
2490		skipleft = (skipleft + blit_w) % pCache->orig_w;
2491	    }
2492	    height -= blit_h;
2493
2494	    if(start) {
2495		(*infoRec->SubsequentScreenToScreenCopy)(pScrn,
2496			pBox->x1, y + blit_h, pBox->x1, y, width, start);
2497		height -= start;
2498		y += start;
2499	    }
2500	    start = blit_h;
2501
2502	    while(height) {
2503		if(blit_h > height) blit_h = height;
2504		(*infoRec->SubsequentScreenToScreenCopy)(pScrn,
2505			pBox->x1, y,
2506			pBox->x1, y + start, width, blit_h);
2507		height -= blit_h;
2508		start += blit_h;
2509		blit_h <<= 1;
2510	    }
2511	} else {
2512	    while(1) {
2513		w = width; skipleft = phaseX; x = pBox->x1;
2514		blit_h = pCache->h - phaseY;
2515		if(blit_h > height) blit_h = height;
2516
2517		while(1) {
2518		    blit_w = pCache->w - skipleft;
2519		    if(blit_w > w) blit_w = w;
2520		    (*infoRec->SubsequentScreenToScreenCopy)(pScrn,
2521			pCache->x + skipleft, pCache->y + phaseY,
2522			x, y, blit_w, blit_h);
2523		    w -= blit_w;
2524		    if(!w) break;
2525		    x += blit_w;
2526		    skipleft = (skipleft + blit_w) % pCache->orig_w;
2527		}
2528		height -= blit_h;
2529		if(!height) break;
2530		y += blit_h;
2531		phaseY = (phaseY + blit_h) % pCache->orig_h;
2532	    }
2533	}
2534	pBox++;
2535    }
2536
2537    SET_SYNC_FLAG(infoRec);
2538}
2539