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>
This commit is contained in:
Nuno Lucas 2011-03-28 15:30:59 +02:00 committed by Denys Vlasenko
parent 55068c478e
commit 0e89fd9c39

View File

@ -27,10 +27,6 @@
/* If you want logging messages on /tmp/fbsplash.log... */ /* If you want logging messages on /tmp/fbsplash.log... */
#define DEBUG 0 #define DEBUG 0
#define BYTES_PER_PIXEL 2
typedef unsigned short DATA;
struct globals { struct globals {
#if DEBUG #if DEBUG
bool bdebug_messages; // enable/disable logging bool bdebug_messages; // enable/disable logging
@ -41,6 +37,7 @@ struct globals {
const char *image_filename; const char *image_filename;
struct fb_var_screeninfo scr_var; struct fb_var_screeninfo scr_var;
struct fb_fix_screeninfo scr_fix; struct fb_fix_screeninfo scr_fix;
unsigned bytes_per_pixel;
}; };
#define G (*ptr_to_globals) #define G (*ptr_to_globals)
#define INIT_G() do { \ #define INIT_G() do { \
@ -67,7 +64,7 @@ struct globals {
/** /**
* Open and initialize the framebuffer device * Open and initialize the framebuffer device
* \param *strfb_device pointer to framebuffer device * \param *strfb_device pointer to framebuffer device
*/ */
static void fb_open(const char *strfb_device) static void fb_open(const char *strfb_device)
@ -78,62 +75,98 @@ static void fb_open(const char *strfb_device)
xioctl(fbfd, FBIOGET_VSCREENINFO, &G.scr_var); xioctl(fbfd, FBIOGET_VSCREENINFO, &G.scr_var);
xioctl(fbfd, FBIOGET_FSCREENINFO, &G.scr_fix); xioctl(fbfd, FBIOGET_FSCREENINFO, &G.scr_fix);
if (G.scr_var.bits_per_pixel != 16) if (G.scr_var.bits_per_pixel < 16 || G.scr_var.bits_per_pixel > 32)
bb_error_msg_and_die("only 16 bpp is supported"); bb_error_msg_and_die("unsupported %u bpp", (int)G.scr_var.bits_per_pixel);
G.bytes_per_pixel = (G.scr_var.bits_per_pixel + 7) >> 3;
// map the device in memory // map the device in memory
G.addr = mmap(NULL, G.addr = mmap(NULL,
G.scr_var.xres * G.scr_var.yres_virtual G.scr_var.xres * G.scr_var.yres * G.bytes_per_pixel,
* BYTES_PER_PIXEL /*(G.scr_var.bits_per_pixel / 8)*/,
PROT_WRITE, MAP_SHARED, fbfd, 0); PROT_WRITE, MAP_SHARED, fbfd, 0);
if (G.addr == MAP_FAILED) if (G.addr == MAP_FAILED)
bb_perror_msg_and_die("mmap"); bb_perror_msg_and_die("mmap");
// point to the start of the visible screen // point to the start of the visible screen
G.addr += G.scr_var.yoffset * G.scr_fix.line_length + G.scr_var.xoffset * BYTES_PER_PIXEL; G.addr += G.scr_var.yoffset * G.scr_fix.line_length + G.scr_var.xoffset * G.bytes_per_pixel;
close(fbfd); close(fbfd);
} }
/** /**
* Draw hollow rectangle on framebuffer * Return pixel value of the passed RGB color
*/
static unsigned fb_pixel_value(unsigned r, unsigned g, unsigned b)
{
if (G.bytes_per_pixel == 2) {
r >>= 3; // 5-bit red
g >>= 2; // 6-bit green
b >>= 3; // 5-bit blue
return b + (g << 5) + (r << (5+6));
}
// RGB 888
return b + (g << 8) + (r << 16);
}
/**
* Draw pixel on framebuffer
*/
static void fb_write_pixel(unsigned char *addr, unsigned pixel)
{
switch (G.bytes_per_pixel) {
case 2:
*(uint16_t *)addr = pixel;
break;
case 4:
*(uint32_t *)addr = pixel;
break;
default: // 24 bits per pixel
addr[0] = pixel;
addr[1] = pixel >> 8;
addr[2] = pixel >> 16;
}
}
/**
* Draw hollow rectangle on framebuffer
*/ */
static void fb_drawrectangle(void) static void fb_drawrectangle(void)
{ {
int cnt; int cnt;
DATA thispix; unsigned thispix;
DATA *ptr1, *ptr2; unsigned char *ptr1, *ptr2;
unsigned char nred = G.nbar_colr/2; unsigned char nred = G.nbar_colr/2;
unsigned char ngreen = G.nbar_colg/2; unsigned char ngreen = G.nbar_colg/2;
unsigned char nblue = G.nbar_colb/2; unsigned char nblue = G.nbar_colb/2;
nred >>= 3; // 5-bit red thispix = fb_pixel_value(nred, ngreen, nblue);
ngreen >>= 2; // 6-bit green
nblue >>= 3; // 5-bit blue
thispix = nblue + (ngreen << 5) + (nred << (5+6));
// horizontal lines // horizontal lines
ptr1 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL); ptr1 = G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * G.bytes_per_pixel;
ptr2 = (DATA*)(G.addr + ((G.nbar_posy + G.nbar_height - 1) * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL); ptr2 = G.addr + ((G.nbar_posy + G.nbar_height - 1) * G.scr_var.xres + G.nbar_posx) * G.bytes_per_pixel;
cnt = G.nbar_width - 1; cnt = G.nbar_width - 1;
do { do {
*ptr1++ = thispix; fb_write_pixel(ptr1, thispix);
*ptr2++ = thispix; fb_write_pixel(ptr2, thispix);
ptr1 += G.bytes_per_pixel;
ptr2 += G.bytes_per_pixel;
} while (--cnt >= 0); } while (--cnt >= 0);
// vertical lines // vertical lines
ptr1 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL); ptr1 = G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * G.bytes_per_pixel;
ptr2 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx + G.nbar_width - 1) * BYTES_PER_PIXEL); ptr2 = G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx + G.nbar_width - 1) * G.bytes_per_pixel;
cnt = G.nbar_height - 1; cnt = G.nbar_height - 1;
do { do {
*ptr1 = thispix; ptr1 += G.scr_var.xres; fb_write_pixel(ptr1, thispix);
*ptr2 = thispix; ptr2 += G.scr_var.xres; fb_write_pixel(ptr2, thispix);
ptr1 += G.scr_var.xres * G.bytes_per_pixel;
ptr2 += G.scr_var.xres * G.bytes_per_pixel;
} while (--cnt >= 0); } while (--cnt >= 0);
} }
/** /**
* Draw filled rectangle on framebuffer * Draw filled rectangle on framebuffer
* \param nx1pos,ny1pos upper left position * \param nx1pos,ny1pos upper left position
* \param nx2pos,ny2pos down right position * \param nx2pos,ny2pos down right position
* \param nred,ngreen,nblue rgb color * \param nred,ngreen,nblue rgb color
@ -142,21 +175,19 @@ static void fb_drawfullrectangle(int nx1pos, int ny1pos, int nx2pos, int ny2pos,
unsigned char nred, unsigned char ngreen, unsigned char nblue) unsigned char nred, unsigned char ngreen, unsigned char nblue)
{ {
int cnt1, cnt2, nypos; int cnt1, cnt2, nypos;
DATA thispix; unsigned thispix;
DATA *ptr; unsigned char *ptr;
nred >>= 3; // 5-bit red thispix = fb_pixel_value(nred, ngreen, nblue);
ngreen >>= 2; // 6-bit green
nblue >>= 3; // 5-bit blue
thispix = nblue + (ngreen << 5) + (nred << (5+6));
cnt1 = ny2pos - ny1pos; cnt1 = ny2pos - ny1pos;
nypos = ny1pos; nypos = ny1pos;
do { do {
ptr = (DATA*)(G.addr + (nypos * G.scr_var.xres + nx1pos) * BYTES_PER_PIXEL); ptr = G.addr + (nypos * G.scr_var.xres + nx1pos) * G.bytes_per_pixel;
cnt2 = nx2pos - nx1pos; cnt2 = nx2pos - nx1pos;
do { do {
*ptr++ = thispix; fb_write_pixel(ptr, thispix);
ptr += G.bytes_per_pixel;
} while (--cnt2 >= 0); } while (--cnt2 >= 0);
nypos++; nypos++;
@ -165,7 +196,7 @@ static void fb_drawfullrectangle(int nx1pos, int ny1pos, int nx2pos, int ny2pos,
/** /**
* Draw a progress bar on framebuffer * Draw a progress bar on framebuffer
* \param percent percentage of loading * \param percent percentage of loading
*/ */
static void fb_drawprogressbar(unsigned percent) static void fb_drawprogressbar(unsigned percent)
@ -215,7 +246,7 @@ static void fb_drawprogressbar(unsigned percent)
/** /**
* Draw image from PPM file * Draw image from PPM file
*/ */
static void fb_drawimage(void) static void fb_drawimage(void)
{ {
@ -276,18 +307,16 @@ static void fb_drawimage(void)
height = G.scr_var.yres; height = G.scr_var.yres;
for (j = 0; j < height; j++) { for (j = 0; j < height; j++) {
unsigned char *pixel; unsigned char *pixel;
DATA *src; unsigned char *src;
if (fread(pixline, 1, line_size, theme_file) != line_size) if (fread(pixline, 1, line_size, theme_file) != line_size)
bb_error_msg_and_die("bad PPM file '%s'", G.image_filename); bb_error_msg_and_die("bad PPM file '%s'", G.image_filename);
pixel = pixline; pixel = pixline;
src = (DATA *)(G.addr + j * G.scr_fix.line_length); src = G.addr + j * G.scr_fix.line_length;
for (i = 0; i < width; i++) { for (i = 0; i < width; i++) {
unsigned thispix; unsigned thispix = fb_pixel_value(pixel[0], pixel[1], pixel[2]);
thispix = (((unsigned)pixel[0] << 8) & 0xf800) fb_write_pixel(src, thispix);
| (((unsigned)pixel[1] << 3) & 0x07e0) src += G.bytes_per_pixel;
| (((unsigned)pixel[2] >> 3));
*src++ = thispix;
pixel += 3; pixel += 3;
} }
} }
@ -297,7 +326,7 @@ static void fb_drawimage(void)
/** /**
* Parse configuration file * Parse configuration file
* \param *cfg_filename name of the configuration file * \param *cfg_filename name of the configuration file
*/ */
static void init(const char *cfg_filename) static void init(const char *cfg_filename)