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