term: clear the screen when nothing to show
[fbpad.git] / draw.c
blob8df83bb47eeb1d35018d01ca507faf9d10262bd0
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 MAXWIDTH (1 << 12)
14 #define BPP sizeof(fbval_t)
16 static int fd;
17 static unsigned char *fb;
18 static struct fb_var_screeninfo vinfo;
19 static struct fb_fix_screeninfo finfo;
21 static int fb_len()
23 return vinfo.xres_virtual * vinfo.yres_virtual * BPP;
26 #define NLEVELS 1 << 8
27 void fb_cmap(void)
29 unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS];
30 struct fb_cmap cmap;
31 int mr = 1 << vinfo.red.length;
32 int mg = 1 << vinfo.green.length;
33 int mb = 1 << vinfo.blue.length;
34 int i;
35 if (finfo.visual == FB_VISUAL_TRUECOLOR)
36 return;
38 for (i = 0; i < mr; i++)
39 red[i] = (65535 / (mr - 1)) * i;
40 for (i = 0; i < mg; i++)
41 green[i] = (65535 / (mg - 1)) * i;
42 for (i = 0; i < mb; i++)
43 blue[i] = (65535 / (mb - 1)) * i;
45 cmap.start = 0;
46 cmap.len = MAX(mr, MAX(mg, mb));
47 cmap.red = red;
48 cmap.green = green;
49 cmap.blue = blue;
50 cmap.transp = 0;
52 ioctl(fd, FBIOPUTCMAP, &cmap);
55 void fb_init(void)
57 fd = open(FBDEV_PATH, O_RDWR);
58 if (fd == -1)
59 xerror("can't open " FBDEV_PATH);
60 if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1)
61 xerror("ioctl failed");
62 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
63 xerror("ioctl failed");
64 fb = mmap(NULL, fb_len(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
65 if (fb == MAP_FAILED)
66 xerror("can't map the framebuffer");
67 fb_cmap();
70 void fb_set(int r, int c, fbval_t *mem, int len)
72 long loc = (c + vinfo.xoffset) * BPP +
73 (r + vinfo.yoffset) * finfo.line_length;
74 memcpy(fb + loc, mem, len * BPP);
77 void fb_free()
79 munmap(fb, fb_len());
80 close(fd);
83 static fbval_t color_bits(struct fb_bitfield *bf, fbval_t v)
85 fbval_t moved = v >> (8 - bf->length);
86 return moved << bf->offset;
89 fbval_t fb_color(unsigned char r, unsigned char g, unsigned char b)
91 return color_bits(&vinfo.red, r) |
92 color_bits(&vinfo.green, g) |
93 color_bits(&vinfo.blue, b);
96 int fb_rows(void)
98 return vinfo.yres;
101 int fb_cols(void)
103 return vinfo.xres;
106 #define FBIOFILLRECT 0x4619
107 #define FBIOCOPYAREA 0x461A
109 void fb_box(int sr, int sc, int er, int ec, fbval_t val)
111 struct fb_fillrect fillrect;
112 fillrect.dy = sr;
113 fillrect.dx = sc;
114 fillrect.height = er - sr;
115 fillrect.width = ec - sc;
116 fillrect.color = val;
117 fillrect.rop = ROP_COPY;
118 if (ioctl(fd, FBIOFILLRECT, &fillrect) == -1)
119 xerror("fillrect failed");
122 void fb_scroll(int sr, int nr, int n, fbval_t val)
124 struct fb_copyarea copyarea;
125 copyarea.dy = sr + n;
126 copyarea.dx = 0;
127 copyarea.sy = sr;
128 copyarea.sx = 0;
129 copyarea.height = nr;
130 copyarea.width = fb_cols();
131 if (ioctl(fd, FBIOCOPYAREA, &copyarea) == -1)
132 xerror("copyarea failed");
133 if (n > 0)
134 fb_box(sr, 0, sr + n, fb_cols(), val);
135 else
136 fb_box(sr + nr + n, 0, sr + nr, fb_cols(), val);
140 static unsigned char *rowaddr(int r)
142 return fb + (r + vinfo.yoffset) * finfo.line_length;
145 static unsigned long cache[MAXWIDTH];
146 void fb_box(int sr, int sc, int er, int ec, fbval_t val)
148 int i;
149 int pc = sizeof(cache[0]) / sizeof(val);
150 int cn = MIN((ec - sc) / pc + 1, ARRAY_SIZE(cache));
151 unsigned long nv = val;
152 for (i = 1; i < pc; i++)
153 nv = (nv << (sizeof(val) * 8)) | val;
154 for (i = 0; i < cn; i++)
155 cache[i] = nv;
156 for (i = sr; i < er; i++)
157 memcpy(rowaddr(i) + sc * BPP, cache, (ec - sc) * BPP);
160 void fb_scroll(int sr, int nr, int n, fbval_t val)
162 memmove(rowaddr(sr + n), rowaddr(sr), nr * finfo.line_length);
163 if (n > 0)
164 fb_box(sr, 0, sr + n, fb_cols(), val);
165 else
166 fb_box(sr + nr + n, 0, sr + nr, fb_cols(), val);