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