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