Acked-by: Che-Liang Chiou <clch...@chromium.org>
On Fri, Sep 28, 2012 at 6:11 PM, Simon Glass <s...@chromium.org> wrote: > From: Tom Wai-Hong Tam <waih...@google.com> > > Add support for drawing compressed RLE8 bitmaps. > > Reference: http://www.digicamsoft.com/bmp/bmp.html > > Signed-off-by: Che-Liang Chiou <clch...@chromium.org> > Signed-off-by: Tom Wai-Hong Tam <waih...@chromium.org> > Signed-off-by: Simon Glass <s...@chromium.org> > --- > README | 5 ++ > common/lcd.c | 144 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 149 insertions(+), 0 deletions(-) > > diff --git a/README b/README > index 5793b0a..40899d9 100644 > --- a/README > +++ b/README > @@ -1440,6 +1440,11 @@ The following options need to be configured: > Normally display is black on white background; define > CONFIG_SYS_WHITE_ON_BLACK to get it inverted. > > + CONFIG_LCD_BMP_RLE8 > + > + Support drawing of RLE8-compressed bitmaps on the LCD. > + > + > - Splash Screen Support: CONFIG_SPLASH_SCREEN > > If this option is set, the environment is checked for > diff --git a/common/lcd.c b/common/lcd.c > index 004a6be..68df6d0 100644 > --- a/common/lcd.c > +++ b/common/lcd.c > @@ -642,6 +642,136 @@ static void splash_align_axis(int *axis, unsigned long > panel_size, > } > #endif > > + > +#ifdef CONFIG_LCD_BMP_RLE8 > + > +#define BMP_RLE8_ESCAPE 0 > +#define BMP_RLE8_EOL 0 > +#define BMP_RLE8_EOBMP 1 > +#define BMP_RLE8_DELTA 2 > + > +static void draw_unencoded_bitmap(ushort **fbp, uchar *bmap, ushort *cmap, > + int cnt) > +{ > + while (cnt > 0) { > + *(*fbp)++ = cmap[*bmap++]; > + cnt--; > + } > +} > + > +static void draw_encoded_bitmap(ushort **fbp, ushort c, int cnt) > +{ > + ushort *fb = *fbp; > + int cnt_8copy = cnt >> 3; > + cnt -= cnt_8copy << 3; > + while (cnt_8copy > 0) { > + *fb++ = c; > + *fb++ = c; > + *fb++ = c; > + *fb++ = c; > + *fb++ = c; > + *fb++ = c; > + *fb++ = c; > + *fb++ = c; > + cnt_8copy--; > + } > + while (cnt > 0) { > + *fb++ = c; > + cnt--; > + } > + (*fbp) = fb; > +} > + > +/* Do not call this function directly, must be called from > + * lcd_display_bitmap. > + */ > +static void lcd_display_rle8_bitmap(bmp_image_t *bmp, ushort *cmap, uchar > *fb, > + int x_off, int y_off) > +{ > + uchar *bmap; > + ulong width, height; > + ulong cnt, runlen; > + int x, y; > + int decode = 1; > + > + width = le32_to_cpu(bmp->header.width); > + height = le32_to_cpu(bmp->header.height); > + bmap = (uchar *)bmp + le32_to_cpu(bmp->header.data_offset); > + > + x = 0; > + y = height - 1; > + > + while (decode) { > + if (bmap[0] == BMP_RLE8_ESCAPE) { > + switch (bmap[1]) { > + case BMP_RLE8_EOL: > + /* end of line */ > + bmap += 2; > + x = 0; > + y--; > + /* 16bpix, 2-byte per pixel, width should *2 > */ > + fb -= (width * 2 + lcd_line_length); > + break; > + case BMP_RLE8_EOBMP: > + /* end of bitmap */ > + decode = 0; > + break; > + case BMP_RLE8_DELTA: > + /* delta run */ > + x += bmap[2]; > + y -= bmap[3]; > + /* 16bpix, 2-byte per pixel, x should *2 */ > + fb = (uchar *) (lcd_base + (y + y_off - 1) > + * lcd_line_length + (x + x_off) * 2); > + bmap += 4; > + break; > + default: > + /* unencoded run */ > + runlen = bmap[1]; > + bmap += 2; > + if (y < height) { > + if (x < width) { > + if (x + runlen > width) > + cnt = width - x; > + else > + cnt = runlen; > + draw_unencoded_bitmap( > + (ushort **)&fb, > + bmap, cmap, cnt); > + } > + x += runlen; > + } > + bmap += runlen; > + if (runlen & 1) > + bmap++; > + } > + } else { > + /* encoded run */ > + if (y < height) { > + runlen = bmap[0]; > + if (x < width) { > + /* aggregate the same code */ > + while (bmap[0] == 0xff && > + bmap[2] != BMP_RLE8_ESCAPE && > + bmap[1] == bmap[3]) { > + runlen += bmap[2]; > + bmap += 2; > + } > + if (x + runlen > width) > + cnt = width - x; > + else > + cnt = runlen; > + draw_encoded_bitmap((ushort **)&fb, > + cmap[bmap[1]], cnt); > + } > + x += runlen; > + } > + bmap += 2; > + } > + } > +} > +#endif > + > #if defined(CONFIG_MPC823) || defined(CONFIG_MCC200) > #define FB_PUT_BYTE(fb, from) *(fb)++ = (255 - *(from)++) > #else > @@ -679,6 +809,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) > unsigned long width, height, byte_width; > unsigned long pwidth = panel_info.vl_col; > unsigned colors, bpix, bmp_bpix; > + unsigned long compression; > > if (!bmp || !((bmp->header.signature[0] == 'B') && > (bmp->header.signature[1] == 'M'))) { > @@ -691,6 +822,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) > height = le32_to_cpu(bmp->header.height); > bmp_bpix = le16_to_cpu(bmp->header.bit_count); > colors = 1 << bmp_bpix; > + compression = le32_to_cpu(bmp->header.compression); > > bpix = NBITS(panel_info.vl_bpix); > > @@ -783,6 +915,18 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) > switch (bmp_bpix) { > case 1: /* pass through */ > case 8: > +#ifdef CONFIG_LCD_BMP_RLE8 > + if (compression == BMP_BI_RLE8) { > + if (bpix != 16) { > + /* TODO implement render code for bpix != 16 > */ > + printf("Error: only support 16 bpix"); > + return 1; > + } > + lcd_display_rle8_bitmap(bmp, cmap_base, fb, x, y); > + break; > + } > +#endif > + > if (bpix != 16) > byte_width = width; > else > -- > 1.7.7.3 > _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot