1
2
3#ifdef HAVE_XORG_CONFIG_H
4#include <xorg-config.h>
5#endif
6
7#include "xaa.h"
8#include "xaalocal.h"
9#include "xaacexp.h"
10#include "xf86.h"
11
12
13/********** byte swapping ***************/
14
15
16#ifdef FIXEDBASE
17# define DEST(i)	*dest
18# define RETURN(i)	return(dest)
19#else
20# define DEST(i)	dest[i]
21# define RETURN(i)	return(dest + i)
22#endif
23
24#ifdef MSBFIRST
25# define SOURCE(i)	SWAP_BITS_IN_BYTES(src[i])
26#else
27# define SOURCE(i)	src[i]
28#endif
29
30
31typedef CARD32 *(* BitmapScanlineProcPtr)(CARD32 *, CARD32 *, int, int);
32
33#ifdef TRIPLE_BITS
34static CARD32*
35BitmapScanline(
36   CARD32 *src, CARD32 *base,
37   int count, int skipleft )
38{
39     CARD32 bits;
40
41     while(count >= 3) {
42	bits = *src;
43	WRITE_BITS3(bits);
44	src++;
45	count -= 3;
46     }
47     if (count == 2) {
48	bits = *src;
49	WRITE_BITS2(bits);
50     } else if (count == 1) {
51	bits = *src;
52	WRITE_BITS1(bits);
53     }
54
55     return base;
56}
57
58static CARD32*
59BitmapScanline_Inverted(
60   CARD32 *src, CARD32 *base,
61   int count, int skipleft )
62{
63     CARD32 bits;
64
65     while(count >= 3) {
66	bits = ~(*src);
67	WRITE_BITS3(bits);
68	src++;
69	count -= 3;
70     }
71     if (count == 2) {
72	bits = ~(*src);
73	WRITE_BITS2(bits);
74     } else if (count == 1) {
75	bits = ~(*src);
76	WRITE_BITS1(bits);
77     }
78
79     return base;
80}
81
82
83static CARD32*
84BitmapScanline_Shifted(
85   CARD32 *src, CARD32 *base,
86   int count, int skipleft )
87{
88     CARD32 bits;
89
90     while(count >= 3) {
91	bits = SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft));
92	WRITE_BITS3(bits);
93	src++;
94	count -= 3;
95     }
96     if (count == 2) {
97	bits = SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft));
98	WRITE_BITS2(bits);
99     } else if (count == 1) {
100	bits = SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft));
101	WRITE_BITS1(bits);
102     }
103
104     return base;
105}
106
107static CARD32*
108BitmapScanline_Shifted_Inverted(
109   CARD32 *src, CARD32 *base,
110   int count, int skipleft )
111{
112     CARD32 bits;
113
114     while(count >= 3) {
115	bits = ~(SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft)));
116	WRITE_BITS3(bits);
117	src++;
118	count -= 3;
119     }
120     if (count == 2) {
121	bits = ~(SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft)));
122	WRITE_BITS2(bits);
123     } else if (count == 1) {
124	bits = ~(SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft)));
125	WRITE_BITS1(bits);
126     }
127
128     return base;
129}
130
131#define BitmapScanline_Shifted_Careful BitmapScanline_Shifted
132#define BitmapScanline_Shifted_Inverted_Careful BitmapScanline_Shifted_Inverted
133
134#else
135static CARD32*
136BitmapScanline(
137   CARD32 *src, CARD32 *dest,
138   int count, int skipleft )
139{
140   while(count >= 4) {
141	DEST(0) = SOURCE(0);
142	DEST(1) = SOURCE(1);
143	DEST(2) = SOURCE(2);
144	DEST(3) = SOURCE(3);
145	count -= 4;
146	src += 4;
147#ifndef FIXEDBASE
148	dest += 4;
149#endif
150   }
151
152   if(!count) return dest;
153   DEST(0) = SOURCE(0);
154   if(count == 1) RETURN(1);
155   DEST(1) = SOURCE(1);
156   if(count == 2) RETURN(2);
157   DEST(2) = SOURCE(2);
158   RETURN(3);
159}
160
161static CARD32*
162BitmapScanline_Inverted(
163   CARD32 *src, CARD32 *dest,
164   int count, int skipleft )
165{
166   while(count >= 4) {
167	DEST(0) = ~SOURCE(0);
168	DEST(1) = ~SOURCE(1);
169	DEST(2) = ~SOURCE(2);
170	DEST(3) = ~SOURCE(3);
171	count -= 4;
172	src += 4;
173#ifndef FIXEDBASE
174	dest += 4;
175#endif
176   }
177
178   if(!count) return dest;
179   DEST(0) = ~SOURCE(0);
180   if(count == 1) RETURN(1);
181   DEST(1) = ~SOURCE(1);
182   if(count == 2) RETURN(2);
183   DEST(2) = ~SOURCE(2);
184   RETURN(3);
185}
186
187
188static CARD32*
189BitmapScanline_Shifted(
190   CARD32 *bits, CARD32 *base,
191   int count, int skipleft )
192{
193     while(count--) {
194	register CARD32 tmp = SHIFT_R(*bits,skipleft) |
195			      SHIFT_L(*(bits + 1),(32 - skipleft));
196	WRITE_BITS(tmp);
197	bits++;
198     }
199     return base;
200}
201
202static CARD32*
203BitmapScanline_Shifted_Inverted(
204   CARD32 *bits, CARD32 *base,
205   int count, int skipleft )
206{
207     while(count--) {
208	register CARD32 tmp = ~(SHIFT_R(*bits,skipleft) |
209				SHIFT_L(*(bits + 1),(32 - skipleft)));
210	WRITE_BITS(tmp);
211	bits++;
212     }
213     return base;
214}
215
216static CARD32*
217BitmapScanline_Shifted_Careful(
218   CARD32 *bits, CARD32 *base,
219   int count, int skipleft )
220{
221     register CARD32 tmp;
222     while(--count) {
223 	tmp = SHIFT_R(*bits,skipleft) | SHIFT_L(*(bits + 1),(32 - skipleft));
224	WRITE_BITS(tmp);
225	bits++;
226     }
227     tmp = SHIFT_R(*bits,skipleft);
228     WRITE_BITS(tmp);
229
230     return base;
231}
232
233static CARD32*
234BitmapScanline_Shifted_Inverted_Careful(
235   CARD32 *bits, CARD32 *base,
236   int count, int skipleft )
237{
238     register CARD32 tmp;
239     while(--count) {
240	tmp = ~(SHIFT_R(*bits,skipleft) | SHIFT_L(*(bits + 1),(32 - skipleft)));
241	WRITE_BITS(tmp);
242	bits++;
243     }
244     tmp = ~(SHIFT_R(*bits,skipleft));
245     WRITE_BITS(tmp);
246     return base;
247}
248
249#endif
250
251/*
252    When the accelerator is TRANSPARENCY_ONLY, WriteBitmap can do
253    the fill in two passes, inverting the source on the second pass.
254    For GXcopy we can fill the backing rectangle as a solid rect and
255    avoid the invert.
256*/
257
258void
259#ifdef TRIPLE_BITS
260EXPNAME(XAAWriteBitmapColorExpand3)(
261#else
262EXPNAME(XAAWriteBitmapColorExpand)(
263#endif
264    ScrnInfoPtr pScrn,
265    int x, int y, int w, int H,
266    unsigned char *src,
267    int srcwidth,
268    int skipleft,
269    int fg, int bg,
270    int rop,
271    unsigned int planemask
272)
273{
274    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
275    CARD32* base;
276    unsigned char *srcp = src;
277    int SecondPassColor = -1;
278    int shift = 0, dwords;
279    BitmapScanlineProcPtr firstFunc;
280    BitmapScanlineProcPtr secondFunc;
281    int flag;
282    int h = H;
283
284#ifdef TRIPLE_BITS
285    if((bg != -1) &&
286	((infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) ||
287	((infoRec->CPUToScreenColorExpandFillFlags & RGB_EQUAL) &&
288	(!CHECK_RGB_EQUAL(bg))))) {
289#else
290    if((bg != -1) &&
291	(infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) {
292#endif
293	if((rop == GXcopy) && infoRec->SetupForSolidFill) {
294    	    (*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask);
295            (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
296	} else SecondPassColor = bg;
297	bg = -1;
298    }
299
300#ifdef TRIPLE_BITS
301    if(skipleft) {
302#else
303    if(skipleft &&
304	(!(infoRec->CPUToScreenColorExpandFillFlags & LEFT_EDGE_CLIPPING) ||
305	(!(infoRec->CPUToScreenColorExpandFillFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) &&
306		(skipleft > x)))) {
307#endif
308	if((skipleft + ((w + 31) & ~31)) > ((skipleft + w + 31) & ~31)) {
309	    /* don't read past the end */
310	    firstFunc = BitmapScanline_Shifted_Careful;
311 	    secondFunc = BitmapScanline_Shifted_Inverted_Careful;
312	} else {
313	    firstFunc = BitmapScanline_Shifted;
314 	    secondFunc = BitmapScanline_Shifted_Inverted;
315	}
316	shift = skipleft;
317	skipleft = 0;
318    } else {
319	firstFunc = BitmapScanline;
320 	secondFunc = BitmapScanline_Inverted;
321	w += skipleft;
322	x -= skipleft;
323    }
324
325#ifdef TRIPLE_BITS
326    dwords = (3 * w + 31) >> 5;
327#else
328    dwords = (w + 31) >> 5;
329#endif
330
331SECOND_PASS:
332
333    flag = (infoRec->CPUToScreenColorExpandFillFlags
334	     & CPU_TRANSFER_PAD_QWORD) && ((dwords * h) & 0x01);
335    (*infoRec->SetupForCPUToScreenColorExpandFill)(
336					pScrn, fg, bg, rop, planemask);
337    (*infoRec->SubsequentCPUToScreenColorExpandFill)(
338					pScrn, x, y, w, h, skipleft);
339
340    base = (CARD32*)infoRec->ColorExpandBase;
341
342#ifndef FIXEDBASE
343    if((dwords * h) <= infoRec->ColorExpandRange)
344	while(h--) {
345	    base = (*firstFunc)((CARD32*)srcp, base, dwords, shift);
346	    srcp += srcwidth;
347    	}
348    else
349#endif
350	while(h--) {
351	    (*firstFunc)((CARD32*)srcp, base, dwords, shift);
352	    srcp += srcwidth;
353	}
354
355    if(flag){
356        base = (CARD32*)infoRec->ColorExpandBase;
357	base[0] = 0x00000000;
358    }
359
360    if(SecondPassColor != -1) {
361	h = H; /* Reset height */
362	fg = SecondPassColor;
363	SecondPassColor = -1;
364	firstFunc = secondFunc;
365	srcp = src;
366	goto SECOND_PASS;
367    }
368
369    if(infoRec->CPUToScreenColorExpandFillFlags & SYNC_AFTER_COLOR_EXPAND)
370	(*infoRec->Sync)(pScrn);
371    else SET_SYNC_FLAG(infoRec);
372}
373
374#ifndef FIXEDBASE
375
376void
377#ifdef TRIPLE_BITS
378EXPNAME(XAAWriteBitmapScanlineColorExpand3)(
379#else
380EXPNAME(XAAWriteBitmapScanlineColorExpand)(
381#endif
382    ScrnInfoPtr pScrn,
383    int x, int y, int w, int h,
384    unsigned char *src,
385    int srcwidth,
386    int skipleft,
387    int fg, int bg,
388    int rop,
389    unsigned int planemask
390)
391{
392    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
393    CARD32* base;
394    unsigned char *srcp = src;
395    int SecondPassColor = -1;
396    int shift = 0, dwords, bufferNo;
397    BitmapScanlineProcPtr firstFunc;
398    BitmapScanlineProcPtr secondFunc;
399
400#ifdef TRIPLE_BITS
401    if((bg != -1) &&
402	((infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)
403	|| ((infoRec->ScanlineCPUToScreenColorExpandFillFlags & RGB_EQUAL) &&
404	(!CHECK_RGB_EQUAL(bg))))) {
405#else
406    if((bg != -1) &&
407	(infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)){
408#endif
409	if((rop == GXcopy) && infoRec->SetupForSolidFill) {
410    	    (*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask);
411            (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
412	} else SecondPassColor = bg;
413	bg = -1;
414    }
415
416#ifdef TRIPLE_BITS
417    if(skipleft) {
418#else
419    if(skipleft &&
420	(!(infoRec->ScanlineCPUToScreenColorExpandFillFlags &
421		LEFT_EDGE_CLIPPING) ||
422	(!(infoRec->ScanlineCPUToScreenColorExpandFillFlags &
423		 LEFT_EDGE_CLIPPING_NEGATIVE_X) && (skipleft > x)))) {
424#endif
425	if((skipleft + ((w + 31) & ~31)) > ((skipleft + w + 31) & ~31)) {
426	    /* don't read past the end */
427	    firstFunc = BitmapScanline_Shifted_Careful;
428 	    secondFunc = BitmapScanline_Shifted_Inverted_Careful;
429	} else {
430	    firstFunc = BitmapScanline_Shifted;
431 	    secondFunc = BitmapScanline_Shifted_Inverted;
432	}
433	shift = skipleft;
434	skipleft = 0;
435    } else {
436	firstFunc = BitmapScanline;
437 	secondFunc = BitmapScanline_Inverted;
438	w += skipleft;
439	x -= skipleft;
440    }
441
442#ifdef TRIPLE_BITS
443    dwords = (3 * w + 31) >> 5;
444#else
445    dwords = (w + 31) >> 5;
446#endif
447
448SECOND_PASS:
449
450    (*infoRec->SetupForScanlineCPUToScreenColorExpandFill)(pScrn, fg, bg, rop, planemask);
451    (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)(
452					pScrn, x, y, w, h, skipleft);
453
454    bufferNo = 0;
455
456    while(h--) {
457	base = (CARD32*)infoRec->ScanlineColorExpandBuffers[bufferNo];
458	(*firstFunc)((CARD32*)srcp, base, dwords, shift);
459	(*infoRec->SubsequentColorExpandScanline)(pScrn, bufferNo++);
460	srcp += srcwidth;
461	if(bufferNo >= infoRec->NumScanlineColorExpandBuffers)
462	    bufferNo = 0;
463    }
464
465    if(SecondPassColor != -1) {
466	fg = SecondPassColor;
467	SecondPassColor = -1;
468	firstFunc = secondFunc;
469	srcp = src;
470	goto SECOND_PASS;
471    }
472
473    SET_SYNC_FLAG(infoRec);
474}
475
476#endif
477