xref: /OK3568_Linux_fs/external/xserver/fb/fbblt.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 1998 Keith Packard
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission to use, copy, modify, distribute, and sell this software and its
5*4882a593Smuzhiyun  * documentation for any purpose is hereby granted without fee, provided that
6*4882a593Smuzhiyun  * the above copyright notice appear in all copies and that both that
7*4882a593Smuzhiyun  * copyright notice and this permission notice appear in supporting
8*4882a593Smuzhiyun  * documentation, and that the name of Keith Packard not be used in
9*4882a593Smuzhiyun  * advertising or publicity pertaining to distribution of the software without
10*4882a593Smuzhiyun  * specific, written prior permission.  Keith Packard makes no
11*4882a593Smuzhiyun  * representations about the suitability of this software for any purpose.  It
12*4882a593Smuzhiyun  * is provided "as is" without express or implied warranty.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15*4882a593Smuzhiyun  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16*4882a593Smuzhiyun  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17*4882a593Smuzhiyun  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18*4882a593Smuzhiyun  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19*4882a593Smuzhiyun  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20*4882a593Smuzhiyun  * PERFORMANCE OF THIS SOFTWARE.
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
24*4882a593Smuzhiyun #include <dix-config.h>
25*4882a593Smuzhiyun #endif
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include <string.h>
28*4882a593Smuzhiyun #include "fb.h"
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #define InitializeShifts(sx,dx,ls,rs) { \
31*4882a593Smuzhiyun     if (sx != dx) { \
32*4882a593Smuzhiyun 	if (sx > dx) { \
33*4882a593Smuzhiyun 	    ls = sx - dx; \
34*4882a593Smuzhiyun 	    rs = FB_UNIT - ls; \
35*4882a593Smuzhiyun 	} else { \
36*4882a593Smuzhiyun 	    rs = dx - sx; \
37*4882a593Smuzhiyun 	    ls = FB_UNIT - rs; \
38*4882a593Smuzhiyun 	} \
39*4882a593Smuzhiyun     } \
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun void
fbBlt(FbBits * srcLine,FbStride srcStride,int srcX,FbBits * dstLine,FbStride dstStride,int dstX,int width,int height,int alu,FbBits pm,int bpp,Bool reverse,Bool upsidedown)43*4882a593Smuzhiyun fbBlt(FbBits * srcLine,
44*4882a593Smuzhiyun       FbStride srcStride,
45*4882a593Smuzhiyun       int srcX,
46*4882a593Smuzhiyun       FbBits * dstLine,
47*4882a593Smuzhiyun       FbStride dstStride,
48*4882a593Smuzhiyun       int dstX,
49*4882a593Smuzhiyun       int width,
50*4882a593Smuzhiyun       int height, int alu, FbBits pm, int bpp, Bool reverse, Bool upsidedown)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun     FbBits *src, *dst;
53*4882a593Smuzhiyun     int leftShift, rightShift;
54*4882a593Smuzhiyun     FbBits startmask, endmask;
55*4882a593Smuzhiyun     FbBits bits, bits1;
56*4882a593Smuzhiyun     int n, nmiddle;
57*4882a593Smuzhiyun     Bool destInvarient;
58*4882a593Smuzhiyun     int startbyte, endbyte;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun     FbDeclareMergeRop();
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun     if (alu == GXcopy && pm == FB_ALLONES &&
63*4882a593Smuzhiyun         !(srcX & 7) && !(dstX & 7) && !(width & 7))
64*4882a593Smuzhiyun     {
65*4882a593Smuzhiyun         CARD8           *src_byte = (CARD8 *) srcLine + (srcX >> 3);
66*4882a593Smuzhiyun         CARD8           *dst_byte = (CARD8 *) dstLine + (dstX >> 3);
67*4882a593Smuzhiyun         FbStride        src_byte_stride = srcStride << (FB_SHIFT - 3);
68*4882a593Smuzhiyun         FbStride        dst_byte_stride = dstStride << (FB_SHIFT - 3);
69*4882a593Smuzhiyun         int             width_byte = (width >> 3);
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun         /* Make sure there's no overlap; we can't use memcpy in that
72*4882a593Smuzhiyun          * case as it's not well defined, so fall through to the
73*4882a593Smuzhiyun          * general code
74*4882a593Smuzhiyun          */
75*4882a593Smuzhiyun         if (src_byte + width_byte <= dst_byte ||
76*4882a593Smuzhiyun             dst_byte + width_byte <= src_byte)
77*4882a593Smuzhiyun         {
78*4882a593Smuzhiyun             int i;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun             if (!upsidedown)
81*4882a593Smuzhiyun                 for (i = 0; i < height; i++)
82*4882a593Smuzhiyun                     MEMCPY_WRAPPED(dst_byte + i * dst_byte_stride,
83*4882a593Smuzhiyun                                    src_byte + i * src_byte_stride,
84*4882a593Smuzhiyun                                    width_byte);
85*4882a593Smuzhiyun             else
86*4882a593Smuzhiyun                 for (i = height - 1; i >= 0; i--)
87*4882a593Smuzhiyun                     MEMCPY_WRAPPED(dst_byte + i * dst_byte_stride,
88*4882a593Smuzhiyun                                    src_byte + i * src_byte_stride,
89*4882a593Smuzhiyun                                    width_byte);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun             return;
92*4882a593Smuzhiyun         }
93*4882a593Smuzhiyun     }
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun     FbInitializeMergeRop(alu, pm);
96*4882a593Smuzhiyun     destInvarient = FbDestInvarientMergeRop();
97*4882a593Smuzhiyun     if (upsidedown) {
98*4882a593Smuzhiyun         srcLine += (height - 1) * (srcStride);
99*4882a593Smuzhiyun         dstLine += (height - 1) * (dstStride);
100*4882a593Smuzhiyun         srcStride = -srcStride;
101*4882a593Smuzhiyun         dstStride = -dstStride;
102*4882a593Smuzhiyun     }
103*4882a593Smuzhiyun     FbMaskBitsBytes(dstX, width, destInvarient, startmask, startbyte,
104*4882a593Smuzhiyun                     nmiddle, endmask, endbyte);
105*4882a593Smuzhiyun     if (reverse) {
106*4882a593Smuzhiyun         srcLine += ((srcX + width - 1) >> FB_SHIFT) + 1;
107*4882a593Smuzhiyun         dstLine += ((dstX + width - 1) >> FB_SHIFT) + 1;
108*4882a593Smuzhiyun         srcX = (srcX + width - 1) & FB_MASK;
109*4882a593Smuzhiyun         dstX = (dstX + width - 1) & FB_MASK;
110*4882a593Smuzhiyun     }
111*4882a593Smuzhiyun     else {
112*4882a593Smuzhiyun         srcLine += srcX >> FB_SHIFT;
113*4882a593Smuzhiyun         dstLine += dstX >> FB_SHIFT;
114*4882a593Smuzhiyun         srcX &= FB_MASK;
115*4882a593Smuzhiyun         dstX &= FB_MASK;
116*4882a593Smuzhiyun     }
117*4882a593Smuzhiyun     if (srcX == dstX) {
118*4882a593Smuzhiyun         while (height--) {
119*4882a593Smuzhiyun             src = srcLine;
120*4882a593Smuzhiyun             srcLine += srcStride;
121*4882a593Smuzhiyun             dst = dstLine;
122*4882a593Smuzhiyun             dstLine += dstStride;
123*4882a593Smuzhiyun             if (reverse) {
124*4882a593Smuzhiyun                 if (endmask) {
125*4882a593Smuzhiyun                     bits = READ(--src);
126*4882a593Smuzhiyun                     --dst;
127*4882a593Smuzhiyun                     FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
128*4882a593Smuzhiyun                 }
129*4882a593Smuzhiyun                 n = nmiddle;
130*4882a593Smuzhiyun                 if (destInvarient) {
131*4882a593Smuzhiyun                     while (n--)
132*4882a593Smuzhiyun                         WRITE(--dst, FbDoDestInvarientMergeRop(READ(--src)));
133*4882a593Smuzhiyun                 }
134*4882a593Smuzhiyun                 else {
135*4882a593Smuzhiyun                     while (n--) {
136*4882a593Smuzhiyun                         bits = READ(--src);
137*4882a593Smuzhiyun                         --dst;
138*4882a593Smuzhiyun                         WRITE(dst, FbDoMergeRop(bits, READ(dst)));
139*4882a593Smuzhiyun                     }
140*4882a593Smuzhiyun                 }
141*4882a593Smuzhiyun                 if (startmask) {
142*4882a593Smuzhiyun                     bits = READ(--src);
143*4882a593Smuzhiyun                     --dst;
144*4882a593Smuzhiyun                     FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
145*4882a593Smuzhiyun                 }
146*4882a593Smuzhiyun             }
147*4882a593Smuzhiyun             else {
148*4882a593Smuzhiyun                 if (startmask) {
149*4882a593Smuzhiyun                     bits = READ(src++);
150*4882a593Smuzhiyun                     FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
151*4882a593Smuzhiyun                     dst++;
152*4882a593Smuzhiyun                 }
153*4882a593Smuzhiyun                 n = nmiddle;
154*4882a593Smuzhiyun                 if (destInvarient) {
155*4882a593Smuzhiyun #if 0
156*4882a593Smuzhiyun                     /*
157*4882a593Smuzhiyun                      * This provides some speedup on screen->screen blts
158*4882a593Smuzhiyun                      * over the PCI bus, usually about 10%.  But fb
159*4882a593Smuzhiyun                      * isn't usually used for this operation...
160*4882a593Smuzhiyun                      */
161*4882a593Smuzhiyun                     if (_ca2 + 1 == 0 && _cx2 == 0) {
162*4882a593Smuzhiyun                         FbBits t1, t2, t3, t4;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun                         while (n >= 4) {
165*4882a593Smuzhiyun                             t1 = *src++;
166*4882a593Smuzhiyun                             t2 = *src++;
167*4882a593Smuzhiyun                             t3 = *src++;
168*4882a593Smuzhiyun                             t4 = *src++;
169*4882a593Smuzhiyun                             *dst++ = t1;
170*4882a593Smuzhiyun                             *dst++ = t2;
171*4882a593Smuzhiyun                             *dst++ = t3;
172*4882a593Smuzhiyun                             *dst++ = t4;
173*4882a593Smuzhiyun                             n -= 4;
174*4882a593Smuzhiyun                         }
175*4882a593Smuzhiyun                     }
176*4882a593Smuzhiyun #endif
177*4882a593Smuzhiyun                     while (n--)
178*4882a593Smuzhiyun                         WRITE(dst++, FbDoDestInvarientMergeRop(READ(src++)));
179*4882a593Smuzhiyun                 }
180*4882a593Smuzhiyun                 else {
181*4882a593Smuzhiyun                     while (n--) {
182*4882a593Smuzhiyun                         bits = READ(src++);
183*4882a593Smuzhiyun                         WRITE(dst, FbDoMergeRop(bits, READ(dst)));
184*4882a593Smuzhiyun                         dst++;
185*4882a593Smuzhiyun                     }
186*4882a593Smuzhiyun                 }
187*4882a593Smuzhiyun                 if (endmask) {
188*4882a593Smuzhiyun                     bits = READ(src);
189*4882a593Smuzhiyun                     FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
190*4882a593Smuzhiyun                 }
191*4882a593Smuzhiyun             }
192*4882a593Smuzhiyun         }
193*4882a593Smuzhiyun     }
194*4882a593Smuzhiyun     else {
195*4882a593Smuzhiyun         if (srcX > dstX) {
196*4882a593Smuzhiyun             leftShift = srcX - dstX;
197*4882a593Smuzhiyun             rightShift = FB_UNIT - leftShift;
198*4882a593Smuzhiyun         }
199*4882a593Smuzhiyun         else {
200*4882a593Smuzhiyun             rightShift = dstX - srcX;
201*4882a593Smuzhiyun             leftShift = FB_UNIT - rightShift;
202*4882a593Smuzhiyun         }
203*4882a593Smuzhiyun         while (height--) {
204*4882a593Smuzhiyun             src = srcLine;
205*4882a593Smuzhiyun             srcLine += srcStride;
206*4882a593Smuzhiyun             dst = dstLine;
207*4882a593Smuzhiyun             dstLine += dstStride;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun             bits1 = 0;
210*4882a593Smuzhiyun             if (reverse) {
211*4882a593Smuzhiyun                 if (srcX < dstX)
212*4882a593Smuzhiyun                     bits1 = READ(--src);
213*4882a593Smuzhiyun                 if (endmask) {
214*4882a593Smuzhiyun                     bits = FbScrRight(bits1, rightShift);
215*4882a593Smuzhiyun                     if (FbScrRight(endmask, leftShift)) {
216*4882a593Smuzhiyun                         bits1 = READ(--src);
217*4882a593Smuzhiyun                         bits |= FbScrLeft(bits1, leftShift);
218*4882a593Smuzhiyun                     }
219*4882a593Smuzhiyun                     --dst;
220*4882a593Smuzhiyun                     FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
221*4882a593Smuzhiyun                 }
222*4882a593Smuzhiyun                 n = nmiddle;
223*4882a593Smuzhiyun                 if (destInvarient) {
224*4882a593Smuzhiyun                     while (n--) {
225*4882a593Smuzhiyun                         bits = FbScrRight(bits1, rightShift);
226*4882a593Smuzhiyun                         bits1 = READ(--src);
227*4882a593Smuzhiyun                         bits |= FbScrLeft(bits1, leftShift);
228*4882a593Smuzhiyun                         --dst;
229*4882a593Smuzhiyun                         WRITE(dst, FbDoDestInvarientMergeRop(bits));
230*4882a593Smuzhiyun                     }
231*4882a593Smuzhiyun                 }
232*4882a593Smuzhiyun                 else {
233*4882a593Smuzhiyun                     while (n--) {
234*4882a593Smuzhiyun                         bits = FbScrRight(bits1, rightShift);
235*4882a593Smuzhiyun                         bits1 = READ(--src);
236*4882a593Smuzhiyun                         bits |= FbScrLeft(bits1, leftShift);
237*4882a593Smuzhiyun                         --dst;
238*4882a593Smuzhiyun                         WRITE(dst, FbDoMergeRop(bits, READ(dst)));
239*4882a593Smuzhiyun                     }
240*4882a593Smuzhiyun                 }
241*4882a593Smuzhiyun                 if (startmask) {
242*4882a593Smuzhiyun                     bits = FbScrRight(bits1, rightShift);
243*4882a593Smuzhiyun                     if (FbScrRight(startmask, leftShift)) {
244*4882a593Smuzhiyun                         bits1 = READ(--src);
245*4882a593Smuzhiyun                         bits |= FbScrLeft(bits1, leftShift);
246*4882a593Smuzhiyun                     }
247*4882a593Smuzhiyun                     --dst;
248*4882a593Smuzhiyun                     FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
249*4882a593Smuzhiyun                 }
250*4882a593Smuzhiyun             }
251*4882a593Smuzhiyun             else {
252*4882a593Smuzhiyun                 if (srcX > dstX)
253*4882a593Smuzhiyun                     bits1 = READ(src++);
254*4882a593Smuzhiyun                 if (startmask) {
255*4882a593Smuzhiyun                     bits = FbScrLeft(bits1, leftShift);
256*4882a593Smuzhiyun                     if (FbScrLeft(startmask, rightShift)) {
257*4882a593Smuzhiyun                         bits1 = READ(src++);
258*4882a593Smuzhiyun                         bits |= FbScrRight(bits1, rightShift);
259*4882a593Smuzhiyun                     }
260*4882a593Smuzhiyun                     FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
261*4882a593Smuzhiyun                     dst++;
262*4882a593Smuzhiyun                 }
263*4882a593Smuzhiyun                 n = nmiddle;
264*4882a593Smuzhiyun                 if (destInvarient) {
265*4882a593Smuzhiyun                     while (n--) {
266*4882a593Smuzhiyun                         bits = FbScrLeft(bits1, leftShift);
267*4882a593Smuzhiyun                         bits1 = READ(src++);
268*4882a593Smuzhiyun                         bits |= FbScrRight(bits1, rightShift);
269*4882a593Smuzhiyun                         WRITE(dst, FbDoDestInvarientMergeRop(bits));
270*4882a593Smuzhiyun                         dst++;
271*4882a593Smuzhiyun                     }
272*4882a593Smuzhiyun                 }
273*4882a593Smuzhiyun                 else {
274*4882a593Smuzhiyun                     while (n--) {
275*4882a593Smuzhiyun                         bits = FbScrLeft(bits1, leftShift);
276*4882a593Smuzhiyun                         bits1 = READ(src++);
277*4882a593Smuzhiyun                         bits |= FbScrRight(bits1, rightShift);
278*4882a593Smuzhiyun                         WRITE(dst, FbDoMergeRop(bits, READ(dst)));
279*4882a593Smuzhiyun                         dst++;
280*4882a593Smuzhiyun                     }
281*4882a593Smuzhiyun                 }
282*4882a593Smuzhiyun                 if (endmask) {
283*4882a593Smuzhiyun                     bits = FbScrLeft(bits1, leftShift);
284*4882a593Smuzhiyun                     if (FbScrLeft(endmask, rightShift)) {
285*4882a593Smuzhiyun                         bits1 = READ(src);
286*4882a593Smuzhiyun                         bits |= FbScrRight(bits1, rightShift);
287*4882a593Smuzhiyun                     }
288*4882a593Smuzhiyun                     FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
289*4882a593Smuzhiyun                 }
290*4882a593Smuzhiyun             }
291*4882a593Smuzhiyun         }
292*4882a593Smuzhiyun     }
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun void
fbBltStip(FbStip * src,FbStride srcStride,int srcX,FbStip * dst,FbStride dstStride,int dstX,int width,int height,int alu,FbBits pm,int bpp)296*4882a593Smuzhiyun fbBltStip(FbStip * src, FbStride srcStride,     /* in FbStip units, not FbBits units */
297*4882a593Smuzhiyun           int srcX, FbStip * dst, FbStride dstStride,   /* in FbStip units, not FbBits units */
298*4882a593Smuzhiyun           int dstX, int width, int height, int alu, FbBits pm, int bpp)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun     fbBlt((FbBits *) src, FbStipStrideToBitsStride(srcStride), srcX,
301*4882a593Smuzhiyun           (FbBits *) dst, FbStipStrideToBitsStride(dstStride), dstX,
302*4882a593Smuzhiyun           width, height, alu, pm, bpp, FALSE, FALSE);
303*4882a593Smuzhiyun }
304