in drivers/video/cfb_console.c [1306:1681]
int video_display_bitmap(ulong bmp_image, int x, int y)
{
ushort xcount, ycount;
uchar *fb;
struct bmp_image *bmp = (struct bmp_image *)bmp_image;
uchar *bmap;
ushort padded_line;
unsigned long width, height, bpp;
unsigned colors;
unsigned long compression;
struct bmp_color_table_entry cte;
#ifdef CONFIG_VIDEO_BMP_GZIP
unsigned char *dst = NULL;
ulong len;
#endif
WATCHDOG_RESET();
if (!((bmp->header.signature[0] == 'B') &&
(bmp->header.signature[1] == 'M'))) {
#ifdef CONFIG_VIDEO_BMP_GZIP
/*
* Could be a gzipped bmp image, try to decrompress...
*/
len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE;
dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
if (dst == NULL) {
printf("Error: malloc in gunzip failed!\n");
return 1;
}
/*
* NB: we need to force offset of +2
* See doc/README.displaying-bmps
*/
if (gunzip(dst+2, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE-2,
(uchar *) bmp_image,
&len) != 0) {
printf("Error: no valid bmp or bmp.gz image at %lx\n",
bmp_image);
free(dst);
return 1;
}
if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) {
printf("Image could be truncated "
"(increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n");
}
/*
* Set addr to decompressed image
*/
bmp = (struct bmp_image *)(dst+2);
if (!((bmp->header.signature[0] == 'B') &&
(bmp->header.signature[1] == 'M'))) {
printf("Error: no valid bmp.gz image at %lx\n",
bmp_image);
free(dst);
return 1;
}
#else
printf("Error: no valid bmp image at %lx\n", bmp_image);
return 1;
#endif /* CONFIG_VIDEO_BMP_GZIP */
}
width = le32_to_cpu(bmp->header.width);
height = le32_to_cpu(bmp->header.height);
bpp = le16_to_cpu(bmp->header.bit_count);
colors = le32_to_cpu(bmp->header.colors_used);
compression = le32_to_cpu(bmp->header.compression);
debug("Display-bmp: %ld x %ld with %d colors\n",
width, height, colors);
if (compression != BMP_BI_RGB
#ifdef CONFIG_VIDEO_BMP_RLE8
&& compression != BMP_BI_RLE8
#endif
) {
printf("Error: compression type %ld not supported\n",
compression);
#ifdef CONFIG_VIDEO_BMP_GZIP
if (dst)
free(dst);
#endif
return 1;
}
padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3;
#ifdef CONFIG_SPLASH_SCREEN_ALIGN
if (x == BMP_ALIGN_CENTER)
x = max(0, (int)(VIDEO_VISIBLE_COLS - width) / 2);
else if (x < 0)
x = max(0, (int)(VIDEO_VISIBLE_COLS - width + x + 1));
if (y == BMP_ALIGN_CENTER)
y = max(0, (int)(VIDEO_VISIBLE_ROWS - height) / 2);
else if (y < 0)
y = max(0, (int)(VIDEO_VISIBLE_ROWS - height + y + 1));
#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
/*
* Just ignore elements which are completely beyond screen
* dimensions.
*/
if ((x >= VIDEO_VISIBLE_COLS) || (y >= VIDEO_VISIBLE_ROWS))
return 0;
if ((x + width) > VIDEO_VISIBLE_COLS)
width = VIDEO_VISIBLE_COLS - x;
if ((y + height) > VIDEO_VISIBLE_ROWS)
height = VIDEO_VISIBLE_ROWS - y;
bmap = (uchar *) bmp + le32_to_cpu(bmp->header.data_offset);
fb = (uchar *) (video_fb_address +
((y + height - 1) * VIDEO_LINE_LEN) +
x * VIDEO_PIXEL_SIZE);
#ifdef CONFIG_VIDEO_BMP_RLE8
if (compression == BMP_BI_RLE8) {
return display_rle8_bitmap(bmp, x, y, width, height);
}
#endif
/* We handle only 4, 8, or 24 bpp bitmaps */
switch (le16_to_cpu(bmp->header.bit_count)) {
case 4:
padded_line -= width / 2;
ycount = height;
switch (VIDEO_DATA_FORMAT) {
case GDF_32BIT_X888RGB:
while (ycount--) {
WATCHDOG_RESET();
/*
* Don't assume that 'width' is an
* even number
*/
for (xcount = 0; xcount < width; xcount++) {
uchar idx;
if (xcount & 1) {
idx = *bmap & 0xF;
bmap++;
} else
idx = *bmap >> 4;
cte = bmp->color_table[idx];
FILL_32BIT_X888RGB(cte.red, cte.green,
cte.blue);
}
bmap += padded_line;
fb -= VIDEO_LINE_LEN + width *
VIDEO_PIXEL_SIZE;
}
break;
default:
puts("4bpp bitmap unsupported with current "
"video mode\n");
break;
}
break;
case 8:
padded_line -= width;
if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
/* Copy colormap */
for (xcount = 0; xcount < colors; ++xcount) {
cte = bmp->color_table[xcount];
video_set_lut(xcount, cte.red, cte.green,
cte.blue);
}
}
ycount = height;
switch (VIDEO_DATA_FORMAT) {
case GDF__8BIT_INDEX:
while (ycount--) {
WATCHDOG_RESET();
xcount = width;
while (xcount--) {
*fb++ = *bmap++;
}
bmap += padded_line;
fb -= VIDEO_LINE_LEN + width *
VIDEO_PIXEL_SIZE;
}
break;
case GDF__8BIT_332RGB:
while (ycount--) {
WATCHDOG_RESET();
xcount = width;
while (xcount--) {
cte = bmp->color_table[*bmap++];
FILL_8BIT_332RGB(cte.red, cte.green,
cte.blue);
}
bmap += padded_line;
fb -= VIDEO_LINE_LEN + width *
VIDEO_PIXEL_SIZE;
}
break;
case GDF_15BIT_555RGB:
while (ycount--) {
#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
int xpos = x;
#endif
WATCHDOG_RESET();
xcount = width;
while (xcount--) {
cte = bmp->color_table[*bmap++];
#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
fill_555rgb_pswap(fb, xpos++, cte.red,
cte.green,
cte.blue);
fb += 2;
#else
FILL_15BIT_555RGB(cte.red, cte.green,
cte.blue);
#endif
}
bmap += padded_line;
fb -= VIDEO_LINE_LEN + width *
VIDEO_PIXEL_SIZE;
}
break;
case GDF_16BIT_565RGB:
while (ycount--) {
WATCHDOG_RESET();
xcount = width;
while (xcount--) {
cte = bmp->color_table[*bmap++];
FILL_16BIT_565RGB(cte.red, cte.green,
cte.blue);
}
bmap += padded_line;
fb -= VIDEO_LINE_LEN + width *
VIDEO_PIXEL_SIZE;
}
break;
case GDF_32BIT_X888RGB:
while (ycount--) {
WATCHDOG_RESET();
xcount = width;
while (xcount--) {
cte = bmp->color_table[*bmap++];
FILL_32BIT_X888RGB(cte.red, cte.green,
cte.blue);
}
bmap += padded_line;
fb -= VIDEO_LINE_LEN + width *
VIDEO_PIXEL_SIZE;
}
break;
case GDF_24BIT_888RGB:
while (ycount--) {
WATCHDOG_RESET();
xcount = width;
while (xcount--) {
cte = bmp->color_table[*bmap++];
FILL_24BIT_888RGB(cte.red, cte.green,
cte.blue);
}
bmap += padded_line;
fb -= VIDEO_LINE_LEN + width *
VIDEO_PIXEL_SIZE;
}
break;
}
break;
case 24:
padded_line -= 3 * width;
ycount = height;
switch (VIDEO_DATA_FORMAT) {
case GDF__8BIT_332RGB:
while (ycount--) {
WATCHDOG_RESET();
xcount = width;
while (xcount--) {
FILL_8BIT_332RGB(bmap[2], bmap[1],
bmap[0]);
bmap += 3;
}
bmap += padded_line;
fb -= VIDEO_LINE_LEN + width *
VIDEO_PIXEL_SIZE;
}
break;
case GDF_15BIT_555RGB:
while (ycount--) {
#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
int xpos = x;
#endif
WATCHDOG_RESET();
xcount = width;
while (xcount--) {
#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
fill_555rgb_pswap(fb, xpos++, bmap[2],
bmap[1], bmap[0]);
fb += 2;
#else
FILL_15BIT_555RGB(bmap[2], bmap[1],
bmap[0]);
#endif
bmap += 3;
}
bmap += padded_line;
fb -= VIDEO_LINE_LEN + width *
VIDEO_PIXEL_SIZE;
}
break;
case GDF_16BIT_565RGB:
while (ycount--) {
WATCHDOG_RESET();
xcount = width;
while (xcount--) {
FILL_16BIT_565RGB(bmap[2], bmap[1],
bmap[0]);
bmap += 3;
}
bmap += padded_line;
fb -= VIDEO_LINE_LEN + width *
VIDEO_PIXEL_SIZE;
}
break;
case GDF_32BIT_X888RGB:
while (ycount--) {
WATCHDOG_RESET();
xcount = width;
while (xcount--) {
FILL_32BIT_X888RGB(bmap[2], bmap[1],
bmap[0]);
bmap += 3;
}
bmap += padded_line;
fb -= VIDEO_LINE_LEN + width *
VIDEO_PIXEL_SIZE;
}
break;
case GDF_24BIT_888RGB:
while (ycount--) {
WATCHDOG_RESET();
xcount = width;
while (xcount--) {
FILL_24BIT_888RGB(bmap[2], bmap[1],
bmap[0]);
bmap += 3;
}
bmap += padded_line;
fb -= VIDEO_LINE_LEN + width *
VIDEO_PIXEL_SIZE;
}
break;
default:
printf("Error: 24 bits/pixel bitmap incompatible "
"with current video mode\n");
break;
}
break;
default:
printf("Error: %d bit/pixel bitmaps not supported by U-Boot\n",
le16_to_cpu(bmp->header.bit_count));
break;
}
#ifdef CONFIG_VIDEO_BMP_GZIP
if (dst) {
free(dst);
}
#endif
if (cfb_do_flush_cache)
flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
return (0);
}