1 | /* |
2 | * linux/drivers/video/console/softcursor.c |
3 | * |
4 | * Generic software cursor for frame buffer devices |
5 | * |
6 | * Created 14 Nov 2002 by James Simmons |
7 | * |
8 | * This file is subject to the terms and conditions of the GNU General |
9 | * Public License. See the file COPYING in the main directory of this |
10 | * archive for more details. |
11 | */ |
12 | |
13 | #include <linux/module.h> |
14 | #include <linux/string.h> |
15 | #include <linux/fb.h> |
16 | #include <linux/slab.h> |
17 | |
18 | #include <asm/io.h> |
19 | |
20 | #include "fbcon.h" |
21 | |
22 | int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) |
23 | { |
24 | struct fbcon_ops *ops = info->fbcon_par; |
25 | unsigned int scan_align = info->pixmap.scan_align - 1; |
26 | unsigned int buf_align = info->pixmap.buf_align - 1; |
27 | unsigned int i, size, dsize, s_pitch, d_pitch; |
28 | struct fb_image *image; |
29 | u8 *src, *dst; |
30 | |
31 | if (info->state != FBINFO_STATE_RUNNING) |
32 | return 0; |
33 | |
34 | s_pitch = (cursor->image.width + 7) >> 3; |
35 | dsize = s_pitch * cursor->image.height; |
36 | |
37 | if (dsize + sizeof(struct fb_image) != ops->cursor_size) { |
38 | kfree(objp: ops->cursor_src); |
39 | ops->cursor_size = dsize + sizeof(struct fb_image); |
40 | |
41 | ops->cursor_src = kmalloc(size: ops->cursor_size, GFP_ATOMIC); |
42 | if (!ops->cursor_src) { |
43 | ops->cursor_size = 0; |
44 | return -ENOMEM; |
45 | } |
46 | } |
47 | |
48 | src = ops->cursor_src + sizeof(struct fb_image); |
49 | image = (struct fb_image *)ops->cursor_src; |
50 | *image = cursor->image; |
51 | d_pitch = (s_pitch + scan_align) & ~scan_align; |
52 | |
53 | size = d_pitch * image->height + buf_align; |
54 | size &= ~buf_align; |
55 | dst = fb_get_buffer_offset(info, buf: &info->pixmap, size); |
56 | |
57 | if (cursor->enable) { |
58 | switch (cursor->rop) { |
59 | case ROP_XOR: |
60 | for (i = 0; i < dsize; i++) |
61 | src[i] = image->data[i] ^ cursor->mask[i]; |
62 | break; |
63 | case ROP_COPY: |
64 | default: |
65 | for (i = 0; i < dsize; i++) |
66 | src[i] = image->data[i] & cursor->mask[i]; |
67 | break; |
68 | } |
69 | } else |
70 | memcpy(src, image->data, dsize); |
71 | |
72 | fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height: image->height); |
73 | image->data = dst; |
74 | info->fbops->fb_imageblit(info, image); |
75 | return 0; |
76 | } |
77 | |