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(struct fb_info
*p
, unsigned long *dst
, int dst_idx
,
26 unsigned long pat
, unsigned n
, int bits
)
28 unsigned long first
, last
;
33 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
34 last
= ~(FB_SHIFT_HIGH(p
, ~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(struct fb_info
*p
, unsigned long *dst
, int dst_idx
,
82 unsigned long pat
, int left
, int right
, unsigned n
, int bits
)
84 unsigned long first
, last
;
89 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
90 last
= ~(FB_SHIFT_HIGH(p
, ~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(struct fb_info
*p
, unsigned long *dst
, int dst_idx
,
136 unsigned long pat
, unsigned n
, int bits
)
138 unsigned long val
= pat
;
139 unsigned long first
, last
;
144 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
145 last
= ~(FB_SHIFT_HIGH(p
, ~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(struct fb_info
*p
, unsigned long *dst
, int dst_idx
,
192 unsigned long pat
, int left
, int right
, unsigned n
,
195 unsigned long first
, last
;
200 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
201 last
= ~(FB_SHIFT_HIGH(p
, ~0UL, (dst_idx
+n
) % bits
));
203 if (dst_idx
+n
<= bits
) {
207 *dst
= comp(*dst
^ pat
, *dst
, first
);
209 /* Multiple destination words */
213 *dst
= comp(*dst
^ pat
, *dst
, first
);
215 pat
= pat
<< left
| pat
>> right
;
223 pat
= pat
<< left
| pat
>> right
;
225 pat
= pat
<< left
| pat
>> right
;
227 pat
= pat
<< left
| pat
>> right
;
229 pat
= pat
<< left
| pat
>> right
;
234 pat
= pat
<< left
| pat
>> right
;
239 *dst
= comp(*dst
^ pat
, *dst
, last
);
243 void sys_fillrect(struct fb_info
*p
, const struct fb_fillrect
*rect
)
245 unsigned long pat
, 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
;
252 if (p
->state
!= FBINFO_STATE_RUNNING
)
255 if (p
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
256 p
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
257 fg
= ((u32
*) (p
->pseudo_palette
))[rect
->color
];
261 pat
= pixel_to_pat( bpp
, fg
);
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 /* FIXME For now we support 1-32 bpp only */
268 if (p
->fbops
->fb_sync
)
269 p
->fbops
->fb_sync(p
);
271 void (*fill_op32
)(struct fb_info
*p
, unsigned long *dst
,
272 int dst_idx
, unsigned long pat
, unsigned n
,
277 fill_op32
= bitfill_aligned_rev
;
280 fill_op32
= bitfill_aligned
;
283 printk( KERN_ERR
"cfb_fillrect(): unknown rop, "
284 "defaulting to ROP_COPY\n");
285 fill_op32
= bitfill_aligned
;
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;
297 int rot
= (left
-dst_idx
) % bpp
;
298 void (*fill_op
)(struct fb_info
*p
, unsigned long *dst
,
299 int dst_idx
, unsigned long pat
, int left
,
300 int right
, unsigned n
, int bits
) = NULL
;
302 /* rotate pattern to correct start position */
303 pat
= pat
<< rot
| pat
>> (bpp
-rot
);
308 fill_op
= bitfill_unaligned_rev
;
311 fill_op
= bitfill_unaligned
;
314 printk(KERN_ERR
"cfb_fillrect(): unknown rop, "
315 "defaulting to ROP_COPY\n");
316 fill_op
= bitfill_unaligned
;
320 dst
+= dst_idx
>> (ffs(bits
) - 1);
321 dst_idx
&= (bits
- 1);
322 fill_op(p
, dst
, dst_idx
, pat
, left
, right
,
324 r
= (p
->fix
.line_length
*8) % bpp
;
325 pat
= pat
<< (bpp
-r
) | pat
>> r
;
326 dst_idx
+= p
->fix
.line_length
*8;
331 EXPORT_SYMBOL(sys_fillrect
);
333 MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
334 MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");
335 MODULE_LICENSE("GPL");