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