4 * Utility routines for framebuffer interaction
6 * Copyright 2002 Russell King and Doug Lowder
8 * This file is placed under the GPL. Please see the
9 * file COPYING for details.
20 #include <sys/ioctl.h>
39 static int con_fd, fb_fd, last_vt = -1;
40 static struct fb_fix_screeninfo fix;
41 static struct fb_var_screeninfo var;
42 static unsigned char *fbuffer;
43 static unsigned char **line_addr;
45 static int bytes_per_pixel;
46 static unsigned colormap [256];
49 static char *defaultfbdevice = "/dev/fb0";
50 static char *defaultconsoledevice = "/dev/tty";
51 static char *fbdevice = NULL;
52 static char *consoledevice = NULL;
54 int open_framebuffer(void)
61 struct tssetting *tset;
62 tset = ts_setting(TS_ENV);
64 if ((fbdevice = getenv ("TSLIB_FBDEVICE")) == NULL) {
66 fbdevice = tset->fbdev;
68 fbdevice = defaultfbdevice;
72 if ((consoledevice = getenv ("TSLIB_CONSOLEDEVICE")) == NULL) {
74 consoledevice = tset->condev;
76 consoledevice = defaultconsoledevice;
80 if (strcmp (consoledevice, "none") != 0) {
81 sprintf (vtname,"%s%d", consoledevice, 1);
82 fd = open (vtname, O_WRONLY);
84 perror("open consoledevice");
88 if (ioctl(fd, VT_OPENQRY, &nr) < 0) {
89 perror("ioctl VT_OPENQRY");
94 sprintf(vtname, "%s%d", consoledevice, nr);
96 con_fd = open(vtname, O_RDWR | O_NDELAY);
102 if (ioctl(con_fd, VT_GETSTATE, &vts) == 0)
103 last_vt = vts.v_active;
105 if (ioctl(con_fd, VT_ACTIVATE, nr) < 0) {
106 perror("VT_ACTIVATE");
111 if (ioctl(con_fd, VT_WAITACTIVE, nr) < 0) {
112 perror("VT_WAITACTIVE");
117 if (ioctl(con_fd, KDSETMODE, KD_GRAPHICS) < 0) {
125 fb_fd = open(fbdevice, O_RDWR);
127 perror("open fbdevice");
131 if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fix) < 0) {
132 perror("ioctl FBIOGET_FSCREENINFO");
137 if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &var) < 0) {
138 perror("ioctl FBIOGET_VSCREENINFO");
145 fbuffer = mmap(NULL, fix.smem_len, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fb_fd, 0);
146 if (fbuffer == (unsigned char *)-1) {
147 perror("mmap framebuffer");
151 memset(fbuffer,0,fix.smem_len);
153 bytes_per_pixel = (var.bits_per_pixel + 7) / 8;
154 line_addr = malloc (sizeof (__u32) * var.yres_virtual);
156 for (y = 0; y < var.yres_virtual; y++, addr += fix.line_length)
157 line_addr [y] = fbuffer + addr;
163 void close_framebuffer(void)
165 munmap(fbuffer, fix.smem_len);
169 if(strcmp(consoledevice,"none")!=0) {
171 if (ioctl(con_fd, KDSETMODE, KD_TEXT) < 0)
175 if (ioctl(con_fd, VT_ACTIVATE, last_vt))
176 perror("VT_ACTIVATE");
184 void put_cross(int x, int y, unsigned colidx)
186 line (x - 10, y, x - 2, y, colidx);
187 line (x + 2, y, x + 10, y, colidx);
188 line (x, y - 10, x, y - 2, colidx);
189 line (x, y + 2, x, y + 10, colidx);
192 line (x - 6, y - 9, x - 9, y - 9, colidx + 1);
193 line (x - 9, y - 8, x - 9, y - 6, colidx + 1);
194 line (x - 9, y + 6, x - 9, y + 9, colidx + 1);
195 line (x - 8, y + 9, x - 6, y + 9, colidx + 1);
196 line (x + 6, y + 9, x + 9, y + 9, colidx + 1);
197 line (x + 9, y + 8, x + 9, y + 6, colidx + 1);
198 line (x + 9, y - 6, x + 9, y - 9, colidx + 1);
199 line (x + 8, y - 9, x + 6, y - 9, colidx + 1);
201 line (x - 7, y - 7, x - 4, y - 4, colidx + 1);
202 line (x - 7, y + 7, x - 4, y + 4, colidx + 1);
203 line (x + 4, y - 4, x + 7, y - 7, colidx + 1);
204 line (x + 4, y + 4, x + 7, y + 7, colidx + 1);
208 void put_char(int x, int y, int c, int colidx)
212 for (i = 0; i < font_vga_8x8.height; i++) {
213 bits = font_vga_8x8.data [font_vga_8x8.height * c + i];
214 for (j = 0; j < font_vga_8x8.width; j++, bits <<= 1)
216 pixel (x + j, y + i, colidx);
220 void put_string(int x, int y, char *s, unsigned colidx)
223 for (i = 0; *s; i++, x += font_vga_8x8.width, s++)
224 put_char (x, y, *s, colidx);
227 void put_string_center(int x, int y, char *s, unsigned colidx)
229 size_t sl = strlen (s);
230 put_string (x - (sl / 2) * font_vga_8x8.width,
231 y - font_vga_8x8.height / 2, s, colidx);
234 void setcolor(unsigned colidx, unsigned value)
237 unsigned short red, green, blue;
242 fprintf (stderr, "WARNING: color index = %u, must be <256\n",
248 switch (bytes_per_pixel) {
252 red = (value >> 8) & 0xff00;
253 green = value & 0xff00;
254 blue = (value << 8) & 0xff00;
262 if (ioctl (fb_fd, FBIOPUTCMAP, &cmap) < 0)
263 perror("ioctl FBIOPUTCMAP");
267 red = (value >> 16) & 0xff;
268 green = (value >> 8) & 0xff;
270 res = ((red >> (8 - var.red.length)) << var.red.offset) |
271 ((green >> (8 - var.green.length)) << var.green.offset) |
272 ((blue >> (8 - var.blue.length)) << var.blue.offset);
274 colormap [colidx] = res;
277 static inline void __setpixel (union multiptr loc, unsigned xormode, unsigned color)
279 switch(bytes_per_pixel) {
302 void pixel (int x, int y, unsigned colidx)
307 if ((x < 0) || ((__u32)x >= var.xres_virtual) ||
308 (y < 0) || ((__u32)y >= var.yres_virtual))
311 xormode = colidx & XORMODE;
316 fprintf (stderr, "WARNING: color value = %u, must be <256\n",
322 loc.p8 = line_addr [y] + x * bytes_per_pixel;
323 __setpixel (loc, xormode, colormap [colidx]);
326 void line (int x1, int y1, int x2, int y2, unsigned colidx)
332 if (abs (dx) < abs (dy)) {
334 tmp = x1; x1 = x2; x2 = tmp;
335 tmp = y1; y1 = y2; y2 = tmp;
339 /* dy is apriori >0 */
340 dx = (dx << 16) / dy;
342 pixel (x1 >> 16, y1, colidx);
348 tmp = x1; x1 = x2; x2 = tmp;
349 tmp = y1; y1 = y2; y2 = tmp;
353 dy = dx ? (dy << 16) / dx : 0;
355 pixel (x1, y1 >> 16, colidx);
362 void rect (int x1, int y1, int x2, int y2, unsigned colidx)
364 line (x1, y1, x2, y1, colidx);
365 line (x2, y1, x2, y2, colidx);
366 line (x2, y2, x1, y2, colidx);
367 line (x1, y2, x1, y1, colidx);
370 void fillrect (int x1, int y1, int x2, int y2, unsigned colidx)
376 /* Clipping and sanity checking */
377 if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; }
378 if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; }
379 if (x1 < 0) x1 = 0; if ((__u32)x1 >= xres) x1 = xres - 1;
380 if (x2 < 0) x2 = 0; if ((__u32)x2 >= xres) x2 = xres - 1;
381 if (y1 < 0) y1 = 0; if ((__u32)y1 >= yres) y1 = yres - 1;
382 if (y2 < 0) y2 = 0; if ((__u32)y2 >= yres) y2 = yres - 1;
384 if ((x1 > x2) || (y1 > y2))
387 xormode = colidx & XORMODE;
392 fprintf (stderr, "WARNING: color value = %u, must be <256\n",
398 colidx = colormap [colidx];
400 for (; y1 <= y2; y1++) {
401 loc.p8 = line_addr [y1] + x1 * bytes_per_pixel;
402 for (tmp = x1; tmp <= x2; tmp++) {
403 __setpixel (loc, xormode, colidx);
404 loc.p8 += bytes_per_pixel;