[PATCH 4/6] video: bmp: Rework with video_rgb_to_pixel_*
Jiaxun Yang
jiaxun.yang at flygoat.com
Fri May 17 00:16:44 CEST 2024
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 at 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;
}
--
2.34.1
More information about the U-Boot
mailing list