1706f2543Smrg
2706f2543Smrg#ifdef HAVE_XORG_CONFIG_H
3706f2543Smrg#include <xorg-config.h>
4706f2543Smrg#endif
5706f2543Smrg
6706f2543Smrg#include "xaa.h"
7706f2543Smrg#include "xaalocal.h"
8706f2543Smrg#include "xaacexp.h"
9706f2543Smrg#include "xf86.h"
10706f2543Smrg
11706f2543Smrgstatic CARD32* StipplePowerOfTwo(CARD32*, CARD32*, int, int, int);
12706f2543Smrgstatic CARD32* StipplePowerOfTwo_Inverted(CARD32*, CARD32*, int, int, int);
13706f2543Smrgstatic CARD32* StippleUpTo32(CARD32*, CARD32*, int, int, int);
14706f2543Smrgstatic CARD32* StippleUpTo32_Inverted(CARD32*, CARD32*, int, int, int);
15706f2543Smrgstatic CARD32* StippleOver32(CARD32*, CARD32*, int, int, int);
16706f2543Smrgstatic CARD32* StippleOver32_Inverted(CARD32*, CARD32*, int, int, int);
17706f2543Smrg
18706f2543Smrg#ifdef TRIPLE_BITS
19706f2543Smrg#define stipple_scanline_func EXPNAME(XAAStippleScanlineFunc3)
20706f2543Smrg#define stipple_get_scanline_func EXPNAME(XAAGetStippleScanlineFunc3)
21706f2543Smrg#else
22706f2543Smrg#define stipple_scanline_func EXPNAME(XAAStippleScanlineFunc)
23706f2543Smrg#define stipple_get_scanline_func EXPNAME(XAAGetStippleScanlineFunc)
24706f2543Smrg#endif
25706f2543Smrg
26706f2543SmrgStippleScanlineProcPtr stipple_scanline_func[6] = {
27706f2543Smrg   StipplePowerOfTwo,
28706f2543Smrg   StippleUpTo32,
29706f2543Smrg   StippleOver32,
30706f2543Smrg   StipplePowerOfTwo_Inverted,
31706f2543Smrg   StippleUpTo32_Inverted,
32706f2543Smrg   StippleOver32_Inverted
33706f2543Smrg};
34706f2543Smrg
35706f2543SmrgStippleScanlineProcPtr *stipple_get_scanline_func(void) {
36706f2543Smrg   return stipple_scanline_func;
37706f2543Smrg}
38706f2543Smrg
39706f2543Smrg#ifdef FIXEDBASE
40706f2543Smrg# define DEST(i)	*dest
41706f2543Smrg# define RETURN(i)	return(dest)
42706f2543Smrg#else
43706f2543Smrg# define DEST(i)	dest[i]
44706f2543Smrg# define RETURN(i)	return(dest + i)
45706f2543Smrg#endif
46706f2543Smrg
47706f2543Smrg
48706f2543Smrg/* TRIPLE_BITS pattern expansion */
49706f2543Smrg#ifdef TRIPLE_BITS
50706f2543Smrg#define EXPAND_PAT \
51706f2543Smrg	CARD32 pat1 = byte_expand3[pat & 0xFF], \
52706f2543Smrg	       pat2 = byte_expand3[(pat & 0xFF00) >> 8], \
53706f2543Smrg	       pat3 = byte_expand3[(pat & 0xFF0000) >> 16], \
54706f2543Smrg	       pat4 = byte_expand3[(pat & 0xFF000000) >> 24], \
55706f2543Smrg	       patA = pat1 | (pat2 << 24), \
56706f2543Smrg	       patB = (pat2 >> 8) | (pat3 << 16), \
57706f2543Smrg	       patC = (pat3 >> 16) | (pat4 << 8)
58706f2543Smrg#ifdef FIXED_BASE
59706f2543Smrg#define WRITE_PAT1 { \
60706f2543Smrg	*dest = patA; }
61706f2543Smrg#define WRITE_PAT2 { \
62706f2543Smrg	*dest = patA; \
63706f2543Smrg	*dest = patB; }
64706f2543Smrg#define WRITE_PAT3 { \
65706f2543Smrg	*dest = patA; \
66706f2543Smrg	*dest = patB; \
67706f2543Smrg	*dest = patC; }
68706f2543Smrg#else
69706f2543Smrg#define WRITE_PAT1 { \
70706f2543Smrg	*(dest++) = patA; }
71706f2543Smrg#define WRITE_PAT2 { \
72706f2543Smrg	*(dest) = patA; \
73706f2543Smrg	*(dest + 1) = patB; \
74706f2543Smrg	dest += 2; }
75706f2543Smrg#define WRITE_PAT3 { \
76706f2543Smrg	*(dest) = patA; \
77706f2543Smrg	*(dest + 1) = patB; \
78706f2543Smrg	*(dest + 2) = patC; \
79706f2543Smrg	dest += 3; }
80706f2543Smrg#endif
81706f2543Smrg#endif
82706f2543Smrg
83706f2543Smrg
84706f2543Smrg#if !defined(FIXEDBASE) && !defined(MSBFIRST) && !defined(TRIPLE_BITS)
85706f2543Smrg
86706f2543Smrgunsigned int XAAShiftMasks[32] = {
87706f2543Smrg  /* gcc is rather pedantic about SHIFT_R(0xFFFFFFFF,32) */
88706f2543Smrg          0x00000000    , SHIFT_R(0xFFFFFFFF,31),
89706f2543Smrg  SHIFT_R(0xFFFFFFFF,30), SHIFT_R(0xFFFFFFFF,29),
90706f2543Smrg  SHIFT_R(0xFFFFFFFF,28), SHIFT_R(0xFFFFFFFF,27),
91706f2543Smrg  SHIFT_R(0xFFFFFFFF,26), SHIFT_R(0xFFFFFFFF,25),
92706f2543Smrg  SHIFT_R(0xFFFFFFFF,24), SHIFT_R(0xFFFFFFFF,23),
93706f2543Smrg  SHIFT_R(0xFFFFFFFF,22), SHIFT_R(0xFFFFFFFF,21),
94706f2543Smrg  SHIFT_R(0xFFFFFFFF,20), SHIFT_R(0xFFFFFFFF,19),
95706f2543Smrg  SHIFT_R(0xFFFFFFFF,18), SHIFT_R(0xFFFFFFFF,17),
96706f2543Smrg  SHIFT_R(0xFFFFFFFF,16), SHIFT_R(0xFFFFFFFF,15),
97706f2543Smrg  SHIFT_R(0xFFFFFFFF,14), SHIFT_R(0xFFFFFFFF,13),
98706f2543Smrg  SHIFT_R(0xFFFFFFFF,12), SHIFT_R(0xFFFFFFFF,11),
99706f2543Smrg  SHIFT_R(0xFFFFFFFF,10), SHIFT_R(0xFFFFFFFF,9),
100706f2543Smrg  SHIFT_R(0xFFFFFFFF,8),  SHIFT_R(0xFFFFFFFF,7),
101706f2543Smrg  SHIFT_R(0xFFFFFFFF,6),  SHIFT_R(0xFFFFFFFF,5),
102706f2543Smrg  SHIFT_R(0xFFFFFFFF,4),  SHIFT_R(0xFFFFFFFF,3),
103706f2543Smrg  SHIFT_R(0xFFFFFFFF,2),  SHIFT_R(0xFFFFFFFF,1)
104706f2543Smrg};
105706f2543Smrg
106706f2543Smrg#endif
107706f2543Smrg
108706f2543Smrgvoid
109706f2543Smrg#ifdef TRIPLE_BITS
110706f2543SmrgEXPNAME(XAAFillColorExpandRects3)(
111706f2543Smrg#else
112706f2543SmrgEXPNAME(XAAFillColorExpandRects)(
113706f2543Smrg#endif
114706f2543Smrg   ScrnInfoPtr pScrn,
115706f2543Smrg   int fg, int bg, int rop,
116706f2543Smrg   unsigned int planemask,
117706f2543Smrg   int nBox,
118706f2543Smrg   BoxPtr pBox,
119706f2543Smrg   int xorg, int yorg,
120706f2543Smrg   PixmapPtr pPix
121706f2543Smrg){
122706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
123706f2543Smrg    CARD32 *base;
124706f2543Smrg    Bool TwoPass = FALSE, FirstPass = TRUE;
125706f2543Smrg    StippleScanlineProcPtr StippleFunc, FirstFunc, SecondFunc;
126706f2543Smrg    int stipplewidth = pPix->drawable.width;
127706f2543Smrg    int stippleheight = pPix->drawable.height;
128706f2543Smrg    int srcwidth = pPix->devKind;
129706f2543Smrg    int dwords, srcy, srcx, funcNo = 2, h;
130706f2543Smrg    unsigned char *src = (unsigned char*)pPix->devPrivate.ptr;
131706f2543Smrg    unsigned char *srcp;
132706f2543Smrg    int flag;
133706f2543Smrg
134706f2543Smrg    if(stipplewidth <= 32) {
135706f2543Smrg	if(stipplewidth & (stipplewidth - 1))
136706f2543Smrg	  funcNo = 1;
137706f2543Smrg	else
138706f2543Smrg	  funcNo = 0;
139706f2543Smrg    }
140706f2543Smrg    StippleFunc = stipple_scanline_func[funcNo];
141706f2543Smrg    SecondFunc = stipple_scanline_func[funcNo];
142706f2543Smrg    FirstFunc = stipple_scanline_func[funcNo + 3];
143706f2543Smrg
144706f2543Smrg#ifdef TRIPLE_BITS
145706f2543Smrg    if((bg == -1) ||
146706f2543Smrg	(!(infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) &&
147706f2543Smrg	(!(infoRec->CPUToScreenColorExpandFillFlags & RGB_EQUAL) ||
148706f2543Smrg	(CHECK_RGB_EQUAL(bg))))) {
149706f2543Smrg#else
150706f2543Smrg    if((bg == -1) ||
151706f2543Smrg	!(infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) {
152706f2543Smrg#endif
153706f2543Smrg	/* one pass */
154706f2543Smrg    } else if((rop == GXcopy) && infoRec->FillSolidRects) {
155706f2543Smrg	/* one pass but we fill background rects first */
156706f2543Smrg	(*infoRec->FillSolidRects)(pScrn, bg, rop, planemask, nBox, pBox);
157706f2543Smrg	bg = -1;
158706f2543Smrg    } else {
159706f2543Smrg	/* gotta do two passes */
160706f2543Smrg	TwoPass = TRUE;
161706f2543Smrg    }
162706f2543Smrg
163706f2543Smrg    if(!TwoPass)
164706f2543Smrg	(*infoRec->SetupForCPUToScreenColorExpandFill)(
165706f2543Smrg					pScrn, fg, bg, rop, planemask);
166706f2543Smrg
167706f2543Smrg    while(nBox--) {
168706f2543Smrg#ifdef TRIPLE_BITS
169706f2543Smrg	dwords = (3 * (pBox->x2 - pBox->x1) + 31) >> 5;
170706f2543Smrg#else
171706f2543Smrg	dwords = (pBox->x2 - pBox->x1 + 31) >> 5;
172706f2543Smrg#endif
173706f2543Smrg
174706f2543SmrgSECOND_PASS:
175706f2543Smrg	if(TwoPass) {
176706f2543Smrg	    (*infoRec->SetupForCPUToScreenColorExpandFill)(pScrn,
177706f2543Smrg			(FirstPass) ? bg : fg, -1, rop, planemask);
178706f2543Smrg	    StippleFunc = (FirstPass) ? FirstFunc : SecondFunc;
179706f2543Smrg	}
180706f2543Smrg
181706f2543Smrg	h = pBox->y2 - pBox->y1;
182706f2543Smrg	flag = (infoRec->CPUToScreenColorExpandFillFlags
183706f2543Smrg		& CPU_TRANSFER_PAD_QWORD) && ((dwords * h) & 0x01);
184706f2543Smrg
185706f2543Smrg        (*infoRec->SubsequentCPUToScreenColorExpandFill)(
186706f2543Smrg			pScrn, pBox->x1, pBox->y1,
187706f2543Smrg 			pBox->x2 - pBox->x1, h, 0);
188706f2543Smrg
189706f2543Smrg	base = (CARD32*)infoRec->ColorExpandBase;
190706f2543Smrg
191706f2543Smrg	srcy = (pBox->y1 - yorg) % stippleheight;
192706f2543Smrg	if(srcy < 0) srcy += stippleheight;
193706f2543Smrg	srcx = (pBox->x1 - xorg) % stipplewidth;
194706f2543Smrg	if(srcx < 0) srcx += stipplewidth;
195706f2543Smrg
196706f2543Smrg	srcp = (srcwidth * srcy) + src;
197706f2543Smrg
198706f2543Smrg#ifndef FIXEDBASE
199706f2543Smrg	if((dwords * h) <= infoRec->ColorExpandRange) {
200706f2543Smrg	   while(h--) {
201706f2543Smrg		base = (*StippleFunc)(
202706f2543Smrg			base, (CARD32*)srcp, srcx, stipplewidth, dwords);
203706f2543Smrg		srcy++;
204706f2543Smrg		srcp += srcwidth;
205706f2543Smrg		if (srcy >= stippleheight) {
206706f2543Smrg		   srcy = 0;
207706f2543Smrg		   srcp = src;
208706f2543Smrg		}
209706f2543Smrg	   }
210706f2543Smrg	} else
211706f2543Smrg#endif
212706f2543Smrg	   while(h--) {
213706f2543Smrg		(*StippleFunc)(base, (CARD32*)srcp, srcx, stipplewidth, dwords);
214706f2543Smrg		srcy++;
215706f2543Smrg		srcp += srcwidth;
216706f2543Smrg		if (srcy >= stippleheight) {
217706f2543Smrg		   srcy = 0;
218706f2543Smrg		   srcp = src;
219706f2543Smrg		}
220706f2543Smrg	   }
221706f2543Smrg
222706f2543Smrg	  if (flag) {
223706f2543Smrg	      base = (CARD32*)infoRec->ColorExpandBase;
224706f2543Smrg	      base[0] = 0x00000000;
225706f2543Smrg	  }
226706f2543Smrg
227706f2543Smrg	if(TwoPass) {
228706f2543Smrg	   if(FirstPass) {
229706f2543Smrg		FirstPass = FALSE;
230706f2543Smrg		goto SECOND_PASS;
231706f2543Smrg	   } else FirstPass = TRUE;
232706f2543Smrg	}
233706f2543Smrg
234706f2543Smrg	pBox++;
235706f2543Smrg     }
236706f2543Smrg
237706f2543Smrg    if(infoRec->CPUToScreenColorExpandFillFlags & SYNC_AFTER_COLOR_EXPAND)
238706f2543Smrg	(*infoRec->Sync)(pScrn);
239706f2543Smrg    else SET_SYNC_FLAG(infoRec);
240706f2543Smrg}
241706f2543Smrg
242706f2543Smrg
243706f2543Smrg
244706f2543Smrgvoid
245706f2543Smrg#ifdef TRIPLE_BITS
246706f2543SmrgEXPNAME(XAAFillColorExpandSpans3)(
247706f2543Smrg#else
248706f2543SmrgEXPNAME(XAAFillColorExpandSpans)(
249706f2543Smrg#endif
250706f2543Smrg   ScrnInfoPtr pScrn,
251706f2543Smrg   int fg, int bg, int rop,
252706f2543Smrg   unsigned int planemask,
253706f2543Smrg   int n,
254706f2543Smrg   DDXPointPtr ppt,
255706f2543Smrg   int *pwidth,
256706f2543Smrg   int fSorted,
257706f2543Smrg   int xorg, int yorg,
258706f2543Smrg   PixmapPtr pPix
259706f2543Smrg){
260706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
261706f2543Smrg    CARD32 *base;
262706f2543Smrg    Bool TwoPass = FALSE, FirstPass = TRUE;
263706f2543Smrg    StippleScanlineProcPtr StippleFunc, FirstFunc, SecondFunc;
264706f2543Smrg    int stipplewidth = pPix->drawable.width;
265706f2543Smrg    int stippleheight = pPix->drawable.height;
266706f2543Smrg    int dwords, srcy, srcx, funcNo = 2;
267706f2543Smrg    unsigned char *srcp;
268706f2543Smrg
269706f2543Smrg    if(stipplewidth <= 32) {
270706f2543Smrg	if(stipplewidth & (stipplewidth - 1))
271706f2543Smrg	  funcNo = 1;
272706f2543Smrg	else
273706f2543Smrg	  funcNo = 0;
274706f2543Smrg    }
275706f2543Smrg    StippleFunc = stipple_scanline_func[funcNo];
276706f2543Smrg    SecondFunc = stipple_scanline_func[funcNo];
277706f2543Smrg    FirstFunc = stipple_scanline_func[funcNo + 3];
278706f2543Smrg
279706f2543Smrg#ifdef TRIPLE_BITS
280706f2543Smrg    if((bg == -1) ||
281706f2543Smrg	(!(infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) &&
282706f2543Smrg	(!(infoRec->CPUToScreenColorExpandFillFlags & RGB_EQUAL) ||
283706f2543Smrg	(CHECK_RGB_EQUAL(bg))))) {
284706f2543Smrg#else
285706f2543Smrg    if((bg == -1) ||
286706f2543Smrg	!(infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) {
287706f2543Smrg#endif
288706f2543Smrg	/* one pass */
289706f2543Smrg    } else if((rop == GXcopy) && infoRec->FillSolidSpans) {
290706f2543Smrg	/* one pass but we fill background rects first */
291706f2543Smrg	(*infoRec->FillSolidSpans)(
292706f2543Smrg		pScrn, bg, rop, planemask, n, ppt, pwidth, fSorted);
293706f2543Smrg	bg = -1;
294706f2543Smrg    } else {
295706f2543Smrg	/* gotta do two passes */
296706f2543Smrg	TwoPass = TRUE;
297706f2543Smrg    }
298706f2543Smrg
299706f2543Smrg    if(!TwoPass)
300706f2543Smrg	(*infoRec->SetupForCPUToScreenColorExpandFill)(
301706f2543Smrg				pScrn, fg, bg, rop, planemask);
302706f2543Smrg
303706f2543Smrg    while(n--) {
304706f2543Smrg#ifdef TRIPLE_BITS
305706f2543Smrg	dwords = (3 * *pwidth + 31) >> 5;
306706f2543Smrg#else
307706f2543Smrg	dwords = (*pwidth + 31) >> 5;
308706f2543Smrg#endif
309706f2543Smrg
310706f2543Smrg	srcy = (ppt->y - yorg) % stippleheight;
311706f2543Smrg	if(srcy < 0) srcy += stippleheight;
312706f2543Smrg	srcx = (ppt->x - xorg) % stipplewidth;
313706f2543Smrg	if(srcx < 0) srcx += stipplewidth;
314706f2543Smrg
315706f2543Smrg	srcp = (pPix->devKind * srcy) + (unsigned char*)pPix->devPrivate.ptr;
316706f2543Smrg
317706f2543SmrgSECOND_PASS:
318706f2543Smrg	if(TwoPass) {
319706f2543Smrg	    (*infoRec->SetupForCPUToScreenColorExpandFill)(pScrn,
320706f2543Smrg			(FirstPass) ? bg : fg, -1, rop, planemask);
321706f2543Smrg	    StippleFunc = (FirstPass) ? FirstFunc : SecondFunc;
322706f2543Smrg	}
323706f2543Smrg
324706f2543Smrg        (*infoRec->SubsequentCPUToScreenColorExpandFill)(pScrn, ppt->x, ppt->y,
325706f2543Smrg 			*pwidth, 1, 0);
326706f2543Smrg
327706f2543Smrg	base = (CARD32*)infoRec->ColorExpandBase;
328706f2543Smrg
329706f2543Smrg	(*StippleFunc)(base, (CARD32*)srcp, srcx, stipplewidth, dwords);
330706f2543Smrg
331706f2543Smrg	if((infoRec->CPUToScreenColorExpandFillFlags & CPU_TRANSFER_PAD_QWORD)
332706f2543Smrg			&& (dwords & 0x01)) {
333706f2543Smrg	    base = (CARD32*)infoRec->ColorExpandBase;
334706f2543Smrg	    base[0] = 0x00000000;
335706f2543Smrg    	}
336706f2543Smrg
337706f2543Smrg	if(TwoPass) {
338706f2543Smrg	   if(FirstPass) {
339706f2543Smrg		FirstPass = FALSE;
340706f2543Smrg		goto SECOND_PASS;
341706f2543Smrg	   } else FirstPass = TRUE;
342706f2543Smrg	}
343706f2543Smrg
344706f2543Smrg	ppt++; pwidth++;
345706f2543Smrg     }
346706f2543Smrg
347706f2543Smrg    if(infoRec->CPUToScreenColorExpandFillFlags & SYNC_AFTER_COLOR_EXPAND)
348706f2543Smrg	(*infoRec->Sync)(pScrn);
349706f2543Smrg    else SET_SYNC_FLAG(infoRec);
350706f2543Smrg}
351706f2543Smrg
352706f2543Smrg
353706f2543Smrg#ifndef FIXEDBASE
354706f2543Smrg
355706f2543Smrgvoid
356706f2543Smrg#ifdef TRIPLE_BITS
357706f2543SmrgEXPNAME(XAAFillScanlineColorExpandRects3)(
358706f2543Smrg#else
359706f2543SmrgEXPNAME(XAAFillScanlineColorExpandRects)(
360706f2543Smrg#endif
361706f2543Smrg   ScrnInfoPtr pScrn,
362706f2543Smrg   int fg, int bg, int rop,
363706f2543Smrg   unsigned int planemask,
364706f2543Smrg   int nBox,
365706f2543Smrg   BoxPtr pBox,
366706f2543Smrg   int xorg, int yorg,
367706f2543Smrg   PixmapPtr pPix
368706f2543Smrg){
369706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
370706f2543Smrg    CARD32 *base;
371706f2543Smrg    Bool TwoPass = FALSE, FirstPass = TRUE;
372706f2543Smrg    StippleScanlineProcPtr StippleFunc, FirstFunc, SecondFunc;
373706f2543Smrg    int stipplewidth = pPix->drawable.width;
374706f2543Smrg    int stippleheight = pPix->drawable.height;
375706f2543Smrg    int srcwidth = pPix->devKind;
376706f2543Smrg    int dwords, srcy, srcx, funcNo = 2, bufferNo, h;
377706f2543Smrg    unsigned char *src = pPix->devPrivate.ptr;
378706f2543Smrg    unsigned char *srcp;
379706f2543Smrg
380706f2543Smrg    if(stipplewidth <= 32) {
381706f2543Smrg	if(stipplewidth & (stipplewidth - 1))
382706f2543Smrg	  funcNo = 1;
383706f2543Smrg	else
384706f2543Smrg	  funcNo = 0;
385706f2543Smrg    }
386706f2543Smrg    StippleFunc = stipple_scanline_func[funcNo];
387706f2543Smrg    SecondFunc = stipple_scanline_func[funcNo];
388706f2543Smrg    FirstFunc = stipple_scanline_func[funcNo + 3];
389706f2543Smrg
390706f2543Smrg#ifdef TRIPLE_BITS
391706f2543Smrg    if((bg == -1) ||
392706f2543Smrg      (!(infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) &&
393706f2543Smrg      (!(infoRec->ScanlineCPUToScreenColorExpandFillFlags & RGB_EQUAL) ||
394706f2543Smrg      (CHECK_RGB_EQUAL(bg))))) {
395706f2543Smrg#else
396706f2543Smrg    if((bg == -1) ||
397706f2543Smrg      !(infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) {
398706f2543Smrg#endif
399706f2543Smrg	/* one pass */
400706f2543Smrg    } else if((rop == GXcopy) && infoRec->FillSolidRects) {
401706f2543Smrg	/* one pass but we fill background rects first */
402706f2543Smrg	(*infoRec->FillSolidRects)(pScrn, bg, rop, planemask, nBox, pBox);
403706f2543Smrg	bg = -1;
404706f2543Smrg    } else {
405706f2543Smrg	/* gotta do two passes */
406706f2543Smrg	TwoPass = TRUE;
407706f2543Smrg    }
408706f2543Smrg
409706f2543Smrg    if(!TwoPass)
410706f2543Smrg	(*infoRec->SetupForScanlineCPUToScreenColorExpandFill)(
411706f2543Smrg				pScrn, fg, bg, rop, planemask);
412706f2543Smrg
413706f2543Smrg    while(nBox--) {
414706f2543Smrg#ifdef TRIPLE_BITS
415706f2543Smrg	dwords = (3 * (pBox->x2 - pBox->x1) + 31) >> 5;
416706f2543Smrg#else
417706f2543Smrg	dwords = (pBox->x2 - pBox->x1 + 31) >> 5;
418706f2543Smrg#endif
419706f2543Smrg
420706f2543SmrgSECOND_PASS:
421706f2543Smrg	if(TwoPass) {
422706f2543Smrg	    (*infoRec->SetupForScanlineCPUToScreenColorExpandFill)(pScrn,
423706f2543Smrg			(FirstPass) ? bg : fg, -1, rop, planemask);
424706f2543Smrg	    StippleFunc = (FirstPass) ? FirstFunc : SecondFunc;
425706f2543Smrg	}
426706f2543Smrg
427706f2543Smrg	h = pBox->y2 - pBox->y1;
428706f2543Smrg
429706f2543Smrg        (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)(
430706f2543Smrg		pScrn, pBox->x1, pBox->y1, pBox->x2 - pBox->x1, h, 0);
431706f2543Smrg
432706f2543Smrg	bufferNo = 0;
433706f2543Smrg
434706f2543Smrg	srcy = (pBox->y1 - yorg) % stippleheight;
435706f2543Smrg	if(srcy < 0) srcy += stippleheight;
436706f2543Smrg	srcx = (pBox->x1 - xorg) % stipplewidth;
437706f2543Smrg	if(srcx < 0) srcx += stipplewidth;
438706f2543Smrg
439706f2543Smrg	srcp = (srcwidth * srcy) + src;
440706f2543Smrg
441706f2543Smrg	while(h--) {
442706f2543Smrg   	    base = (CARD32*)infoRec->ScanlineColorExpandBuffers[bufferNo];
443706f2543Smrg	    (*StippleFunc)(base, (CARD32*)srcp, srcx, stipplewidth, dwords);
444706f2543Smrg	    (*infoRec->SubsequentColorExpandScanline)(pScrn, bufferNo++);
445706f2543Smrg	    if(bufferNo >= infoRec->NumScanlineColorExpandBuffers)
446706f2543Smrg		bufferNo = 0;
447706f2543Smrg	    srcy++;
448706f2543Smrg	    srcp += srcwidth;
449706f2543Smrg	    if (srcy >= stippleheight) {
450706f2543Smrg		srcy = 0;
451706f2543Smrg		srcp = src;
452706f2543Smrg	    }
453706f2543Smrg	}
454706f2543Smrg
455706f2543Smrg	if(TwoPass) {
456706f2543Smrg	   if(FirstPass) {
457706f2543Smrg		FirstPass = FALSE;
458706f2543Smrg		goto SECOND_PASS;
459706f2543Smrg	   } else FirstPass = TRUE;
460706f2543Smrg	}
461706f2543Smrg
462706f2543Smrg	pBox++;
463706f2543Smrg     }
464706f2543Smrg
465706f2543Smrg     SET_SYNC_FLAG(infoRec);
466706f2543Smrg}
467706f2543Smrg
468706f2543Smrgvoid
469706f2543Smrg#ifdef TRIPLE_BITS
470706f2543SmrgEXPNAME(XAAFillScanlineColorExpandSpans3)(
471706f2543Smrg#else
472706f2543SmrgEXPNAME(XAAFillScanlineColorExpandSpans)(
473706f2543Smrg#endif
474706f2543Smrg   ScrnInfoPtr pScrn,
475706f2543Smrg   int fg, int bg, int rop,
476706f2543Smrg   unsigned int planemask,
477706f2543Smrg   int n,
478706f2543Smrg   DDXPointPtr ppt,
479706f2543Smrg   int *pwidth,
480706f2543Smrg   int fSorted,
481706f2543Smrg   int xorg, int yorg,
482706f2543Smrg   PixmapPtr pPix
483706f2543Smrg){
484706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
485706f2543Smrg    CARD32 *base;
486706f2543Smrg    Bool TwoPass = FALSE, FirstPass = TRUE;
487706f2543Smrg    StippleScanlineProcPtr StippleFunc, FirstFunc, SecondFunc;
488706f2543Smrg    int stipplewidth = pPix->drawable.width;
489706f2543Smrg    int stippleheight = pPix->drawable.height;
490706f2543Smrg    int dwords, srcy, srcx, funcNo = 2;
491706f2543Smrg    unsigned char *srcp;
492706f2543Smrg
493706f2543Smrg    if(stipplewidth <= 32) {
494706f2543Smrg	if(stipplewidth & (stipplewidth - 1))
495706f2543Smrg	  funcNo = 1;
496706f2543Smrg	else
497706f2543Smrg	  funcNo = 0;
498706f2543Smrg    }
499706f2543Smrg    StippleFunc = stipple_scanline_func[funcNo];
500706f2543Smrg    SecondFunc = stipple_scanline_func[funcNo];
501706f2543Smrg    FirstFunc = stipple_scanline_func[funcNo + 3];
502706f2543Smrg
503706f2543Smrg#ifdef TRIPLE_BITS
504706f2543Smrg    if((bg == -1) ||
505706f2543Smrg      (!(infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) &&
506706f2543Smrg      (!(infoRec->ScanlineCPUToScreenColorExpandFillFlags & RGB_EQUAL) ||
507706f2543Smrg      (CHECK_RGB_EQUAL(bg))))) {
508706f2543Smrg#else
509706f2543Smrg    if((bg == -1) ||
510706f2543Smrg      !(infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) {
511706f2543Smrg#endif
512706f2543Smrg	/* one pass */
513706f2543Smrg    } else if((rop == GXcopy) && infoRec->FillSolidSpans) {
514706f2543Smrg	/* one pass but we fill background rects first */
515706f2543Smrg	(*infoRec->FillSolidSpans)(
516706f2543Smrg		pScrn, bg, rop, planemask, n, ppt, pwidth, fSorted);
517706f2543Smrg	bg = -1;
518706f2543Smrg    } else {
519706f2543Smrg	/* gotta do two passes */
520706f2543Smrg	TwoPass = TRUE;
521706f2543Smrg    }
522706f2543Smrg
523706f2543Smrg    if(!TwoPass)
524706f2543Smrg	(*infoRec->SetupForScanlineCPUToScreenColorExpandFill)(
525706f2543Smrg				pScrn, fg, bg, rop, planemask);
526706f2543Smrg
527706f2543Smrg
528706f2543Smrg    while(n--) {
529706f2543Smrg#ifdef TRIPLE_BITS
530706f2543Smrg	dwords = (3 * *pwidth + 31) >> 5;
531706f2543Smrg#else
532706f2543Smrg	dwords = (*pwidth + 31) >> 5;
533706f2543Smrg#endif
534706f2543Smrg
535706f2543Smrg	srcy = (ppt->y - yorg) % stippleheight;
536706f2543Smrg	if(srcy < 0) srcy += stippleheight;
537706f2543Smrg	srcx = (ppt->x - xorg) % stipplewidth;
538706f2543Smrg	if(srcx < 0) srcx += stipplewidth;
539706f2543Smrg
540706f2543Smrg	srcp = (pPix->devKind * srcy) + (unsigned char*)pPix->devPrivate.ptr;
541706f2543Smrg
542706f2543SmrgSECOND_PASS:
543706f2543Smrg	if(TwoPass) {
544706f2543Smrg	    (*infoRec->SetupForScanlineCPUToScreenColorExpandFill)(pScrn,
545706f2543Smrg			(FirstPass) ? bg : fg, -1, rop, planemask);
546706f2543Smrg	    StippleFunc = (FirstPass) ? FirstFunc : SecondFunc;
547706f2543Smrg	}
548706f2543Smrg
549706f2543Smrg        (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)(
550706f2543Smrg				pScrn, ppt->x, ppt->y, *pwidth, 1, 0);
551706f2543Smrg
552706f2543Smrg	base = (CARD32*)infoRec->ScanlineColorExpandBuffers[0];
553706f2543Smrg
554706f2543Smrg	(*StippleFunc)(base, (CARD32*)srcp, srcx, stipplewidth, dwords);
555706f2543Smrg	(*infoRec->SubsequentColorExpandScanline)(pScrn, 0);
556706f2543Smrg
557706f2543Smrg	if(TwoPass) {
558706f2543Smrg	   if(FirstPass) {
559706f2543Smrg		FirstPass = FALSE;
560706f2543Smrg		goto SECOND_PASS;
561706f2543Smrg	   } else FirstPass = TRUE;
562706f2543Smrg	}
563706f2543Smrg
564706f2543Smrg	ppt++; pwidth++;
565706f2543Smrg     }
566706f2543Smrg
567706f2543Smrg     SET_SYNC_FLAG(infoRec);
568706f2543Smrg}
569706f2543Smrg
570706f2543Smrg#endif
571706f2543Smrg
572706f2543Smrgstatic CARD32 *
573706f2543SmrgStipplePowerOfTwo(
574706f2543Smrg   CARD32* dest, CARD32* src,
575706f2543Smrg   int shift, int width, int dwords
576706f2543Smrg){
577706f2543Smrg    CARD32 pat = *src;
578706f2543Smrg    if(width < 32) {
579706f2543Smrg	pat &= XAAShiftMasks[width];
580706f2543Smrg	while(width < 32) {
581706f2543Smrg	    pat |= SHIFT_L(pat,width);
582706f2543Smrg	    width <<= 1;
583706f2543Smrg	}
584706f2543Smrg    }
585706f2543Smrg
586706f2543Smrg    if(shift)
587706f2543Smrg	pat = SHIFT_R(pat,shift) | SHIFT_L(pat,32 - shift);
588706f2543Smrg
589706f2543Smrg#ifdef MSBFIRST
590706f2543Smrg    pat = SWAP_BITS_IN_BYTES(pat);
591706f2543Smrg#endif
592706f2543Smrg
593706f2543Smrg#ifdef TRIPLE_BITS
594706f2543Smrg    {
595706f2543Smrg	EXPAND_PAT;
596706f2543Smrg
597706f2543Smrg	while(dwords >= 3) {
598706f2543Smrg	    WRITE_PAT3;
599706f2543Smrg	    dwords -= 3;
600706f2543Smrg	}
601706f2543Smrg	if (dwords == 2) {
602706f2543Smrg	    WRITE_PAT2;
603706f2543Smrg	} else if (dwords == 1) {
604706f2543Smrg	    WRITE_PAT1;
605706f2543Smrg	}
606706f2543Smrg
607706f2543Smrg	return dest;
608706f2543Smrg    }
609706f2543Smrg#else /* TRIPLE_BITS */
610706f2543Smrg   while(dwords >= 4) {
611706f2543Smrg	DEST(0) = pat;
612706f2543Smrg	DEST(1) = pat;
613706f2543Smrg	DEST(2) = pat;
614706f2543Smrg	DEST(3) = pat;
615706f2543Smrg	dwords -= 4;
616706f2543Smrg#ifndef FIXEDBASE
617706f2543Smrg	dest += 4;
618706f2543Smrg#endif
619706f2543Smrg   }
620706f2543Smrg
621706f2543Smrg   if(!dwords) return dest;
622706f2543Smrg   DEST(0) = pat;
623706f2543Smrg   if(dwords == 1) RETURN(1);
624706f2543Smrg   DEST(1) = pat;
625706f2543Smrg   if(dwords == 2) RETURN(2);
626706f2543Smrg   DEST(2) = pat;
627706f2543Smrg   RETURN(3);
628706f2543Smrg#endif /* TRIPLE_BITS */
629706f2543Smrg}
630706f2543Smrg
631706f2543Smrgstatic CARD32 *
632706f2543SmrgStipplePowerOfTwo_Inverted(
633706f2543Smrg   CARD32* dest, CARD32* src,
634706f2543Smrg   int shift, int width, int dwords
635706f2543Smrg){
636706f2543Smrg    CARD32 pat = *src;
637706f2543Smrg    if(width < 32) {
638706f2543Smrg	pat &= XAAShiftMasks[width];
639706f2543Smrg	while(width < 32) {
640706f2543Smrg	    pat |= SHIFT_L(pat,width);
641706f2543Smrg	    width <<= 1;
642706f2543Smrg	}
643706f2543Smrg    }
644706f2543Smrg
645706f2543Smrg    if(shift)
646706f2543Smrg	pat = SHIFT_R(pat,shift) | SHIFT_L(pat,32 - shift);
647706f2543Smrg
648706f2543Smrg#ifdef MSBFIRST
649706f2543Smrg    pat = SWAP_BITS_IN_BYTES(pat);
650706f2543Smrg#endif
651706f2543Smrg
652706f2543Smrg   pat = ~pat;
653706f2543Smrg
654706f2543Smrg#ifdef TRIPLE_BITS
655706f2543Smrg    {
656706f2543Smrg	EXPAND_PAT;
657706f2543Smrg
658706f2543Smrg	while(dwords >= 3) {
659706f2543Smrg	    WRITE_PAT3;
660706f2543Smrg	    dwords -= 3;
661706f2543Smrg	}
662706f2543Smrg	if (dwords == 2) {
663706f2543Smrg	    WRITE_PAT2;
664706f2543Smrg	} else if (dwords == 1) {
665706f2543Smrg	    WRITE_PAT1;
666706f2543Smrg	}
667706f2543Smrg
668706f2543Smrg	return dest;
669706f2543Smrg    }
670706f2543Smrg#else /* TRIPLE_BITS */
671706f2543Smrg   while(dwords >= 4) {
672706f2543Smrg	DEST(0) = pat;
673706f2543Smrg	DEST(1) = pat;
674706f2543Smrg	DEST(2) = pat;
675706f2543Smrg	DEST(3) = pat;
676706f2543Smrg	dwords -= 4;
677706f2543Smrg#ifndef FIXEDBASE
678706f2543Smrg	dest += 4;
679706f2543Smrg#endif
680706f2543Smrg   }
681706f2543Smrg
682706f2543Smrg   if(!dwords) return dest;
683706f2543Smrg   DEST(0) = pat;
684706f2543Smrg   if(dwords == 1) RETURN(1);
685706f2543Smrg   DEST(1) = pat;
686706f2543Smrg   if(dwords == 2) RETURN(2);
687706f2543Smrg   DEST(2) = pat;
688706f2543Smrg   RETURN(3);
689706f2543Smrg#endif /* TRIPLE_BITS */
690706f2543Smrg}
691706f2543Smrg
692706f2543Smrg
693706f2543Smrgstatic CARD32 *
694706f2543SmrgStippleUpTo32(
695706f2543Smrg   CARD32* base, CARD32* src,
696706f2543Smrg   int shift, int width, int dwords
697706f2543Smrg){
698706f2543Smrg    CARD32 pat = *src & XAAShiftMasks[width];
699706f2543Smrg
700706f2543Smrg    while(width <= 15) {
701706f2543Smrg	pat |= SHIFT_L(pat,width);
702706f2543Smrg	width <<= 1;
703706f2543Smrg    }
704706f2543Smrg    pat |= SHIFT_L(pat,width);
705706f2543Smrg
706706f2543Smrg    while(dwords--) {
707706f2543Smrg	CARD32 bits = SHIFT_R(pat,shift) | SHIFT_L(pat,width-shift);
708706f2543Smrg#ifdef TRIPLE_BITS
709706f2543Smrg	if(dwords >= 2) {
710706f2543Smrg	    WRITE_BITS3(bits);
711706f2543Smrg	    dwords -= 2;
712706f2543Smrg	} else if(dwords > 0) {
713706f2543Smrg	    WRITE_BITS2(bits);
714706f2543Smrg	    dwords--;
715706f2543Smrg	} else {
716706f2543Smrg	    WRITE_BITS1(bits);
717706f2543Smrg	}
718706f2543Smrg#else
719706f2543Smrg	WRITE_BITS(bits);
720706f2543Smrg#endif
721706f2543Smrg
722706f2543Smrg	shift += 32;
723706f2543Smrg	shift %= width;
724706f2543Smrg    }
725706f2543Smrg    return base;
726706f2543Smrg}
727706f2543Smrg
728706f2543Smrg
729706f2543Smrgstatic CARD32 *
730706f2543SmrgStippleUpTo32_Inverted(
731706f2543Smrg   CARD32* base, CARD32* src,
732706f2543Smrg   int shift, int width, int dwords
733706f2543Smrg){
734706f2543Smrg    CARD32 pat = *src & XAAShiftMasks[width];
735706f2543Smrg
736706f2543Smrg    while(width <= 15) {
737706f2543Smrg	pat |= SHIFT_L(pat,width);
738706f2543Smrg	width <<= 1;
739706f2543Smrg    }
740706f2543Smrg    pat |= SHIFT_L(pat,width);
741706f2543Smrg
742706f2543Smrg    while(dwords--) {
743706f2543Smrg	CARD32 bits = ~(SHIFT_R(pat,shift) | SHIFT_L(pat,width-shift));
744706f2543Smrg#ifdef TRIPLE_BITS
745706f2543Smrg	if(dwords >= 2) {
746706f2543Smrg	    WRITE_BITS3(bits);
747706f2543Smrg	    dwords -= 2;
748706f2543Smrg	} else if(dwords > 0) {
749706f2543Smrg	    WRITE_BITS2(bits);
750706f2543Smrg	    dwords--;
751706f2543Smrg	} else {
752706f2543Smrg	    WRITE_BITS1(bits);
753706f2543Smrg	}
754706f2543Smrg#else
755706f2543Smrg	WRITE_BITS(bits);
756706f2543Smrg#endif
757706f2543Smrg
758706f2543Smrg	shift += 32;
759706f2543Smrg	shift %= width;
760706f2543Smrg    }
761706f2543Smrg    return base;
762706f2543Smrg}
763706f2543Smrg
764706f2543Smrg
765706f2543Smrgstatic CARD32 *
766706f2543SmrgStippleOver32(
767706f2543Smrg   CARD32* base, CARD32* src,
768706f2543Smrg   int offset, int width, int dwords
769706f2543Smrg){
770706f2543Smrg   CARD32* srcp;
771706f2543Smrg   CARD32 bits;
772706f2543Smrg   int bitsleft, shift, usable;
773706f2543Smrg
774706f2543Smrg   while(dwords--) {
775706f2543Smrg        bitsleft = width - offset;
776706f2543Smrg        srcp = src + (offset >> 5);
777706f2543Smrg        shift = offset & 31;
778706f2543Smrg        usable = 32 - shift;
779706f2543Smrg
780706f2543Smrg        if(bitsleft < 32) {
781706f2543Smrg            if(bitsleft <= usable) {
782706f2543Smrg                 bits = SHIFT_L(*src,bitsleft) |
783706f2543Smrg                       (SHIFT_R(*srcp,shift) & XAAShiftMasks[bitsleft]);
784706f2543Smrg            } else {
785706f2543Smrg                 bits = SHIFT_L(*src,bitsleft) |
786706f2543Smrg                       (SHIFT_L(srcp[1],usable) & XAAShiftMasks[bitsleft]) |
787706f2543Smrg                       (SHIFT_R(*srcp,shift) & XAAShiftMasks[usable]);
788706f2543Smrg            }
789706f2543Smrg        }
790706f2543Smrg        else if(shift)
791706f2543Smrg            bits = SHIFT_R(*srcp,shift) | SHIFT_L(srcp[1],usable);
792706f2543Smrg        else
793706f2543Smrg            bits = *srcp;
794706f2543Smrg
795706f2543Smrg#ifdef TRIPLE_BITS
796706f2543Smrg	if(dwords >= 2) {
797706f2543Smrg	    WRITE_BITS3(bits);
798706f2543Smrg	    dwords -= 2;
799706f2543Smrg	} else if(dwords > 0) {
800706f2543Smrg	    WRITE_BITS2(bits);
801706f2543Smrg	    dwords--;
802706f2543Smrg	} else {
803706f2543Smrg	    WRITE_BITS1(bits);
804706f2543Smrg	}
805706f2543Smrg#else
806706f2543Smrg	WRITE_BITS(bits);
807706f2543Smrg#endif
808706f2543Smrg
809706f2543Smrg	offset += 32;
810706f2543Smrg	offset %= width;
811706f2543Smrg   }
812706f2543Smrg   return base;
813706f2543Smrg}
814706f2543Smrg
815706f2543Smrg
816706f2543Smrgstatic CARD32 *
817706f2543SmrgStippleOver32_Inverted(
818706f2543Smrg   CARD32* base, CARD32* src,
819706f2543Smrg   int offset, int width, int dwords
820706f2543Smrg){
821706f2543Smrg   CARD32* srcp;
822706f2543Smrg   CARD32 bits;
823706f2543Smrg   int bitsleft, shift, usable;
824706f2543Smrg
825706f2543Smrg   while(dwords--) {
826706f2543Smrg        bitsleft = width - offset;
827706f2543Smrg        srcp = src + (offset >> 5);
828706f2543Smrg        shift = offset & 31;
829706f2543Smrg        usable = 32 - shift;
830706f2543Smrg
831706f2543Smrg        if(bitsleft < 32) {
832706f2543Smrg            if(bitsleft <= usable) {
833706f2543Smrg                 bits = SHIFT_L(*src,bitsleft) |
834706f2543Smrg                       (SHIFT_R(*srcp,shift) & XAAShiftMasks[bitsleft]);
835706f2543Smrg            } else {
836706f2543Smrg                 bits = SHIFT_L(*src,bitsleft) |
837706f2543Smrg                       (SHIFT_L(srcp[1],usable) & XAAShiftMasks[bitsleft]) |
838706f2543Smrg                       (SHIFT_R(*srcp,shift) & XAAShiftMasks[usable]);
839706f2543Smrg            }
840706f2543Smrg        }
841706f2543Smrg        else if(shift)
842706f2543Smrg            bits = SHIFT_R(*srcp,shift) | SHIFT_L(srcp[1],usable);
843706f2543Smrg        else
844706f2543Smrg            bits = *srcp;
845706f2543Smrg
846706f2543Smrg	bits = ~bits;
847706f2543Smrg
848706f2543Smrg#ifdef TRIPLE_BITS
849706f2543Smrg	if(dwords >= 2) {
850706f2543Smrg	    WRITE_BITS3(bits);
851706f2543Smrg	    dwords -= 2;
852706f2543Smrg	} else if(dwords > 0) {
853706f2543Smrg	    WRITE_BITS2(bits);
854706f2543Smrg	    dwords--;
855706f2543Smrg	} else {
856706f2543Smrg	    WRITE_BITS1(bits);
857706f2543Smrg	}
858706f2543Smrg#else
859706f2543Smrg	WRITE_BITS(bits);
860706f2543Smrg#endif
861706f2543Smrg
862706f2543Smrg	offset += 32;
863706f2543Smrg	offset %= width;
864706f2543Smrg   }
865706f2543Smrg   return base;
866706f2543Smrg}
867