term: enable switching signals using the second argument of term_exec()
[fbpad.git] / draw.c
blobb9890fc23cbaa8387e8c0609cda49e28aefdd0b5
1 #include <fcntl.h>
2 #include <linux/fb.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sys/ioctl.h>
7 #include <sys/mman.h>
8 #include <unistd.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 struct fb_var_screeninfo vinfo; /* linux-specific FB structure */
16 static struct fb_fix_screeninfo finfo; /* linux-specific FB structure */
17 static char fbdev[1024]; /* FB device */
18 static int fd; /* FB device file descriptor */
19 static void *fb; /* mmap()ed FB memory */
20 static int bpp; /* bytes per pixel */
21 static int nr, ng, nb; /* color levels */
22 static int rl, rr, gl, gr, bl, br; /* shifts per color */
23 static int xres, yres, xoff, yoff; /* drawing region */
25 static int fb_len(void)
27 return finfo.line_length * vinfo.yres_virtual;
30 static void fb_cmap_save(int save)
32 static unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS];
33 struct fb_cmap cmap;
34 if (finfo.visual == FB_VISUAL_TRUECOLOR)
35 return;
36 cmap.start = 0;
37 cmap.len = MAX(nr, MAX(ng, nb));
38 cmap.red = red;
39 cmap.green = green;
40 cmap.blue = blue;
41 cmap.transp = NULL;
42 ioctl(fd, save ? FBIOGETCMAP : FBIOPUTCMAP, &cmap);
45 void fb_cmap(void)
47 unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS];
48 struct fb_cmap cmap;
49 int i;
50 if (finfo.visual == FB_VISUAL_TRUECOLOR)
51 return;
53 for (i = 0; i < nr; i++)
54 red[i] = (65535 / (nr - 1)) * i;
55 for (i = 0; i < ng; i++)
56 green[i] = (65535 / (ng - 1)) * i;
57 for (i = 0; i < nb; i++)
58 blue[i] = (65535 / (nb - 1)) * i;
60 cmap.start = 0;
61 cmap.len = MAX(nr, MAX(ng, nb));
62 cmap.red = red;
63 cmap.green = green;
64 cmap.blue = blue;
65 cmap.transp = NULL;
67 ioctl(fd, FBIOPUTCMAP, &cmap);
70 unsigned fb_mode(void)
72 return ((rl < gl) << 22) | ((rl < bl) << 21) | ((gl < bl) << 20) |
73 (bpp << 16) | (vinfo.red.length << 8) |
74 (vinfo.green.length << 4) | (vinfo.blue.length);
77 static void init_colors(void)
79 nr = 1 << vinfo.red.length;
80 ng = 1 << vinfo.blue.length;
81 nb = 1 << vinfo.green.length;
82 rr = 8 - vinfo.red.length;
83 rl = vinfo.red.offset;
84 gr = 8 - vinfo.green.length;
85 gl = vinfo.green.offset;
86 br = 8 - vinfo.blue.length;
87 bl = vinfo.blue.offset;
90 int fb_init(char *dev)
92 char *path = dev ? dev : FBDEV;
93 char *geom = dev ? strchr(dev, ':') : NULL;
94 if (geom) {
95 *geom = '\0';
96 sscanf(geom + 1, "%dx%d%d%d", &xres, &yres, &xoff, &yoff);
98 snprintf(fbdev, sizeof(fbdev), "%s", path);
99 fd = open(path, O_RDWR);
100 if (fd < 0)
101 goto failed;
102 if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0)
103 goto failed;
104 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) < 0)
105 goto failed;
106 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
107 bpp = (vinfo.bits_per_pixel + 7) >> 3;
108 fb = mmap(NULL, fb_len(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
109 if (fb == MAP_FAILED)
110 goto failed;
111 init_colors();
112 fb_cmap_save(1);
113 fb_cmap();
114 return 0;
115 failed:
116 perror("fb_init()");
117 close(fd);
118 return 1;
121 void fb_free(void)
123 fb_cmap_save(0);
124 munmap(fb, fb_len());
125 close(fd);
128 int fb_rows(void)
130 return yres ? yres : vinfo.yres;
133 int fb_cols(void)
135 return xres ? xres : vinfo.xres;
138 void *fb_mem(int r)
140 return fb + (r + vinfo.yoffset + yoff) * finfo.line_length + (vinfo.xoffset + xoff) * bpp;
143 unsigned fb_val(int r, int g, int b)
145 return ((r >> rr) << rl) | ((g >> gr) << gl) | ((b >> br) << bl);
148 char *fb_dev(void)
150 return fbdev;