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