The patch titled fbdev: fix fillrect for 24bpp modes has been added to the -mm tree. Its filename is fbdev-fix-fillrect-for-24bpp-modes.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/SubmitChecklist when testing your code *** See http://userweb.kernel.org/~akpm/stuff/added-to-mm.txt to find out what to do about this The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/ ------------------------------------------------------ Subject: fbdev: fix fillrect for 24bpp modes From: Michal Januszewski <spock@xxxxxxxxxx> The software fillrect routines do not work properly when the number of pixels per machine word is not an integer. To see that, run the following command on a fbdev console with a 24bpp video mode, using a non-accelerated driver such as (u)vesafb: reset ; echo -e '\e[41mtest\e[K' The expected result is 'test' displayed on a line with red background. Instead of that, 'test' has a red background, but the rest of the line (rendered using fillrect()) contains a distored colorful pattern. This patch fixes the problem by correctly computing rotation shifts. It has been tested in a 24bpp mode on 32- and 64-bit little-endian machines. Signed-off-by: Michal Januszewski <spock@xxxxxxxxxx> Cc: Krzysztof Helt <krzysztof.h1@xxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- drivers/video/cfbfillrect.c | 23 +++++++++++------------ drivers/video/fb_draw.h | 8 ++++---- drivers/video/sysfillrect.c | 17 ++++++++++------- 3 files changed, 25 insertions(+), 23 deletions(-) diff -puN drivers/video/cfbfillrect.c~fbdev-fix-fillrect-for-24bpp-modes drivers/video/cfbfillrect.c --- a/drivers/video/cfbfillrect.c~fbdev-fix-fillrect-for-24bpp-modes +++ a/drivers/video/cfbfillrect.c @@ -9,10 +9,6 @@ * * NOTES: * - * The code for depths like 24 that don't have integer number of pixels per - * long is broken and needs to be fixed. For now I turned these types of - * mode off. - * * Also need to add code to deal with cards endians that are different than * the native cpu endians. I also need to deal with MSB position in the word. * @@ -139,7 +135,7 @@ bitfill_unaligned(struct fb_info *p, uns // Trailing bits if (last) - FB_WRITEL(comp(pat, FB_READL(dst), first), dst); + FB_WRITEL(comp(pat, FB_READL(dst), last), dst); } } @@ -297,7 +293,7 @@ void cfb_fillrect(struct fb_info *p, con else fg = rect->color; - pat = pixel_to_pat( bpp, fg); + pat = pixel_to_pat(bpp, fg); dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1)); dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8; @@ -333,17 +329,20 @@ void cfb_fillrect(struct fb_info *p, con dst_idx += p->fix.line_length*8; } } else { - int right; - int r; - int rot = (left-dst_idx) % bpp; + int right, r; void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, unsigned long pat, int left, int right, unsigned n, int bits) = NULL; - +#ifdef __LITTLE_ENDIAN + right = left; + left = bpp - right; +#else + right = bpp - left; +#endif /* rotate pattern to correct start position */ - pat = pat << rot | pat >> (bpp-rot); + r = dst_idx >> (ffs(bits) - 1); + pat = pat << ((left*r) % bpp) | pat >> ((right*r) % bpp); - right = bpp-left; switch (rect->rop) { case ROP_XOR: fill_op = bitfill_unaligned_rev; diff -puN drivers/video/fb_draw.h~fbdev-fix-fillrect-for-24bpp-modes drivers/video/fb_draw.h --- a/drivers/video/fb_draw.h~fbdev-fix-fillrect-for-24bpp-modes +++ a/drivers/video/fb_draw.h @@ -33,11 +33,11 @@ pixel_to_pat( u32 bpp, u32 pixel) case 8: return 0x0101010101010101ul*pixel; case 12: - return 0x0001001001001001ul*pixel; + return 0x1001001001001001ul*pixel; case 16: return 0x0001000100010001ul*pixel; case 24: - return 0x0000000001000001ul*pixel; + return 0x0001000001000001ul*pixel; case 32: return 0x0000000100000001ul*pixel; default: @@ -58,11 +58,11 @@ pixel_to_pat( u32 bpp, u32 pixel) case 8: return 0x01010101ul*pixel; case 12: - return 0x00001001ul*pixel; + return 0x01001001ul*pixel; case 16: return 0x00010001ul*pixel; case 24: - return 0x00000001ul*pixel; + return 0x01000001ul*pixel; case 32: return 0x00000001ul*pixel; default: diff -puN drivers/video/sysfillrect.c~fbdev-fix-fillrect-for-24bpp-modes drivers/video/sysfillrect.c --- a/drivers/video/sysfillrect.c~fbdev-fix-fillrect-for-24bpp-modes +++ a/drivers/video/sysfillrect.c @@ -124,7 +124,7 @@ bitfill_unaligned(struct fb_info *p, uns /* Trailing bits */ if (last) - *dst = comp(pat, *dst, first); + *dst = comp(pat, *dst, last); } } @@ -292,17 +292,20 @@ void sys_fillrect(struct fb_info *p, con dst_idx += p->fix.line_length*8; } } else { - int right; - int r; - int rot = (left-dst_idx) % bpp; + int right, r; void (*fill_op)(struct fb_info *p, unsigned long *dst, int dst_idx, unsigned long pat, int left, int right, unsigned n, int bits) = NULL; - +#ifdef __LITTLE_ENDIAN + right = left; + left = bpp - right; +#else + right = bpp - left; +#endif /* rotate pattern to correct start position */ - pat = pat << rot | pat >> (bpp-rot); + r = dst_idx >> (ffs(bits) - 1); + pat = pat << ((left*r) % bpp) | pat >> ((right*r) % bpp); - right = bpp-left; switch (rect->rop) { case ROP_XOR: fill_op = bitfill_unaligned_rev; _ Patches currently in -mm which might be from spock@xxxxxxxxxx are linux-next.patch fbdev-fix-fillrect-for-24bpp-modes.patch -- To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html