Re: [Linux-fbdev-devel] [PATCH] fbdev: fix fillrect for 24bpp modes
- From: Krzysztof Helt <krzysztof.h1@xxxxxxxxx>
- Date: Fri, 17 Apr 2009 18:36:17 +0200
On Mon, 13 Apr 2009 19:09:54 +0200
Michal Januszewski <spock@xxxxxxxxxx> wrote:
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.
I can confirm the patch fixes the issue it describes if the line is not padded
or padded in a special way. See my comments below.
Signed-off-by: Michal Januszewski <spock@xxxxxxxxxx>
---
diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c
index 64b3576..396e676 100644
--- a/drivers/video/cfbfillrect.c
+++ b/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, unsigned long __iomem *dst, int dst_idx,
// 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, const struct fb_fillrect *rect)
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, const struct fb_fillrect *rect)
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);
The r is simply dst_idx / bits. Most compilers will optimize it away into
a simple shift because the bits has only one bit set (it is number of bits in a long variable, ie. 32 or 64).
+ pat = pat << ((left*r) % bpp) | pat >> ((right*r) % bpp);
If the r = (dst_idx / bits) it is number of long words. The shift by ((left*r) % bpp) does
not make much sense (try left = 3 and r = 24 words - it is always zero but should be 3).
It is even worse if a line is padded so line's length modulo bpp is not
zero it does not work. A colorful pattern is produced after the "mtest" text.
A dst_idx offset is not taken into account (it could be non-zero only for depths < 8 bits).
Kind regards,
Krzysztof
----------------------------------------------------------------------
Najlepsze dzwonki MP3 na telefon komorkowy!
Sprawdz >> http://link.interia.pl/f2128
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
- Follow-Ups:
- Re: [Linux-fbdev-devel] [PATCH] fbdev: fix fillrect for 24bpp modes
- From: Andrew Morton
- Re: [Linux-fbdev-devel] [PATCH] fbdev: fix fillrect for 24bpp modes
- References:
- [PATCH] fbdev: fix fillrect for 24bpp modes
- From: Michal Januszewski
- [PATCH] fbdev: fix fillrect for 24bpp modes
- Prev by Date: Re: [PATCH 2/4] x86/pvops: target CREATE_TRACE_POINTS to particular subsystems
- Next by Date: Re: [PATCH] netfilter: use per-cpu spinlock rather than RCU (v3)
- Previous by thread: [PATCH] fbdev: fix fillrect for 24bpp modes
- Next by thread: Re: [Linux-fbdev-devel] [PATCH] fbdev: fix fillrect for 24bpp modes
- Index(es):
Relevant Pages
|