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