mga_storm.c revision eda3803b
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	pMga->SrcOrg = 0;
1134	OUTREG(MGAREG_SRCORG, pMga->realSrcOrg);
1135	OUTREG(MGAREG_DSTORG, pMga->DstOrg);
1136	break;
1137    default:
1138	break;
1139    }
1140
1141    if (pMga->is_G200WB)
1142    {
1143        CARD32 dwgctl = MGADWG_RSTR | 0x00060000 | MGADWG_SHIFTZERO |
1144			MGADWG_BITBLT | MGADWG_BFCOL;
1145        WAITFIFO(7);
1146        OUTREG(MGAREG_DWGCTL, dwgctl);
1147        OUTREG(MGAREG_SGN, 0);
1148        OUTREG(MGAREG_AR5, 1);
1149        OUTREG(MGAREG_AR0, 1);
1150        OUTREG(MGAREG_AR3, 0);
1151        OUTREG(MGAREG_FXBNDRY, (1 << 16) | (1 & 0xffff));
1152        OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (1 << 16) | 1);
1153    }
1154
1155    xf86SetLastScrnFlag(pScrn->entityList[0], pScrn->scrnIndex);
1156}
1157
1158
1159static void
1160MGASetClippingRectangle(
1161   ScrnInfoPtr pScrn,
1162   int x1, int y1, int x2, int y2
1163){
1164    MGAPtr pMga = MGAPTR(pScrn);
1165
1166    CHECK_DMA_QUIESCENT(pMga, pScrn);
1167
1168    WAITFIFO(3);
1169    OUTREG(MGAREG_CXBNDRY,(x2 << 16) | x1);
1170    OUTREG(MGAREG_YTOP, (y1 * pScrn->displayWidth) + pMga->YDstOrg);
1171    OUTREG(MGAREG_YBOT, (y2 * pScrn->displayWidth) + pMga->YDstOrg);
1172    pMga->AccelFlags |= CLIPPER_ON;
1173}
1174
1175static void
1176MGADisableClipping(ScrnInfoPtr pScrn)
1177{
1178    MGAPtr pMga = MGAPTR(pScrn);
1179
1180    CHECK_DMA_QUIESCENT(pMga, pScrn);
1181
1182    WAITFIFO(3);
1183    OUTREG(MGAREG_CXBNDRY, 0xFFFF0000);     /* (maxX << 16) | minX */
1184    OUTREG(MGAREG_YTOP, 0x00000000);        /* minPixelPointer */
1185    OUTREG(MGAREG_YBOT, 0x007FFFFF);        /* maxPixelPointer */
1186    pMga->AccelFlags &= ~CLIPPER_ON;
1187}
1188
1189
1190static CARD32
1191common_setup_for_pattern_fill( MGAPtr pMga, int fg, int bg, int rop,
1192			       int planemask,
1193			       CARD32 * reg_data, unsigned int count,
1194			       CARD32 cmd )
1195{
1196    unsigned int replicate_fg = 0;
1197    unsigned int replicate_bg = 0;
1198    unsigned int replicate_pm = 0;
1199    unsigned int i;
1200
1201
1202    common_replicate_colors_and_mask( fg, bg, planemask,
1203				      pMga->CurrentLayout.bitsPerPixel,
1204				      & replicate_fg, & replicate_bg,
1205				      & replicate_pm );
1206
1207
1208    if( bg == -1 ) {
1209    	if ( (pMga->CurrentLayout.bitsPerPixel == 24) && !RGBEQUAL(fg) ) {
1210            cmd |= MGADWG_TRANSC | pMga->AtypeNoBLK[rop];
1211	}
1212	else {
1213            cmd |= MGADWG_TRANSC | pMga->Atype[rop];
1214	}
1215
1216	WAITFIFO( count + 3 );
1217    }
1218    else {
1219	/* (Packed) 24-bit is a funky mode.  We only use the Atype table in
1220	 * 24-bit if the components of the foreground color and the components
1221	 * of the background color are the same (e.g., fg = 0xf8f8f8 and bg =
1222	 * 0x131313).
1223	 */
1224
1225	if( ((pMga->AccelFlags & BLK_OPAQUE_EXPANSION) != 0)
1226	    && ((pMga->CurrentLayout.bitsPerPixel != 24)
1227		|| (RGBEQUAL(fg) && RGBEQUAL(bg))) ) {
1228	    cmd |= pMga->Atype[rop];
1229	}
1230	else {
1231	    cmd |= pMga->AtypeNoBLK[rop];
1232	}
1233
1234	WAITFIFO( count + 4 );
1235	SET_BACKGROUND_REPLICATED( bg, replicate_bg );
1236    }
1237
1238    SET_FOREGROUND_REPLICATED( fg, replicate_fg );
1239    SET_PLANEMASK_REPLICATED( planemask, replicate_pm,
1240			      pMga->CurrentLayout.bitsPerPixel );
1241
1242    /* FIXME: Is this the right order? */
1243
1244    for ( i = 0 ; i < count ; i++ ) {
1245	OUTREG( reg_data[0], reg_data[1] );
1246	reg_data += 2;
1247    }
1248
1249    OUTREG(MGAREG_DWGCTL, cmd);
1250
1251    return cmd;
1252}
1253
1254
1255	/*********************************************\
1256	|            Screen-to-Screen Copy            |
1257	\*********************************************/
1258
1259#define BLIT_LEFT	1
1260#define BLIT_UP		4
1261
1262void mgaDoSetupForScreenToScreenCopy( ScrnInfoPtr pScrn, int xdir, int ydir,
1263				      int rop, unsigned int planemask,
1264				      int trans, unsigned bpp )
1265{
1266    MGAPtr pMga = MGAPTR(pScrn);
1267    CARD32 dwgctl = pMga->AtypeNoBLK[rop] | MGADWG_SHIFTZERO |
1268			MGADWG_BITBLT | MGADWG_BFCOL;
1269    unsigned int tmp;
1270    unsigned int replicated_trans = 0;
1271    unsigned int replicated_mask = 0;
1272
1273
1274    CHECK_DMA_QUIESCENT(pMga, pScrn);
1275
1276    pMga->AccelInfoRec->SubsequentScreenToScreenCopy =
1277      mgaSubsequentScreenToScreenCopy;
1278
1279    pMga->BltScanDirection = 0;
1280    if(ydir == -1) pMga->BltScanDirection |= BLIT_UP;
1281    if(xdir == -1)
1282	pMga->BltScanDirection |= BLIT_LEFT;
1283    else if(pMga->HasFBitBlt && (rop == GXcopy) && !pMga->DrawTransparent)
1284	pMga->AccelInfoRec->SubsequentScreenToScreenCopy =
1285		mgaSubsequentScreenToScreenCopy_FastBlit;
1286
1287
1288    common_replicate_colors_and_mask( trans, 0, planemask, bpp,
1289				      & replicated_trans, & tmp,
1290				      & replicated_mask );
1291
1292    if(pMga->DrawTransparent) {
1293	dwgctl |= MGADWG_TRANSC;
1294	WAITFIFO(2);
1295
1296	SET_FOREGROUND_REPLICATED( trans, replicated_trans );
1297	SET_BACKGROUND_REPLICATED( ~0, ~0 );
1298    }
1299
1300    WAITFIFO(4);
1301    OUTREG(MGAREG_DWGCTL, dwgctl);
1302    OUTREG(MGAREG_SGN, pMga->BltScanDirection);
1303
1304    SET_PLANEMASK_REPLICATED( planemask, replicated_mask, bpp );
1305    OUTREG(MGAREG_AR5, ydir * pMga->CurrentLayout.displayWidth);
1306}
1307
1308
1309void mgaSetupForScreenToScreenCopy( ScrnInfoPtr pScrn, int xdir, int ydir,
1310				    int rop, unsigned int planemask,
1311				    int trans )
1312{
1313    MGAPtr pMga = MGAPTR(pScrn);
1314
1315    mgaDoSetupForScreenToScreenCopy( pScrn, xdir, ydir, rop, planemask, trans,
1316				     pMga->CurrentLayout.bitsPerPixel );
1317}
1318
1319
1320void mgaSubsequentScreenToScreenCopy( ScrnInfoPtr pScrn,
1321				      int srcX, int srcY, int dstX, int dstY,
1322				      int w, int h )
1323{
1324    int start, end, SrcOrg = 0, DstOrg = 0;
1325    MGAPtr pMga = MGAPTR(pScrn);
1326
1327    if (pMga->AccelFlags & LARGE_ADDRESSES) {
1328	const unsigned int display_bit_width =
1329	  (pMga->CurrentLayout.displayWidth * pMga->CurrentLayout.bitsPerPixel);
1330
1331	SrcOrg = ((srcY & ~1023) * display_bit_width) >> 9;
1332	DstOrg = ((dstY & ~1023) * display_bit_width) >> 9;
1333        dstY &= 1023;
1334    }
1335
1336    if(pMga->BltScanDirection & BLIT_UP) {
1337	srcY += h - 1;
1338	dstY += h - 1;
1339    }
1340
1341    w--;
1342    start = end = XYADDRESS(srcX, srcY);
1343
1344    if(pMga->BltScanDirection & BLIT_LEFT) start += w;
1345    else end += w;
1346
1347    if (pMga->AccelFlags & LARGE_ADDRESSES) {
1348	WAITFIFO(7);
1349	if(DstOrg)
1350	    OUTREG(MGAREG_DSTORG, (DstOrg << 6) + pMga->DstOrg);
1351	if(SrcOrg != pMga->SrcOrg) {
1352	    pMga->SrcOrg = SrcOrg;
1353	    OUTREG(MGAREG_SRCORG, (SrcOrg << 6) + pMga->realSrcOrg);
1354 	}
1355	if(SrcOrg) {
1356	    SrcOrg = (SrcOrg << 9) / pMga->CurrentLayout.bitsPerPixel;
1357	    end -= SrcOrg;
1358	    start -= SrcOrg;
1359	}
1360	OUTREG(MGAREG_AR0, end);
1361	OUTREG(MGAREG_AR3, start);
1362	OUTREG(MGAREG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff));
1363	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h);
1364	if(DstOrg)
1365	   OUTREG(MGAREG_DSTORG, pMga->DstOrg);
1366    } else {
1367	WAITFIFO(4);
1368	OUTREG(MGAREG_AR0, end);
1369	OUTREG(MGAREG_AR3, start);
1370	OUTREG(MGAREG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff));
1371	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h);
1372    }
1373}
1374
1375
1376void mgaSubsequentScreenToScreenCopy_FastBlit( ScrnInfoPtr pScrn,
1377					       int srcX, int srcY,
1378					       int dstX, int dstY,
1379					       int w, int h )
1380{
1381    int start, end;
1382    MGAPtr pMga = MGAPTR(pScrn);
1383    static const unsigned int masks[5] = {
1384	0, 0x07f, 0x03f, 0x7f, 0x1f
1385    };
1386
1387    if(pMga->BltScanDirection & BLIT_UP) {
1388	srcY += h - 1;
1389	dstY += h - 1;
1390    }
1391
1392    w--;
1393    start = XYADDRESS(srcX, srcY);
1394    end = start + w;
1395
1396    /* we assume the driver asserts screen pitches such that
1397	we can always use fastblit for scrolling */
1398    if(((srcX ^ dstX) & masks[ pMga->CurrentLayout.bitsPerPixel / 8 ]) == 0) {
1399	if(pMga->MaxFastBlitY) {
1400	   if(pMga->BltScanDirection & BLIT_UP) {
1401		if((srcY >= pMga->MaxFastBlitY) ||
1402				(dstY >= pMga->MaxFastBlitY))
1403			goto FASTBLIT_BAILOUT;
1404	   } else {
1405		if(((srcY + h) > pMga->MaxFastBlitY) ||
1406				((dstY + h) > pMga->MaxFastBlitY))
1407			goto FASTBLIT_BAILOUT;
1408	   }
1409	}
1410
1411	/* Millennium 1 fastblit bug fix */
1412        if(pMga->AccelFlags & FASTBLT_BUG) {
1413	    int fxright = dstX + w;
1414	    int tmp_dstX = dstX;
1415	    int tmp_fxright = fxright;
1416	    static const unsigned shift_tab[5] = {
1417		0, 6, 5, 6, 4
1418	    };
1419	    const unsigned shift = shift_tab[pMga->CurrentLayout.bitsPerPixel / 8];
1420
1421	   if (pMga->CurrentLayout.bitsPerPixel == 24) {
1422	       tmp_dstX *= 3;
1423	       tmp_fxright = fxright * 3 + 2;
1424	   }
1425
1426           if( (tmp_dstX & (1 << shift))
1427	       && (((tmp_fxright >> shift) - (tmp_dstX >> shift)) & 7) == 7) {
1428	       fxright = (tmp_fxright | (1 << shift));
1429	       if (pMga->CurrentLayout.bitsPerPixel == 24) {
1430		   fxright /= 3;
1431	       }
1432
1433	       WAITFIFO(8);
1434	       OUTREG(MGAREG_CXRIGHT, dstX + w);
1435	       OUTREG(MGAREG_DWGCTL, 0x040A400C);
1436	       OUTREG(MGAREG_AR0, end);
1437	       OUTREG(MGAREG_AR3, start);
1438	       OUTREG(MGAREG_FXBNDRY, (fxright << 16) | (dstX & 0xffff));
1439	       OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h);
1440	       OUTREG(MGAREG_DWGCTL, pMga->AtypeNoBLK[GXcopy] |
1441		      MGADWG_SHIFTZERO | MGADWG_BITBLT | MGADWG_BFCOL);
1442	       OUTREG(MGAREG_CXRIGHT, 0xFFFF);
1443	       return;
1444	    }
1445	}
1446
1447   	WAITFIFO(6);
1448    	OUTREG(MGAREG_DWGCTL, 0x040A400C);
1449    	OUTREG(MGAREG_AR0, end);
1450    	OUTREG(MGAREG_AR3, start);
1451    	OUTREG(MGAREG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff));
1452    	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h);
1453    	OUTREG(MGAREG_DWGCTL, pMga->AtypeNoBLK[GXcopy] | MGADWG_SHIFTZERO |
1454			MGADWG_BITBLT | MGADWG_BFCOL);
1455	return;
1456    }
1457
1458FASTBLIT_BAILOUT:
1459
1460    WAITFIFO(4);
1461    OUTREG(MGAREG_AR0, end);
1462    OUTREG(MGAREG_AR3, start);
1463    OUTREG(MGAREG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff));
1464    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dstY << 16) | h);
1465}
1466
1467        /******************\
1468	|   Solid Fills    |
1469	\******************/
1470
1471void mgaDoSetupForSolidFill( ScrnInfoPtr pScrn, int color, int rop,
1472			     unsigned int planemask, unsigned int bpp )
1473{
1474    MGAPtr pMga = MGAPTR(pScrn);
1475    unsigned int tmp;
1476    unsigned int replicated_color = 0;
1477    unsigned int replicated_planemask = 0;
1478
1479    common_replicate_colors_and_mask( color, 0, planemask, bpp,
1480				      & replicated_color, & tmp,
1481				      & replicated_planemask );
1482
1483    CHECK_DMA_QUIESCENT(pMga, pScrn);
1484
1485    if ( (bpp == 24) && !RGBEQUAL(color) ) {
1486	pMga->FilledRectCMD = MGADWG_TRAP | MGADWG_SOLID | MGADWG_ARZERO |
1487	  MGADWG_SGNZERO | MGADWG_SHIFTZERO |
1488	  MGADWG_BMONOLEF | pMga->AtypeNoBLK[rop];
1489    }
1490    else {
1491	pMga->FilledRectCMD = MGADWG_TRAP | MGADWG_SOLID | MGADWG_ARZERO |
1492	  MGADWG_SGNZERO | MGADWG_SHIFTZERO |
1493	  MGADWG_BMONOLEF | pMga->Atype[rop];
1494    }
1495
1496    pMga->SolidLineCMD = MGADWG_SOLID | MGADWG_SHIFTZERO | MGADWG_BFCOL |
1497      pMga->AtypeNoBLK[rop];
1498
1499    if(pMga->AccelFlags & TRANSC_SOLID_FILL)
1500	pMga->FilledRectCMD |= MGADWG_TRANSC;
1501
1502    WAITFIFO(3);
1503    if ( color != pMga->FgColor ) {
1504	pMga->FgColor = color;
1505	OUTREG( MGAREG_FCOL, replicated_color );
1506    }
1507
1508    if ( (bpp != 24)
1509	 && !(pMga->AccelFlags & MGA_NO_PLANEMASK)
1510	 && (planemask != pMga->PlaneMask) ) {
1511	pMga->PlaneMask = planemask;
1512	OUTREG( MGAREG_PLNWT, replicated_planemask );
1513    }
1514
1515    OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD);
1516}
1517
1518void mgaSetupForSolidFill( ScrnInfoPtr pScrn, int color, int rop,
1519			   unsigned int planemask )
1520{
1521    MGAPtr pMga = MGAPTR(pScrn);
1522
1523    mgaDoSetupForSolidFill( pScrn, color, rop, planemask,
1524			    pMga->CurrentLayout.bitsPerPixel );
1525}
1526
1527void mgaSubsequentSolidFillRect( ScrnInfoPtr pScrn,
1528				 int x, int y, int w, int h )
1529{
1530    MGAPtr pMga = MGAPTR(pScrn);
1531
1532    WAITFIFO(2);
1533    OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff));
1534    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1535}
1536
1537void mgaSubsequentSolidFillTrap( ScrnInfoPtr pScrn, int y, int h,
1538				 int left, int dxL, int dyL, int eL,
1539				 int right, int dxR, int dyR, int eR )
1540{
1541    MGAPtr pMga = MGAPTR(pScrn);
1542    int sdxl = (dxL < 0);
1543    int ar2 = sdxl? dxL : -dxL;
1544    int sdxr = (dxR < 0);
1545    int ar5 = sdxr? dxR : -dxR;
1546
1547    WAITFIFO(11);
1548    OUTREG(MGAREG_DWGCTL,
1549		pMga->FilledRectCMD & ~(MGADWG_ARZERO | MGADWG_SGNZERO));
1550    OUTREG(MGAREG_AR0, dyL);
1551    OUTREG(MGAREG_AR1, ar2 - eL);
1552    OUTREG(MGAREG_AR2, ar2);
1553    OUTREG(MGAREG_AR4, ar5 - eR);
1554    OUTREG(MGAREG_AR5, ar5);
1555    OUTREG(MGAREG_AR6, dyR);
1556    OUTREG(MGAREG_SGN, (sdxl << 1) | (sdxr << 5));
1557    OUTREG(MGAREG_FXBNDRY, ((right + 1) << 16) | (left & 0xffff));
1558    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1559    OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD);
1560}
1561
1562
1563	/***************\
1564	|  Solid Lines  |
1565	\***************/
1566
1567void mgaSubsequentSolidHorVertLine( ScrnInfoPtr pScrn, int x, int y,
1568				    int len, int dir )
1569{
1570    MGAPtr pMga = MGAPTR(pScrn);
1571
1572    if(dir == DEGREES_0) {
1573	WAITFIFO(2);
1574	OUTREG(MGAREG_FXBNDRY, ((x + len) << 16) | (x & 0xffff));
1575	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | 1);
1576    } else if(pMga->AccelFlags & USE_RECTS_FOR_LINES) {
1577	WAITFIFO(2);
1578	OUTREG(MGAREG_FXBNDRY, ((x + 1) << 16) | (x & 0xffff));
1579	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | len);
1580    } else {
1581	WAITFIFO(4);
1582	OUTREG(MGAREG_DWGCTL, pMga->SolidLineCMD | MGADWG_AUTOLINE_OPEN);
1583	OUTREG(MGAREG_XYSTRT, (y << 16) | (x & 0xffff));
1584	OUTREG(MGAREG_XYEND + MGAREG_EXEC, ((y + len) << 16) | (x & 0xffff));
1585	OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD);
1586    }
1587}
1588
1589
1590void mgaSubsequentSolidTwoPointLine( ScrnInfoPtr pScrn, int x1, int y1,
1591				     int x2, int y2, int flags )
1592{
1593    MGAPtr pMga = MGAPTR(pScrn);
1594
1595    WAITFIFO(4);
1596    OUTREG(MGAREG_DWGCTL, pMga->SolidLineCMD |
1597        ((flags & OMIT_LAST) ? MGADWG_AUTOLINE_OPEN : MGADWG_AUTOLINE_CLOSE));
1598    OUTREG(MGAREG_XYSTRT, (y1 << 16) | (x1 & 0xFFFF));
1599    OUTREG(MGAREG_XYEND + MGAREG_EXEC, (y2 << 16) | (x2 & 0xFFFF));
1600    OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD);
1601}
1602
1603
1604	/***************************\
1605	|   8x8 Mono Pattern Fills  |
1606	\***************************/
1607
1608
1609void mgaSetupForMono8x8PatternFill( ScrnInfoPtr pScrn,
1610				    int patx, int paty, int fg, int bg,
1611				    int rop, unsigned int planemask )
1612{
1613    MGAPtr pMga = MGAPTR(pScrn);
1614    XAAInfoRecPtr infoRec = pMga->AccelInfoRec;
1615    CARD32 regs[4];
1616
1617    CHECK_DMA_QUIESCENT(pMga, pScrn);
1618
1619    infoRec->SubsequentMono8x8PatternFillRect =
1620		mgaSubsequentMono8x8PatternFillRect;
1621
1622    regs[0] = MGAREG_PAT0;
1623    regs[1] = patx;
1624    regs[2] = MGAREG_PAT1;
1625    regs[3] = paty;
1626
1627    pMga->PatternRectCMD = common_setup_for_pattern_fill( pMga, fg, bg, rop,
1628							  planemask, regs, 2,
1629							  (MGADWG_TRAP
1630							   | MGADWG_ARZERO
1631							   | MGADWG_SGNZERO
1632							   | MGADWG_BMONOLEF) );
1633}
1634
1635
1636void mgaSubsequentMono8x8PatternFillRect( ScrnInfoPtr pScrn,
1637					  int patx, int paty,
1638					  int x, int y, int w, int h )
1639{
1640    MGAPtr pMga = MGAPTR(pScrn);
1641
1642    WAITFIFO(3);
1643    OUTREG(MGAREG_SHIFT, (paty << 4) | patx);
1644    OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff));
1645    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1646    pMga->AccelInfoRec->SubsequentMono8x8PatternFillRect =
1647		mgaSubsequentMono8x8PatternFillRect_Additional;
1648}
1649
1650static void mgaSubsequentMono8x8PatternFillRect_Additional( ScrnInfoPtr pScrn,
1651							    int patx, int paty,
1652							    int x, int y,
1653							    int w, int h )
1654{
1655    MGAPtr pMga = MGAPTR(pScrn);
1656
1657    WAITFIFO(2);
1658    OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff));
1659    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1660}
1661
1662
1663void mgaSubsequentMono8x8PatternFillTrap( ScrnInfoPtr pScrn,
1664					  int patx, int paty,
1665					  int y, int h,
1666					  int left, int dxL, int dyL, int eL,
1667					  int right, int dxR, int dyR, int eR )
1668{
1669    MGAPtr pMga = MGAPTR(pScrn);
1670
1671    int sdxl = (dxL < 0) ? (1<<1) : 0;
1672    int ar2 = sdxl? dxL : -dxL;
1673    int sdxr = (dxR < 0) ? (1<<5) : 0;
1674    int ar5 = sdxr? dxR : -dxR;
1675
1676    WAITFIFO(12);
1677    OUTREG(MGAREG_SHIFT, (paty << 4) | patx);
1678    OUTREG(MGAREG_DWGCTL,
1679	pMga->PatternRectCMD & ~(MGADWG_ARZERO | MGADWG_SGNZERO));
1680    OUTREG(MGAREG_AR0, dyL);
1681    OUTREG(MGAREG_AR1, ar2 - eL);
1682    OUTREG(MGAREG_AR2, ar2);
1683    OUTREG(MGAREG_AR4, ar5 - eR);
1684    OUTREG(MGAREG_AR5, ar5);
1685    OUTREG(MGAREG_AR6, dyR);
1686    OUTREG(MGAREG_SGN, sdxl | sdxr);
1687    OUTREG(MGAREG_FXBNDRY, ((right + 1) << 16) | (left & 0xffff));
1688    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1689    OUTREG(MGAREG_DWGCTL, pMga->PatternRectCMD);
1690}
1691
1692	/***********************\
1693	|   Color Expand Rect   |
1694	\***********************/
1695
1696
1697void mgaSetupForScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn,
1698						    int fg, int bg,
1699						    int rop,
1700						    unsigned int planemask )
1701{
1702    MGAPtr pMga = MGAPTR(pScrn);
1703
1704
1705    CHECK_DMA_QUIESCENT(pMga, pScrn);
1706
1707    (void) common_setup_for_pattern_fill( pMga, fg, bg, rop,
1708					  planemask, NULL, 0,
1709					  MGADWG_ILOAD | MGADWG_LINEAR
1710					  | MGADWG_SGNZERO | MGADWG_SHIFTZERO
1711					  | MGADWG_BMONOLEF );
1712}
1713
1714
1715void mgaSubsequentScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn,
1716	int x, int y, int w, int h,
1717	int skipleft )
1718{
1719    MGAPtr pMga = MGAPTR(pScrn);
1720
1721    pMga->AccelFlags |= CLIPPER_ON;
1722    pMga->expandDWORDs = (w + 31) >> 5;
1723    if((pMga->expandDWORDs * h) > pMga->MaxBlitDWORDS) {
1724	pMga->expandHeight = pMga->MaxBlitDWORDS / pMga->expandDWORDs;
1725	pMga->expandRemaining = h / pMga->expandHeight;
1726	if(!(h = h % pMga->expandHeight)) {
1727	   pMga->expandRemaining--;
1728	   h = pMga->expandHeight;
1729	}
1730	pMga->expandY = y + h;
1731    } else
1732	pMga->expandRemaining = 0;
1733    pMga->expandRows = h;
1734
1735    WAITFIFO(5);
1736    OUTREG(MGAREG_CXBNDRY, ((x + w - 1) << 16) | ((x + skipleft) & 0xFFFF));
1737    w = pMga->expandDWORDs << 5;     /* source is dword padded */
1738    OUTREG(MGAREG_AR0, (w * h) - 1);
1739    OUTREG(MGAREG_AR3, 0);  /* crashes occasionally without this */
1740    OUTREG(MGAREG_FXBNDRY, ((x + w - 1) << 16) | (x & 0xFFFF));
1741    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1742
1743#if defined(__alpha__)
1744    if(1) /* force indirect always on Alpha */
1745#else
1746    if(pMga->expandDWORDs > pMga->FifoSize)
1747#endif
1748    {
1749        pMga->AccelInfoRec->SubsequentColorExpandScanline =
1750                mgaSubsequentColorExpandScanlineIndirect;
1751        pMga->AccelInfoRec->ScanlineColorExpandBuffers =
1752                (unsigned char**)(&pMga->ScratchBuffer);
1753    } else {
1754        pMga->AccelInfoRec->SubsequentColorExpandScanline =
1755                mgaSubsequentColorExpandScanline;
1756        pMga->AccelInfoRec->ScanlineColorExpandBuffers =
1757                (unsigned char**)(&pMga->ColorExpandBase);
1758	WAITFIFO(pMga->expandDWORDs);
1759    }
1760}
1761
1762
1763void mgaSubsequentColorExpandScanlineIndirect( ScrnInfoPtr pScrn,
1764					       int bufno )
1765{
1766    MGAPtr pMga = MGAPTR(pScrn);
1767    int dwords = pMga->expandDWORDs;
1768    CARD32 *src = (CARD32*)(pMga->ScratchBuffer);
1769
1770    while(dwords > pMga->FifoSize) {
1771	WAITFIFO(pMga->FifoSize);
1772	MGAMoveDWORDS((CARD32*)(pMga->ColorExpandBase), src, pMga->FifoSize);
1773	src += pMga->FifoSize;
1774	dwords -= pMga->FifoSize;
1775    }
1776
1777    WAITFIFO(dwords);
1778    MGAMoveDWORDS((CARD32*)(pMga->ColorExpandBase), src, dwords);
1779
1780    if(!(--pMga->expandRows)) {
1781	if(pMga->expandRemaining) {
1782	    WAITFIFO(3);
1783	    OUTREG(MGAREG_AR0,((pMga->expandDWORDs<< 5)*pMga->expandHeight)-1);
1784	    OUTREG(MGAREG_AR3, 0);  /* crashes occasionally without this */
1785	    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (pMga->expandY << 16) |
1786	                                      pMga->expandHeight);
1787	    pMga->expandY += pMga->expandHeight;
1788            pMga->expandRows = pMga->expandHeight;
1789	    pMga->expandRemaining--;
1790	} else {
1791            DISABLE_CLIP();
1792	}
1793    }
1794}
1795
1796
1797void mgaSubsequentColorExpandScanline( ScrnInfoPtr pScrn,
1798				       int bufno )
1799{
1800    MGAPtr pMga = MGAPTR(pScrn);
1801
1802    if(--pMga->expandRows) {
1803	WAITFIFO(pMga->expandDWORDs);
1804    } else if(pMga->expandRemaining) {
1805	WAITFIFO(3);
1806	OUTREG(MGAREG_AR0,((pMga->expandDWORDs<<5)*pMga->expandHeight)-1);
1807	OUTREG(MGAREG_AR3, 0);  /* crashes occasionally without this */
1808	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (pMga->expandY << 16) |
1809	                                      pMga->expandHeight);
1810	pMga->expandY += pMga->expandHeight;
1811        pMga->expandRows = pMga->expandHeight;
1812	pMga->expandRemaining--;
1813	WAITFIFO(pMga->expandDWORDs);
1814    } else {
1815        DISABLE_CLIP();
1816    }
1817}
1818
1819
1820	/*******************\
1821	|   Image Writes    |
1822	\*******************/
1823
1824
1825void mgaSetupForScanlineImageWrite( ScrnInfoPtr pScrn, int rop,
1826				    unsigned int planemask,
1827				    int transparency_color,
1828				    int bpp, int depth )
1829{
1830    MGAPtr pMga = MGAPTR(pScrn);
1831    unsigned int replicate_pm = 0;
1832
1833    switch( pMga->CurrentLayout.bitsPerPixel ) {
1834    case 8:
1835	replicate_pm = REPLICATE_8( planemask );
1836	break;
1837    case 16:
1838	replicate_pm = REPLICATE_16( planemask );
1839	break;
1840    case 24:
1841	replicate_pm = REPLICATE_24( planemask );
1842	break;
1843    case 32:
1844	replicate_pm = REPLICATE_32( planemask );
1845	break;
1846    }
1847
1848    CHECK_DMA_QUIESCENT(pMga, pScrn);
1849
1850    WAITFIFO(3);
1851    OUTREG(MGAREG_AR5, 0);
1852    SET_PLANEMASK_REPLICATED( planemask, replicate_pm,
1853			      pMga->CurrentLayout.bitsPerPixel );
1854    OUTREG(MGAREG_DWGCTL, MGADWG_ILOAD | MGADWG_BFCOL | MGADWG_SHIFTZERO |
1855			MGADWG_SGNZERO | pMga->AtypeNoBLK[rop]);
1856}
1857
1858
1859void mgaSubsequentScanlineImageWriteRect( ScrnInfoPtr pScrn,
1860					  int x, int y, int w, int h,
1861					  int skipleft )
1862{
1863    MGAPtr pMga = MGAPTR(pScrn);
1864
1865    pMga->AccelFlags |= CLIPPER_ON;
1866    pMga->expandRows = h;
1867    pMga->expandDWORDs = ((w * pMga->CurrentLayout.bitsPerPixel) + 31) >> 5;
1868
1869    WAITFIFO(5);
1870    OUTREG(MGAREG_CXBNDRY, 0xFFFF0000 | ((x + skipleft) & 0xFFFF));
1871    OUTREG(MGAREG_AR0, w - 1);
1872    OUTREG(MGAREG_AR3, 0);
1873    OUTREG(MGAREG_FXBNDRY, ((x + w - 1) << 16) | (x & 0xFFFF));
1874    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
1875}
1876
1877
1878void mgaSubsequentImageWriteScanline( ScrnInfoPtr pScrn, int bufno )
1879{
1880    MGAPtr pMga = MGAPTR(pScrn);
1881    int dwords = pMga->expandDWORDs;
1882    CARD32 *src = (CARD32*)(pMga->ScratchBuffer);
1883
1884    while(dwords > pMga->FifoSize) {
1885	WAITFIFO(pMga->FifoSize);
1886        MGAMoveDWORDS((CARD32*)(pMga->ColorExpandBase), src, pMga->FifoSize);
1887        src += pMga->FifoSize;
1888        dwords -= pMga->FifoSize;
1889    }
1890
1891    WAITFIFO(dwords);
1892    MGAMoveDWORDS((CARD32*)(pMga->ColorExpandBase), src, dwords);
1893
1894    if(!(--pMga->expandRows)) {
1895	DISABLE_CLIP();
1896    }
1897}
1898
1899
1900#if X_BYTE_ORDER == X_LITTLE_ENDIAN
1901
1902	/***************************\
1903	|      Dashed  Lines        |
1904	\***************************/
1905
1906void mgaSetupForDashedLine( ScrnInfoPtr pScrn,
1907			    int fg, int bg, int rop,
1908			    unsigned int planemask, int length,
1909			    unsigned char *pattern )
1910{
1911    MGAPtr pMga = MGAPTR(pScrn);
1912    CARD32 *DashPattern = (CARD32*)pattern;
1913    CARD32 NiceDashPattern = DashPattern[0];
1914    int dwords = (length + 31) >> 5;
1915    unsigned int replicate_fg = 0;
1916    unsigned int replicate_bg = 0;
1917    unsigned int replicate_pm = 0;
1918
1919
1920    common_replicate_colors_and_mask( fg, bg, planemask,
1921				      pMga->CurrentLayout.bitsPerPixel,
1922				      & replicate_fg, & replicate_bg,
1923				      & replicate_pm );
1924
1925    CHECK_DMA_QUIESCENT(pMga, pScrn);
1926
1927    pMga->DashCMD = MGADWG_BFCOL | pMga->AtypeNoBLK[rop];
1928    pMga->StyleLen = length - 1;
1929
1930    if(bg == -1) {
1931        pMga->DashCMD |= MGADWG_TRANSC;
1932	WAITFIFO(dwords + 2);
1933    } else {
1934	WAITFIFO(dwords + 3);
1935	SET_BACKGROUND_REPLICATED( bg, replicate_bg );
1936    }
1937
1938    SET_PLANEMASK_REPLICATED( planemask, replicate_pm,
1939			      pMga->CurrentLayout.bitsPerPixel );
1940    SET_FOREGROUND_REPLICATED( fg, replicate_fg );
1941
1942
1943    /* We see if we can draw horizontal lines as 8x8 pattern fills.  This is
1944     * worthwhile since the pattern fills can use block mode and the default X
1945     * pattern is 8 pixels long.  The forward pattern is the top scanline, the
1946     * backwards pattern is the next one.
1947     */
1948    switch(length) {
1949    case 2:	NiceDashPattern |= NiceDashPattern << 2;
1950    case 4:	NiceDashPattern |= NiceDashPattern << 4;
1951    case 8: {
1952	NiceDashPattern |= byte_reversed[NiceDashPattern] << 16;
1953	NiceDashPattern |= NiceDashPattern << 8;
1954	pMga->NiceDashCMD = MGADWG_TRAP | MGADWG_ARZERO |
1955	  MGADWG_SGNZERO | MGADWG_BMONOLEF;
1956	pMga->AccelFlags |= NICE_DASH_PATTERN;
1957
1958	if( bg == -1 ) {
1959	    if ( (pMga->CurrentLayout.bitsPerPixel == 24) && !RGBEQUAL(fg) ) {
1960		pMga->NiceDashCMD |= MGADWG_TRANSC | pMga->AtypeNoBLK[rop];
1961	    }
1962	    else {
1963		pMga->NiceDashCMD |= MGADWG_TRANSC | pMga->Atype[rop];
1964	    }
1965	}
1966	else {
1967	    /* (Packed) 24-bit is a funky mode.  We only use the Atype table
1968	     * in 24-bit if the components of the foreground color and the
1969	     * components of the background color are the same (e.g., fg =
1970	     * 0xf8f8f8 and bg = 0x131313).
1971	     */
1972
1973	    if( ((pMga->AccelFlags & BLK_OPAQUE_EXPANSION) != 0)
1974		&& ((pMga->CurrentLayout.bitsPerPixel != 24)
1975		    || (RGBEQUAL(fg) && RGBEQUAL(bg))) ) {
1976		pMga->NiceDashCMD |= pMga->Atype[rop];
1977	    }
1978	    else {
1979		pMga->NiceDashCMD |= pMga->AtypeNoBLK[rop];
1980	    }
1981	}
1982	OUTREG(MGAREG_SRC0, NiceDashPattern);
1983	break;
1984    }
1985    default: {
1986	pMga->AccelFlags &= ~NICE_DASH_PATTERN;
1987	switch (dwords) {
1988	case 4:  OUTREG(MGAREG_SRC3, DashPattern[3]);
1989	case 3:  OUTREG(MGAREG_SRC2, DashPattern[2]);
1990	case 2:	 OUTREG(MGAREG_SRC1, DashPattern[1]);
1991	default: OUTREG(MGAREG_SRC0, DashPattern[0]);
1992	}
1993    }
1994    }
1995}
1996
1997
1998void mgaSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn,
1999				      int x1, int y1, int x2, int y2,
2000				      int flags, int phase )
2001{
2002    MGAPtr pMga = MGAPTR(pScrn);
2003
2004    WAITFIFO(4);
2005    if((pMga->AccelFlags & NICE_DASH_PATTERN) && (y1 == y2)) {
2006    	OUTREG(MGAREG_DWGCTL, pMga->NiceDashCMD);
2007	if(x2 < x1) {
2008	   if(flags & OMIT_LAST) x2++;
2009   	   OUTREG(MGAREG_SHIFT, ((-y1 & 0x07) << 4) |
2010				((7 - phase - x1) & 0x07));
2011   	   OUTREG(MGAREG_FXBNDRY, ((x1 + 1) << 16) | (x2 & 0xffff));
2012    	} else {
2013 	   if(!flags) x2++;
2014   	   OUTREG(MGAREG_SHIFT, (((1 - y1) & 0x07) << 4) |
2015				((phase - x1) & 0x07));
2016     	   OUTREG(MGAREG_FXBNDRY, (x2 << 16) | (x1 & 0xffff));
2017	}
2018    	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y1 << 16) | 1);
2019    } else {
2020	OUTREG(MGAREG_SHIFT, (pMga->StyleLen << 16 ) |
2021				(pMga->StyleLen - phase));
2022	OUTREG(MGAREG_DWGCTL, pMga->DashCMD | ((flags & OMIT_LAST) ?
2023			MGADWG_AUTOLINE_OPEN : MGADWG_AUTOLINE_CLOSE));
2024	OUTREG(MGAREG_XYSTRT, (y1 << 16) | (x1 & 0xFFFF));
2025	OUTREG(MGAREG_XYEND + MGAREG_EXEC, (y2 << 16) | (x2 & 0xFFFF));
2026    }
2027}
2028#endif /* X_BYTE_ORDER == X_LITTLE_ENDIAN */
2029
2030
2031	/******************************************\
2032	|  Planar Screen to Screen Color Expansion |
2033	\******************************************/
2034
2035void mgaSetupForPlanarScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
2036						     int fg, int bg,
2037						     int rop,
2038						     unsigned int planemask )
2039{
2040    MGAPtr pMga = MGAPTR(pScrn);
2041    CARD32 mgaCMD = pMga->AtypeNoBLK[rop] | MGADWG_BITBLT |
2042				MGADWG_SGNZERO | MGADWG_BPLAN;
2043    CARD32 regs[2];
2044
2045
2046    regs[0] = MGAREG_AR5;
2047    regs[1] = pScrn->displayWidth;
2048
2049    CHECK_DMA_QUIESCENT(pMga, pScrn);
2050
2051    (void) common_setup_for_pattern_fill( pMga, fg, bg, 0, planemask, regs, 1,
2052					  mgaCMD );
2053}
2054
2055
2056void mgaSubsequentPlanarScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
2057						       int x, int y, int w, int h,
2058						       int srcx, int srcy,
2059						       int skipleft )
2060{
2061    MGAPtr pMga = MGAPTR(pScrn);
2062    int start, end;
2063
2064    w--;
2065    start = XYADDRESS(srcx, srcy) + skipleft;
2066    end = start + w;
2067
2068    WAITFIFO(4);
2069    OUTREG(MGAREG_AR3, start);
2070    OUTREG(MGAREG_AR0, end);
2071    OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff));
2072    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
2073}
2074
2075
2076	/***********************************\
2077	|  Screen to Screen Color Expansion |
2078	\***********************************/
2079
2080void mgaSetupForScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
2081					       int fg, int bg,
2082					       int rop,
2083					       unsigned int planemask )
2084{
2085    MGAPtr pMga = MGAPTR(pScrn);
2086    CARD32 regs[2];
2087
2088    regs[0] = MGAREG_AR5;
2089    regs[1] = pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel;
2090
2091    CHECK_DMA_QUIESCENT(pMga, pScrn);
2092
2093    (void) common_setup_for_pattern_fill( pMga, fg, bg, rop, planemask,
2094					  regs, 1,
2095					  MGADWG_BITBLT | MGADWG_SGNZERO
2096					  | MGADWG_SHIFTZERO );
2097}
2098
2099
2100void mgaSubsequentScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
2101						 int x, int y, int w, int h,
2102						 int srcx, int srcy,
2103						 int skipleft )
2104{
2105    MGAPtr pMga = MGAPTR(pScrn);
2106    const unsigned int display_bit_width =
2107      (pMga->CurrentLayout.displayWidth * pMga->CurrentLayout.bitsPerPixel);
2108    int start, end, next, num;
2109    Bool resetDstOrg = FALSE;
2110
2111    if (pMga->AccelFlags & LARGE_ADDRESSES) {
2112        const int DstOrg = ((y & ~1023) * display_bit_width) >> 9;
2113        const int SrcOrg = ((srcy & ~1023) * display_bit_width) >> 9;
2114
2115	y &= 1023;
2116	srcy &= 1023;
2117
2118	WAITFIFO(2);
2119	if(DstOrg) {
2120            OUTREG(MGAREG_DSTORG, (DstOrg << 6) + pMga->DstOrg);
2121	    resetDstOrg = TRUE;
2122	}
2123        if(SrcOrg != pMga->SrcOrg) {
2124            pMga->SrcOrg = SrcOrg;
2125            OUTREG(MGAREG_SRCORG, (SrcOrg << 6) + pMga->realSrcOrg);
2126        }
2127    }
2128
2129    w--;
2130    start = (XYADDRESS(srcx, srcy) * pMga->CurrentLayout.bitsPerPixel)
2131      + skipleft;
2132    end = start + w + (display_bit_width * (h - 1));
2133
2134    /* src cannot split a 2 Meg boundary from SrcOrg */
2135    if(!((start ^ end) & 0xff000000)) {
2136	WAITFIFO(4);
2137	OUTREG(MGAREG_AR3, start);
2138	OUTREG(MGAREG_AR0, start + w);
2139	OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff));
2140	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | h);
2141    } else {
2142	while(h) {
2143	    next = (start + 0x00ffffff) & 0xff000000;
2144	    if(next <= (start + w)) {
2145		num = next - start - 1;
2146
2147		WAITFIFO(7);
2148		OUTREG(MGAREG_AR3, start);
2149		OUTREG(MGAREG_AR0, start + num);
2150		OUTREG(MGAREG_FXBNDRY, ((x + num) << 16) | (x & 0xffff));
2151		OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | 1);
2152
2153		OUTREG(MGAREG_AR3, next);
2154		OUTREG(MGAREG_AR0, start + w );
2155		OUTREG(MGAREG_FXBNDRY + MGAREG_EXEC, ((x + w) << 16) |
2156                                                     ((x + num + 1) & 0xffff));
2157		start += display_bit_width;
2158		h--; y++;
2159	    } else {
2160		num = ((next - start - w)/display_bit_width) + 1;
2161		if(num > h) num = h;
2162
2163		WAITFIFO(4);
2164		OUTREG(MGAREG_AR3, start);
2165		OUTREG(MGAREG_AR0, start + w);
2166		OUTREG(MGAREG_FXBNDRY, ((x + w) << 16) | (x & 0xffff));
2167		OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | num);
2168
2169		start += num * display_bit_width;
2170		h -= num; y += num;
2171	    }
2172	}
2173    }
2174
2175    if(resetDstOrg) {
2176	WAITFIFO(1);
2177	OUTREG(MGAREG_DSTORG, pMga->DstOrg);
2178    }
2179}
2180
2181
2182static void
2183MGAFillSolidRectsDMA(
2184    ScrnInfoPtr pScrn,
2185    int	fg, int rop,
2186    unsigned int planemask,
2187    int		nBox, 		/* number of rectangles to fill */
2188    BoxPtr	pBox  		/* Pointer to first rectangle to fill */
2189){
2190    MGAPtr pMga = MGAPTR(pScrn);
2191    XAAInfoRecPtr infoRec = pMga->AccelInfoRec;
2192    CARD32 *base = (CARD32*)pMga->ILOADBase;
2193
2194    CHECK_DMA_QUIESCENT(pMga, pScrn);
2195
2196    SET_SYNC_FLAG(infoRec);
2197    (*infoRec->SetupForSolidFill)(pScrn, fg, rop, planemask);
2198
2199    if(nBox & 1) {
2200	OUTREG(MGAREG_FXBNDRY, ((pBox->x2) << 16) | (pBox->x1 & 0xffff));
2201	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC,
2202		(pBox->y1 << 16) | (pBox->y2 - pBox->y1));
2203	nBox--; pBox++;
2204    }
2205
2206    if(!nBox) return;
2207
2208    OUTREG(MGAREG_OPMODE, MGAOPM_DMA_GENERAL);
2209    while(nBox) {
2210	base[0] = DMAINDICES(MGAREG_FXBNDRY, MGAREG_YDSTLEN + MGAREG_EXEC,
2211                MGAREG_FXBNDRY, MGAREG_YDSTLEN + MGAREG_EXEC);
2212	base[1] = ((pBox->x2) << 16) | (pBox->x1 & 0xffff);
2213	base[2] = (pBox->y1 << 16) | (pBox->y2 - pBox->y1);
2214	pBox++;
2215	base[3] = ((pBox->x2) << 16) | (pBox->x1 & 0xffff);
2216	base[4] = (pBox->y1 << 16) | (pBox->y2 - pBox->y1);
2217	pBox++;
2218	base += 5; nBox -= 2;
2219    }
2220    OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT);
2221}
2222
2223static void
2224MGAFillSolidSpansDMA(
2225   ScrnInfoPtr pScrn,
2226   int fg, int rop,
2227   unsigned int planemask,
2228   int n,
2229   DDXPointPtr ppt,
2230   int *pwidth, int fSorted
2231){
2232    MGAPtr pMga = MGAPTR(pScrn);
2233    XAAInfoRecPtr infoRec = pMga->AccelInfoRec;
2234    CARD32 *base = (CARD32*)pMga->ILOADBase;
2235
2236    CHECK_DMA_QUIESCENT(pMga, pScrn);
2237    SET_SYNC_FLAG(infoRec);
2238
2239    if(infoRec->ClipBox) {
2240	OUTREG(MGAREG_CXBNDRY,
2241	   ((infoRec->ClipBox->x2 - 1) << 16) | infoRec->ClipBox->x1);
2242	OUTREG(MGAREG_YTOP,
2243	   (infoRec->ClipBox->y1 * pScrn->displayWidth) + pMga->YDstOrg);
2244	OUTREG(MGAREG_YBOT,
2245	   ((infoRec->ClipBox->y2 - 1) * pScrn->displayWidth) + pMga->YDstOrg);
2246    }
2247
2248    (*infoRec->SetupForSolidFill)(pScrn, fg, rop, planemask);
2249
2250    if(n & 1) {
2251	OUTREG(MGAREG_FXBNDRY, ((ppt->x + *pwidth) << 16) | (ppt->x & 0xffff));
2252	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (ppt->y << 16) | 1);
2253	ppt++; pwidth++; n--;
2254    }
2255
2256    if(n) {
2257	if(n > 838860) n = 838860;  /* maximum number we have room for */
2258
2259	OUTREG(MGAREG_OPMODE, MGAOPM_DMA_GENERAL);
2260	while(n) {
2261	    base[0] = DMAINDICES(MGAREG_FXBNDRY, MGAREG_YDSTLEN + MGAREG_EXEC,
2262                MGAREG_FXBNDRY, MGAREG_YDSTLEN + MGAREG_EXEC);
2263	    base[1] = ((ppt->x + *(pwidth++)) << 16) | (ppt->x & 0xffff);
2264	    base[2] = (ppt->y << 16) | 1;
2265	    ppt++;
2266	    base[3] = ((ppt->x + *(pwidth++)) << 16) | (ppt->x & 0xffff);
2267	    base[4] = (ppt->y << 16) | 1;
2268	    ppt++;
2269	    base += 5; n -= 2;
2270	}
2271	OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT);
2272    }
2273
2274    if(infoRec->ClipBox) {
2275	OUTREG(MGAREG_CXBNDRY, 0xFFFF0000);     /* (maxX << 16) | minX */
2276	OUTREG(MGAREG_YTOP, 0x00000000);        /* minPixelPointer */
2277	OUTREG(MGAREG_YBOT, 0x007FFFFF);        /* maxPixelPointer */
2278    }
2279}
2280
2281
2282static void
2283MGAFillMono8x8PatternRectsTwoPass(
2284    ScrnInfoPtr pScrn,
2285    int	fg, int bg, int rop,
2286    unsigned int planemask,
2287    int	nBoxInit,
2288    BoxPtr pBoxInit,
2289    int pattern0, int pattern1,
2290    int xorg, int yorg
2291){
2292    MGAPtr pMga = MGAPTR(pScrn);
2293    XAAInfoRecPtr infoRec = pMga->AccelInfoRec;
2294    int	nBox, SecondPassColor;
2295    BoxPtr pBox;
2296
2297    CHECK_DMA_QUIESCENT(pMga, pScrn);
2298
2299    if((rop == GXcopy) && (bg != -1)) {
2300	SecondPassColor = bg;
2301	bg = -1;
2302    } else SecondPassColor = -1;
2303
2304    WAITFIFO(1);
2305    OUTREG(MGAREG_SHIFT, (((-yorg) & 0x07) << 4) | ((-xorg) & 0x07));
2306
2307SECOND_PASS:
2308
2309    nBox = nBoxInit;
2310    pBox = pBoxInit;
2311
2312    (*infoRec->SetupForMono8x8PatternFill)(pScrn, pattern0, pattern1,
2313					fg, bg, rop, planemask);
2314
2315    while(nBox--) {
2316	WAITFIFO(2);
2317	OUTREG(MGAREG_FXBNDRY, ((pBox->x2) << 16) | (pBox->x1 & 0xffff));
2318	OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC,
2319			(pBox->y1 << 16) | (pBox->y2 - pBox->y1));
2320	pBox++;
2321    }
2322
2323    if(SecondPassColor != -1) {
2324	fg = SecondPassColor;
2325	SecondPassColor = -1;
2326	pattern0 = ~pattern0;
2327	pattern1 = ~pattern1;
2328	goto SECOND_PASS;
2329    }
2330
2331    SET_SYNC_FLAG(infoRec);
2332}
2333
2334
2335static void
2336MGAValidatePolyArc(
2337   GCPtr 	pGC,
2338   unsigned long changes,
2339   DrawablePtr pDraw
2340){
2341   ScrnInfoPtr pScrn = xf86Screens[pGC->pScreen->myNum];
2342   MGAPtr pMga = MGAPTR(pScrn);
2343   Bool fullPlanemask = TRUE;
2344
2345   if((pGC->planemask & pMga->AccelInfoRec->FullPlanemask) !=
2346	pMga->AccelInfoRec->FullPlanemask)
2347   {
2348	if(pMga->AccelFlags & MGA_NO_PLANEMASK) return;
2349	fullPlanemask = FALSE;
2350   }
2351
2352   if(!pGC->lineWidth &&
2353      (pGC->fillStyle == FillSolid) &&
2354      (pGC->lineStyle == LineSolid) &&
2355      ((pGC->alu != GXcopy) || !fullPlanemask))
2356   {
2357	pGC->ops->PolyArc = MGAPolyArcThinSolid;
2358   }
2359}
2360
2361static void
2362MGAPolyPoint (
2363    DrawablePtr pDraw,
2364    GCPtr pGC,
2365    int mode,
2366    int npt,
2367    xPoint *ppt
2368){
2369    int numRects = REGION_NUM_RECTS(pGC->pCompositeClip);
2370    XAAInfoRecPtr infoRec;
2371    BoxPtr pbox;
2372    MGAPtr pMga;
2373    int xorg, yorg;
2374    ScrnInfoPtr pScrn;
2375
2376    if(!numRects) return;
2377
2378    if(numRects != 1) {
2379	XAAGetFallbackOps()->PolyPoint(pDraw, pGC, mode, npt, ppt);
2380	return;
2381    }
2382
2383    infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
2384    pScrn = infoRec->pScrn;
2385    pMga = MGAPTR(pScrn);
2386    xorg = pDraw->x;
2387    yorg = pDraw->y;
2388
2389    pbox = REGION_RECTS(pGC->pCompositeClip);
2390
2391    (*infoRec->SetClippingRectangle)(infoRec->pScrn,
2392                pbox->x1, pbox->y1, pbox->x2 - 1, pbox->y2 - 1);
2393    (*infoRec->SetupForSolidFill)(infoRec->pScrn, pGC->fgPixel, pGC->alu,
2394				   pGC->planemask);
2395
2396    if(mode == CoordModePrevious) {
2397	while(npt--) {
2398	    xorg += ppt->x;
2399	    yorg += ppt->y;
2400	    WAITFIFO(2);
2401	    OUTREG(MGAREG_FXBNDRY, ((xorg + 1) << 16) | (xorg & 0xffff));
2402	    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (yorg << 16) | 1);
2403	    ppt++;
2404	}
2405    } else {
2406	int x;
2407	while(npt--) {
2408	    x = ppt->x + xorg;
2409	    WAITFIFO(2);
2410	    OUTREG(MGAREG_FXBNDRY, ((x + 1) << 16) | (x & 0xffff));
2411	    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, ((ppt->y + yorg) << 16) | 1);
2412	    ppt++;
2413	}
2414    }
2415
2416    (*infoRec->DisableClipping)(infoRec->pScrn);
2417
2418    SET_SYNC_FLAG(infoRec);
2419}
2420
2421
2422static void
2423MGAValidatePolyPoint(
2424   GCPtr 	pGC,
2425   unsigned long changes,
2426   DrawablePtr pDraw
2427){
2428   ScrnInfoPtr pScrn = xf86Screens[pGC->pScreen->myNum];
2429   MGAPtr pMga = MGAPTR(pScrn);
2430   Bool fullPlanemask = TRUE;
2431
2432   pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint;
2433
2434   if((pGC->planemask & pMga->AccelInfoRec->FullPlanemask) !=
2435	pMga->AccelInfoRec->FullPlanemask)
2436   {
2437	if(pMga->AccelFlags & MGA_NO_PLANEMASK) return;
2438	fullPlanemask = FALSE;
2439   }
2440
2441   if((pGC->alu != GXcopy) || !fullPlanemask)
2442	pGC->ops->PolyPoint = MGAPolyPoint;
2443}
2444
2445
2446static void
2447MGAFillCacheBltRects(
2448   ScrnInfoPtr pScrn,
2449   int rop,
2450   unsigned int planemask,
2451   int nBox,
2452   BoxPtr pBox,
2453   int xorg, int yorg,
2454   XAACacheInfoPtr pCache
2455){
2456    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
2457    int x, y, phaseY, phaseX, skipleft, height, width, w, blit_w, blit_h, start;
2458
2459    CHECK_DMA_QUIESCENT(MGAPTR(pScrn), pScrn);
2460
2461    (*infoRec->SetupForScreenToScreenCopy)(pScrn, 1, 1, rop, planemask,
2462		pCache->trans_color);
2463
2464    while(nBox--) {
2465	y = pBox->y1;
2466	phaseY = (y - yorg) % pCache->orig_h;
2467	if(phaseY < 0) phaseY += pCache->orig_h;
2468	phaseX = (pBox->x1 - xorg) % pCache->orig_w;
2469	if(phaseX < 0) phaseX += pCache->orig_w;
2470	height = pBox->y2 - y;
2471	width = pBox->x2 - pBox->x1;
2472	start = phaseY ? (pCache->orig_h - phaseY) : 0;
2473
2474	/* This is optimized for WRAM */
2475
2476	if ((rop == GXcopy) && (height >= (pCache->orig_h + start))) {
2477	    w = width; skipleft = phaseX; x = pBox->x1;
2478	    blit_h = pCache->orig_h;
2479
2480	    while(1) {
2481		blit_w = pCache->w - skipleft;
2482		if(blit_w > w) blit_w = w;
2483		(*infoRec->SubsequentScreenToScreenCopy)(pScrn,
2484			pCache->x + skipleft, pCache->y,
2485			x, y + start, blit_w, blit_h);
2486		w -= blit_w;
2487		if(!w) break;
2488		x += blit_w;
2489		skipleft = (skipleft + blit_w) % pCache->orig_w;
2490	    }
2491	    height -= blit_h;
2492
2493	    if(start) {
2494		(*infoRec->SubsequentScreenToScreenCopy)(pScrn,
2495			pBox->x1, y + blit_h, pBox->x1, y, width, start);
2496		height -= start;
2497		y += start;
2498	    }
2499	    start = blit_h;
2500
2501	    while(height) {
2502		if(blit_h > height) blit_h = height;
2503		(*infoRec->SubsequentScreenToScreenCopy)(pScrn,
2504			pBox->x1, y,
2505			pBox->x1, y + start, width, blit_h);
2506		height -= blit_h;
2507		start += blit_h;
2508		blit_h <<= 1;
2509	    }
2510	} else {
2511	    while(1) {
2512		w = width; skipleft = phaseX; x = pBox->x1;
2513		blit_h = pCache->h - phaseY;
2514		if(blit_h > height) blit_h = height;
2515
2516		while(1) {
2517		    blit_w = pCache->w - skipleft;
2518		    if(blit_w > w) blit_w = w;
2519		    (*infoRec->SubsequentScreenToScreenCopy)(pScrn,
2520			pCache->x + skipleft, pCache->y + phaseY,
2521			x, y, blit_w, blit_h);
2522		    w -= blit_w;
2523		    if(!w) break;
2524		    x += blit_w;
2525		    skipleft = (skipleft + blit_w) % pCache->orig_w;
2526		}
2527		height -= blit_h;
2528		if(!height) break;
2529		y += blit_h;
2530		phaseY = (phaseY + blit_h) % pCache->orig_h;
2531	    }
2532	}
2533	pBox++;
2534    }
2535
2536    SET_SYNC_FLAG(infoRec);
2537}
2538