aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNuno Lucas <ntlucas@gmail.com>2011-03-28 15:30:59 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-03-28 15:30:59 +0200
commit0e89fd9c39655fe721dd8a7a09a6c532f4255c42 (patch)
tree965989052ed70ec7cadb462e3529c648df362f4c
parent55068c478ee8e8c058b0c9e37ce0ca57612c95b1 (diff)
downloadbusybox-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>
-rw-r--r--miscutils/fbsplash.c117
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
32typedef unsigned short DATA;
33
34struct globals { 30struct 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 */
73static void fb_open(const char *strfb_device) 70static 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 */
98static 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 */
113static 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 */
101static void fb_drawrectangle(void) 133static 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 */
171static void fb_drawprogressbar(unsigned percent) 202static 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 */
220static void fb_drawimage(void) 251static 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 */
303static void init(const char *cfg_filename) 332static void init(const char *cfg_filename)