Ignore:
Timestamp:
Jan 1, 2014, 12:47:38 AM (7 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.21.1
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3.2/mindi-busybox/miscutils/fbsplash.c

    r2725 r3232  
    2222 */
    2323
     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
    2436#include "libbb.h"
    2537#include <linux/fb.h>
     
    2739/* If you want logging messages on /tmp/fbsplash.log... */
    2840#define DEBUG 0
    29 
    30 #define BYTES_PER_PIXEL 2
    31 
    32 typedef unsigned short DATA;
    3341
    3442struct globals {
     
    4250    struct fb_var_screeninfo scr_var;
    4351    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;
    4457};
    4558#define G (*ptr_to_globals)
     
    6679#endif
    6780
    68 
    69 /**
    70  *  Open and initialize the framebuffer device
     81/**
     82 * Configure palette for RGB:332
     83 */
     84static 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
    71121 * \param *strfb_device pointer to framebuffer device
    72122 */
     
    79129    xioctl(fbfd, FBIOGET_FSCREENINFO, &G.scr_fix);
    80130
    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;
    83150
    84151    // map the device in memory
    85152    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,
    88154            PROT_WRITE, MAP_SHARED, fbfd, 0);
    89155    if (G.addr == MAP_FAILED)
    90156        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;
    91160    close(fbfd);
    92161}
     
    94163
    95164/**
    96  *  Draw hollow rectangle on framebuffer
     165 * Return pixel value of the passed RGB color.
     166 * This is performance critical fn.
     167 */
     168static 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 */
     198static 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
    97220 */
    98221static void fb_drawrectangle(void)
    99222{
    100223    int cnt;
    101     DATA thispix;
    102     DATA *ptr1, *ptr2;
     224    unsigned thispix;
     225    unsigned char *ptr1, *ptr2;
    103226    unsigned char nred = G.nbar_colr/2;
    104227    unsigned char ngreen =  G.nbar_colg/2;
    105228    unsigned char nblue = G.nbar_colb/2;
    106229
    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);
    111231
    112232    // 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;
    115235    cnt = G.nbar_width - 1;
    116236    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;
    119241    } while (--cnt >= 0);
    120242
    121243    // 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;
    124246    cnt = G.nbar_height - 1;
    125247    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;
    128252    } while (--cnt >= 0);
    129253}
     
    131255
    132256/**
    133  *  Draw filled rectangle on framebuffer
     257 * Draw filled rectangle on framebuffer
    134258 * \param nx1pos,ny1pos upper left position
    135259 * \param nx2pos,ny2pos down right position
     
    140264{
    141265    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);
    149270
    150271    cnt1 = ny2pos - ny1pos;
    151272    nypos = ny1pos;
    152273    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;
    154275        cnt2 = nx2pos - nx1pos;
    155276        do {
    156             *ptr++ = thispix;
     277            fb_write_pixel(ptr, thispix);
     278            ptr += G.bytes_per_pixel;
    157279        } while (--cnt2 >= 0);
    158280
     
    163285
    164286/**
    165  *  Draw a progress bar on framebuffer
     287 * Draw a progress bar on framebuffer
    166288 * \param percent percentage of loading
    167289 */
    168290static void fb_drawprogressbar(unsigned percent)
    169291{
    170     int i, left_x, top_y, width, height;
     292    int left_x, top_y, pos_x;
     293    unsigned width, height;
    171294
    172295    // outer box
     
    175298    width = G.nbar_width - 1;
    176299    height = G.nbar_height - 1;
    177     if ((height | width) < 0)
     300    if ((int)(height | width) < 0)
    178301        return;
    179302    // NB: "width" of 1 actually makes rect with width of 2!
     
    185308    width -= 2;
    186309    height -= 2;
    187     if ((height | width) < 0)
     310    if ((int)(height | width) < 0)
    188311        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;
    194314    if (percent > 0) {
     315        int i, y;
     316
    195317        // actual progress bar
    196         width = width * percent / 100;
     318        pos_x += (unsigned)(width * percent) / 100;
     319
     320        y = top_y;
    197321        i = height;
    198322        if (height == 0)
     
    201325            // draw one-line thick "rectangle"
    202326            // 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;
    204328            fb_drawfullrectangle(
    205                     left_x, top_y, left_x + width, top_y,
     329                    left_x, y, pos_x, y,
    206330                    gray_level, gray_level, gray_level);
    207             top_y++;
     331            y++;
    208332            i--;
    209333        }
    210334    }
    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
    216345 */
    217346static void fb_drawimage(void)
     
    274403    for (j = 0; j < height; j++) {
    275404        unsigned char *pixel;
    276         DATA *src;
     405        unsigned char *src;
    277406
    278407        if (fread(pixline, 1, line_size, theme_file) != line_size)
    279408            bb_error_msg_and_die("bad PPM file '%s'", G.image_filename);
    280409        pixel = pixline;
    281         src = (DATA *)(G.addr + j * G.scr_fix.line_length);
     410        src = G.addr + j * G.scr_fix.line_length;
    282411        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;
    288415            pixel += 3;
    289416        }
     
    295422
    296423/**
    297  *  Parse configuration file
     424 * Parse configuration file
    298425 * \param *cfg_filename name of the configuration file
    299426 */
Note: See TracChangeset for help on using the changeset viewer.