[U-Boot] [PATCH 1/2] video: fix bug in logo_plot

If logo_plot() should ever be called with x starting position other than zero and for pixel depths greater than 8bpp, logo colors distortion will be observed. This patch fixes the issue.
Signed-off-by: Anatolij Gustschin agust@denx.de --- drivers/video/cfb_console.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 68b9861..97a37ba 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -1071,7 +1071,9 @@ void logo_plot (void *screen, int width, int x, int y) int ycount = VIDEO_LOGO_HEIGHT; unsigned char r, g, b, *logo_red, *logo_blue, *logo_green; unsigned char *source; - unsigned char *dest = (unsigned char *)screen + ((y * width * VIDEO_PIXEL_SIZE) + x); + unsigned char *dest = (unsigned char *)screen + + ((y * width * VIDEO_PIXEL_SIZE) + + x * VIDEO_PIXEL_SIZE);
#ifdef CONFIG_VIDEO_BMP_LOGO source = bmp_logo_bitmap;

FILL_15BIT_555RGB macro extension for pixel swapping by commit bed53753dd1d7e6bcbea4339be0fb7760214cc35 introduced a bug in cfb_console:
Bitmaps with odd-numbered width won't be rendered correctly and even U-Boot crashes are observed on some platforms while repeated rendering of such bitmaps with "bmp display". Also if a bitmap is rendered to an odd-numbered x starting position, the same problem occurs. This patch is an atempt to fix it.
Signed-off-by: Anatolij Gustschin agust@denx.de --- drivers/video/cfb_console.c | 59 ++++++++++++++++++++++++++---------------- 1 files changed, 36 insertions(+), 23 deletions(-)
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 97a37ba..d313e90 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -751,24 +751,10 @@ void video_puts (const char *s) fb ++; \ }
-#if !defined(VIDEO_FB_16BPP_PIXEL_SWAP) #define FILL_15BIT_555RGB(r,g,b) { \ *(unsigned short *)fb = SWAP16((unsigned short)(((r>>3)<<10) | ((g>>3)<<5) | (b>>3))); \ fb += 2; \ } -#else -static int tgl; -static unsigned short p0; -#define FILL_15BIT_555RGB(r,g,b) { \ - if (!tgl++) { \ - p0 = SWAP16((unsigned short)(((r>>3)<<10) | ((g>>3)<<5) | (b>>3))); \ - } else { \ - tgl=0; \ - *(unsigned long *)(fb-2) = (SWAP16((unsigned short)(((r>>3)<<10) | ((g>>3)<<5) | (b>>3)))<<16) | p0; \ - } \ - fb += 2; \ -} -#endif
#define FILL_16BIT_565RGB(r,g,b) { \ *(unsigned short *)fb = SWAP16((unsigned short)((((r)>>3)<<11) | (((g)>>2)<<5) | ((b)>>3))); \ @@ -796,6 +782,20 @@ static unsigned short p0; } #endif
+#if defined(VIDEO_FB_16BPP_PIXEL_SWAP) +static void inline fill_555rgb_pswap(uchar *fb, int x, + u8 r, u8 g, u8 b) +{ + ushort *dst = (ushort *)fb; + ushort color = (ushort)(((r >> 3) << 10) | + ((g >> 3) << 5) | + (b >> 3)); + if (x & 1) + *(--dst) = color; + else + *(++dst) = color; +} +#endif
/* * Display the BMP file located at address bmp_image. @@ -927,11 +927,20 @@ int video_display_bitmap (ulong bmp_image, int x, int y) 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_15BIT_555RGB (cte.red, cte.green, cte.blue); +#else + fill_555rgb_pswap (fb, xpos++, cte.red, + cte.green, cte.blue); + fb += 2; +#endif } bmap += padded_line; fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE; @@ -993,10 +1002,19 @@ int video_display_bitmap (ulong bmp_image, int x, int y) 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_15BIT_555RGB (bmap[2], bmap[1], bmap[0]); +#else + fill_555rgb_pswap (fb, xpos++, bmap[2], + bmap[1], bmap[0]); + fb += 2; +#endif bmap += 3; } bmap += padded_line; @@ -1103,6 +1121,9 @@ void logo_plot (void *screen, int width, int x, int y) }
while (ycount--) { +#if defined(VIDEO_FB_16BPP_PIXEL_SWAP) + int xpos = x; +#endif xcount = VIDEO_LOGO_WIDTH; while (xcount--) { r = logo_red[*source - VIDEO_LOGO_LUT_OFFSET]; @@ -1121,15 +1142,7 @@ void logo_plot (void *screen, int width, int x, int y) *(unsigned short *) dest = SWAP16 ((unsigned short) (((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3))); #else - { - if (!tgl++) { - p0 = SWAP16 ((unsigned short) (((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3))); - } else { - *(unsigned long *)(dest-2) = - (SWAP16 ((unsigned short) (((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)))<<16) | p0; - tgl=0; - } - } + fill_555rgb_pswap (dest, xpos++, r, g, b); #endif break; case GDF_16BIT_565RGB:

Dear Anatolij Gustschin,
In message 1218211240-21667-2-git-send-email-agust@denx.de you wrote:
FILL_15BIT_555RGB macro extension for pixel swapping by commit bed53753dd1d7e6bcbea4339be0fb7760214cc35 introduced a bug in cfb_console:
Bitmaps with odd-numbered width won't be rendered correctly and even U-Boot crashes are observed on some platforms while repeated rendering of such bitmaps with "bmp display". Also if a bitmap is rendered to an odd-numbered x starting position, the same problem occurs. This patch is an atempt to fix it.
Signed-off-by: Anatolij Gustschin agust@denx.de
drivers/video/cfb_console.c | 59 ++++++++++++++++++++++++++---------------- 1 files changed, 36 insertions(+), 23 deletions(-)
Applied, thanks.
Viele Grüße,
Wolfgang Denk

On 18:00 Fri 08 Aug , Anatolij Gustschin wrote:
If logo_plot() should ever be called with x starting position other than zero and for pixel depths greater than 8bpp, logo colors distortion will be observed. This patch fixes the issue.
Signed-off-by: Anatolij Gustschin agust@denx.de
drivers/video/cfb_console.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 68b9861..97a37ba 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -1071,7 +1071,9 @@ void logo_plot (void *screen, int width, int x, int y) int ycount = VIDEO_LOGO_HEIGHT; unsigned char r, g, b, *logo_red, *logo_blue, *logo_green; unsigned char *source;
- unsigned char *dest = (unsigned char *)screen + ((y * width * VIDEO_PIXEL_SIZE) + x);
- unsigned char *dest = (unsigned char *)screen +
((y * width * VIDEO_PIXEL_SIZE) +
x * VIDEO_PIXEL_SIZE);
why not simplify it?
- unsigned char *dest = (unsigned char *)screen +
((y * width + x) * VIDEO_PIXEL_SIZE);
#ifdef CONFIG_VIDEO_BMP_LOGO source = bmp_logo_bitmap; -- 1.5.4.3
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Jean-Christophe PLAGNIOL-VILLARD wrote:
<snip>
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 68b9861..97a37ba 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -1071,7 +1071,9 @@ void logo_plot (void *screen, int width, int x, int y) int ycount = VIDEO_LOGO_HEIGHT; unsigned char r, g, b, *logo_red, *logo_blue, *logo_green; unsigned char *source;
- unsigned char *dest = (unsigned char *)screen + ((y * width * VIDEO_PIXEL_SIZE) + x);
- unsigned char *dest = (unsigned char *)screen +
((y * width * VIDEO_PIXEL_SIZE) +
x * VIDEO_PIXEL_SIZE);
why not simplify it?
- unsigned char *dest = (unsigned char *)screen +
((y * width + x) * VIDEO_PIXEL_SIZE);
we could also drop the cast then. How about
+ unsigned char *dest = screen + (y * width + x) * VIDEO_PIXEL_SIZE; ?

Dear Anatolij Gustschin,
In message 1218211240-21667-1-git-send-email-agust@denx.de you wrote:
If logo_plot() should ever be called with x starting position other than zero and for pixel depths greater than 8bpp, logo colors distortion will be observed. This patch fixes the issue.
Signed-off-by: Anatolij Gustschin agust@denx.de
drivers/video/cfb_console.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
Applied, thanks.
Best regards,
Wolfgang Denk
participants (3)
-
Anatolij Gustschin
-
Jean-Christophe PLAGNIOL-VILLARD
-
Wolfgang Denk