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:
		
				
					committed by
					
						
						Denys Vlasenko
					
				
			
			
				
	
			
			
			
						parent
						
							55068c478e
						
					
				
				
					commit
					0e89fd9c39
				
			@@ -27,10 +27,6 @@
 | 
			
		||||
/* If you want logging messages on /tmp/fbsplash.log... */
 | 
			
		||||
#define DEBUG 0
 | 
			
		||||
 | 
			
		||||
#define BYTES_PER_PIXEL 2
 | 
			
		||||
 | 
			
		||||
typedef unsigned short DATA;
 | 
			
		||||
 | 
			
		||||
struct globals {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
	bool bdebug_messages;	// enable/disable logging
 | 
			
		||||
@@ -41,6 +37,7 @@ struct globals {
 | 
			
		||||
	const char *image_filename;
 | 
			
		||||
	struct fb_var_screeninfo scr_var;
 | 
			
		||||
	struct fb_fix_screeninfo scr_fix;
 | 
			
		||||
	unsigned bytes_per_pixel;
 | 
			
		||||
};
 | 
			
		||||
#define G (*ptr_to_globals)
 | 
			
		||||
#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
 | 
			
		||||
 */
 | 
			
		||||
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_FSCREENINFO, &G.scr_fix);
 | 
			
		||||
 | 
			
		||||
	if (G.scr_var.bits_per_pixel != 16)
 | 
			
		||||
		bb_error_msg_and_die("only 16 bpp is supported");
 | 
			
		||||
	if (G.scr_var.bits_per_pixel < 16 || G.scr_var.bits_per_pixel > 32)
 | 
			
		||||
		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
 | 
			
		||||
	G.addr = mmap(NULL,
 | 
			
		||||
			G.scr_var.xres * G.scr_var.yres_virtual
 | 
			
		||||
			* BYTES_PER_PIXEL /*(G.scr_var.bits_per_pixel / 8)*/,
 | 
			
		||||
			G.scr_var.xres * G.scr_var.yres * G.bytes_per_pixel,
 | 
			
		||||
			PROT_WRITE, MAP_SHARED, fbfd, 0);
 | 
			
		||||
	if (G.addr == MAP_FAILED)
 | 
			
		||||
		bb_perror_msg_and_die("mmap");
 | 
			
		||||
 | 
			
		||||
	// 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *	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)
 | 
			
		||||
{
 | 
			
		||||
	int cnt;
 | 
			
		||||
	DATA thispix;
 | 
			
		||||
	DATA *ptr1, *ptr2;
 | 
			
		||||
	unsigned thispix;
 | 
			
		||||
	unsigned char *ptr1, *ptr2;
 | 
			
		||||
	unsigned char nred = G.nbar_colr/2;
 | 
			
		||||
	unsigned char ngreen =  G.nbar_colg/2;
 | 
			
		||||
	unsigned char nblue = G.nbar_colb/2;
 | 
			
		||||
 | 
			
		||||
	nred   >>= 3;  // 5-bit red
 | 
			
		||||
	ngreen >>= 2;  // 6-bit green
 | 
			
		||||
	nblue  >>= 3;  // 5-bit blue
 | 
			
		||||
	thispix = nblue + (ngreen << 5) + (nred << (5+6));
 | 
			
		||||
	thispix = fb_pixel_value(nred, ngreen, nblue);
 | 
			
		||||
 | 
			
		||||
	// horizontal lines
 | 
			
		||||
	ptr1 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL);
 | 
			
		||||
	ptr2 = (DATA*)(G.addr + ((G.nbar_posy + G.nbar_height - 1) * 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 = 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;
 | 
			
		||||
	do {
 | 
			
		||||
		*ptr1++ = thispix;
 | 
			
		||||
		*ptr2++ = thispix;
 | 
			
		||||
		fb_write_pixel(ptr1, thispix);
 | 
			
		||||
		fb_write_pixel(ptr2, thispix);
 | 
			
		||||
		ptr1 += G.bytes_per_pixel;
 | 
			
		||||
		ptr2 += G.bytes_per_pixel;
 | 
			
		||||
	} while (--cnt >= 0);
 | 
			
		||||
 | 
			
		||||
	// vertical lines
 | 
			
		||||
	ptr1 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL);
 | 
			
		||||
	ptr2 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx + G.nbar_width - 1) * BYTES_PER_PIXEL);
 | 
			
		||||
	ptr1 = G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * G.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;
 | 
			
		||||
	do {
 | 
			
		||||
		*ptr1 = thispix; ptr1 += G.scr_var.xres;
 | 
			
		||||
		*ptr2 = thispix; ptr2 += G.scr_var.xres;
 | 
			
		||||
		fb_write_pixel(ptr1, thispix);
 | 
			
		||||
		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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *	Draw filled rectangle on framebuffer
 | 
			
		||||
 * Draw filled rectangle on framebuffer
 | 
			
		||||
 * \param nx1pos,ny1pos upper left position
 | 
			
		||||
 * \param nx2pos,ny2pos down right position
 | 
			
		||||
 * \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)
 | 
			
		||||
{
 | 
			
		||||
	int cnt1, cnt2, nypos;
 | 
			
		||||
	DATA thispix;
 | 
			
		||||
	DATA *ptr;
 | 
			
		||||
	unsigned thispix;
 | 
			
		||||
	unsigned char *ptr;
 | 
			
		||||
 | 
			
		||||
	nred   >>= 3;  // 5-bit red
 | 
			
		||||
	ngreen >>= 2;  // 6-bit green
 | 
			
		||||
	nblue  >>= 3;  // 5-bit blue
 | 
			
		||||
	thispix = nblue + (ngreen << 5) + (nred << (5+6));
 | 
			
		||||
	thispix = fb_pixel_value(nred, ngreen, nblue);
 | 
			
		||||
 | 
			
		||||
	cnt1 = ny2pos - ny1pos;
 | 
			
		||||
	nypos = ny1pos;
 | 
			
		||||
	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;
 | 
			
		||||
		do {
 | 
			
		||||
			*ptr++ = thispix;
 | 
			
		||||
			fb_write_pixel(ptr, thispix);
 | 
			
		||||
			ptr += G.bytes_per_pixel;
 | 
			
		||||
		} while (--cnt2 >= 0);
 | 
			
		||||
 | 
			
		||||
		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
 | 
			
		||||
 */
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
@@ -276,18 +307,16 @@ static void fb_drawimage(void)
 | 
			
		||||
		height = G.scr_var.yres;
 | 
			
		||||
	for (j = 0; j < height; j++) {
 | 
			
		||||
		unsigned char *pixel;
 | 
			
		||||
		DATA *src;
 | 
			
		||||
		unsigned char *src;
 | 
			
		||||
 | 
			
		||||
		if (fread(pixline, 1, line_size, theme_file) != line_size)
 | 
			
		||||
			bb_error_msg_and_die("bad PPM file '%s'", G.image_filename);
 | 
			
		||||
		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++) {
 | 
			
		||||
			unsigned thispix;
 | 
			
		||||
			thispix = (((unsigned)pixel[0] << 8) & 0xf800)
 | 
			
		||||
				| (((unsigned)pixel[1] << 3) & 0x07e0)
 | 
			
		||||
				| (((unsigned)pixel[2] >> 3));
 | 
			
		||||
			*src++ = thispix;
 | 
			
		||||
			unsigned thispix = fb_pixel_value(pixel[0], pixel[1], pixel[2]);
 | 
			
		||||
			fb_write_pixel(src, thispix);
 | 
			
		||||
			src += G.bytes_per_pixel;
 | 
			
		||||
			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
 | 
			
		||||
 */
 | 
			
		||||
static void init(const char *cfg_filename)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user