1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/module.h>
15#include <linux/string.h>
16#include <linux/fb.h>
17#include <asm/types.h>
18#include "fb_draw.h"
19
20
21
22
23
24static void
25bitfill_aligned(struct fb_info *p, unsigned long *dst, int dst_idx,
26 unsigned long pat, unsigned n, int bits)
27{
28 unsigned long first, last;
29
30 if (!n)
31 return;
32
33 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
34 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
35
36 if (dst_idx+n <= bits) {
37
38 if (last)
39 first &= last;
40 *dst = comp(pat, *dst, first);
41 } else {
42
43
44
45 if (first!= ~0UL) {
46 *dst = comp(pat, *dst, first);
47 dst++;
48 n -= bits - dst_idx;
49 }
50
51
52 n /= bits;
53 while (n >= 8) {
54 *dst++ = pat;
55 *dst++ = pat;
56 *dst++ = pat;
57 *dst++ = pat;
58 *dst++ = pat;
59 *dst++ = pat;
60 *dst++ = pat;
61 *dst++ = pat;
62 n -= 8;
63 }
64 while (n--)
65 *dst++ = pat;
66
67 if (last)
68 *dst = comp(pat, *dst, last);
69 }
70}
71
72
73
74
75
76
77
78
79
80static void
81bitfill_unaligned(struct fb_info *p, unsigned long *dst, int dst_idx,
82 unsigned long pat, int left, int right, unsigned n, int bits)
83{
84 unsigned long first, last;
85
86 if (!n)
87 return;
88
89 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
90 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
91
92 if (dst_idx+n <= bits) {
93
94 if (last)
95 first &= last;
96 *dst = comp(pat, *dst, first);
97 } else {
98
99
100 if (first) {
101 *dst = comp(pat, *dst, first);
102 dst++;
103 pat = pat << left | pat >> right;
104 n -= bits - dst_idx;
105 }
106
107
108 n /= bits;
109 while (n >= 4) {
110 *dst++ = pat;
111 pat = pat << left | pat >> right;
112 *dst++ = pat;
113 pat = pat << left | pat >> right;
114 *dst++ = pat;
115 pat = pat << left | pat >> right;
116 *dst++ = pat;
117 pat = pat << left | pat >> right;
118 n -= 4;
119 }
120 while (n--) {
121 *dst++ = pat;
122 pat = pat << left | pat >> right;
123 }
124
125
126 if (last)
127 *dst = comp(pat, *dst, last);
128 }
129}
130
131
132
133
134static void
135bitfill_aligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
136 unsigned long pat, unsigned n, int bits)
137{
138 unsigned long val = pat;
139 unsigned long first, last;
140
141 if (!n)
142 return;
143
144 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
145 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
146
147 if (dst_idx+n <= bits) {
148
149 if (last)
150 first &= last;
151 *dst = comp(*dst ^ val, *dst, first);
152 } else {
153
154
155 if (first!=0UL) {
156 *dst = comp(*dst ^ val, *dst, first);
157 dst++;
158 n -= bits - dst_idx;
159 }
160
161
162 n /= bits;
163 while (n >= 8) {
164 *dst++ ^= val;
165 *dst++ ^= val;
166 *dst++ ^= val;
167 *dst++ ^= val;
168 *dst++ ^= val;
169 *dst++ ^= val;
170 *dst++ ^= val;
171 *dst++ ^= val;
172 n -= 8;
173 }
174 while (n--)
175 *dst++ ^= val;
176
177 if (last)
178 *dst = comp(*dst ^ val, *dst, last);
179 }
180}
181
182
183
184
185
186
187
188
189
190static void
191bitfill_unaligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
192 unsigned long pat, int left, int right, unsigned n,
193 int bits)
194{
195 unsigned long first, last;
196
197 if (!n)
198 return;
199
200 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
201 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
202
203 if (dst_idx+n <= bits) {
204
205 if (last)
206 first &= last;
207 *dst = comp(*dst ^ pat, *dst, first);
208 } else {
209
210
211
212 if (first != 0UL) {
213 *dst = comp(*dst ^ pat, *dst, first);
214 dst++;
215 pat = pat << left | pat >> right;
216 n -= bits - dst_idx;
217 }
218
219
220 n /= bits;
221 while (n >= 4) {
222 *dst++ ^= pat;
223 pat = pat << left | pat >> right;
224 *dst++ ^= pat;
225 pat = pat << left | pat >> right;
226 *dst++ ^= pat;
227 pat = pat << left | pat >> right;
228 *dst++ ^= pat;
229 pat = pat << left | pat >> right;
230 n -= 4;
231 }
232 while (n--) {
233 *dst ^= pat;
234 pat = pat << left | pat >> right;
235 }
236
237
238 if (last)
239 *dst = comp(*dst ^ pat, *dst, last);
240 }
241}
242
243void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
244{
245 unsigned long pat, pat2, fg;
246 unsigned long width = rect->width, height = rect->height;
247 int bits = BITS_PER_LONG, bytes = bits >> 3;
248 u32 bpp = p->var.bits_per_pixel;
249 unsigned long *dst;
250 int dst_idx, left;
251
252 if (p->state != FBINFO_STATE_RUNNING)
253 return;
254
255 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
256 p->fix.visual == FB_VISUAL_DIRECTCOLOR )
257 fg = ((u32 *) (p->pseudo_palette))[rect->color];
258 else
259 fg = rect->color;
260
261 pat = pixel_to_pat( bpp, fg);
262
263 dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1));
264 dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
265 dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
266
267 left = bits % bpp;
268 if (p->fbops->fb_sync)
269 p->fbops->fb_sync(p);
270 if (!left) {
271 void (*fill_op32)(struct fb_info *p, unsigned long *dst,
272 int dst_idx, unsigned long pat, unsigned n,
273 int bits) = NULL;
274
275 switch (rect->rop) {
276 case ROP_XOR:
277 fill_op32 = bitfill_aligned_rev;
278 break;
279 case ROP_COPY:
280 fill_op32 = bitfill_aligned;
281 break;
282 default:
283 printk( KERN_ERR "cfb_fillrect(): unknown rop, "
284 "defaulting to ROP_COPY\n");
285 fill_op32 = bitfill_aligned;
286 break;
287 }
288 while (height--) {
289 dst += dst_idx >> (ffs(bits) - 1);
290 dst_idx &= (bits - 1);
291 fill_op32(p, dst, dst_idx, pat, width*bpp, bits);
292 dst_idx += p->fix.line_length*8;
293 }
294 } else {
295 int right, r;
296 void (*fill_op)(struct fb_info *p, unsigned long *dst,
297 int dst_idx, unsigned long pat, int left,
298 int right, unsigned n, int bits) = NULL;
299#ifdef __LITTLE_ENDIAN
300 right = left;
301 left = bpp - right;
302#else
303 right = bpp - left;
304#endif
305 switch (rect->rop) {
306 case ROP_XOR:
307 fill_op = bitfill_unaligned_rev;
308 break;
309 case ROP_COPY:
310 fill_op = bitfill_unaligned;
311 break;
312 default:
313 printk(KERN_ERR "sys_fillrect(): unknown rop, "
314 "defaulting to ROP_COPY\n");
315 fill_op = bitfill_unaligned;
316 break;
317 }
318 while (height--) {
319 dst += dst_idx / bits;
320 dst_idx &= (bits - 1);
321 r = dst_idx % bpp;
322
323 pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
324 fill_op(p, dst, dst_idx, pat2, left, right,
325 width*bpp, bits);
326 dst_idx += p->fix.line_length*8;
327 }
328 }
329}
330
331EXPORT_SYMBOL(sys_fillrect);
332
333MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
334MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");
335MODULE_LICENSE("GPL");
336