Hardware Design: SIE
Sign in or create your account | Project List | Help
Hardware Design: SIE Git Source Tree
Root/
| 1 | /* |
| 2 | * fbutils.c |
| 3 | * |
| 4 | * Utility routines for framebuffer interaction |
| 5 | * |
| 6 | * Copyright 2002 Russell King and Doug Lowder |
| 7 | * |
| 8 | * This file is placed under the GPL. Please see the |
| 9 | * file COPYING for details. |
| 10 | * |
| 11 | */ |
| 12 | |
| 13 | #include <stdio.h> |
| 14 | #include <stdlib.h> |
| 15 | #include <string.h> |
| 16 | #include <unistd.h> |
| 17 | #include <sys/fcntl.h> |
| 18 | #include <sys/ioctl.h> |
| 19 | #include <sys/mman.h> |
| 20 | #include <sys/time.h> |
| 21 | |
| 22 | #include <linux/vt.h> |
| 23 | #include <linux/kd.h> |
| 24 | #include <linux/fb.h> |
| 25 | |
| 26 | #include "font.h" |
| 27 | #include "fbutils.h" |
| 28 | |
| 29 | union multiptr { |
| 30 | unsigned char *p8; |
| 31 | unsigned short *p16; |
| 32 | unsigned long *p32; |
| 33 | }; |
| 34 | |
| 35 | static int con_fd, last_vt = -1; |
| 36 | static struct fb_fix_screeninfo fix; |
| 37 | static struct fb_var_screeninfo var; |
| 38 | static unsigned char *fbuffer; |
| 39 | static unsigned char **line_addr; |
| 40 | static int fb_fd=0; |
| 41 | static int bytes_per_pixel; |
| 42 | static unsigned colormap [256]; |
| 43 | __u32 xres, yres; |
| 44 | |
| 45 | static char *defaultfbdevice = "/dev/fb0"; |
| 46 | static char *defaultconsoledevice = "/dev/tty"; |
| 47 | static char *fbdevice = NULL; |
| 48 | static char *consoledevice = NULL; |
| 49 | |
| 50 | int open_framebuffer(void) |
| 51 | { |
| 52 | struct vt_stat vts; |
| 53 | char vtname[128]; |
| 54 | int fd, nr; |
| 55 | unsigned y, addr; |
| 56 | |
| 57 | if ((fbdevice = getenv ("TSLIB_FBDEVICE")) == NULL) |
| 58 | fbdevice = defaultfbdevice; |
| 59 | |
| 60 | if ((consoledevice = getenv ("TSLIB_CONSOLEDEVICE")) == NULL) |
| 61 | consoledevice = defaultconsoledevice; |
| 62 | |
| 63 | if (strcmp (consoledevice, "none") != 0) { |
| 64 | sprintf (vtname,"%s%d", consoledevice, 1); |
| 65 | fd = open (vtname, O_WRONLY); |
| 66 | if (fd < 0) { |
| 67 | perror("open consoledevice"); |
| 68 | return -1; |
| 69 | } |
| 70 | |
| 71 | if (ioctl(fd, VT_OPENQRY, &nr) < 0) { |
| 72 | perror("ioctl VT_OPENQRY"); |
| 73 | return -1; |
| 74 | } |
| 75 | close(fd); |
| 76 | |
| 77 | sprintf(vtname, "%s%d", consoledevice, nr); |
| 78 | |
| 79 | con_fd = open(vtname, O_RDWR | O_NDELAY); |
| 80 | if (con_fd < 0) { |
| 81 | perror("open tty"); |
| 82 | return -1; |
| 83 | } |
| 84 | |
| 85 | if (ioctl(con_fd, VT_GETSTATE, &vts) == 0) |
| 86 | last_vt = vts.v_active; |
| 87 | |
| 88 | if (ioctl(con_fd, VT_ACTIVATE, nr) < 0) { |
| 89 | perror("VT_ACTIVATE"); |
| 90 | close(con_fd); |
| 91 | return -1; |
| 92 | } |
| 93 | |
| 94 | if (ioctl(con_fd, VT_WAITACTIVE, nr) < 0) { |
| 95 | perror("VT_WAITACTIVE"); |
| 96 | close(con_fd); |
| 97 | return -1; |
| 98 | } |
| 99 | |
| 100 | if (ioctl(con_fd, KDSETMODE, KD_GRAPHICS) < 0) { |
| 101 | perror("KDSETMODE"); |
| 102 | close(con_fd); |
| 103 | return -1; |
| 104 | } |
| 105 | |
| 106 | } |
| 107 | |
| 108 | fb_fd = open(fbdevice, O_RDWR); |
| 109 | if (fb_fd == -1) { |
| 110 | perror("open fbdevice"); |
| 111 | return -1; |
| 112 | } |
| 113 | |
| 114 | if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fix) < 0) { |
| 115 | perror("ioctl FBIOGET_FSCREENINFO"); |
| 116 | close(fb_fd); |
| 117 | return -1; |
| 118 | } |
| 119 | |
| 120 | if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &var) < 0) { |
| 121 | perror("ioctl FBIOGET_VSCREENINFO"); |
| 122 | close(fb_fd); |
| 123 | return -1; |
| 124 | } |
| 125 | xres = var.xres; |
| 126 | yres = var.yres; |
| 127 | |
| 128 | fbuffer = mmap(NULL, fix.smem_len, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fb_fd, 0); |
| 129 | if (fbuffer == (unsigned char *)-1) { |
| 130 | perror("mmap framebuffer"); |
| 131 | close(fb_fd); |
| 132 | return -1; |
| 133 | } |
| 134 | memset(fbuffer,0,fix.smem_len); |
| 135 | |
| 136 | bytes_per_pixel = (var.bits_per_pixel + 7) / 8; |
| 137 | line_addr = malloc (sizeof (__u32) * var.yres_virtual); |
| 138 | addr = 0; |
| 139 | for (y = 0; y < var.yres_virtual; y++, addr += fix.line_length) |
| 140 | line_addr [y] = fbuffer + addr; |
| 141 | |
| 142 | return 0; |
| 143 | } |
| 144 | |
| 145 | void close_framebuffer(void) |
| 146 | { |
| 147 | munmap(fbuffer, fix.smem_len); |
| 148 | close(fb_fd); |
| 149 | |
| 150 | |
| 151 | if(strcmp(consoledevice,"none")!=0) { |
| 152 | |
| 153 | if (ioctl(con_fd, KDSETMODE, KD_TEXT) < 0) |
| 154 | perror("KDSETMODE"); |
| 155 | |
| 156 | if (last_vt >= 0) |
| 157 | if (ioctl(con_fd, VT_ACTIVATE, last_vt)) |
| 158 | perror("VT_ACTIVATE"); |
| 159 | |
| 160 | close(con_fd); |
| 161 | } |
| 162 | |
| 163 | free (line_addr); |
| 164 | } |
| 165 | |
| 166 | void put_cross(int x, int y, unsigned colidx) |
| 167 | { |
| 168 | line (x - 10, y, x - 2, y, colidx); |
| 169 | line (x + 2, y, x + 10, y, colidx); |
| 170 | line (x, y - 10, x, y - 2, colidx); |
| 171 | line (x, y + 2, x, y + 10, colidx); |
| 172 | |
| 173 | #if 1 |
| 174 | line (x - 6, y - 9, x - 9, y - 9, colidx + 1); |
| 175 | line (x - 9, y - 8, x - 9, y - 6, colidx + 1); |
| 176 | line (x - 9, y + 6, x - 9, y + 9, colidx + 1); |
| 177 | line (x - 8, y + 9, x - 6, y + 9, colidx + 1); |
| 178 | line (x + 6, y + 9, x + 9, y + 9, colidx + 1); |
| 179 | line (x + 9, y + 8, x + 9, y + 6, colidx + 1); |
| 180 | line (x + 9, y - 6, x + 9, y - 9, colidx + 1); |
| 181 | line (x + 8, y - 9, x + 6, y - 9, colidx + 1); |
| 182 | #else |
| 183 | line (x - 7, y - 7, x - 4, y - 4, colidx + 1); |
| 184 | line (x - 7, y + 7, x - 4, y + 4, colidx + 1); |
| 185 | line (x + 4, y - 4, x + 7, y - 7, colidx + 1); |
| 186 | line (x + 4, y + 4, x + 7, y + 7, colidx + 1); |
| 187 | #endif |
| 188 | } |
| 189 | |
| 190 | void put_char(int x, int y, int c, int colidx) |
| 191 | { |
| 192 | int i,j,bits; |
| 193 | |
| 194 | for (i = 0; i < font_vga_8x8.height; i++) { |
| 195 | bits = font_vga_8x8.data [font_vga_8x8.height * c + i]; |
| 196 | for (j = 0; j < font_vga_8x8.width; j++, bits <<= 1) |
| 197 | if (bits & 0x80) |
| 198 | pixel (x + j, y + i, colidx); |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | void put_string(int x, int y, char *s, unsigned colidx) |
| 203 | { |
| 204 | int i; |
| 205 | for (i = 0; *s; i++, x += font_vga_8x8.width, s++) |
| 206 | put_char (x, y, *s, colidx); |
| 207 | } |
| 208 | |
| 209 | void put_string_center(int x, int y, char *s, unsigned colidx) |
| 210 | { |
| 211 | size_t sl = strlen (s); |
| 212 | put_string (x - (sl / 2) * font_vga_8x8.width, |
| 213 | y - font_vga_8x8.height / 2, s, colidx); |
| 214 | } |
| 215 | |
| 216 | void setcolor(unsigned colidx, unsigned value) |
| 217 | { |
| 218 | unsigned res; |
| 219 | unsigned short red, green, blue; |
| 220 | struct fb_cmap cmap; |
| 221 | |
| 222 | #ifdef DEBUG |
| 223 | if (colidx > 255) { |
| 224 | fprintf (stderr, "WARNING: color index = %u, must be <256\n", |
| 225 | colidx); |
| 226 | return; |
| 227 | } |
| 228 | #endif |
| 229 | |
| 230 | switch (bytes_per_pixel) { |
| 231 | default: |
| 232 | case 1: |
| 233 | res = colidx; |
| 234 | red = (value >> 8) & 0xff00; |
| 235 | green = value & 0xff00; |
| 236 | blue = (value << 8) & 0xff00; |
| 237 | cmap.start = colidx; |
| 238 | cmap.len = 1; |
| 239 | cmap.red = &red; |
| 240 | cmap.green = &green; |
| 241 | cmap.blue = &blue; |
| 242 | cmap.transp = NULL; |
| 243 | |
| 244 | if (ioctl (fb_fd, FBIOPUTCMAP, &cmap) < 0) |
| 245 | perror("ioctl FBIOPUTCMAP"); |
| 246 | break; |
| 247 | case 2: |
| 248 | case 4: |
| 249 | red = (value >> 16) & 0xff; |
| 250 | green = (value >> 8) & 0xff; |
| 251 | blue = value & 0xff; |
| 252 | res = ((red >> (8 - var.red.length)) << var.red.offset) | |
| 253 | ((green >> (8 - var.green.length)) << var.green.offset) | |
| 254 | ((blue >> (8 - var.blue.length)) << var.blue.offset); |
| 255 | } |
| 256 | colormap [colidx] = res; |
| 257 | } |
| 258 | |
| 259 | static inline void __setpixel (union multiptr loc, unsigned xormode, unsigned color) |
| 260 | { |
| 261 | switch(bytes_per_pixel) { |
| 262 | case 1: |
| 263 | default: |
| 264 | if (xormode) |
| 265 | *loc.p8 ^= color; |
| 266 | else |
| 267 | *loc.p8 = color; |
| 268 | break; |
| 269 | case 2: |
| 270 | if (xormode) |
| 271 | *loc.p16 ^= color; |
| 272 | else |
| 273 | *loc.p16 = color; |
| 274 | break; |
| 275 | case 4: |
| 276 | if (xormode) |
| 277 | *loc.p32 ^= color; |
| 278 | else |
| 279 | *loc.p32 = color; |
| 280 | break; |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | void pixel (int x, int y, unsigned colidx) |
| 285 | { |
| 286 | unsigned xormode; |
| 287 | union multiptr loc; |
| 288 | |
| 289 | if ((x < 0) || ((__u32)x >= var.xres_virtual) || |
| 290 | (y < 0) || ((__u32)y >= var.yres_virtual)) |
| 291 | return; |
| 292 | |
| 293 | xormode = colidx & XORMODE; |
| 294 | colidx &= ~XORMODE; |
| 295 | |
| 296 | #ifdef DEBUG |
| 297 | if (colidx > 255) { |
| 298 | fprintf (stderr, "WARNING: color value = %u, must be <256\n", |
| 299 | colidx); |
| 300 | return; |
| 301 | } |
| 302 | #endif |
| 303 | |
| 304 | loc.p8 = line_addr [y] + x * bytes_per_pixel; |
| 305 | __setpixel (loc, xormode, colormap [colidx]); |
| 306 | } |
| 307 | |
| 308 | void line (int x1, int y1, int x2, int y2, unsigned colidx) |
| 309 | { |
| 310 | int tmp; |
| 311 | int dx = x2 - x1; |
| 312 | int dy = y2 - y1; |
| 313 | |
| 314 | if (abs (dx) < abs (dy)) { |
| 315 | if (y1 > y2) { |
| 316 | tmp = x1; x1 = x2; x2 = tmp; |
| 317 | tmp = y1; y1 = y2; y2 = tmp; |
| 318 | dx = -dx; dy = -dy; |
| 319 | } |
| 320 | x1 <<= 16; |
| 321 | /* dy is apriori >0 */ |
| 322 | dx = (dx << 16) / dy; |
| 323 | while (y1 <= y2) { |
| 324 | pixel (x1 >> 16, y1, colidx); |
| 325 | x1 += dx; |
| 326 | y1++; |
| 327 | } |
| 328 | } else { |
| 329 | if (x1 > x2) { |
| 330 | tmp = x1; x1 = x2; x2 = tmp; |
| 331 | tmp = y1; y1 = y2; y2 = tmp; |
| 332 | dx = -dx; dy = -dy; |
| 333 | } |
| 334 | y1 <<= 16; |
| 335 | dy = dx ? (dy << 16) / dx : 0; |
| 336 | while (x1 <= x2) { |
| 337 | pixel (x1, y1 >> 16, colidx); |
| 338 | y1 += dy; |
| 339 | x1++; |
| 340 | } |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | void rect (int x1, int y1, int x2, int y2, unsigned colidx) |
| 345 | { |
| 346 | line (x1, y1, x2, y1, colidx); |
| 347 | line (x2, y1, x2, y2, colidx); |
| 348 | line (x2, y2, x1, y2, colidx); |
| 349 | line (x1, y2, x1, y1, colidx); |
| 350 | } |
| 351 | |
| 352 | void fillrect (int x1, int y1, int x2, int y2, unsigned colidx) |
| 353 | { |
| 354 | int tmp; |
| 355 | unsigned xormode; |
| 356 | union multiptr loc; |
| 357 | |
| 358 | /* Clipping and sanity checking */ |
| 359 | if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; } |
| 360 | if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; } |
| 361 | if (x1 < 0) x1 = 0; if ((__u32)x1 >= xres) x1 = xres - 1; |
| 362 | if (x2 < 0) x2 = 0; if ((__u32)x2 >= xres) x2 = xres - 1; |
| 363 | if (y1 < 0) y1 = 0; if ((__u32)y1 >= yres) y1 = yres - 1; |
| 364 | if (y2 < 0) y2 = 0; if ((__u32)y2 >= yres) y2 = yres - 1; |
| 365 | |
| 366 | if ((x1 > x2) || (y1 > y2)) |
| 367 | return; |
| 368 | |
| 369 | xormode = colidx & XORMODE; |
| 370 | colidx &= ~XORMODE; |
| 371 | |
| 372 | #ifdef DEBUG |
| 373 | if (colidx > 255) { |
| 374 | fprintf (stderr, "WARNING: color value = %u, must be <256\n", |
| 375 | colidx); |
| 376 | return; |
| 377 | } |
| 378 | #endif |
| 379 | |
| 380 | colidx = colormap [colidx]; |
| 381 | |
| 382 | for (; y1 <= y2; y1++) { |
| 383 | loc.p8 = line_addr [y1] + x1 * bytes_per_pixel; |
| 384 | for (tmp = x1; tmp <= x2; tmp++) { |
| 385 | __setpixel (loc, xormode, colidx); |
| 386 | loc.p8 += bytes_per_pixel; |
| 387 | } |
| 388 | } |
| 389 | } |
| 390 | |
| 391 | /*****************************TEST FRAMEBUFFER*********************************/ |
| 392 | static int palette [] = \ |
| 393 | { |
| 394 | 0x000000, 0xffffff, 0xff0000, 0x00ff00, 0x0000ff |
| 395 | }; |
| 396 | #define NR_COLORS (sizeof (palette) / sizeof (palette [0])) |
| 397 | |
| 398 | int main() |
| 399 | { |
| 400 | int i,j,k; |
| 401 | |
| 402 | printf("Opening framebuffer...\n\n"); |
| 403 | |
| 404 | if (open_framebuffer()) { |
| 405 | close_framebuffer(); |
| 406 | exit(1); |
| 407 | printf("Framebuffer could not be opened!!\n\n"); |
| 408 | } |
| 409 | |
| 410 | |
| 411 | for (i = 0; i < NR_COLORS; i++) |
| 412 | setcolor (i, palette [i]); |
| 413 | |
| 414 | printf("Testing... Reslution:%dx%d \n\n",xres,yres); |
| 415 | |
| 416 | k=10; |
| 417 | while(k<=xres/5){ |
| 418 | for (i = 0; i < xres; i++) |
| 419 | for (j = 0; j < yres; j++) |
| 420 | if(j<yres/2) |
| 421 | pixel(i,j,(i/k)%5); |
| 422 | else |
| 423 | pixel(i,j,(j/k)%5); |
| 424 | k+=10; |
| 425 | } |
| 426 | |
| 427 | while(1) |
| 428 | { |
| 429 | put_string_center (xres / 2, yres *0.6, |
| 430 | "Universidad Nacional de Colombia", 1); |
| 431 | put_string_center (xres / 2, yres *0.6 + 80, |
| 432 | "2010-III - Plataforma SIE", 2); |
| 433 | } |
| 434 | close_framebuffer(); |
| 435 | printf("Framebuffer closed...\n\n"); |
| 436 | } |
| 437 | |
| 438 |
Branches:
master
