diff options
| author | Nuno Lucas <ntlucas@gmail.com> | 2011-03-28 15:30:59 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-03-28 15:30:59 +0200 |
| commit | 0e89fd9c39655fe721dd8a7a09a6c532f4255c42 (patch) | |
| tree | 965989052ed70ec7cadb462e3529c648df362f4c /miscutils | |
| parent | 55068c478ee8e8c058b0c9e37ce0ca57612c95b1 (diff) | |
| download | busybox-w32-0e89fd9c39655fe721dd8a7a09a6c532f4255c42.tar.gz busybox-w32-0e89fd9c39655fe721dd8a7a09a6c532f4255c42.tar.bz2 busybox-w32-0e89fd9c39655fe721dd8a7a09a6c532f4255c42.zip | |
fbsplash: Add support for 24 and 32 bit color depth
function old new delta
fb_drawprogressbar 372 447 +75
fb_pixel_value - 50 +50
fb_write_pixel - 47 +47
fbsplash_main 889 920 +31
fb_drawfullrectangle 101 131 +30
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 3/0 up/down: 233/0) Total: 233 bytes
Signed-off-by: Nuno Lucas <ntlucas@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
| -rw-r--r-- | miscutils/fbsplash.c | 117 |
1 files changed, 73 insertions, 44 deletions
diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c index 150992343..770e70026 100644 --- a/miscutils/fbsplash.c +++ b/miscutils/fbsplash.c | |||
| @@ -27,10 +27,6 @@ | |||
| 27 | /* If you want logging messages on /tmp/fbsplash.log... */ | 27 | /* If you want logging messages on /tmp/fbsplash.log... */ |
| 28 | #define DEBUG 0 | 28 | #define DEBUG 0 |
| 29 | 29 | ||
| 30 | #define BYTES_PER_PIXEL 2 | ||
| 31 | |||
| 32 | typedef unsigned short DATA; | ||
| 33 | |||
| 34 | struct globals { | 30 | struct globals { |
| 35 | #if DEBUG | 31 | #if DEBUG |
| 36 | bool bdebug_messages; // enable/disable logging | 32 | bool bdebug_messages; // enable/disable logging |
| @@ -41,6 +37,7 @@ struct globals { | |||
| 41 | const char *image_filename; | 37 | const char *image_filename; |
| 42 | struct fb_var_screeninfo scr_var; | 38 | struct fb_var_screeninfo scr_var; |
| 43 | struct fb_fix_screeninfo scr_fix; | 39 | struct fb_fix_screeninfo scr_fix; |
| 40 | unsigned bytes_per_pixel; | ||
| 44 | }; | 41 | }; |
| 45 | #define G (*ptr_to_globals) | 42 | #define G (*ptr_to_globals) |
| 46 | #define INIT_G() do { \ | 43 | #define INIT_G() do { \ |
| @@ -67,7 +64,7 @@ struct globals { | |||
| 67 | 64 | ||
| 68 | 65 | ||
| 69 | /** | 66 | /** |
| 70 | * Open and initialize the framebuffer device | 67 | * Open and initialize the framebuffer device |
| 71 | * \param *strfb_device pointer to framebuffer device | 68 | * \param *strfb_device pointer to framebuffer device |
| 72 | */ | 69 | */ |
| 73 | static void fb_open(const char *strfb_device) | 70 | static void fb_open(const char *strfb_device) |
| @@ -78,62 +75,98 @@ static void fb_open(const char *strfb_device) | |||
| 78 | xioctl(fbfd, FBIOGET_VSCREENINFO, &G.scr_var); | 75 | xioctl(fbfd, FBIOGET_VSCREENINFO, &G.scr_var); |
| 79 | xioctl(fbfd, FBIOGET_FSCREENINFO, &G.scr_fix); | 76 | xioctl(fbfd, FBIOGET_FSCREENINFO, &G.scr_fix); |
| 80 | 77 | ||
| 81 | if (G.scr_var.bits_per_pixel != 16) | 78 | if (G.scr_var.bits_per_pixel < 16 || G.scr_var.bits_per_pixel > 32) |
| 82 | bb_error_msg_and_die("only 16 bpp is supported"); | 79 | bb_error_msg_and_die("unsupported %u bpp", (int)G.scr_var.bits_per_pixel); |
| 80 | G.bytes_per_pixel = (G.scr_var.bits_per_pixel + 7) >> 3; | ||
| 83 | 81 | ||
| 84 | // map the device in memory | 82 | // map the device in memory |
| 85 | G.addr = mmap(NULL, | 83 | G.addr = mmap(NULL, |
| 86 | G.scr_var.xres * G.scr_var.yres_virtual | 84 | G.scr_var.xres * G.scr_var.yres * G.bytes_per_pixel, |
| 87 | * BYTES_PER_PIXEL /*(G.scr_var.bits_per_pixel / 8)*/, | ||
| 88 | PROT_WRITE, MAP_SHARED, fbfd, 0); | 85 | PROT_WRITE, MAP_SHARED, fbfd, 0); |
| 89 | if (G.addr == MAP_FAILED) | 86 | if (G.addr == MAP_FAILED) |
| 90 | bb_perror_msg_and_die("mmap"); | 87 | bb_perror_msg_and_die("mmap"); |
| 91 | 88 | ||
| 92 | // point to the start of the visible screen | 89 | // point to the start of the visible screen |
| 93 | G.addr += G.scr_var.yoffset * G.scr_fix.line_length + G.scr_var.xoffset * BYTES_PER_PIXEL; | 90 | G.addr += G.scr_var.yoffset * G.scr_fix.line_length + G.scr_var.xoffset * G.bytes_per_pixel; |
| 94 | close(fbfd); | 91 | close(fbfd); |
| 95 | } | 92 | } |
| 96 | 93 | ||
| 97 | 94 | ||
| 98 | /** | 95 | /** |
| 99 | * Draw hollow rectangle on framebuffer | 96 | * Return pixel value of the passed RGB color |
| 97 | */ | ||
| 98 | static unsigned fb_pixel_value(unsigned r, unsigned g, unsigned b) | ||
| 99 | { | ||
| 100 | if (G.bytes_per_pixel == 2) { | ||
| 101 | r >>= 3; // 5-bit red | ||
| 102 | g >>= 2; // 6-bit green | ||
| 103 | b >>= 3; // 5-bit blue | ||
| 104 | return b + (g << 5) + (r << (5+6)); | ||
| 105 | } | ||
| 106 | // RGB 888 | ||
| 107 | return b + (g << 8) + (r << 16); | ||
| 108 | } | ||
| 109 | |||
| 110 | /** | ||
| 111 | * Draw pixel on framebuffer | ||
| 112 | */ | ||
| 113 | static void fb_write_pixel(unsigned char *addr, unsigned pixel) | ||
| 114 | { | ||
| 115 | switch (G.bytes_per_pixel) { | ||
| 116 | case 2: | ||
| 117 | *(uint16_t *)addr = pixel; | ||
| 118 | break; | ||
| 119 | case 4: | ||
| 120 | *(uint32_t *)addr = pixel; | ||
| 121 | break; | ||
| 122 | default: // 24 bits per pixel | ||
| 123 | addr[0] = pixel; | ||
| 124 | addr[1] = pixel >> 8; | ||
| 125 | addr[2] = pixel >> 16; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | |||
| 130 | /** | ||
| 131 | * Draw hollow rectangle on framebuffer | ||
| 100 | */ | 132 | */ |
| 101 | static void fb_drawrectangle(void) | 133 | static void fb_drawrectangle(void) |
| 102 | { | 134 | { |
| 103 | int cnt; | 135 | int cnt; |
| 104 | DATA thispix; | 136 | unsigned thispix; |
| 105 | DATA *ptr1, *ptr2; | 137 | unsigned char *ptr1, *ptr2; |
| 106 | unsigned char nred = G.nbar_colr/2; | 138 | unsigned char nred = G.nbar_colr/2; |
| 107 | unsigned char ngreen = G.nbar_colg/2; | 139 | unsigned char ngreen = G.nbar_colg/2; |
| 108 | unsigned char nblue = G.nbar_colb/2; | 140 | unsigned char nblue = G.nbar_colb/2; |
| 109 | 141 | ||
| 110 | nred >>= 3; // 5-bit red | 142 | thispix = fb_pixel_value(nred, ngreen, nblue); |
| 111 | ngreen >>= 2; // 6-bit green | ||
| 112 | nblue >>= 3; // 5-bit blue | ||
| 113 | thispix = nblue + (ngreen << 5) + (nred << (5+6)); | ||
| 114 | 143 | ||
| 115 | // horizontal lines | 144 | // horizontal lines |
| 116 | ptr1 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL); | 145 | ptr1 = G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * G.bytes_per_pixel; |
| 117 | ptr2 = (DATA*)(G.addr + ((G.nbar_posy + G.nbar_height - 1) * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL); | 146 | ptr2 = G.addr + ((G.nbar_posy + G.nbar_height - 1) * G.scr_var.xres + G.nbar_posx) * G.bytes_per_pixel; |
| 118 | cnt = G.nbar_width - 1; | 147 | cnt = G.nbar_width - 1; |
| 119 | do { | 148 | do { |
| 120 | *ptr1++ = thispix; | 149 | fb_write_pixel(ptr1, thispix); |
| 121 | *ptr2++ = thispix; | 150 | fb_write_pixel(ptr2, thispix); |
| 151 | ptr1 += G.bytes_per_pixel; | ||
| 152 | ptr2 += G.bytes_per_pixel; | ||
| 122 | } while (--cnt >= 0); | 153 | } while (--cnt >= 0); |
| 123 | 154 | ||
| 124 | // vertical lines | 155 | // vertical lines |
| 125 | ptr1 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL); | 156 | ptr1 = G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * G.bytes_per_pixel; |
| 126 | ptr2 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx + G.nbar_width - 1) * BYTES_PER_PIXEL); | 157 | ptr2 = G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx + G.nbar_width - 1) * G.bytes_per_pixel; |
| 127 | cnt = G.nbar_height - 1; | 158 | cnt = G.nbar_height - 1; |
| 128 | do { | 159 | do { |
| 129 | *ptr1 = thispix; ptr1 += G.scr_var.xres; | 160 | fb_write_pixel(ptr1, thispix); |
| 130 | *ptr2 = thispix; ptr2 += G.scr_var.xres; | 161 | fb_write_pixel(ptr2, thispix); |
| 162 | ptr1 += G.scr_var.xres * G.bytes_per_pixel; | ||
| 163 | ptr2 += G.scr_var.xres * G.bytes_per_pixel; | ||
| 131 | } while (--cnt >= 0); | 164 | } while (--cnt >= 0); |
| 132 | } | 165 | } |
| 133 | 166 | ||
| 134 | 167 | ||
| 135 | /** | 168 | /** |
| 136 | * Draw filled rectangle on framebuffer | 169 | * Draw filled rectangle on framebuffer |
| 137 | * \param nx1pos,ny1pos upper left position | 170 | * \param nx1pos,ny1pos upper left position |
| 138 | * \param nx2pos,ny2pos down right position | 171 | * \param nx2pos,ny2pos down right position |
| 139 | * \param nred,ngreen,nblue rgb color | 172 | * \param nred,ngreen,nblue rgb color |
| @@ -142,21 +175,19 @@ static void fb_drawfullrectangle(int nx1pos, int ny1pos, int nx2pos, int ny2pos, | |||
| 142 | unsigned char nred, unsigned char ngreen, unsigned char nblue) | 175 | unsigned char nred, unsigned char ngreen, unsigned char nblue) |
| 143 | { | 176 | { |
| 144 | int cnt1, cnt2, nypos; | 177 | int cnt1, cnt2, nypos; |
| 145 | DATA thispix; | 178 | unsigned thispix; |
| 146 | DATA *ptr; | 179 | unsigned char *ptr; |
| 147 | 180 | ||
| 148 | nred >>= 3; // 5-bit red | 181 | thispix = fb_pixel_value(nred, ngreen, nblue); |
| 149 | ngreen >>= 2; // 6-bit green | ||
| 150 | nblue >>= 3; // 5-bit blue | ||
| 151 | thispix = nblue + (ngreen << 5) + (nred << (5+6)); | ||
| 152 | 182 | ||
| 153 | cnt1 = ny2pos - ny1pos; | 183 | cnt1 = ny2pos - ny1pos; |
| 154 | nypos = ny1pos; | 184 | nypos = ny1pos; |
| 155 | do { | 185 | do { |
| 156 | ptr = (DATA*)(G.addr + (nypos * G.scr_var.xres + nx1pos) * BYTES_PER_PIXEL); | 186 | ptr = G.addr + (nypos * G.scr_var.xres + nx1pos) * G.bytes_per_pixel; |
| 157 | cnt2 = nx2pos - nx1pos; | 187 | cnt2 = nx2pos - nx1pos; |
| 158 | do { | 188 | do { |
| 159 | *ptr++ = thispix; | 189 | fb_write_pixel(ptr, thispix); |
| 190 | ptr += G.bytes_per_pixel; | ||
| 160 | } while (--cnt2 >= 0); | 191 | } while (--cnt2 >= 0); |
| 161 | 192 | ||
| 162 | nypos++; | 193 | nypos++; |
| @@ -165,7 +196,7 @@ static void fb_drawfullrectangle(int nx1pos, int ny1pos, int nx2pos, int ny2pos, | |||
| 165 | 196 | ||
| 166 | 197 | ||
| 167 | /** | 198 | /** |
| 168 | * Draw a progress bar on framebuffer | 199 | * Draw a progress bar on framebuffer |
| 169 | * \param percent percentage of loading | 200 | * \param percent percentage of loading |
| 170 | */ | 201 | */ |
| 171 | static void fb_drawprogressbar(unsigned percent) | 202 | static void fb_drawprogressbar(unsigned percent) |
| @@ -215,7 +246,7 @@ static void fb_drawprogressbar(unsigned percent) | |||
| 215 | 246 | ||
| 216 | 247 | ||
| 217 | /** | 248 | /** |
| 218 | * Draw image from PPM file | 249 | * Draw image from PPM file |
| 219 | */ | 250 | */ |
| 220 | static void fb_drawimage(void) | 251 | static void fb_drawimage(void) |
| 221 | { | 252 | { |
| @@ -276,18 +307,16 @@ static void fb_drawimage(void) | |||
| 276 | height = G.scr_var.yres; | 307 | height = G.scr_var.yres; |
| 277 | for (j = 0; j < height; j++) { | 308 | for (j = 0; j < height; j++) { |
| 278 | unsigned char *pixel; | 309 | unsigned char *pixel; |
| 279 | DATA *src; | 310 | unsigned char *src; |
| 280 | 311 | ||
| 281 | if (fread(pixline, 1, line_size, theme_file) != line_size) | 312 | if (fread(pixline, 1, line_size, theme_file) != line_size) |
| 282 | bb_error_msg_and_die("bad PPM file '%s'", G.image_filename); | 313 | bb_error_msg_and_die("bad PPM file '%s'", G.image_filename); |
| 283 | pixel = pixline; | 314 | pixel = pixline; |
| 284 | src = (DATA *)(G.addr + j * G.scr_fix.line_length); | 315 | src = G.addr + j * G.scr_fix.line_length; |
| 285 | for (i = 0; i < width; i++) { | 316 | for (i = 0; i < width; i++) { |
| 286 | unsigned thispix; | 317 | unsigned thispix = fb_pixel_value(pixel[0], pixel[1], pixel[2]); |
| 287 | thispix = (((unsigned)pixel[0] << 8) & 0xf800) | 318 | fb_write_pixel(src, thispix); |
| 288 | | (((unsigned)pixel[1] << 3) & 0x07e0) | 319 | src += G.bytes_per_pixel; |
| 289 | | (((unsigned)pixel[2] >> 3)); | ||
| 290 | *src++ = thispix; | ||
| 291 | pixel += 3; | 320 | pixel += 3; |
| 292 | } | 321 | } |
| 293 | } | 322 | } |
| @@ -297,7 +326,7 @@ static void fb_drawimage(void) | |||
| 297 | 326 | ||
| 298 | 327 | ||
| 299 | /** | 328 | /** |
| 300 | * Parse configuration file | 329 | * Parse configuration file |
| 301 | * \param *cfg_filename name of the configuration file | 330 | * \param *cfg_filename name of the configuration file |
| 302 | */ | 331 | */ |
| 303 | static void init(const char *cfg_filename) | 332 | static void init(const char *cfg_filename) |
