Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/miscutils/fbsplash.c
- Timestamp:
- Jan 1, 2014, 12:47:38 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.2/mindi-busybox/miscutils/fbsplash.c
r2725 r3232 22 22 */ 23 23 24 //usage:#define fbsplash_trivial_usage 25 //usage: "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD]" 26 //usage:#define fbsplash_full_usage "\n\n" 27 //usage: " -s Image" 28 //usage: "\n -c Hide cursor" 29 //usage: "\n -d Framebuffer device (default /dev/fb0)" 30 //usage: "\n -i Config file (var=value):" 31 //usage: "\n BAR_LEFT,BAR_TOP,BAR_WIDTH,BAR_HEIGHT" 32 //usage: "\n BAR_R,BAR_G,BAR_B" 33 //usage: "\n -f Control pipe (else exit after drawing image)" 34 //usage: "\n commands: 'NN' (% for progress bar) or 'exit'" 35 24 36 #include "libbb.h" 25 37 #include <linux/fb.h> … … 27 39 /* If you want logging messages on /tmp/fbsplash.log... */ 28 40 #define DEBUG 0 29 30 #define BYTES_PER_PIXEL 231 32 typedef unsigned short DATA;33 41 34 42 struct globals { … … 42 50 struct fb_var_screeninfo scr_var; 43 51 struct fb_fix_screeninfo scr_fix; 52 unsigned bytes_per_pixel; 53 // cached (8 - scr_var.COLOR.length): 54 unsigned red_shift; 55 unsigned green_shift; 56 unsigned blue_shift; 44 57 }; 45 58 #define G (*ptr_to_globals) … … 66 79 #endif 67 80 68 69 /** 70 * Open and initialize the framebuffer device 81 /** 82 * Configure palette for RGB:332 83 */ 84 static void fb_setpal(int fd) 85 { 86 struct fb_cmap cmap; 87 /* fb colors are 16 bit */ 88 unsigned short red[256], green[256], blue[256]; 89 unsigned i; 90 91 /* RGB:332 */ 92 for (i = 0; i < 256; i++) { 93 /* Color is encoded in pixel value as rrrgggbb. 94 * 3-bit color is mapped to 16-bit one as: 95 * 000 -> 00000000 00000000 96 * 001 -> 00100100 10010010 97 * ... 98 * 011 -> 01101101 10110110 99 * 100 -> 10010010 01001001 100 * ... 101 * 111 -> 11111111 11111111 102 */ 103 red[i] = (( i >> 5 ) * 0x9249) >> 2; // rrr * 00 10010010 01001001 >> 2 104 green[i] = (((i >> 2) & 0x7) * 0x9249) >> 2; // ggg * 00 10010010 01001001 >> 2 105 /* 2-bit color is easier: */ 106 blue[i] = ( i & 0x3) * 0x5555; // bb * 01010101 01010101 107 } 108 109 cmap.start = 0; 110 cmap.len = 256; 111 cmap.red = red; 112 cmap.green = green; 113 cmap.blue = blue; 114 cmap.transp = 0; 115 116 xioctl(fd, FBIOPUTCMAP, &cmap); 117 } 118 119 /** 120 * Open and initialize the framebuffer device 71 121 * \param *strfb_device pointer to framebuffer device 72 122 */ … … 79 129 xioctl(fbfd, FBIOGET_FSCREENINFO, &G.scr_fix); 80 130 81 if (G.scr_var.bits_per_pixel != 16) 82 bb_error_msg_and_die("only 16 bpp is supported"); 131 switch (G.scr_var.bits_per_pixel) { 132 case 8: 133 fb_setpal(fbfd); 134 break; 135 136 case 16: 137 case 24: 138 case 32: 139 break; 140 141 default: 142 bb_error_msg_and_die("unsupported %u bpp", (int)G.scr_var.bits_per_pixel); 143 break; 144 } 145 146 G.red_shift = 8 - G.scr_var.red.length; 147 G.green_shift = 8 - G.scr_var.green.length; 148 G.blue_shift = 8 - G.scr_var.blue.length; 149 G.bytes_per_pixel = (G.scr_var.bits_per_pixel + 7) >> 3; 83 150 84 151 // map the device in memory 85 152 G.addr = mmap(NULL, 86 G.scr_var.xres * G.scr_var.yres 87 * BYTES_PER_PIXEL /*(G.scr_var.bits_per_pixel / 8)*/, 153 G.scr_var.yres * G.scr_fix.line_length, 88 154 PROT_WRITE, MAP_SHARED, fbfd, 0); 89 155 if (G.addr == MAP_FAILED) 90 156 bb_perror_msg_and_die("mmap"); 157 158 // point to the start of the visible screen 159 G.addr += G.scr_var.yoffset * G.scr_fix.line_length + G.scr_var.xoffset * G.bytes_per_pixel; 91 160 close(fbfd); 92 161 } … … 94 163 95 164 /** 96 * Draw hollow rectangle on framebuffer 165 * Return pixel value of the passed RGB color. 166 * This is performance critical fn. 167 */ 168 static unsigned fb_pixel_value(unsigned r, unsigned g, unsigned b) 169 { 170 /* We assume that the r,g,b values are <= 255 */ 171 172 if (G.bytes_per_pixel == 1) { 173 r = r & 0xe0; // 3-bit red 174 g = (g >> 3) & 0x1c; // 3-bit green 175 b = b >> 6; // 2-bit blue 176 return r + g + b; 177 } 178 if (G.bytes_per_pixel == 2) { 179 // ARM PL110 on Integrator/CP has RGBA5551 bit arrangement. 180 // We want to support bit locations like that. 181 // 182 // First shift out unused bits 183 r = r >> G.red_shift; 184 g = g >> G.green_shift; 185 b = b >> G.blue_shift; 186 // Then shift the remaining bits to their offset 187 return (r << G.scr_var.red.offset) + 188 (g << G.scr_var.green.offset) + 189 (b << G.scr_var.blue.offset); 190 } 191 // RGB 888 192 return b + (g << 8) + (r << 16); 193 } 194 195 /** 196 * Draw pixel on framebuffer 197 */ 198 static void fb_write_pixel(unsigned char *addr, unsigned pixel) 199 { 200 switch (G.bytes_per_pixel) { 201 case 1: 202 *addr = pixel; 203 break; 204 case 2: 205 *(uint16_t *)addr = pixel; 206 break; 207 case 4: 208 *(uint32_t *)addr = pixel; 209 break; 210 default: // 24 bits per pixel 211 addr[0] = pixel; 212 addr[1] = pixel >> 8; 213 addr[2] = pixel >> 16; 214 } 215 } 216 217 218 /** 219 * Draw hollow rectangle on framebuffer 97 220 */ 98 221 static void fb_drawrectangle(void) 99 222 { 100 223 int cnt; 101 DATAthispix;102 DATA*ptr1, *ptr2;224 unsigned thispix; 225 unsigned char *ptr1, *ptr2; 103 226 unsigned char nred = G.nbar_colr/2; 104 227 unsigned char ngreen = G.nbar_colg/2; 105 228 unsigned char nblue = G.nbar_colb/2; 106 229 107 nred >>= 3; // 5-bit red 108 ngreen >>= 2; // 6-bit green 109 nblue >>= 3; // 5-bit blue 110 thispix = nblue + (ngreen << 5) + (nred << (5+6)); 230 thispix = fb_pixel_value(nred, ngreen, nblue); 111 231 112 232 // horizontal lines 113 ptr1 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL);114 ptr2 = (DATA*)(G.addr + ((G.nbar_posy + G.nbar_height - 1) * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL);233 ptr1 = G.addr + G.nbar_posy * G.scr_fix.line_length + G.nbar_posx * G.bytes_per_pixel; 234 ptr2 = G.addr + (G.nbar_posy + G.nbar_height - 1) * G.scr_fix.line_length + G.nbar_posx * G.bytes_per_pixel; 115 235 cnt = G.nbar_width - 1; 116 236 do { 117 *ptr1++ = thispix; 118 *ptr2++ = thispix; 237 fb_write_pixel(ptr1, thispix); 238 fb_write_pixel(ptr2, thispix); 239 ptr1 += G.bytes_per_pixel; 240 ptr2 += G.bytes_per_pixel; 119 241 } while (--cnt >= 0); 120 242 121 243 // vertical lines 122 ptr1 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL);123 ptr2 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx + G.nbar_width - 1) * BYTES_PER_PIXEL);244 ptr1 = G.addr + G.nbar_posy * G.scr_fix.line_length + G.nbar_posx * G.bytes_per_pixel; 245 ptr2 = G.addr + G.nbar_posy * G.scr_fix.line_length + (G.nbar_posx + G.nbar_width - 1) * G.bytes_per_pixel; 124 246 cnt = G.nbar_height - 1; 125 247 do { 126 *ptr1 = thispix; ptr1 += G.scr_var.xres; 127 *ptr2 = thispix; ptr2 += G.scr_var.xres; 248 fb_write_pixel(ptr1, thispix); 249 fb_write_pixel(ptr2, thispix); 250 ptr1 += G.scr_fix.line_length; 251 ptr2 += G.scr_fix.line_length; 128 252 } while (--cnt >= 0); 129 253 } … … 131 255 132 256 /** 133 * 257 * Draw filled rectangle on framebuffer 134 258 * \param nx1pos,ny1pos upper left position 135 259 * \param nx2pos,ny2pos down right position … … 140 264 { 141 265 int cnt1, cnt2, nypos; 142 DATA thispix; 143 DATA *ptr; 144 145 nred >>= 3; // 5-bit red 146 ngreen >>= 2; // 6-bit green 147 nblue >>= 3; // 5-bit blue 148 thispix = nblue + (ngreen << 5) + (nred << (5+6)); 266 unsigned thispix; 267 unsigned char *ptr; 268 269 thispix = fb_pixel_value(nred, ngreen, nblue); 149 270 150 271 cnt1 = ny2pos - ny1pos; 151 272 nypos = ny1pos; 152 273 do { 153 ptr = (DATA*)(G.addr + (nypos * G.scr_var.xres + nx1pos) * BYTES_PER_PIXEL);274 ptr = G.addr + nypos * G.scr_fix.line_length + nx1pos * G.bytes_per_pixel; 154 275 cnt2 = nx2pos - nx1pos; 155 276 do { 156 *ptr++ = thispix; 277 fb_write_pixel(ptr, thispix); 278 ptr += G.bytes_per_pixel; 157 279 } while (--cnt2 >= 0); 158 280 … … 163 285 164 286 /** 165 * 287 * Draw a progress bar on framebuffer 166 288 * \param percent percentage of loading 167 289 */ 168 290 static void fb_drawprogressbar(unsigned percent) 169 291 { 170 int i, left_x, top_y, width, height; 292 int left_x, top_y, pos_x; 293 unsigned width, height; 171 294 172 295 // outer box … … 175 298 width = G.nbar_width - 1; 176 299 height = G.nbar_height - 1; 177 if (( height | width) < 0)300 if ((int)(height | width) < 0) 178 301 return; 179 302 // NB: "width" of 1 actually makes rect with width of 2! … … 185 308 width -= 2; 186 309 height -= 2; 187 if (( height | width) < 0)310 if ((int)(height | width) < 0) 188 311 return; 189 fb_drawfullrectangle( 190 left_x, top_y, 191 left_x + width, top_y + height, 192 G.nbar_colr, G.nbar_colg, G.nbar_colb); 193 312 313 pos_x = left_x; 194 314 if (percent > 0) { 315 int i, y; 316 195 317 // actual progress bar 196 width = width * percent / 100; 318 pos_x += (unsigned)(width * percent) / 100; 319 320 y = top_y; 197 321 i = height; 198 322 if (height == 0) … … 201 325 // draw one-line thick "rectangle" 202 326 // top line will have gray lvl 200, bottom one 100 203 unsigned gray_level = 100 + i*100/height;327 unsigned gray_level = 100 + (unsigned)i*100 / height; 204 328 fb_drawfullrectangle( 205 left_x, top_y, left_x + width, top_y,329 left_x, y, pos_x, y, 206 330 gray_level, gray_level, gray_level); 207 top_y++;331 y++; 208 332 i--; 209 333 } 210 334 } 211 } 212 213 214 /** 215 * Draw image from PPM file 335 336 fb_drawfullrectangle( 337 pos_x, top_y, 338 left_x + width, top_y + height, 339 G.nbar_colr, G.nbar_colg, G.nbar_colb); 340 } 341 342 343 /** 344 * Draw image from PPM file 216 345 */ 217 346 static void fb_drawimage(void) … … 274 403 for (j = 0; j < height; j++) { 275 404 unsigned char *pixel; 276 DATA*src;405 unsigned char *src; 277 406 278 407 if (fread(pixline, 1, line_size, theme_file) != line_size) 279 408 bb_error_msg_and_die("bad PPM file '%s'", G.image_filename); 280 409 pixel = pixline; 281 src = (DATA *)(G.addr + j * G.scr_fix.line_length);410 src = G.addr + j * G.scr_fix.line_length; 282 411 for (i = 0; i < width; i++) { 283 unsigned thispix; 284 thispix = (((unsigned)pixel[0] << 8) & 0xf800) 285 | (((unsigned)pixel[1] << 3) & 0x07e0) 286 | (((unsigned)pixel[2] >> 3)); 287 *src++ = thispix; 412 unsigned thispix = fb_pixel_value(pixel[0], pixel[1], pixel[2]); 413 fb_write_pixel(src, thispix); 414 src += G.bytes_per_pixel; 288 415 pixel += 3; 289 416 } … … 295 422 296 423 /** 297 * 424 * Parse configuration file 298 425 * \param *cfg_filename name of the configuration file 299 426 */
Note:
See TracChangeset
for help on using the changeset viewer.