mga_storm.c revision 4a32b415
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 "xorg-server.h"
9#include "xf86.h"
10#include "xf86_OSproc.h"
11
12/* For correct __inline__ usage */
13#include "compiler.h"
14
15/* Drivers that need to access the PCI config space directly need this */
16#include "xf86Pci.h"
17
18/* Drivers that use XAA need this */
19#ifdef HAVE_XAA_H
20#include "xaa.h"
21#include "xaalocal.h"
22#endif
23#include "xf86fbman.h"
24#include "miline.h"
25#include "servermd.h"
26
27#ifdef MGADRI
28#include "GL/glxtokens.h"
29#endif
30
31#include "mga.h"
32#include "mga_reg.h"
33#include "mga_macros.h"
34
35#ifdef MGADRI
36#include "mga_dri.h"
37#endif
38
39#define REPLICATE_8(r)  (((r) & 0x0ff) | (((r) & 0x0ff) << 8) \
40			 | (((r) & 0x0ff) << 16) | (((r) & 0x0ff) << 24))
41#define REPLICATE_16(r) (((r) & 0x0000ffff) | (((r) & 0x0000ffff) << 16))
42#define REPLICATE_24(r) (((r) & 0x00ffffff) | (((r) & 0x00ffffff) << 24))
43#define REPLICATE_32(r) (r)
44
45
46#define SET_FOREGROUND_REPLICATED(c, rep_c) \
47	if((c) != pMga->FgColor) { \
48	   pMga->FgColor = (c); \
49	   OUTREG(MGAREG_FCOL,(rep_c)); \
50	}
51
52#define SET_BACKGROUND_REPLICATED(c, rep_c) \
53	if((c) != pMga->BgColor) { \
54	   pMga->BgColor = (c); \
55	   OUTREG(MGAREG_BCOL,(rep_c)); \
56	}
57
58
59#define MGAMoveDWORDS(d,s,c) \
60do { \
61  write_mem_barrier(); \
62  XAAMoveDWORDS((d),(s),(c)); \
63} while (0)
64
65#ifdef HAVE_XAA_H
66static void mgaSetupForSolidFill( ScrnInfoPtr pScrn, int color,
67    int rop, unsigned int planemask );
68
69static void mgaSetupForScreenToScreenCopy( ScrnInfoPtr pScrn,
70    int xdir, int ydir, int rop, unsigned int planemask, int trans );
71
72static void mgaSubsequentScreenToScreenCopy( ScrnInfoPtr pScrn,
73    int srcX, int srcY, int dstX, int dstY, int w, int h );
74
75static void mgaSubsequentScreenToScreenCopy_FastBlit( ScrnInfoPtr pScrn,
76    int srcX, int srcY, int dstX, int dstY, int w, int h );
77
78static void mgaSetupForScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn,
79    int fg, int bg, int rop, unsigned int planemask );
80
81static void mgaSubsequentScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn,
82    int x, int y, int w, int h, int skipleft );
83
84static void mgaSubsequentColorExpandScanline( ScrnInfoPtr pScrn, int bufno );
85
86static void mgaSubsequentColorExpandScanlineIndirect( ScrnInfoPtr pScrn,
87    int bufno );
88
89static void mgaSubsequentSolidFillRect( ScrnInfoPtr pScrn, int x, int y,
90    int w, int h );
91
92static void mgaSubsequentSolidFillTrap( ScrnInfoPtr pScrn, int y, int h,
93    int left, int dxL, int dyL, int eL,	int right, int dxR, int dyR, int eR );
94
95static void mgaSubsequentSolidHorVertLine( ScrnInfoPtr pScrn, int x, int y,
96    int len, int dir );
97
98static void mgaSubsequentSolidTwoPointLine( ScrnInfoPtr pScrn,	int x1, int y1,
99    int x2, int y2, int flags );
100
101static void mgaSetupForMono8x8PatternFill( ScrnInfoPtr pScrn,
102    int patx, int paty, int fg, int bg, int rop, unsigned int planemask );
103
104static void mgaSubsequentMono8x8PatternFillRect( ScrnInfoPtr pScrn,
105    int patx, int paty,	int x, int y, int w, int h );
106
107static void mgaSubsequentMono8x8PatternFillRect_Additional( ScrnInfoPtr pScrn,
108    int patx, int paty, int x, int y, int w, int h );
109
110static void mgaSubsequentMono8x8PatternFillTrap( ScrnInfoPtr pScrn,
111    int patx, int paty, int y, int h, int left, int dxL, int dyL, int eL,
112    int right, int dxR, int dyR, int eR );
113
114static void mgaSetupForScanlineImageWrite( ScrnInfoPtr pScrn, int rop,
115    unsigned int planemask, int transparency_color, int bpp, int depth );
116
117static void mgaSubsequentScanlineImageWriteRect( ScrnInfoPtr pScrn,
118    int x, int y, int w, int h, int skipleft );
119
120static void mgaSubsequentImageWriteScanline( ScrnInfoPtr pScrn, int num );
121
122static void mgaSetupForPlanarScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
123    int fg, int bg, int rop, unsigned int planemask );
124
125static void mgaSubsequentPlanarScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
126    int x, int y, int w, int h,	int srcx, int srcy, int skipleft );
127
128static void mgaSetupForScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
129    int fg, int bg, int rop, unsigned int planemask );
130
131static void mgaSubsequentScreenToScreenColorExpandFill( ScrnInfoPtr pScrn,
132    int x, int y, int w, int h, int srcx, int srcy, int skipleft );
133
134#if X_BYTE_ORDER == X_LITTLE_ENDIAN
135static void mgaSetupForDashedLine( ScrnInfoPtr pScrn, int fg, int bg,
136    int rop, unsigned int planemask, int length, unsigned char *pattern );
137
138static void mgaSubsequentDashedTwoPointLine( ScrnInfoPtr pScrn,
139    int x1, int y1, int x2, int y2, int flags, int phase );
140#endif
141
142static void mgaRestoreAccelState( ScrnInfoPtr pScrn );
143
144static void MGASetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1,
145				int x2, int y2);
146static void MGADisableClipping(ScrnInfoPtr pScrn);
147static void MGAFillSolidRectsDMA(ScrnInfoPtr pScrn, int fg, int rop,
148				unsigned int planemask, int nBox, BoxPtr pBox);
149static void MGAFillSolidSpansDMA(ScrnInfoPtr pScrn, int fg, int rop,
150				unsigned int planemask, int n, DDXPointPtr ppt,
151 				int *pwidth, int fSorted);
152static void MGAFillMono8x8PatternRectsTwoPass(ScrnInfoPtr pScrn, int fg, int bg,
153 				int rop, unsigned int planemask, int nBox,
154 				BoxPtr pBox, int pattern0, int pattern1,
155				int xorigin, int yorigin);
156static void MGAValidatePolyArc(GCPtr, unsigned long, DrawablePtr);
157static void MGAValidatePolyPoint(GCPtr, unsigned long, DrawablePtr);
158static void MGAFillCacheBltRects(ScrnInfoPtr, int, unsigned int, int, BoxPtr,
159				int, int, XAACacheInfoPtr);
160
161
162static __inline__ void
163common_replicate_colors_and_mask( unsigned int fg, unsigned int bg,
164				  unsigned int pm,
165				  unsigned int bpp,
166				  unsigned int * rep_fg,
167				  unsigned int * rep_bg,
168				  unsigned int * rep_pm )
169{
170    switch( bpp ) {
171    case 8:
172	*rep_fg = REPLICATE_8( fg );
173	*rep_bg = REPLICATE_8( bg );
174	*rep_pm = REPLICATE_8( pm );
175	break;
176    case 16:
177	*rep_fg = REPLICATE_16( fg );
178	*rep_bg = REPLICATE_16( bg );
179	*rep_pm = REPLICATE_16( pm );
180	break;
181    case 24:
182	*rep_fg = REPLICATE_24( fg );
183	*rep_bg = REPLICATE_24( bg );
184	*rep_pm = REPLICATE_24( pm );
185	break;
186    case 32:
187	*rep_fg = REPLICATE_32( fg );
188	*rep_bg = REPLICATE_32( bg );
189	*rep_pm = REPLICATE_32( pm );
190	break;
191    }
192}
193
194
195#ifdef RENDER
196
197static Bool MGASetupForCPUToScreenAlphaTexture(ScrnInfoPtr pScrn, int op,
198    CARD16 red, CARD16 green, CARD16 blue, CARD16 alpha, int alphaType,
199    CARD8 *alphaPtr, int alphaPitch, int width, int height, int flags);
200
201static Bool MGASetupForCPUToScreenAlphaTextureFaked(ScrnInfoPtr Scrn, int op,
202    CARD16 red, CARD16 green, CARD16 blue, CARD16 alpha, int alphaType,
203    CARD8 *alphaPtr, int alphaPitch, int width, int height, int flags);
204
205static Bool MGASetupForCPUToScreenTexture(ScrnInfoPtr pScrn, int op,
206    int texType, CARD8 *texPtr, int texPitch, int width, int height,
207    int flags);
208
209static void MGASubsequentCPUToScreenTexture(ScrnInfoPtr pScrn, int dstx,
210    int dsty, int srcx, int srcy, int width, int height);
211
212#include "mipict.h"
213#include "dixstruct.h"
214
215static CARD32 MGAAlphaTextureFormats[2] = {PICT_a8, 0};
216static CARD32 MGATextureFormats[2] = {PICT_a8r8g8b8, 0};
217
218static void
219RemoveLinear (FBLinearPtr linear)
220{
221   MGAPtr pMga = (MGAPtr)(linear->devPrivate.ptr);
222
223   pMga->LinearScratch = NULL;  /* just lost our scratch */
224}
225
226static void
227RenderCallback (ScrnInfoPtr pScrn)
228{
229    MGAPtr pMga = MGAPTR(pScrn);
230
231    if((currentTime.milliseconds > pMga->RenderTime) && pMga->LinearScratch) {
232	xf86FreeOffscreenLinear(pMga->LinearScratch);
233	pMga->LinearScratch = NULL;
234    }
235
236    if(!pMga->LinearScratch)
237	pMga->RenderCallback = NULL;
238}
239
240#define RENDER_DELAY	15000
241
242static Bool
243AllocateLinear (
244   ScrnInfoPtr pScrn,
245   int sizeNeeded
246){
247   MGAPtr pMga = MGAPTR(pScrn);
248
249   pMga->RenderTime = currentTime.milliseconds + RENDER_DELAY;
250   pMga->RenderCallback = RenderCallback;
251
252   if(pMga->LinearScratch) {
253	if(pMga->LinearScratch->size >= sizeNeeded)
254	   return TRUE;
255	else {
256	   if(xf86ResizeOffscreenLinear(pMga->LinearScratch, sizeNeeded))
257		return TRUE;
258
259	   xf86FreeOffscreenLinear(pMga->LinearScratch);
260	   pMga->LinearScratch = NULL;
261	}
262   }
263
264   pMga->LinearScratch = xf86AllocateOffscreenLinear(
265				pScrn->pScreen, sizeNeeded, 32,
266				NULL, RemoveLinear, pMga);
267
268   return (pMga->LinearScratch != NULL);
269}
270
271static int
272GetPowerOfTwo(int w)
273{
274    int Pof2 = 0;
275    int i = 12;
276
277    while(--i) {
278        if(w & (1 << i)) {
279            Pof2 = i;
280            if(w & ((1 << i) - 1))
281                Pof2++;
282            break;
283        }
284    }
285    return Pof2;
286}
287
288
289static int tex_padw, tex_padh;
290
291Bool MGASetupForCPUToScreenAlphaTextureFaked( ScrnInfoPtr pScrn, int op,
292					      CARD16 red, CARD16 green,
293					      CARD16 blue, CARD16 alpha,
294					      int alphaType, CARD8 *alphaPtr,
295					      int alphaPitch, int width,
296					      int height, int flags )
297{
298    int log2w, log2h, pitch, sizeNeeded, offset;
299    unsigned int texctl, dwgctl, alphactrl;
300    MGAPtr pMga = MGAPTR(pScrn);
301
302    if(op != PictOpOver)  /* only one tested */
303	return FALSE;
304
305    if((width > 2048) || (height > 2048))
306	return FALSE;
307
308    log2w = GetPowerOfTwo(width);
309    log2h = GetPowerOfTwo(height);
310
311    CHECK_DMA_QUIESCENT(pMga, pScrn);
312
313    pitch = (width + 15) & ~15;
314    sizeNeeded = pitch * height;
315    if(pScrn->bitsPerPixel == 16)
316	sizeNeeded <<= 1;
317
318    if(!AllocateLinear(pScrn, sizeNeeded))
319	return FALSE;
320
321    offset = pMga->LinearScratch->offset << 1;
322    if(pScrn->bitsPerPixel == 32)
323        offset <<= 1;
324
325    if(pMga->AccelInfoRec->NeedToSync)
326	MGAStormSync(pScrn);
327
328    XAA_888_plus_PICT_a8_to_8888(
329	(blue >> 8) | (green & 0xff00) | ((red & 0xff00) << 8),
330	alphaPtr, alphaPitch, (CARD32*)(pMga->FbStart + offset),
331        pitch, width, height);
332
333    tex_padw = 1 << log2w;
334    tex_padh = 1 << log2h;
335
336    WAITFIFO(15);
337    OUTREG(MGAREG_TMR0, (1 << 20) / tex_padw);  /* sx inc */
338    OUTREG(MGAREG_TMR1, 0);  /* sy inc */
339    OUTREG(MGAREG_TMR2, 0);  /* tx inc */
340    OUTREG(MGAREG_TMR3, (1 << 20) / tex_padh);  /* ty inc */
341    OUTREG(MGAREG_TMR4, 0x00000000);
342    OUTREG(MGAREG_TMR5, 0x00000000);
343    OUTREG(MGAREG_TMR8, 0x00010000);
344    OUTREG(MGAREG_TEXORG, offset);
345    OUTREG(MGAREG_TEXWIDTH,  log2w | (((8 - log2w) & 63) << 9) |
346                                ((width - 1) << 18));
347    OUTREG(MGAREG_TEXHEIGHT, log2h | (((8 - log2h) & 63) << 9) |
348                                ((height - 1) << 18));
349
350    texctl = MGA_TW32 | MGA_PITCHLIN | MGA_TAKEY | MGA_CLAMPUV |
351             ((pitch & 0x07FF) << 9);
352    dwgctl = MGADWG_TEXTURE_TRAP | MGADWG_I | MGADWG_ARZERO |
353             MGADWG_SGNZERO | MGADWG_SHIFTZERO | 0xc0000;
354    alphactrl = MGA_SRC_ALPHA | MGA_DST_ONE_MINUS_SRC_ALPHA |
355                MGA_ALPHACHANNEL;
356
357    OUTREG(MGAREG_TEXCTL, texctl);
358    OUTREG(MGAREG_TEXCTL2, MGA_TC2_DECALDIS | MGA_TC2_CKSTRANSDIS);
359    OUTREG(MGAREG_DWGCTL, dwgctl);
360    OUTREG(MGAREG_TEXFILTER, ((0x1e << 20) | MGA_MAG_BILIN));
361    OUTREG(MGAREG_ALPHACTRL, alphactrl);
362
363    return TRUE;
364}
365
366Bool
367MGASetupForCPUToScreenAlphaTexture (
368   ScrnInfoPtr	pScrn,
369   int		op,
370   CARD16	red,
371   CARD16	green,
372   CARD16	blue,
373   CARD16	alpha,
374   int		alphaType,
375   CARD8	*alphaPtr,
376   int		alphaPitch,
377   int		width,
378   int		height,
379   int		flags
380){
381    int log2w, log2h, i, pitch, sizeNeeded, offset;
382    unsigned int texctl, dwgctl, alphactrl;
383    CARD8 *dst;
384    MGAPtr pMga = MGAPTR(pScrn);
385
386    if(op != PictOpOver)  /* only one tested */
387	return FALSE;
388
389    if((width > 2048) || (height > 2048))
390	return FALSE;
391
392    log2w = GetPowerOfTwo(width);
393    log2h = GetPowerOfTwo(height);
394
395    CHECK_DMA_QUIESCENT(pMga, pScrn);
396
397    pitch = (width + 15) & ~15;
398    sizeNeeded = (pitch * height) >> 1;
399    if(pScrn->bitsPerPixel == 32)
400	sizeNeeded >>= 1;
401
402    if(!AllocateLinear(pScrn, sizeNeeded))
403	return FALSE;
404
405    offset = pMga->LinearScratch->offset << 1;
406    if(pScrn->bitsPerPixel == 32)
407        offset <<= 1;
408
409    if(pMga->AccelInfoRec->NeedToSync)
410	MGAStormSync(pScrn);
411
412    i = height;
413    dst = pMga->FbStart + offset;
414    while(i--) {
415	memcpy(dst, alphaPtr, width);
416	dst += pitch;
417	alphaPtr += alphaPitch;
418    }
419
420    tex_padw = 1 << log2w;
421    tex_padh = 1 << log2h;
422
423
424    WAITFIFO(12);
425    OUTREG(MGAREG_DR4, red << 7);  /* red start */
426    OUTREG(MGAREG_DR6, 0);
427    OUTREG(MGAREG_DR7, 0);
428    OUTREG(MGAREG_DR8, green << 7);  /* green start */
429    OUTREG(MGAREG_DR10, 0);
430    OUTREG(MGAREG_DR11, 0);
431    OUTREG(MGAREG_DR12, blue << 7);  /* blue start */
432    OUTREG(MGAREG_DR14, 0);
433    OUTREG(MGAREG_DR15, 0);
434    OUTREG(MGAREG_ALPHASTART, alpha << 7);  /* alpha start */
435    OUTREG(MGAREG_ALPHAXINC, 0);
436    OUTREG(MGAREG_ALPHAYINC, 0);
437
438    WAITFIFO(15);
439    OUTREG(MGAREG_TMR0, (1 << 20) / tex_padw);  /* sx inc */
440    OUTREG(MGAREG_TMR1, 0);  /* sy inc */
441    OUTREG(MGAREG_TMR2, 0);  /* tx inc */
442    OUTREG(MGAREG_TMR3, (1 << 20) / tex_padh);  /* ty inc */
443    OUTREG(MGAREG_TMR4, 0x00000000);
444    OUTREG(MGAREG_TMR5, 0x00000000);
445    OUTREG(MGAREG_TMR8, 0x00010000);
446    OUTREG(MGAREG_TEXORG, offset);
447    OUTREG(MGAREG_TEXWIDTH,  log2w | (((8 - log2w) & 63) << 9) |
448                                ((width - 1) << 18));
449    OUTREG(MGAREG_TEXHEIGHT, log2h | (((8 - log2h) & 63) << 9) |
450                                ((height - 1) << 18));
451
452    texctl = MGA_TW8A | MGA_PITCHLIN | MGA_TAKEY | MGA_CLAMPUV |
453             MGA_TEXMODULATE |
454             ((pitch & 0x07FF) << 9);
455    dwgctl = MGADWG_TEXTURE_TRAP | MGADWG_I | MGADWG_ARZERO |
456             MGADWG_SGNZERO | MGADWG_SHIFTZERO | 0xc0000;
457    alphactrl = MGA_SRC_ONE | MGA_DST_ONE_MINUS_SRC_ALPHA |
458                MGA_ALPHACHANNEL | MGA_MODULATEDALPHA;
459
460    OUTREG(MGAREG_TEXCTL, texctl);
461    OUTREG(MGAREG_TEXCTL2, MGA_TC2_DECALDIS | MGA_TC2_CKSTRANSDIS);
462    OUTREG(MGAREG_DWGCTL, dwgctl);
463    OUTREG(MGAREG_TEXFILTER, ((0x1e << 20) | MGA_MAG_BILIN));
464    OUTREG(MGAREG_ALPHACTRL, alphactrl);
465
466    return TRUE;
467}
468
469
470Bool
471MGASetupForCPUToScreenTexture (
472   ScrnInfoPtr	pScrn,
473   int		op,
474   int		texType,
475   CARD8	*texPtr,
476   int		texPitch,
477   int		width,
478   int		height,
479   int		flags
480){
481    int log2w, log2h, i, pitch, sizeNeeded, offset;
482    unsigned int texctl, dwgctl, alphactrl;
483    MGAPtr pMga = MGAPTR(pScrn);
484
485    if(op != PictOpOver)  /* only one tested */
486	return FALSE;
487
488    if((width > 2048) || (height > 2048))
489	return FALSE;
490
491    log2w = GetPowerOfTwo(width);
492    log2h = GetPowerOfTwo(height);
493
494    CHECK_DMA_QUIESCENT(pMga, pScrn);
495
496    pitch = (width + 15) & ~15;
497    sizeNeeded = pitch * height;
498    if(pScrn->bitsPerPixel == 16)
499	sizeNeeded <<= 1;
500
501    if(!AllocateLinear(pScrn, sizeNeeded))
502	return FALSE;
503
504    offset = pMga->LinearScratch->offset << 1;
505    if(pScrn->bitsPerPixel == 32)
506        offset <<= 1;
507
508    if(pMga->AccelInfoRec->NeedToSync)
509	MGAStormSync(pScrn);
510
511    {
512	CARD8 *dst = (CARD8*)(pMga->FbStart + offset);
513	i = height;
514	while(i--) {
515            memcpy(dst, texPtr, width << 2);
516	    texPtr += texPitch;
517	    dst += pitch << 2;
518	}
519    }
520
521    tex_padw = 1 << log2w;
522    tex_padh = 1 << log2h;
523
524    WAITFIFO(15);
525    OUTREG(MGAREG_TMR0, (1 << 20) / tex_padw);  /* sx inc */
526    OUTREG(MGAREG_TMR1, 0);  /* sy inc */
527    OUTREG(MGAREG_TMR2, 0);  /* tx inc */
528    OUTREG(MGAREG_TMR3, (1 << 20) / tex_padh);  /* ty inc */
529    OUTREG(MGAREG_TMR4, 0x00000000);
530    OUTREG(MGAREG_TMR5, 0x00000000);
531    OUTREG(MGAREG_TMR8, 0x00010000);
532    OUTREG(MGAREG_TEXORG, offset);
533    OUTREG(MGAREG_TEXWIDTH,  log2w | (((8 - log2w) & 63) << 9) |
534                                ((width - 1) << 18));
535    OUTREG(MGAREG_TEXHEIGHT, log2h | (((8 - log2h) & 63) << 9) |
536                                ((height - 1) << 18));
537
538    texctl = MGA_TW32 | MGA_PITCHLIN | MGA_TAKEY | MGA_CLAMPUV |
539             ((pitch & 0x07FF) << 9);
540    dwgctl = MGADWG_TEXTURE_TRAP | MGADWG_I | MGADWG_ARZERO |
541             MGADWG_SGNZERO | MGADWG_SHIFTZERO | 0xc0000;
542    alphactrl = MGA_SRC_ONE | MGA_DST_ONE_MINUS_SRC_ALPHA |
543                MGA_ALPHACHANNEL;
544
545    OUTREG(MGAREG_TEXCTL, texctl);
546    OUTREG(MGAREG_TEXCTL2, MGA_TC2_DECALDIS | MGA_TC2_CKSTRANSDIS);
547    OUTREG(MGAREG_DWGCTL, dwgctl);
548    OUTREG(MGAREG_TEXFILTER, ((0x1e << 20) | MGA_MAG_BILIN));
549    OUTREG(MGAREG_ALPHACTRL, alphactrl);
550
551    return TRUE;
552}
553void
554MGASubsequentCPUToScreenTexture (
555    ScrnInfoPtr	pScrn,
556    int		dstx,
557    int		dsty,
558    int		srcx,
559    int		srcy,
560    int		width,
561    int		height
562){
563    MGAPtr pMga = MGAPTR(pScrn);
564
565    WAITFIFO(4);
566    OUTREG(MGAREG_TMR6, (srcx << 20) / tex_padw);
567    OUTREG(MGAREG_TMR7, (srcy << 20) / tex_padh);
568    OUTREG(MGAREG_FXBNDRY, ((dstx + width) << 16) | (dstx & 0xffff));
569    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (dsty << 16) | height);
570
571    pMga->AccelInfoRec->NeedToSync = TRUE;
572}
573
574
575#endif /* defined(RENDER) */
576#endif
577
578Bool mgaAccelInit( ScreenPtr pScreen )
579{
580#ifdef HAVE_XAA_H
581    XAAInfoRecPtr infoPtr;
582#endif
583    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
584    MGAPtr pMga = MGAPTR(pScrn);
585    int maxFastBlitMem, maxlines;
586    Bool doRender = FALSE;
587    BoxRec AvailFBArea;
588    int i;
589
590    pMga->ScratchBuffer = malloc(((pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel) + 127) >> 3);
591    if(!pMga->ScratchBuffer) return FALSE;
592
593#ifdef HAVE_XAA_H
594    pMga->AccelInfoRec = infoPtr = XAACreateInfoRec();
595    if(!infoPtr) return FALSE;
596#endif
597
598    pMga->RenderTime = 0;
599    pMga->LinearScratch = 0;
600
601    pMga->MaxFastBlitY = 0;
602    pMga->MaxBlitDWORDS = 0x40000 >> 5;
603
604
605    /* Set initial acceleration flags.
606     */
607    pMga->AccelFlags = pMga->chip_attribs->accel_flags;
608
609    if ((pMga->FbMapSize > 8*1024*1024) && (pScrn->depth == 8)) {
610	pMga->AccelFlags |= LARGE_ADDRESSES;
611    }
612
613    if (pMga->CurrentLayout.bitsPerPixel == 24) {
614	pMga->AccelFlags |= MGA_NO_PLANEMASK;
615    }
616
617    if (pMga->SecondCrtc) {
618	pMga->HasFBitBlt = FALSE;
619    }
620
621    if(pMga->HasSDRAM) {
622	pMga->Atype = pMga->AtypeNoBLK = MGAAtypeNoBLK;
623	pMga->AccelFlags &= ~TWO_PASS_COLOR_EXPAND;
624    } else {
625	pMga->Atype = MGAAtype;
626	pMga->AtypeNoBLK = MGAAtypeNoBLK;
627    }
628
629#ifdef HAVE_XAA_H
630    /* fill out infoPtr here */
631    infoPtr->Flags = 	PIXMAP_CACHE |
632			OFFSCREEN_PIXMAPS |
633			LINEAR_FRAMEBUFFER |
634			MICROSOFT_ZERO_LINE_BIAS;
635
636    /* sync */
637    infoPtr->Sync = MGAStormSync;
638
639    /* screen to screen copy */
640    infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
641    infoPtr->SetupForScreenToScreenCopy =
642        	mgaSetupForScreenToScreenCopy;
643    infoPtr->SubsequentScreenToScreenCopy = mgaSubsequentScreenToScreenCopy;
644
645    if(pMga->HasFBitBlt) {
646	infoPtr->FillCacheBltRects = MGAFillCacheBltRects;
647	infoPtr->FillCacheBltRectsFlags = NO_TRANSPARENCY;
648    }
649    /* solid fills */
650    infoPtr->SetupForSolidFill = mgaSetupForSolidFill;
651    infoPtr->SubsequentSolidFillRect = mgaSubsequentSolidFillRect;
652    infoPtr->SubsequentSolidFillTrap = mgaSubsequentSolidFillTrap;
653
654    /* solid lines */
655    infoPtr->SetupForSolidLine = infoPtr->SetupForSolidFill;
656    infoPtr->SubsequentSolidHorVertLine = mgaSubsequentSolidHorVertLine;
657    infoPtr->SubsequentSolidTwoPointLine = mgaSubsequentSolidTwoPointLine;
658
659    /* clipping */
660    infoPtr->SetClippingRectangle = MGASetClippingRectangle;
661    infoPtr->DisableClipping = MGADisableClipping;
662    infoPtr->ClippingFlags = 	HARDWARE_CLIP_SOLID_LINE  |
663				HARDWARE_CLIP_DASHED_LINE |
664				HARDWARE_CLIP_SOLID_FILL  |
665				HARDWARE_CLIP_MONO_8x8_FILL;
666
667#if X_BYTE_ORDER == X_LITTLE_ENDIAN
668    /* dashed lines */
669    infoPtr->DashedLineFlags = LINE_PATTERN_MSBFIRST_LSBJUSTIFIED;
670    infoPtr->SetupForDashedLine = mgaSetupForDashedLine;
671    infoPtr->SubsequentDashedTwoPointLine = mgaSubsequentDashedTwoPointLine;
672    infoPtr->DashPatternMaxLength = 128;
673#endif
674
675    /* 8x8 mono patterns */
676    infoPtr->Mono8x8PatternFillFlags = HARDWARE_PATTERN_PROGRAMMED_BITS |
677					HARDWARE_PATTERN_PROGRAMMED_ORIGIN |
678					HARDWARE_PATTERN_SCREEN_ORIGIN |
679					BIT_ORDER_IN_BYTE_MSBFIRST;
680    infoPtr->SetupForMono8x8PatternFill = mgaSetupForMono8x8PatternFill;
681    infoPtr->SubsequentMono8x8PatternFillRect =
682		mgaSubsequentMono8x8PatternFillRect;
683    infoPtr->SubsequentMono8x8PatternFillTrap =
684		mgaSubsequentMono8x8PatternFillTrap;
685
686    /* cpu to screen color expansion */
687    infoPtr->ScanlineCPUToScreenColorExpandFillFlags =
688					CPU_TRANSFER_PAD_DWORD |
689					SCANLINE_PAD_DWORD |
690#if X_BYTE_ORDER == X_BIG_ENDIAN
691					BIT_ORDER_IN_BYTE_MSBFIRST |
692#else
693					BIT_ORDER_IN_BYTE_LSBFIRST |
694#endif
695					LEFT_EDGE_CLIPPING |
696					LEFT_EDGE_CLIPPING_NEGATIVE_X;
697
698    if(pMga->ILOADBase) {
699	pMga->ColorExpandBase = pMga->ILOADBase;
700    } else {
701	pMga->ColorExpandBase = pMga->IOBase;
702    }
703    infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
704		mgaSetupForScanlineCPUToScreenColorExpandFill;
705    infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
706		mgaSubsequentScanlineCPUToScreenColorExpandFill;
707    infoPtr->SubsequentColorExpandScanline = mgaSubsequentColorExpandScanline;
708    infoPtr->NumScanlineColorExpandBuffers = 1;
709    infoPtr->ScanlineColorExpandBuffers = &(pMga->ColorExpandBase);
710
711    /* screen to screen color expansion */
712    if(pMga->AccelFlags & USE_LINEAR_EXPANSION) {
713	infoPtr->ScreenToScreenColorExpandFillFlags =
714#if X_BYTE_ORDER == X_BIG_ENDIAN
715						BIT_ORDER_IN_BYTE_MSBFIRST;
716#else
717						BIT_ORDER_IN_BYTE_LSBFIRST;
718#endif
719	infoPtr->SetupForScreenToScreenColorExpandFill =
720		mgaSetupForScreenToScreenColorExpandFill;
721	infoPtr->SubsequentScreenToScreenColorExpandFill =
722		mgaSubsequentScreenToScreenColorExpandFill;
723    }
724    else if ( pMga->CurrentLayout.bitsPerPixel != 24 ) {
725	/* Alternate (but slower) planar expansions */
726	infoPtr->SetupForScreenToScreenColorExpandFill =
727	  mgaSetupForPlanarScreenToScreenColorExpandFill;
728	infoPtr->SubsequentScreenToScreenColorExpandFill =
729	  mgaSubsequentPlanarScreenToScreenColorExpandFill;
730	infoPtr->CacheColorExpandDensity = pMga->CurrentLayout.bitsPerPixel;
731	infoPtr->CacheMonoStipple = XAAGetCachePlanarMonoStipple();
732
733	/* It's faster to blit the stipples if you have fastbilt
734	 */
735	if(pMga->HasFBitBlt)
736	    infoPtr->ScreenToScreenColorExpandFillFlags = TRANSPARENCY_ONLY;
737    }
738
739    /* image writes */
740    infoPtr->ScanlineImageWriteFlags = 	CPU_TRANSFER_PAD_DWORD |
741					SCANLINE_PAD_DWORD |
742					LEFT_EDGE_CLIPPING |
743					LEFT_EDGE_CLIPPING_NEGATIVE_X |
744					NO_TRANSPARENCY |
745					NO_GXCOPY;
746
747    infoPtr->SetupForScanlineImageWrite = mgaSetupForScanlineImageWrite;
748    infoPtr->SubsequentScanlineImageWriteRect =
749      mgaSubsequentScanlineImageWriteRect;
750    infoPtr->SubsequentImageWriteScanline = mgaSubsequentImageWriteScanline;
751    infoPtr->NumScanlineImageWriteBuffers = 1;
752    infoPtr->ScanlineImageWriteBuffers = &(pMga->ScratchBuffer);
753
754
755    /* midrange replacements */
756
757    if(pMga->ILOADBase && pMga->UsePCIRetry && infoPtr->SetupForSolidFill) {
758	infoPtr->FillSolidRects = MGAFillSolidRectsDMA;
759	infoPtr->FillSolidSpans = MGAFillSolidSpansDMA;
760    }
761
762    if(pMga->AccelFlags & TWO_PASS_COLOR_EXPAND) {
763	if(infoPtr->SetupForMono8x8PatternFill)
764	    infoPtr->FillMono8x8PatternRects =
765				MGAFillMono8x8PatternRectsTwoPass;
766    }
767
768    if(infoPtr->SetupForSolidFill) {
769	infoPtr->ValidatePolyArc = MGAValidatePolyArc;
770	infoPtr->PolyArcMask = GCFunction | GCLineWidth | GCPlaneMask |
771				GCLineStyle | GCFillStyle;
772	infoPtr->ValidatePolyPoint = MGAValidatePolyPoint;
773	infoPtr->PolyPointMask = GCFunction | GCPlaneMask;
774    }
775    if(pMga->AccelFlags & MGA_NO_PLANEMASK) {
776	infoPtr->ScanlineImageWriteFlags |= NO_PLANEMASK;
777	infoPtr->ScreenToScreenCopyFlags |= NO_PLANEMASK;
778	infoPtr->ScanlineCPUToScreenColorExpandFillFlags |= NO_PLANEMASK;
779	infoPtr->SolidFillFlags |= NO_PLANEMASK;
780	infoPtr->SolidLineFlags |= NO_PLANEMASK;
781#if X_BYTE_ORDER == X_LITTLE_ENDIAN
782	infoPtr->DashedLineFlags |= NO_PLANEMASK;
783#endif
784	infoPtr->Mono8x8PatternFillFlags |= NO_PLANEMASK;
785	infoPtr->ScreenToScreenColorExpandFillFlags |= NO_PLANEMASK;
786	infoPtr->FillSolidRectsFlags |= NO_PLANEMASK;
787	infoPtr->FillSolidSpansFlags |= NO_PLANEMASK;
788	infoPtr->FillMono8x8PatternRectsFlags |= NO_PLANEMASK;
789	infoPtr->FillCacheBltRectsFlags |= NO_PLANEMASK;
790    }
791
792
793    maxFastBlitMem = (pMga->Interleave ? 4096 : 2048) * 1024;
794
795    if(pMga->FbMapSize > maxFastBlitMem) {
796	pMga->MaxFastBlitY = maxFastBlitMem / (pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel / 8);
797    }
798
799#endif
800
801    switch (pMga->Chipset) {
802    case PCI_CHIP_MGAG200_SE_A_PCI:
803    case PCI_CHIP_MGAG200_SE_B_PCI:
804	maxlines = (min(pMga->FbUsableSize, 1*1024*1024)) /
805		   (pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel / 8);
806	break;
807    default:
808	maxlines = (min(pMga->FbUsableSize, 16*1024*1024)) /
809		   (pScrn->displayWidth * pMga->CurrentLayout.bitsPerPixel / 8);
810	break;
811    }
812
813#ifdef MGADRI
814    if ( pMga->directRenderingEnabled ) {
815       MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
816       BoxRec MemBox;
817       int cpp = pScrn->bitsPerPixel / 8;
818       int widthBytes = pScrn->displayWidth * cpp;
819       int bufferSize = ((pScrn->virtualY * widthBytes + MGA_BUFFER_ALIGN)
820			 & ~MGA_BUFFER_ALIGN);
821       int scanlines;
822
823       pMGADRIServer->frontOffset = 0;
824       pMGADRIServer->frontPitch = widthBytes;
825
826       /* Try for front, back, depth, and two framebuffers worth of
827	* pixmap cache.  Should be enough for a fullscreen background
828	* image plus some leftovers.
829	*/
830       pMGADRIServer->textureSize = pMga->FbMapSize - 5 * bufferSize;
831
832       /* If that gives us less than half the available memory, let's
833	* be greedy and grab some more.  Sorry, I care more about 3D
834	* performance than playing nicely, and you'll get around a full
835	* framebuffer's worth of pixmap cache anyway.
836	*/
837       if ( pMGADRIServer->textureSize < (int)pMga->FbMapSize / 2 ) {
838	  pMGADRIServer->textureSize = pMga->FbMapSize - 4 * bufferSize;
839       }
840
841       /* Check to see if there is more room available after the maximum
842	* scanline for textures.
843	*/
844       if ( (int)pMga->FbMapSize - maxlines * widthBytes - bufferSize * 2
845	    > pMGADRIServer->textureSize ) {
846	  pMGADRIServer->textureSize = (pMga->FbMapSize -
847					maxlines * widthBytes -
848					bufferSize * 2);
849       }
850
851       /* Set a minimum usable local texture heap size.  This will fit
852	* two 256x256x32bpp textures.
853	*/
854       if ( pMGADRIServer->textureSize < 512 * 1024 ) {
855	  pMGADRIServer->textureOffset = 0;
856	  pMGADRIServer->textureSize = 0;
857       }
858
859       /* Reserve space for textures */
860       pMGADRIServer->textureOffset = (pMga->FbMapSize -
861				       pMGADRIServer->textureSize +
862				       MGA_BUFFER_ALIGN) & ~MGA_BUFFER_ALIGN;
863
864       /* Reserve space for the shared depth buffer */
865       pMGADRIServer->depthOffset = (pMGADRIServer->textureOffset -
866				     bufferSize +
867				     MGA_BUFFER_ALIGN) & ~MGA_BUFFER_ALIGN;
868       pMGADRIServer->depthPitch = widthBytes;
869
870       /* Reserve space for the shared back buffer */
871       pMGADRIServer->backOffset = (pMGADRIServer->depthOffset - bufferSize +
872				    MGA_BUFFER_ALIGN) & ~MGA_BUFFER_ALIGN;
873       pMGADRIServer->backPitch = widthBytes;
874
875       scanlines = pMGADRIServer->backOffset / widthBytes - 1;
876       if ( scanlines > maxlines ) scanlines = maxlines;
877
878       MemBox.x1 = 0;
879       MemBox.y1 = 0;
880       MemBox.x2 = pScrn->displayWidth;
881       MemBox.y2 = scanlines;
882
883       if ( !xf86InitFBManager( pScreen, &MemBox ) ) {
884	  xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
885		      "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
886		      MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2 );
887	  return FALSE;
888       } else {
889	  int width, height;
890
891	  xf86DrvMsg( pScrn->scrnIndex, X_INFO,
892		      "Memory manager initialized to (%d,%d) (%d,%d)\n",
893		      MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2 );
894
895	  if ( xf86QueryLargestOffscreenArea( pScreen, &width,
896					      &height, 0, 0, 0 ) ) {
897	     xf86DrvMsg( pScrn->scrnIndex, X_INFO,
898			 "Largest offscreen area available: %d x %d\n",
899			 width, height );
900	  }
901       }
902
903       xf86DrvMsg( pScrn->scrnIndex, X_INFO,
904		   "Reserved back buffer at offset 0x%x\n",
905		   pMGADRIServer->backOffset );
906       xf86DrvMsg( pScrn->scrnIndex, X_INFO,
907		   "Reserved depth buffer at offset 0x%x\n",
908		   pMGADRIServer->depthOffset );
909       xf86DrvMsg( pScrn->scrnIndex, X_INFO,
910		   "Reserved %d kb for textures at offset 0x%x\n",
911		   pMGADRIServer->textureSize/1024,
912		   pMGADRIServer->textureOffset );
913    }
914    else
915#endif /* defined(MGADRI) */
916    {
917       AvailFBArea.x1 = 0;
918       AvailFBArea.x2 = pScrn->displayWidth;
919       AvailFBArea.y1 = 0;
920       AvailFBArea.y2 = maxlines;
921
922       /*
923	* Need to keep a strip of memory to the right of screen to workaround
924	* a display problem with the second CRTC.
925	*/
926       if (pMga->SecondCrtc)
927	  AvailFBArea.x2 = pScrn->virtualX;
928
929       xf86InitFBManager(pScreen, &AvailFBArea);
930       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %d lines for offscreen "
931		  "memory.\n",
932		  maxlines - pScrn->virtualY);
933
934    }
935
936#ifdef HAVE_XAA_H
937    for (i = 0; i < pScrn->numEntities; i++) {
938	if (xf86IsEntityShared(pScrn->entityList[i])) {
939	    infoPtr->RestoreAccelState = mgaRestoreAccelState;
940	    break;
941	}
942    }
943
944#ifdef RENDER
945   if(doRender && ((pScrn->bitsPerPixel == 32) || (pScrn->bitsPerPixel == 16)))
946   {
947       if(pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550) {
948           infoPtr->CPUToScreenAlphaTextureFlags = XAA_RENDER_NO_TILE;
949           infoPtr->SetupForCPUToScreenAlphaTexture =
950				MGASetupForCPUToScreenAlphaTexture;
951       } else {
952           infoPtr->CPUToScreenAlphaTextureFlags = XAA_RENDER_NO_TILE |
953					       XAA_RENDER_NO_SRC_ALPHA;
954           infoPtr->SetupForCPUToScreenAlphaTexture =
955				MGASetupForCPUToScreenAlphaTextureFaked;
956       }
957       infoPtr->SubsequentCPUToScreenAlphaTexture =
958				MGASubsequentCPUToScreenTexture;
959       infoPtr->CPUToScreenAlphaTextureFormats = MGAAlphaTextureFormats;
960
961       infoPtr->SetupForCPUToScreenTexture = MGASetupForCPUToScreenTexture;
962       infoPtr->SubsequentCPUToScreenTexture = MGASubsequentCPUToScreenTexture;
963       infoPtr->CPUToScreenTextureFlags = XAA_RENDER_NO_TILE;
964       infoPtr->CPUToScreenTextureFormats = MGATextureFormats;
965    }
966#endif /* defined(RENDER) */
967
968    return(XAAInit(pScreen, infoPtr));
969#else
970    return TRUE;
971#endif
972}
973
974
975#ifdef HAVE_XAA_H
976/* Support for multiscreen */
977static void mgaRestoreAccelState(ScrnInfoPtr pScrn)
978{
979   MGAPtr pMga = MGAPTR(pScrn);
980   MGAFBLayout *pLayout = &pMga->CurrentLayout;
981    unsigned int replicate_fg = 0;
982    unsigned int replicate_bg = 0;
983    unsigned int replicate_pm = 0;
984
985   MGAStormSync(pScrn);
986   WAITFIFO(12);
987   pMga->SrcOrg = 0;
988   OUTREG(MGAREG_MACCESS, pMga->MAccess);
989   OUTREG(MGAREG_PITCH, pLayout->displayWidth);
990   OUTREG(MGAREG_YDSTORG, pMga->YDstOrg);
991
992
993    common_replicate_colors_and_mask( pMga->FgColor, pMga->BgColor,
994				      pMga->PlaneMask, pLayout->bitsPerPixel,
995				      & replicate_fg, & replicate_bg,
996				      & replicate_pm );
997
998    if( (pLayout->bitsPerPixel != 24)
999	&& ((pMga->AccelFlags & MGA_NO_PLANEMASK) == 0) ) {
1000	OUTREG( MGAREG_PLNWT, replicate_pm );
1001    }
1002
1003    OUTREG( MGAREG_BCOL, replicate_bg );
1004    OUTREG( MGAREG_FCOL, replicate_fg );
1005
1006   OUTREG(MGAREG_SRCORG, pMga->realSrcOrg);
1007   OUTREG(MGAREG_DSTORG, pMga->DstOrg);
1008#if X_BYTE_ORDER == X_LITTLE_ENDIAN
1009   OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT );
1010#else
1011   OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT | 0x10000);
1012#endif
1013   OUTREG(MGAREG_CXBNDRY, 0xFFFF0000); /* (maxX << 16) | minX */
1014   OUTREG(MGAREG_YTOP, 0x00000000);    /* minPixelPointer */
1015   OUTREG(MGAREG_YBOT, 0x007FFFFF);    /* maxPixelPointer */
1016   pMga->AccelFlags &= ~CLIPPER_ON;
1017}
1018#endif
1019
1020CARD32 MGAAtype[16] = {
1021   MGADWG_RPL  | 0x00000000, MGADWG_RSTR | 0x00080000,
1022   MGADWG_RSTR | 0x00040000, MGADWG_BLK  | 0x000c0000,
1023   MGADWG_RSTR | 0x00020000, MGADWG_RSTR | 0x000a0000,
1024   MGADWG_RSTR | 0x00060000, MGADWG_RSTR | 0x000e0000,
1025   MGADWG_RSTR | 0x00010000, MGADWG_RSTR | 0x00090000,
1026   MGADWG_RSTR | 0x00050000, MGADWG_RSTR | 0x000d0000,
1027   MGADWG_RPL  | 0x00030000, MGADWG_RSTR | 0x000b0000,
1028   MGADWG_RSTR | 0x00070000, MGADWG_RPL  | 0x000f0000
1029};
1030
1031
1032CARD32 MGAAtypeNoBLK[16] = {
1033   MGADWG_RPL  | 0x00000000, MGADWG_RSTR | 0x00080000,
1034   MGADWG_RSTR | 0x00040000, MGADWG_RPL  | 0x000c0000,
1035   MGADWG_RSTR | 0x00020000, MGADWG_RSTR | 0x000a0000,
1036   MGADWG_RSTR | 0x00060000, MGADWG_RSTR | 0x000e0000,
1037   MGADWG_RSTR | 0x00010000, MGADWG_RSTR | 0x00090000,
1038   MGADWG_RSTR | 0x00050000, MGADWG_RSTR | 0x000d0000,
1039   MGADWG_RPL  | 0x00030000, MGADWG_RSTR | 0x000b0000,
1040   MGADWG_RSTR | 0x00070000, MGADWG_RPL  | 0x000f0000
1041};
1042
1043
1044Bool
1045MGAStormAccelInit(ScreenPtr pScreen)
1046{
1047    return mgaAccelInit( pScreen );
1048}
1049
1050
1051
1052void
1053MGAStormSync(ScrnInfoPtr pScrn)
1054{
1055    MGAPtr pMga = MGAPTR(pScrn);
1056
1057    CHECK_DMA_QUIESCENT(pMga, pScrn);
1058
1059    /* MGAISBUSY() reportedly causes a freeze for Mystique revisions 0 and 1 */
1060    if (!(pMga->Chipset == PCI_CHIP_MGA1064 && (pMga->ChipRev >= 0 && pMga->ChipRev <= 1)))
1061	while(MGAISBUSY());
1062    /* flush cache before a read (mga-1064g 5.1.6) */
1063    OUTREG8(MGAREG_CRTC_INDEX, 0);
1064    if(pMga->AccelFlags & CLIPPER_ON) {
1065        pMga->AccelFlags &= ~CLIPPER_ON;
1066        OUTREG(MGAREG_CXBNDRY, 0xFFFF0000);
1067    }
1068}
1069
1070
1071void MGAStormEngineInit( ScrnInfoPtr pScrn )
1072{
1073    long maccess = 0;
1074    MGAPtr pMga = MGAPTR(pScrn);
1075    MGAFBLayout *pLayout = &pMga->CurrentLayout;
1076    CARD32 opmode;
1077    static const unsigned int maccess_table[5] = {
1078   /* bpp:  8  16  24  32 */
1079	0,  0,  1,  3,  2
1080    };
1081    static const unsigned int opmode_table[5] = {
1082        /* bpp:        8       16       24       32 */
1083	0x00000, 0x00000, 0x10000, 0x20000, 0x20000
1084    };
1085
1086    CHECK_DMA_QUIESCENT(pMga, pScrn);
1087
1088    if ((pMga->Chipset == PCI_CHIP_MGAG100)
1089	|| (pMga->Chipset == PCI_CHIP_MGAG100_PCI))
1090    	maccess = 1 << 14;
1091
1092    opmode = INREG(MGAREG_OPMODE);
1093
1094    maccess |= maccess_table[ pLayout->bitsPerPixel / 8 ];
1095    if ( pLayout->depth == 15 ) {
1096        maccess |= (1 << 31);
1097    }
1098
1099    opmode |= opmode_table[ pLayout->bitsPerPixel / 8 ];
1100#if X_BYTE_ORDER == X_LITTLE_ENDIAN
1101    opmode &= ~0x30000;
1102#endif
1103
1104#ifdef HAVE_XAA_H
1105    pMga->SetupForSolidFill = mgaSetupForSolidFill;
1106    pMga->SubsequentSolidFillRect = mgaSubsequentSolidFillRect;
1107    pMga->RestoreAccelState = mgaRestoreAccelState;
1108#endif
1109
1110
1111    pMga->fifoCount = 0;
1112
1113    while(MGAISBUSY());
1114
1115    if(!pMga->FifoSize) {
1116	pMga->FifoSize = INREG8(MGAREG_FIFOSTATUS);
1117	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%i DWORD fifo\n",
1118						pMga->FifoSize);
1119    }
1120
1121    OUTREG(MGAREG_PITCH, pLayout->displayWidth);
1122    OUTREG(MGAREG_YDSTORG, pMga->YDstOrg);
1123    OUTREG(MGAREG_MACCESS, maccess);
1124    pMga->MAccess = maccess;
1125    pMga->PlaneMask = ~0;
1126    /* looks like this doesn't apply to mga g100 pci */
1127
1128    if ((pMga->Chipset != PCI_CHIP_MGAG100)
1129	&& (pMga->Chipset != PCI_CHIP_MGAG100_PCI))
1130        OUTREG(MGAREG_PLNWT, pMga->PlaneMask);
1131
1132    pMga->FgColor = 0;
1133    OUTREG(MGAREG_FCOL, pMga->FgColor);
1134    pMga->BgColor = 0;
1135    OUTREG(MGAREG_BCOL, pMga->BgColor);
1136    OUTREG(MGAREG_OPMODE, MGAOPM_DMA_BLIT | opmode);
1137
1138    /* put clipping in a known state */
1139    OUTREG(MGAREG_CXBNDRY, 0xFFFF0000);	/* (maxX << 16) | minX */
1140    OUTREG(MGAREG_YTOP, 0x00000000);	/* minPixelPointer */
1141    OUTREG(MGAREG_YBOT, 0x007FFFFF);	/* maxPixelPointer */
1142    pMga->AccelFlags &= ~CLIPPER_ON;
1143
1144    switch(pMga->Chipset) {
1145    case PCI_CHIP_MGAG550:
1146    case PCI_CHIP_MGAG400:
1147    case PCI_CHIP_MGAG200:
1148    case PCI_CHIP_MGAG200_PCI:
1149    case PCI_CHIP_MGAG200_SE_A_PCI:
1150    case PCI_CHIP_MGAG200_SE_B_PCI:
1151    case PCI_CHIP_MGAG200_WINBOND_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