
Using RGB to pixel conversion function provided in previous patch to implement frame buffer writing functions.
Massively simplifed the code, also get rid of limitations on bmp_bpix vs display_bpix.
Test cases are also corrected to refect a tiny change in color quantization.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- drivers/video/video_bmp.c | 201 +++++++++++++--------------------------------- test/dm/video.c | 4 +- 2 files changed, 59 insertions(+), 146 deletions(-)
diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c index 83380a87fd2b..80c276aaf231 100644 --- a/drivers/video/video_bmp.c +++ b/drivers/video/video_bmp.c @@ -17,42 +17,6 @@ #define BMP_RLE8_EOBMP 1 #define BMP_RLE8_DELTA 2
-/** - * get_bmp_col_16bpp() - Convert a colour-table entry into a 16bpp pixel value - * - * Return: value to write to the 16bpp frame buffer for this palette entry - */ -static uint get_bmp_col_16bpp(struct bmp_color_table_entry cte) -{ - return ((cte.red << 8) & 0xf800) | - ((cte.green << 3) & 0x07e0) | - ((cte.blue >> 3) & 0x001f); -} - -/** - * get_bmp_col_x2r10g10b10() - Convert a colour-table entry into a x2r10g10b10 pixel value - * - * Return: value to write to the x2r10g10b10 frame buffer for this palette entry - */ -static u32 get_bmp_col_x2r10g10b10(struct bmp_color_table_entry *cte) -{ - return ((cte->red << 22U) | - (cte->green << 12U) | - (cte->blue << 2U)); -} - -/** - * get_bmp_col_rgba8888() - Convert a colour-table entry into a rgba8888 pixel value - * - * Return: value to write to the rgba8888 frame buffer for this palette entry - */ -static u32 get_bmp_col_rgba8888(struct bmp_color_table_entry *cte) -{ - return ((cte->red) | - (cte->green << 8U) | - (cte->blue << 16U) | 0xff << 24U); -} - /** * write_pix8() - Write a pixel from a BMP image into the framebuffer * @@ -63,33 +27,37 @@ static u32 get_bmp_col_rgba8888(struct bmp_color_table_entry *cte) * @palette: BMP palette table * @bmap: Pointer to BMP bitmap position to write. This contains a single byte * which is either written directly (bpix == 8) or used to look up the - * palette to get a colour to write + * palette to get a colour to write, NULL if it's a pseudo palette with one entry. */ static void write_pix8(u8 *fb, uint bpix, enum video_format eformat, struct bmp_color_table_entry *palette, u8 *bmap) { - if (bpix == 8) { - *fb++ = *bmap; - } else if (bpix == 16) { - *(u16 *)fb = get_bmp_col_16bpp(palette[*bmap]); - } else { - /* Only support big endian */ - struct bmp_color_table_entry *cte = &palette[*bmap]; - - if (bpix == 24) { - *fb++ = cte->red; - *fb++ = cte->green; - *fb++ = cte->blue; - } else if (eformat == VIDEO_XRGB2101010) { - *(u32 *)fb = get_bmp_col_x2r10g10b10(cte); - } else if (eformat == VIDEO_RGBA8888) { - *(u32 *)fb = get_bmp_col_rgba8888(cte); - } else { - *fb++ = cte->blue; - *fb++ = cte->green; - *fb++ = cte->red; - *fb++ = 0; - } + const int entry = bmap ? *bmap : 0; + const struct video_rgb rgb = { + .r = palette[entry].red, + .g = palette[entry].green, + .b = palette[entry].blue + }; + + switch (bpix) { +#if CONFIG_IS_ENABLED(VIDEO_BPP8) + case 8: + *(u8 *)fb = video_rgb_to_pixel8(eformat, rgb); + break; +#endif +#if CONFIG_IS_ENABLED(VIDEO_BPP16) + case 16: + *(u16 *)fb = video_rgb_to_pixel16(eformat, rgb); + break; +#endif +#if CONFIG_IS_ENABLED(VIDEO_BPP32) + case 32: + *(u32 *)fb = video_rgb_to_pixel32(eformat, rgb); + break; +#endif + default: + log_debug("Unsupported BPP %d for BMP\n", bpix); + break; } }
@@ -266,6 +234,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, unsigned colours, bpix, bmp_bpix; enum video_format eformat; struct bmp_color_table_entry *palette; + struct bmp_color_table_entry pseudo_cte __maybe_unused; int hdr_size; int ret;
@@ -293,21 +262,6 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, return -EINVAL; }
- /* - * We support displaying 8bpp and 24bpp BMPs on 16bpp LCDs - * and displaying 24bpp BMPs on 32bpp LCDs - */ - if (bpix != bmp_bpix && - !(bmp_bpix == 8 && bpix == 16) && - !(bmp_bpix == 8 && bpix == 24) && - !(bmp_bpix == 8 && bpix == 32) && - !(bmp_bpix == 24 && bpix == 16) && - !(bmp_bpix == 24 && bpix == 32)) { - printf("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n", - bpix, colours); - return -EPERM; - } - debug("Display-bmp: %d x %d with %d colours, display %d\n", (int)width, (int)height, (int)colours, 1 << bpix);
@@ -354,10 +308,10 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, for (j = 0; j < width; j++) { write_pix8(fb, bpix, eformat, palette, bmap); bmap++; - fb += bpix / 8; + fb += bpix / BITS_PER_BYTE; } bmap += (padded_width - width); - fb -= byte_width + priv->line_length; + fb -= priv->line_length + width * (bpix / BITS_PER_BYTE); } break; case 16: @@ -365,93 +319,52 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, for (i = 0; i < height; ++i) { schedule(); for (j = 0; j < width; j++) { - *fb++ = *bmap++; - *fb++ = *bmap++; + u16 bmp_rgb = le16_to_cpu(*(u16 *)bmap); + /* RGB565 */ + pseudo_cte.red = ((bmp_rgb & 0xf800) >> 11) << 3; + pseudo_cte.green = ((bmp_rgb & 0x7e0) >> 5) << 2; + pseudo_cte.blue = (bmp_rgb & 0x1F) << 3; + write_pix8(fb, bpix, eformat, &pseudo_cte, NULL); + fb += (bpix / BITS_PER_BYTE); + bmap += (bmp_bpix / BITS_PER_BYTE); } bmap += (padded_width - width); - fb -= width * 2 + priv->line_length; + fb -= priv->line_length + width * (bpix / BITS_PER_BYTE); } } break; case 24: if (CONFIG_IS_ENABLED(BMP_24BPP)) { for (i = 0; i < height; ++i) { + schedule(); for (j = 0; j < width; j++) { - if (bpix == 16) { - /* 16bit 565RGB format */ - *(u16 *)fb = ((bmap[2] >> 3) - << 11) | - ((bmap[1] >> 2) << 5) | - (bmap[0] >> 3); - bmap += 3; - fb += 2; - } else if (eformat == VIDEO_XRGB2101010) { - u32 pix; - - pix = *bmap++ << 2U; - pix |= *bmap++ << 12U; - pix |= *bmap++ << 22U; - *fb++ = pix & 0xff; - *fb++ = (pix >> 8) & 0xff; - *fb++ = (pix >> 16) & 0xff; - *fb++ = pix >> 24; - } else if (eformat == VIDEO_RGBA8888) { - u32 pix; - - pix = *bmap++ << 8U; /* blue */ - pix |= *bmap++ << 16U; /* green */ - pix |= *bmap++ << 24U; /* red */ - - *fb++ = (pix >> 24) & 0xff; - *fb++ = (pix >> 16) & 0xff; - *fb++ = (pix >> 8) & 0xff; - *fb++ = 0xff; - } else { - *fb++ = *bmap++; - *fb++ = *bmap++; - *fb++ = *bmap++; - *fb++ = 0; - } + pseudo_cte.blue = *bmap++; + pseudo_cte.green = *bmap++; + pseudo_cte.red = *bmap++; + write_pix8(fb, bpix, eformat, &pseudo_cte, NULL); + fb += (bpix / BITS_PER_BYTE); } - fb -= priv->line_length + width * (bpix / 8); bmap += (padded_width - width); + fb -= priv->line_length + width * (bpix / BITS_PER_BYTE); } } break; case 32: if (CONFIG_IS_ENABLED(BMP_32BPP)) { for (i = 0; i < height; ++i) { + schedule(); for (j = 0; j < width; j++) { - if (eformat == VIDEO_XRGB2101010) { - u32 pix; - - pix = *bmap++ << 2U; - pix |= *bmap++ << 12U; - pix |= *bmap++ << 22U; - pix |= (*bmap++ >> 6) << 30U; - *fb++ = pix & 0xff; - *fb++ = (pix >> 8) & 0xff; - *fb++ = (pix >> 16) & 0xff; - *fb++ = pix >> 24; - } else if (eformat == VIDEO_RGBA8888) { - u32 pix; - - pix = *bmap++ << 8U; /* blue */ - pix |= *bmap++ << 16U; /* green */ - pix |= *bmap++ << 24U; /* red */ - bmap++; - *fb++ = (pix >> 24) & 0xff; - *fb++ = (pix >> 16) & 0xff; - *fb++ = (pix >> 8) & 0xff; - *fb++ = 0xff; /* opacity */ - } else { - *fb++ = *bmap++; - *fb++ = *bmap++; - *fb++ = *bmap++; - *fb++ = *bmap++; - } + u32 bmp_rgb = le32_to_cpu(*(u32 *)bmap); + /* RGBX8888 */ + pseudo_cte.red = (bmp_rgb >> 24) & 0xff; + pseudo_cte.green = (bmp_rgb >> 16) & 0xff; + pseudo_cte.blue = (bmp_rgb >> 8) & 0xff; + write_pix8(fb, bpix, eformat, &pseudo_cte, NULL); + fb += (bpix / BITS_PER_BYTE); + bmap += (bmp_bpix / BITS_PER_BYTE); } - fb -= priv->line_length + width * (bpix / 8); + bmap += (padded_width - width); + fb -= priv->line_length + width * (bpix / BITS_PER_BYTE); } } break; diff --git a/test/dm/video.c b/test/dm/video.c index 7dfbeb9555d1..0da96aec5efd 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -400,7 +400,7 @@ static int dm_test_video_bmp8(struct unit_test_state *uts) ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
ut_assertok(video_bmp_display(dev, addr, 0, 0, false)); - ut_asserteq(1247, compress_frame_buffer(uts, dev)); + ut_asserteq(1118, compress_frame_buffer(uts, dev));
return 0; } @@ -541,7 +541,7 @@ static int dm_test_video_comp_bmp8(struct unit_test_state *uts) ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
ut_assertok(video_bmp_display(dev, addr, 0, 0, false)); - ut_asserteq(1247, compress_frame_buffer(uts, dev)); + ut_asserteq(1118, compress_frame_buffer(uts, dev));
return 0; }