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>
21 * Aligned pattern fill using 32/64-bit memory accesses
25 bitfill_aligned(unsigned long *dst
, int dst_idx
, unsigned long pat
,
28 unsigned long first
, last
;
33 first
= FB_SHIFT_HIGH(~0UL, dst_idx
);
34 last
= ~(FB_SHIFT_HIGH(~0UL, (dst_idx
+n
) % bits
));
36 if (dst_idx
+n
<= bits
) {
40 *dst
= comp(pat
, *dst
, first
);
42 /* Multiple destination words */
46 *dst
= comp(pat
, *dst
, first
);
68 *dst
= comp(pat
, *dst
, last
);
74 * Unaligned generic pattern fill using 32/64-bit memory accesses
75 * The pattern must have been expanded to a full 32/64-bit value
76 * Left/right are the appropriate shifts to convert to the pattern to be
77 * used for the next 32/64-bit word
81 bitfill_unaligned(unsigned long *dst
, int dst_idx
, unsigned long pat
,
82 int left
, int right
, unsigned n
, int bits
)
84 unsigned long first
, last
;
89 first
= FB_SHIFT_HIGH(~0UL, dst_idx
);
90 last
= ~(FB_SHIFT_HIGH(~0UL, (dst_idx
+n
) % bits
));
92 if (dst_idx
+n
<= bits
) {
96 *dst
= comp(pat
, *dst
, first
);
98 /* Multiple destination words */
101 *dst
= comp(pat
, *dst
, first
);
103 pat
= pat
<< left
| pat
>> right
;
111 pat
= pat
<< left
| pat
>> right
;
113 pat
= pat
<< left
| pat
>> right
;
115 pat
= pat
<< left
| pat
>> right
;
117 pat
= pat
<< left
| pat
>> right
;
122 pat
= pat
<< left
| pat
>> right
;
127 *dst
= comp(pat
, *dst
, first
);
132 * Aligned pattern invert using 32/64-bit memory accesses
135 bitfill_aligned_rev(unsigned long *dst
, int dst_idx
, unsigned long pat
,
136 unsigned n
, int bits
)
138 unsigned long val
= pat
;
139 unsigned long first
, last
;
144 first
= FB_SHIFT_HIGH(~0UL, dst_idx
);
145 last
= ~(FB_SHIFT_HIGH(~0UL, (dst_idx
+n
) % bits
));
147 if (dst_idx
+n
<= bits
) {
151 *dst
= comp(*dst
^ val
, *dst
, first
);
153 /* Multiple destination words */
156 *dst
= comp(*dst
^ val
, *dst
, first
);
178 *dst
= comp(*dst
^ val
, *dst
, last
);
184 * Unaligned generic pattern invert using 32/64-bit memory accesses
185 * The pattern must have been expanded to a full 32/64-bit value
186 * Left/right are the appropriate shifts to convert to the pattern to be
187 * used for the next 32/64-bit word
191 bitfill_unaligned_rev(unsigned long *dst
, int dst_idx
, unsigned long pat
,
192 int left
, int right
, unsigned n
, int bits
)
194 unsigned long first
, last
;
199 first
= FB_SHIFT_HIGH(~0UL, dst_idx
);
200 last
= ~(FB_SHIFT_HIGH(~0UL, (dst_idx
+n
) % bits
));
202 if (dst_idx
+n
<= bits
) {
206 *dst
= comp(*dst
^ pat
, *dst
, first
);
208 /* Multiple destination words */
212 *dst
= comp(*dst
^ pat
, *dst
, first
);
214 pat
= pat
<< left
| pat
>> right
;
222 pat
= pat
<< left
| pat
>> right
;
224 pat
= pat
<< left
| pat
>> right
;
226 pat
= pat
<< left
| pat
>> right
;
228 pat
= pat
<< left
| pat
>> right
;
233 pat
= pat
<< left
| pat
>> right
;
238 *dst
= comp(*dst
^ pat
, *dst
, last
);
242 void sys_fillrect(struct fb_info
*p
, const struct fb_fillrect
*rect
)
244 unsigned long pat
, fg
;
245 unsigned long width
= rect
->width
, height
= rect
->height
;
246 int bits
= BITS_PER_LONG
, bytes
= bits
>> 3;
247 u32 bpp
= p
->var
.bits_per_pixel
;
251 if (p
->state
!= FBINFO_STATE_RUNNING
)
254 if (p
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
255 p
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
256 fg
= ((u32
*) (p
->pseudo_palette
))[rect
->color
];
260 pat
= pixel_to_pat( bpp
, fg
);
262 dst
= (unsigned long *)((unsigned long)p
->screen_base
& ~(bytes
-1));
263 dst_idx
= ((unsigned long)p
->screen_base
& (bytes
- 1))*8;
264 dst_idx
+= rect
->dy
*p
->fix
.line_length
*8+rect
->dx
*bpp
;
265 /* FIXME For now we support 1-32 bpp only */
267 if (p
->fbops
->fb_sync
)
268 p
->fbops
->fb_sync(p
);
270 void (*fill_op32
)(unsigned long *dst
, int dst_idx
,
271 unsigned long pat
, unsigned n
, int bits
) =
276 fill_op32
= bitfill_aligned_rev
;
279 fill_op32
= bitfill_aligned
;
282 printk( KERN_ERR
"cfb_fillrect(): unknown rop, "
283 "defaulting to ROP_COPY\n");
284 fill_op32
= bitfill_aligned
;
288 dst
+= dst_idx
>> (ffs(bits
) - 1);
289 dst_idx
&= (bits
- 1);
290 fill_op32(dst
, dst_idx
, pat
, width
*bpp
, bits
);
291 dst_idx
+= p
->fix
.line_length
*8;
296 int rot
= (left
-dst_idx
) % bpp
;
297 void (*fill_op
)(unsigned long *dst
, int dst_idx
,
298 unsigned long pat
, int left
, int right
,
299 unsigned n
, int bits
) = NULL
;
301 /* rotate pattern to correct start position */
302 pat
= pat
<< rot
| pat
>> (bpp
-rot
);
307 fill_op
= bitfill_unaligned_rev
;
310 fill_op
= bitfill_unaligned
;
313 printk(KERN_ERR
"cfb_fillrect(): unknown rop, "
314 "defaulting to ROP_COPY\n");
315 fill_op
= bitfill_unaligned
;
319 dst
+= dst_idx
>> (ffs(bits
) - 1);
320 dst_idx
&= (bits
- 1);
321 fill_op(dst
, dst_idx
, pat
, left
, right
,
323 r
= (p
->fix
.line_length
*8) % bpp
;
324 pat
= pat
<< (bpp
-r
) | pat
>> r
;
325 dst_idx
+= p
->fix
.line_length
*8;
330 EXPORT_SYMBOL(sys_fillrect
);
332 MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
333 MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");
334 MODULE_LICENSE("GPL");