Commit | Line | Data |
---|---|---|
a09e091a JB |
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 "fb.h" | |
28 | ||
29 | /* | |
30 | * This is a slight abuse of the preprocessor to generate repetitive | |
31 | * code, the idea is to generate code for each case of a copy-mode | |
32 | * transparent stipple | |
33 | */ | |
34 | #define LaneCases1(c,a) case c: \ | |
35 | while (n--) { FbLaneCase(c,a); a++; } \ | |
36 | break | |
37 | #define LaneCases2(c,a) LaneCases1(c,a); LaneCases1(c+1,a) | |
38 | #define LaneCases4(c,a) LaneCases2(c,a); LaneCases2(c+2,a) | |
39 | #define LaneCases8(c,a) LaneCases4(c,a); LaneCases4(c+4,a) | |
40 | #define LaneCases16(c,a) LaneCases8(c,a); LaneCases8(c+8,a) | |
41 | #define LaneCases32(c,a) LaneCases16(c,a); LaneCases16(c+16,a) | |
42 | #define LaneCases64(c,a) LaneCases32(c,a); LaneCases32(c+32,a) | |
43 | #define LaneCases128(c,a) LaneCases64(c,a); LaneCases64(c+64,a) | |
44 | #define LaneCases256(c,a) LaneCases128(c,a); LaneCases128(c+128,a) | |
45 | ||
46 | #if FB_SHIFT == 6 | |
47 | #define LaneCases(a) LaneCases256(0,a) | |
48 | #endif | |
49 | ||
50 | #if FB_SHIFT == 5 | |
51 | #define LaneCases(a) LaneCases16(0,a) | |
52 | #endif | |
53 | ||
54 | /* | |
55 | * Repeat a transparent stipple across a scanline n times | |
56 | */ | |
57 | ||
58 | void | |
59 | fbTransparentSpan(FbBits * dst, FbBits stip, FbBits fgxor, int n) | |
60 | { | |
61 | FbStip s; | |
62 | ||
63 | s = ((FbStip) (stip) & 0x01); | |
64 | s |= ((FbStip) (stip >> 8) & 0x02); | |
65 | s |= ((FbStip) (stip >> 16) & 0x04); | |
66 | s |= ((FbStip) (stip >> 24) & 0x08); | |
67 | #if FB_SHIFT > 5 | |
68 | s |= ((FbStip) (stip >> 32) & 0x10); | |
69 | s |= ((FbStip) (stip >> 40) & 0x20); | |
70 | s |= ((FbStip) (stip >> 48) & 0x40); | |
71 | s |= ((FbStip) (stip >> 56) & 0x80); | |
72 | #endif | |
73 | switch (s) { | |
74 | LaneCases(dst); | |
75 | } | |
76 | } | |
77 | ||
78 | void | |
79 | fbEvenStipple(FbBits * dst, | |
80 | FbStride dstStride, | |
81 | int dstX, | |
82 | int dstBpp, | |
83 | int width, | |
84 | int height, | |
85 | FbStip * stip, | |
86 | FbStride stipStride, | |
87 | int stipHeight, | |
88 | FbBits fgand, | |
89 | FbBits fgxor, FbBits bgand, FbBits bgxor, int xRot, int yRot) | |
90 | { | |
91 | FbBits startmask, endmask; | |
92 | FbBits mask, and, xor; | |
93 | int nmiddle, n; | |
94 | FbStip *s, *stipEnd, bits; | |
95 | int rot, stipX, stipY; | |
96 | int pixelsPerDst; | |
97 | const FbBits *fbBits; | |
98 | Bool transparent; | |
99 | int startbyte, endbyte; | |
100 | ||
101 | /* | |
102 | * Check for a transparent stipple (stencil) | |
103 | */ | |
104 | transparent = FALSE; | |
105 | if (dstBpp >= 8 && fgand == 0 && bgand == FB_ALLONES && bgxor == 0) | |
106 | transparent = TRUE; | |
107 | ||
108 | pixelsPerDst = FB_UNIT / dstBpp; | |
109 | /* | |
110 | * Adjust dest pointers | |
111 | */ | |
112 | dst += dstX >> FB_SHIFT; | |
113 | dstX &= FB_MASK; | |
114 | FbMaskBitsBytes(dstX, width, fgand == 0 && bgand == 0, | |
115 | startmask, startbyte, nmiddle, endmask, endbyte); | |
116 | ||
117 | if (startmask) | |
118 | dstStride--; | |
119 | dstStride -= nmiddle; | |
120 | ||
121 | xRot *= dstBpp; | |
122 | /* | |
123 | * Compute stip start scanline and rotation parameters | |
124 | */ | |
125 | stipEnd = stip + stipStride * stipHeight; | |
126 | modulus(-yRot, stipHeight, stipY); | |
127 | s = stip + stipStride * stipY; | |
128 | modulus(-xRot, FB_UNIT, stipX); | |
129 | rot = stipX; | |
130 | ||
131 | /* | |
132 | * Get pointer to stipple mask array for this depth | |
133 | */ | |
134 | /* fbStippleTable covers all valid bpp (4,8,16,32) */ | |
135 | fbBits = fbStippleTable[pixelsPerDst]; | |
136 | ||
137 | while (height--) { | |
138 | /* | |
139 | * Extract stipple bits for this scanline; | |
140 | */ | |
141 | bits = READ(s); | |
142 | s += stipStride; | |
143 | if (s == stipEnd) | |
144 | s = stip; | |
145 | #if FB_UNIT > 32 | |
146 | if (pixelsPerDst == 16) | |
147 | mask = FbStipple16Bits(FbLeftStipBits(bits, 16)); | |
148 | else | |
149 | #endif | |
150 | mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; | |
151 | /* | |
152 | * Rotate into position and compute reduced rop values | |
153 | */ | |
154 | mask = FbRotLeft(mask, rot); | |
155 | and = (fgand & mask) | (bgand & ~mask); | |
156 | xor = (fgxor & mask) | (bgxor & ~mask); | |
157 | ||
158 | if (transparent) { | |
159 | if (startmask) { | |
160 | fbTransparentSpan(dst, mask & startmask, fgxor, 1); | |
161 | dst++; | |
162 | } | |
163 | fbTransparentSpan(dst, mask, fgxor, nmiddle); | |
164 | dst += nmiddle; | |
165 | if (endmask) | |
166 | fbTransparentSpan(dst, mask & endmask, fgxor, 1); | |
167 | } | |
168 | else { | |
169 | /* | |
170 | * Fill scanline | |
171 | */ | |
172 | if (startmask) { | |
173 | FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor); | |
174 | dst++; | |
175 | } | |
176 | n = nmiddle; | |
177 | if (!and) | |
178 | while (n--) | |
179 | WRITE(dst++, xor); | |
180 | else { | |
181 | while (n--) { | |
182 | WRITE(dst, FbDoRRop(READ(dst), and, xor)); | |
183 | dst++; | |
184 | } | |
185 | } | |
186 | if (endmask) | |
187 | FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor); | |
188 | } | |
189 | dst += dstStride; | |
190 | } | |
191 | } | |
192 | ||
193 | void | |
194 | fbOddStipple(FbBits * dst, | |
195 | FbStride dstStride, | |
196 | int dstX, | |
197 | int dstBpp, | |
198 | int width, | |
199 | int height, | |
200 | FbStip * stip, | |
201 | FbStride stipStride, | |
202 | int stipWidth, | |
203 | int stipHeight, | |
204 | FbBits fgand, | |
205 | FbBits fgxor, FbBits bgand, FbBits bgxor, int xRot, int yRot) | |
206 | { | |
207 | int stipX, stipY, sx; | |
208 | int widthTmp; | |
209 | int h, w; | |
210 | int x, y; | |
211 | ||
212 | modulus(-yRot, stipHeight, stipY); | |
213 | modulus(dstX / dstBpp - xRot, stipWidth, stipX); | |
214 | y = 0; | |
215 | while (height) { | |
216 | h = stipHeight - stipY; | |
217 | if (h > height) | |
218 | h = height; | |
219 | height -= h; | |
220 | widthTmp = width; | |
221 | x = dstX; | |
222 | sx = stipX; | |
223 | while (widthTmp) { | |
224 | w = (stipWidth - sx) * dstBpp; | |
225 | if (w > widthTmp) | |
226 | w = widthTmp; | |
227 | widthTmp -= w; | |
228 | fbBltOne(stip + stipY * stipStride, | |
229 | stipStride, | |
230 | sx, | |
231 | dst + y * dstStride, | |
232 | dstStride, x, dstBpp, w, h, fgand, fgxor, bgand, bgxor); | |
233 | x += w; | |
234 | sx = 0; | |
235 | } | |
236 | y += h; | |
237 | stipY = 0; | |
238 | } | |
239 | } | |
240 | ||
241 | void | |
242 | fbStipple(FbBits * dst, | |
243 | FbStride dstStride, | |
244 | int dstX, | |
245 | int dstBpp, | |
246 | int width, | |
247 | int height, | |
248 | FbStip * stip, | |
249 | FbStride stipStride, | |
250 | int stipWidth, | |
251 | int stipHeight, | |
252 | Bool even, | |
253 | FbBits fgand, | |
254 | FbBits fgxor, FbBits bgand, FbBits bgxor, int xRot, int yRot) | |
255 | { | |
256 | if (even) | |
257 | fbEvenStipple(dst, dstStride, dstX, dstBpp, width, height, | |
258 | stip, stipStride, stipHeight, | |
259 | fgand, fgxor, bgand, bgxor, xRot, yRot); | |
260 | else | |
261 | fbOddStipple(dst, dstStride, dstX, dstBpp, width, height, | |
262 | stip, stipStride, stipWidth, stipHeight, | |
263 | fgand, fgxor, bgand, bgxor, xRot, yRot); | |
264 | } |