|
From: Pavel P. <pi...@cm...> - 2007-10-09 11:14:13
|
This correct case, when source and destination X coordinates difference is not
multiple of pixels in byte. This is probably rare case, but this case should be
supported for completeness.
Reorganization of FB_READL and FB_WRITEL calls results in code size decrease
for normal build without swapping support and size with support enabled
is reasonable too.
Signed-off-by: Pavel Pisa <pi...@cm...>
--
Hello Tony,
thanks for forwarding two patches to MM tree.
fbdev-support-for-byte-reversed-framebuffer-formats.patch
imxfb-fast-read-flag-and-nonstandard-field-configurable.patch
What are yours plans with the third one. Do you think, that it
can fit in 2.6.24 merge window or you want to push changes
incremental and delay it for 2.6.25. Have you found time to test
it on your setup? I have planed to prepare some in kernel test
with rectangles and copying, because functions are hard to test
from userspace, but I have not found time for that. The code works
right on our HW, but the real range of FB devices is much much
more variable.
Thanks for care
Pavel
drivers/video/cfbcopyarea.c | 84 ++++++++++++++++++++++++++++++--------------
1 file changed, 59 insertions(+), 25 deletions(-)
Index: linux-2.6.23/drivers/video/cfbcopyarea.c
===================================================================
--- linux-2.6.23.orig/drivers/video/cfbcopyarea.c
+++ linux-2.6.23/drivers/video/cfbcopyarea.c
@@ -94,29 +94,34 @@ bitcpy(unsigned long __iomem *dst, int d
FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
}
} else {
+ // Different alignment for source and dest
unsigned long d0, d1;
int m;
- // Different alignment for source and dest
right = shift & (bits - 1);
left = -shift & (bits - 1);
+ bswapmask &= shift;
if (dst_idx+n <= bits) {
// Single destination word
if (last)
first &= last;
+ d0 = FB_READL(src);
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
if (shift > 0) {
// Single source word
- FB_WRITEL( comp( FB_READL(src) >> right, FB_READL(dst), first), dst);
+ d0 >>= right;
} else if (src_idx+n <= bits) {
// Single source word
- FB_WRITEL( comp(FB_READL(src) << left, FB_READL(dst), first), dst);
+ d0 <<= left;;
} else {
// 2 source words
- d0 = FB_READL(src++);
- d1 = FB_READL(src);
- FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst);
+ d1 = FB_READL(src + 1);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0<<left | d1>>right;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL( comp(d0, FB_READL(dst), first), dst);
} else {
// Multiple destination words
/** We must always remember the last value read, because in case
@@ -125,25 +130,31 @@ bitcpy(unsigned long __iomem *dst, int d
overlap with the current long from SRC. We store this value in
'd0'. */
d0 = FB_READL(src++);
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
// Leading bits
if (shift > 0) {
// Single source word
- FB_WRITEL( comp(d0 >> right, FB_READL(dst), first), dst);
+ d1 = d0;
+ d0 >>= right;
dst++;
n -= bits - dst_idx;
} else {
// 2 source words
d1 = FB_READL(src++);
- FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst);
- d0 = d1;
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+
+ d0 = d0<<left | d1>>right;
dst++;
n -= bits - dst_idx;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL( comp(d0, FB_READL(dst), first), dst);
+ d0 = d1;
// Main chunk
m = n % bits;
n /= bits;
- while (n >= 4) {
+ while ((n >= 4) && !bswapmask) {
d1 = FB_READL(src++);
FB_WRITEL(d0 << left | d1 >> right, dst++);
d0 = d1;
@@ -160,7 +171,10 @@ bitcpy(unsigned long __iomem *dst, int d
}
while (n--) {
d1 = FB_READL(src++);
- FB_WRITEL(d0 << left | d1 >> right, dst++);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0 << left | d1 >> right;
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(d0, dst++);
d0 = d1;
}
@@ -168,12 +182,15 @@ bitcpy(unsigned long __iomem *dst, int d
if (last) {
if (m <= right) {
// Single source word
- FB_WRITEL( comp(d0 << left, FB_READL(dst), last), dst);
+ d0 <<= left;
} else {
// 2 source words
d1 = FB_READL(src);
- FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), last), dst);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0<<left | d1>>right;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL( comp(d0, FB_READL(dst), last), dst);
}
}
}
@@ -247,24 +264,32 @@ bitcpy_rev(unsigned long __iomem *dst, i
}
} else {
// Different alignment for source and dest
+ unsigned long d0, d1;
+ int m;
int const left = -shift & (bits-1);
int const right = shift & (bits-1);
+ bswapmask &= shift;
if ((unsigned long)dst_idx+1 >= n) {
// Single destination word
if (last)
first &= last;
+ d0 = FB_READL(src);
if (shift < 0) {
// Single source word
- FB_WRITEL( comp( FB_READL(src)<<left, FB_READL(dst), first), dst);
+ d0 <<= left;
} else if (1+(unsigned long)src_idx >= n) {
// Single source word
- FB_WRITEL( comp( FB_READL(src)>>right, FB_READL(dst), first), dst);
+ d0 >>= right;
} else {
// 2 source words
- FB_WRITEL( comp( (FB_READL(src)>>right | FB_READL(src-1)<<left), FB_READL(dst), first), dst);
+ d1 = FB_READL(src - 1);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0>>right | d1<<left;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL( comp(d0, FB_READL(dst), first), dst);
} else {
// Multiple destination words
/** We must always remember the last value read, because in case
@@ -272,27 +297,30 @@ bitcpy_rev(unsigned long __iomem *dst, i
1bpp), we always collect one full long for DST and that might
overlap with the current long from SRC. We store this value in
'd0'. */
- unsigned long d0, d1;
- int m;
d0 = FB_READL(src--);
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
// Leading bits
if (shift < 0) {
// Single source word
- FB_WRITEL( comp( (d0 << left), FB_READL(dst), first), dst);
+ d1 = d0;
+ d0 <<= left;
} else {
// 2 source words
d1 = FB_READL(src--);
- FB_WRITEL( comp( (d0>>right | d1<<left), FB_READL(dst), first), dst);
- d0 = d1;
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0>>right | d1<<left;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL( comp(d0, FB_READL(dst), first), dst);
+ d0 = d1;
dst--;
n -= dst_idx+1;
// Main chunk
m = n % bits;
n /= bits;
- while (n >= 4) {
+ while ((n >= 4) && !bswapmask) {
d1 = FB_READL(src--);
FB_WRITEL(d0 >> right | d1 << left, dst--);
d0 = d1;
@@ -309,7 +337,10 @@ bitcpy_rev(unsigned long __iomem *dst, i
}
while (n--) {
d1 = FB_READL(src--);
- FB_WRITEL(d0 >> right | d1 << left, dst--);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0 >> right | d1 << left;
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(d0, dst--);
d0 = d1;
}
@@ -317,12 +348,15 @@ bitcpy_rev(unsigned long __iomem *dst, i
if (last) {
if (m <= left) {
// Single source word
- FB_WRITEL( comp(d0 >> right, FB_READL(dst), last), dst);
+ d0 >>= right;
} else {
// 2 source words
d1 = FB_READL(src);
- FB_WRITEL( comp(d0>>right | d1<<left, FB_READL(dst), last), dst);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0>>right | d1<<left;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL( comp(d0, FB_READL(dst), last), dst);
}
}
}
|