draw: fix computing cmap colors
[fbpad.git] / draw.c
blob8f75c3322115ab1e50e0f864994549d2b8e79b41
1 #include <fcntl.h>
2 #include <linux/fb.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <sys/ioctl.h>
6 #include <sys/mman.h>
7 #include <unistd.h>
8 #include <string.h>
9 #include "draw.h"
10 #include "util.h"
12 #define FBDEV_PATH "/dev/fb0"
13 #define BPP sizeof(fbval_t)
15 static int fd;
16 static unsigned char *fb;
17 static struct fb_var_screeninfo vinfo;
18 static struct fb_fix_screeninfo finfo;
20 static int fb_len()
22 return vinfo.xres_virtual * vinfo.yres_virtual * BPP;
25 #define NLEVELS 1 << 8
26 void fb_cmap(void)
28 unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS];
29 struct fb_cmap cmap;
30 int mr = 1 << vinfo.red.length;
31 int mg = 1 << vinfo.green.length;
32 int mb = 1 << vinfo.blue.length;
33 int i;
34 if (finfo.visual == FB_VISUAL_TRUECOLOR)
35 return;
37 for (i = 0; i < mr; i++)
38 red[i] = (65535 / (mr - 1)) * i;
39 for (i = 0; i < mg; i++)
40 green[i] = (65535 / (mg - 1)) * i;
41 for (i = 0; i < mb; i++)
42 blue[i] = (65535 / (mb - 1)) * i;
44 cmap.start = 0;
45 cmap.len = MAX(mr, MAX(mg, mb));
46 cmap.red = red;
47 cmap.green = green;
48 cmap.blue = blue;
49 cmap.transp = 0;
51 ioctl(fd, FBIOPUTCMAP, &cmap);
54 void fb_init(void)
56 fd = open(FBDEV_PATH, O_RDWR);
57 if (fd == -1)
58 xerror("can't open " FBDEV_PATH);
59 if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1)
60 xerror("ioctl failed");
61 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
62 xerror("ioctl failed");
63 fb = mmap(NULL, fb_len(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
64 if (fb == MAP_FAILED)
65 xerror("can't map the framebuffer");
66 fb_cmap();
69 void fb_put(int r, int c, fbval_t val)
71 long loc = (c + vinfo.xoffset) * BPP +
72 (r + vinfo.yoffset) * finfo.line_length;
73 memcpy(fb + loc, &val, BPP);
76 void fb_free()
78 munmap(fb, fb_len());
79 close(fd);
82 static fbval_t color_bits(struct fb_bitfield *bf, fbval_t v)
84 fbval_t moved = v >> (8 - bf->length);
85 return moved << bf->offset;
88 fbval_t fb_color(unsigned char r, unsigned char g, unsigned char b)
90 return color_bits(&vinfo.red, r) |
91 color_bits(&vinfo.green, g) |
92 color_bits(&vinfo.blue, b);
95 int fb_rows(void)
97 return vinfo.yres_virtual;
100 int fb_cols(void)
102 return vinfo.xres_virtual;
105 void fb_box(int sr, int sc, int er, int ec, fbval_t val)
107 int r, c;
108 for (r = sr; r < er; r++)
109 for (c = sc; c < ec; c++)
110 fb_put(r, c, val);
113 static unsigned char *rowaddr(int r)
115 return fb + (r + vinfo.yoffset) * finfo.line_length;
118 void fb_scroll(int sr, int nr, int n, fbval_t val)
120 memmove(rowaddr(sr + n), rowaddr(sr), nr * finfo.line_length);
121 if (n > 0)
122 fb_box(sr, 0, sr + n, fb_cols(), val);
123 else
124 fb_box(sr + nr + n, 0, sr + nr, fb_cols(), val);