return if invalid page number is given to showpage
[fbpdf.git] / draw.c
blobab1c90e5f3eddce193f204b83287f80c614805f2
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 FBDEV_PATH "/dev/fb0"
12 #define MAXWIDTH (1 << 12)
13 #define BPP sizeof(fbval_t)
14 #define NLEVELS (1 << 8)
15 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
17 static void xerror(char *msg)
19 perror(msg);
20 exit(1);
23 static int fd;
24 static unsigned char *fb;
25 static struct fb_var_screeninfo vinfo;
26 static struct fb_fix_screeninfo finfo;
28 static int fb_len()
30 return vinfo.xres_virtual * vinfo.yres_virtual * BPP;
33 static void fb_cmap_save(int save)
35 static unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS];
36 struct fb_cmap cmap;
37 int mr = 1 << vinfo.red.length;
38 int mg = 1 << vinfo.green.length;
39 int mb = 1 << vinfo.blue.length;
40 if (finfo.visual == FB_VISUAL_TRUECOLOR)
41 return;
42 cmap.start = 0;
43 cmap.len = MAX(mr, MAX(mg, mb));
44 cmap.red = red;
45 cmap.green = green;
46 cmap.blue = blue;
47 cmap.transp = 0;
48 if (save)
49 ioctl(fd, FBIOGETCMAP, &cmap);
50 else
51 ioctl(fd, FBIOPUTCMAP, &cmap);
54 void fb_cmap(void)
56 unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS];
57 struct fb_cmap cmap;
58 int mr = 1 << vinfo.red.length;
59 int mg = 1 << vinfo.green.length;
60 int mb = 1 << vinfo.blue.length;
61 int i;
62 if (finfo.visual == FB_VISUAL_TRUECOLOR)
63 return;
65 for (i = 0; i < mr; i++)
66 red[i] = (65535 / (mr - 1)) * i;
67 for (i = 0; i < mg; i++)
68 green[i] = (65535 / (mg - 1)) * i;
69 for (i = 0; i < mb; i++)
70 blue[i] = (65535 / (mb - 1)) * i;
72 cmap.start = 0;
73 cmap.len = MAX(mr, MAX(mg, mb));
74 cmap.red = red;
75 cmap.green = green;
76 cmap.blue = blue;
77 cmap.transp = 0;
79 ioctl(fd, FBIOPUTCMAP, &cmap);
82 static void xdie(char *msg)
84 fprintf(stderr, "%s\n", msg);
85 exit(1);
88 void fb_init(void)
90 fd = open(FBDEV_PATH, O_RDWR);
91 if (fd == -1)
92 xerror("can't open " FBDEV_PATH);
93 if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1)
94 xerror("ioctl failed");
95 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
96 xerror("ioctl failed");
97 if ((vinfo.bits_per_pixel + 7) >> 3 != BPP)
98 xdie("fbval_t does not match framebuffer depth");
99 fb = mmap(NULL, fb_len(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
100 if (fb == MAP_FAILED)
101 xerror("can't map the framebuffer");
102 fb_cmap_save(1);
103 fb_cmap();
106 void fb_set(int r, int c, fbval_t *mem, int len)
108 long loc = (c + vinfo.xoffset) * BPP +
109 (r + vinfo.yoffset) * finfo.line_length;
110 memcpy(fb + loc, mem, len * BPP);
113 void fb_free()
115 fb_cmap_save(0);
116 munmap(fb, fb_len());
117 close(fd);
120 static fbval_t color_bits(struct fb_bitfield *bf, fbval_t v)
122 fbval_t moved = v >> (8 - bf->length);
123 return moved << bf->offset;
126 fbval_t fb_color(unsigned char r, unsigned char g, unsigned char b)
128 return color_bits(&vinfo.red, r) |
129 color_bits(&vinfo.green, g) |
130 color_bits(&vinfo.blue, b);
133 int fb_rows(void)
135 return vinfo.yres;
138 int fb_cols(void)
140 return vinfo.xres;
143 static unsigned char *rowaddr(int r)
145 return fb + (r + vinfo.yoffset) * finfo.line_length;
148 static unsigned long cache[MAXWIDTH];
149 void fb_box(int sr, int sc, int er, int ec, fbval_t val)
151 int i;
152 int pc = sizeof(cache[0]) / sizeof(val);
153 int cn = MIN((ec - sc) / pc + 1, ARRAY_SIZE(cache));
154 unsigned long nv = val;
155 for (i = 1; i < pc; i++)
156 nv = (nv << (sizeof(val) * 8)) | val;
157 for (i = 0; i < cn; i++)
158 cache[i] = nv;
159 for (i = sr; i < er; i++)
160 memcpy(rowaddr(i) + sc * BPP, cache, (ec - sc) * BPP);