fbblt.c revision 1b5d61b8
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
42void
43fbBlt(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
295void
296fbBltStip(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