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