term: introduce candraw() to handle lazy and invisible updates
[fbpad.git] / draw.c
blob15e61a7e2ece0dec9d2b9276fa503945e624f2a8
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"
11 #define MIN(a, b) ((a) < (b) ? (a) : (b))
12 #define MAX(a, b) ((a) > (b) ? (a) : (b))
13 #define NLEVELS (1 << 8)
15 static int fd;
16 static void *fb;
17 static struct fb_var_screeninfo vinfo;
18 static struct fb_fix_screeninfo finfo;
19 static int bpp;
20 static int nr, ng, nb;
21 static int rl, rr, gl, gr, bl, br; /* fb_color() shifts */
23 static int fb_len(void)
25 return finfo.line_length * vinfo.yres_virtual;
28 static void fb_cmap_save(int save)
30 static unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS];
31 struct fb_cmap cmap;
32 if (finfo.visual == FB_VISUAL_TRUECOLOR)
33 return;
34 cmap.start = 0;
35 cmap.len = MAX(nr, MAX(ng, nb));
36 cmap.red = red;
37 cmap.green = green;
38 cmap.blue = blue;
39 cmap.transp = NULL;
40 ioctl(fd, save ? FBIOGETCMAP : FBIOPUTCMAP, &cmap);
43 void fb_cmap(void)
45 unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS];
46 struct fb_cmap cmap;
47 int i;
48 if (finfo.visual == FB_VISUAL_TRUECOLOR)
49 return;
51 for (i = 0; i < nr; i++)
52 red[i] = (65535 / (nr - 1)) * i;
53 for (i = 0; i < ng; i++)
54 green[i] = (65535 / (ng - 1)) * i;
55 for (i = 0; i < nb; i++)
56 blue[i] = (65535 / (nb - 1)) * i;
58 cmap.start = 0;
59 cmap.len = MAX(nr, MAX(ng, nb));
60 cmap.red = red;
61 cmap.green = green;
62 cmap.blue = blue;
63 cmap.transp = NULL;
65 ioctl(fd, FBIOPUTCMAP, &cmap);
68 unsigned fb_mode(void)
70 return (bpp << 16) | (vinfo.red.length << 8) |
71 (vinfo.green.length << 4) | (vinfo.blue.length);
74 static void init_colors(void)
76 nr = 1 << vinfo.red.length;
77 ng = 1 << vinfo.blue.length;
78 nb = 1 << vinfo.green.length;
79 rr = 8 - vinfo.red.length;
80 rl = vinfo.red.offset;
81 gr = 8 - vinfo.green.length;
82 gl = vinfo.green.offset;
83 br = 8 - vinfo.blue.length;
84 bl = vinfo.blue.offset;
87 int fb_init(void)
89 fd = open(FBDEV_PATH, O_RDWR);
90 if (fd == -1)
91 goto failed;
92 if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1)
93 goto failed;
94 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
95 goto failed;
96 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
97 bpp = (vinfo.bits_per_pixel + 7) >> 3;
98 fb = mmap(NULL, fb_len(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
99 if (fb == MAP_FAILED)
100 goto failed;
101 init_colors();
102 fb_cmap_save(1);
103 fb_cmap();
104 return 0;
105 failed:
106 perror("fb_init()");
107 close(fd);
108 return 1;
111 void fb_free(void)
113 fb_cmap_save(0);
114 munmap(fb, fb_len());
115 close(fd);
118 int fb_rows(void)
120 return vinfo.yres;
123 int fb_cols(void)
125 return vinfo.xres;
128 void *fb_mem(int r)
130 return fb + (r + vinfo.yoffset) * finfo.line_length;
133 void fb_set(int r, int c, void *mem, int len)
135 memcpy(fb_mem(r) + (c + vinfo.xoffset) * bpp, mem, len * bpp);
138 unsigned fb_val(int r, int g, int b)
140 return ((r >> rr) << rl) | ((g >> gr) << gl) | ((b >> br) << bl);