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