Imported Upstream version 1.15.1
[deb_xorg-server.git] / fb / fbstipple.c
CommitLineData
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
58void
59fbTransparentSpan(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
78void
79fbEvenStipple(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
193void
194fbOddStipple(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
241void
242fbStipple(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}