2 * Generic fillrect for frame buffers in system RAM with packed pixels of
5 * Based almost entirely from cfbfillrect.c (which is based almost entirely
6 * on Geert Uytterhoeven's fillrect routine)
8 * Copyright (C) 2007 Antonino Daplas <adaplas@pol.net>
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file COPYING in the main directory of this archive for
14 #include <linux/module.h>
15 #include <linux/string.h>
17 #include <asm/types.h>
20 * Compose two values, using a bitmask as decision value
21 * This is equivalent to (a & mask) | (b & ~mask)
24 static inline unsigned long
25 comp(unsigned long a, unsigned long b, unsigned long mask)
27 return ((a ^ b) & mask) ^ b;
31 * Create a pattern with the given pixel's color
34 #if BITS_PER_LONG == 64
35 static inline unsigned long
36 pixel_to_pat( u32 bpp, u32 pixel)
40 return 0xfffffffffffffffful*pixel;
42 return 0x5555555555555555ul*pixel;
44 return 0x1111111111111111ul*pixel;
46 return 0x0101010101010101ul*pixel;
48 return 0x0001001001001001ul*pixel;
50 return 0x0001000100010001ul*pixel;
52 return 0x0000000001000001ul*pixel;
54 return 0x0000000100000001ul*pixel;
56 panic("pixel_to_pat(): unsupported pixelformat\n");
60 static inline unsigned long
61 pixel_to_pat( u32 bpp, u32 pixel)
65 return 0xfffffffful*pixel;
67 return 0x55555555ul*pixel;
69 return 0x11111111ul*pixel;
71 return 0x01010101ul*pixel;
73 return 0x00001001ul*pixel;
75 return 0x00010001ul*pixel;
77 return 0x00000001ul*pixel;
79 return 0x00000001ul*pixel;
81 panic("pixel_to_pat(): unsupported pixelformat\n");
87 * Aligned pattern fill using 32/64-bit memory accesses
91 bitfill_aligned(unsigned long *dst, int dst_idx, unsigned long pat,
94 unsigned long first, last;
99 first = FB_SHIFT_HIGH(~0UL, dst_idx);
100 last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
102 if (dst_idx+n <= bits) {
106 *dst = comp(pat, *dst, first);
108 /* Multiple destination words */
112 *dst = comp(pat, *dst, first);
134 *dst = comp(pat, *dst, last);
140 * Unaligned generic pattern fill using 32/64-bit memory accesses
141 * The pattern must have been expanded to a full 32/64-bit value
142 * Left/right are the appropriate shifts to convert to the pattern to be
143 * used for the next 32/64-bit word
147 bitfill_unaligned(unsigned long *dst, int dst_idx, unsigned long pat,
148 int left, int right, unsigned n, int bits)
150 unsigned long first, last;
155 first = FB_SHIFT_HIGH(~0UL, dst_idx);
156 last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
158 if (dst_idx+n <= bits) {
162 *dst = comp(pat, *dst, first);
164 /* Multiple destination words */
167 *dst = comp(pat, *dst, first);
169 pat = pat << left | pat >> right;
177 pat = pat << left | pat >> right;
179 pat = pat << left | pat >> right;
181 pat = pat << left | pat >> right;
183 pat = pat << left | pat >> right;
188 pat = pat << left | pat >> right;
193 *dst = comp(pat, *dst, first);
198 * Aligned pattern invert using 32/64-bit memory accesses
201 bitfill_aligned_rev(unsigned long *dst, int dst_idx, unsigned long pat,
202 unsigned n, int bits)
204 unsigned long val = pat;
205 unsigned long first, last;
210 first = FB_SHIFT_HIGH(~0UL, dst_idx);
211 last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
213 if (dst_idx+n <= bits) {
217 *dst = comp(*dst ^ val, *dst, first);
219 /* Multiple destination words */
222 *dst = comp(*dst ^ val, *dst, first);
244 *dst = comp(*dst ^ val, *dst, last);
250 * Unaligned generic pattern invert using 32/64-bit memory accesses
251 * The pattern must have been expanded to a full 32/64-bit value
252 * Left/right are the appropriate shifts to convert to the pattern to be
253 * used for the next 32/64-bit word
257 bitfill_unaligned_rev(unsigned long *dst, int dst_idx, unsigned long pat,
258 int left, int right, unsigned n, int bits)
260 unsigned long first, last;
265 first = FB_SHIFT_HIGH(~0UL, dst_idx);
266 last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
268 if (dst_idx+n <= bits) {
272 *dst = comp(*dst ^ pat, *dst, first);
274 /* Multiple destination words */
278 *dst = comp(*dst ^ pat, *dst, first);
280 pat = pat << left | pat >> right;
288 pat = pat << left | pat >> right;
290 pat = pat << left | pat >> right;
292 pat = pat << left | pat >> right;
294 pat = pat << left | pat >> right;
299 pat = pat << left | pat >> right;
304 *dst = comp(*dst ^ pat, *dst, last);
308 void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
310 unsigned long pat, fg;
311 unsigned long width = rect->width, height = rect->height;
312 int bits = BITS_PER_LONG, bytes = bits >> 3;
313 u32 bpp = p->var.bits_per_pixel;
317 if (p->state != FBINFO_STATE_RUNNING)
320 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
321 p->fix.visual == FB_VISUAL_DIRECTCOLOR )
322 fg = ((u32 *) (p->pseudo_palette))[rect->color];
326 pat = pixel_to_pat( bpp, fg);
328 dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1));
329 dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
330 dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
331 /* FIXME For now we support 1-32 bpp only */
333 if (p->fbops->fb_sync)
334 p->fbops->fb_sync(p);
336 void (*fill_op32)(unsigned long *dst, int dst_idx,
337 unsigned long pat, unsigned n, int bits) =
342 fill_op32 = bitfill_aligned_rev;
345 fill_op32 = bitfill_aligned;
348 printk( KERN_ERR "cfb_fillrect(): unknown rop, "
349 "defaulting to ROP_COPY\n");
350 fill_op32 = bitfill_aligned;
354 dst += dst_idx >> (ffs(bits) - 1);
355 dst_idx &= (bits - 1);
356 fill_op32(dst, dst_idx, pat, width*bpp, bits);
357 dst_idx += p->fix.line_length*8;
362 int rot = (left-dst_idx) % bpp;
363 void (*fill_op)(unsigned long *dst, int dst_idx,
364 unsigned long pat, int left, int right,
365 unsigned n, int bits) = NULL;
367 /* rotate pattern to correct start position */
368 pat = pat << rot | pat >> (bpp-rot);
373 fill_op = bitfill_unaligned_rev;
376 fill_op = bitfill_unaligned;
379 printk(KERN_ERR "cfb_fillrect(): unknown rop, "
380 "defaulting to ROP_COPY\n");
381 fill_op = bitfill_unaligned;
385 dst += dst_idx >> (ffs(bits) - 1);
386 dst_idx &= (bits - 1);
387 fill_op(dst, dst_idx, pat, left, right,
389 r = (p->fix.line_length*8) % bpp;
390 pat = pat << (bpp-r) | pat >> r;
391 dst_idx += p->fix.line_length*8;
396 EXPORT_SYMBOL(sys_fillrect);
398 MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
399 MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");
400 MODULE_LICENSE("GPL");