|
From: Antonino D. <ad...@po...> - 2003-01-12 10:35:43
|
On Sun, 2003-01-12 at 03:15, Geert Uytterhoeven wrote:
>
> I'm trying out different fonts with amifb (based on 2.5.56 from Linus).
> - PEARL8x8: OK
> - SUN12x22: garbage (random characters)
> - ProFont6x11: garbage (each different line is filled with a different
> character)
> - MINI4x6: garbage (each different line is filled with a different
> character)
>
> At first I thought it may be caused by xres and yres not divisible by the
> fontsize, so I tried a 800x600 mode with MINI4x6. But the problem stayed the
> same, except that only a 640x600 window in the right part of the screen was
> used.
>
> Is my planar code in amifb to blane, or have other people seen the same?
>
The cfb_imageblit() function exhibited the same behavior. I think we
both made the wrong assumption that all monochrome bitmaps are packed. I
think the rule is:
The first pixel on the next scanline is always at the next byte from
the last pixel of the current scanline.
So a 12x22 font has 16 bits per scanline but only 12 are usable, and the
last 4 are used as padding. It's worse with a 4x6 fonts where the
4-bits are just duplicated in the other nibble.
It's a simple fix for imageblit. So here's a patch.
a. Fix for slow_imageblit() so fonts with widths not a multiple of 8
will work.
b. Fixed fast_imageblit() so it always access tables as 32-bit for it to
to work with a 64-bit machine.
James, can you apply?
Tony
diff -Naur linux-2.5.54/drivers/video/cfbimgblt.c linux/drivers/video/cfbimgblt.c
--- linux-2.5.54/drivers/video/cfbimgblt.c 2003-01-12 09:48:47.000000000 +0000
+++ linux/drivers/video/cfbimgblt.c 2003-01-12 10:06:59.000000000 +0000
@@ -88,11 +88,13 @@
#if defined (__BIG_ENDIAN)
#define LEFT_POS(bpp) (BITS_PER_LONG - bpp)
+#define LEFT_POS32(bpp) (32 - bpp)
#define NEXT_POS(pos, bpp) ((pos) -= (bpp))
#define SHIFT_HIGH(val, bits) ((val) >> (bits))
#define SHIFT_LOW(val, bits) ((val) << (bits))
#else
#define LEFT_POS(bpp) (0)
+#define LEFT_POS32(bpp) (0)
#define NEXT_POS(pos, bpp) ((pos) += (bpp))
#define SHIFT_HIGH(val, bits) ((val) << (bits))
#define SHIFT_LOW(val, bits) ((val) >> (bits))
@@ -161,7 +163,7 @@
unsigned long fgcolor, unsigned long bgcolor,
unsigned long start_index, unsigned long pitch_index)
{
- unsigned long i, j, l = 8;
+ unsigned long i, j, l;
unsigned long shift, color, bpp = p->var.bits_per_pixel;
unsigned long *dst, *dst2, val, pitch = p->fix.line_length;
unsigned long null_bits = BITS_PER_LONG - bpp;
@@ -170,10 +172,11 @@
dst2 = (unsigned long *) dst1;
for (i = image->height; i--; ) {
- shift = 0;
- val = 0;
+ shift = val = 0;
+ l = 8;
j = image->width;
dst = (unsigned long *) dst1;
+ s = src;
/* write leading bits */
if (start_index) {
@@ -182,35 +185,33 @@
val = FB_READL(dst) & start_mask;
shift = start_index;
}
+
while (j--) {
l--;
- if (*src & (1 << l))
- color = fgcolor;
- else
- color = bgcolor;
+ color = (*s & (1 << l)) ? fgcolor : bgcolor;
color <<= LEFT_POS(bpp);
val |= SHIFT_HIGH(color, shift);
/* Did the bitshift spill bits to the next long? */
if (shift >= null_bits) {
FB_WRITEL(val, dst++);
- if (shift == null_bits)
- val = 0;
- else
- val = SHIFT_LOW(color, BITS_PER_LONG - shift);
+ val = (shift == null_bits) ?
+ 0 : SHIFT_LOW(color, BITS_PER_LONG - shift);
}
shift += bpp;
shift &= (BITS_PER_LONG - 1);
- if (!l) { l = 8; src++; };
+ if (!l) { l = 8; s++; };
}
+
/* write trailing bits */
if (shift) {
unsigned long end_mask = SHIFT_HIGH(~0UL, shift);
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
}
- dst1 += pitch;
+ dst1 += pitch;
+ src += (image->width + 7)/8;
if (pitch_index) {
dst2 += pitch;
dst1 = (char *) dst2;
@@ -224,25 +225,25 @@
}
static inline void fast_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1,
- unsigned long fgcolor, unsigned long bgcolor)
+ u32 fgcolor, u32 bgcolor)
{
int i, j, k, l = 8, n;
- unsigned long bit_mask, end_mask, eorx;
- unsigned long fgx = fgcolor, bgx = bgcolor, pad, bpp = p->var.bits_per_pixel;
- unsigned long tmp = (1 << bpp) - 1;
- unsigned long ppw = BITS_PER_LONG/bpp, ppos;
- unsigned long *dst;
+ u32 bit_mask, end_mask, eorx;
+ u32 fgx = fgcolor, bgx = bgcolor, pad, bpp = p->var.bits_per_pixel;
+ u32 tmp = (1 << bpp) - 1;
+ u32 ppw = 32/bpp, ppos;
+ u32 *dst;
u32 *tab = NULL;
char *src = image->data;
- switch (ppw) {
- case 4:
+ switch (bpp) {
+ case 8:
tab = cfb_tab8;
break;
- case 2:
+ case 16:
tab = cfb_tab16;
break;
- case 1:
+ case 32:
tab = cfb_tab32;
break;
}
@@ -264,17 +265,17 @@
k = image->width/ppw;
for (i = image->height; i--; ) {
- dst = (unsigned long *) dst1;
-
+ dst = (u32 *) dst1;
for (j = k; j--; ) {
l -= ppw;
end_mask = tab[(*src >> l) & bit_mask];
- FB_WRITEL((end_mask & eorx)^bgx, dst++);
+ fb_writel((end_mask & eorx)^bgx, dst++);
if (!l) { l = 8; src++; }
}
+
if (n) {
end_mask = 0;
- ppos = LEFT_POS(bpp);
+ ppos = LEFT_POS32(bpp);
for (j = n; j > 0; j--) {
l--;
if (*src & (1 << l))
@@ -282,9 +283,9 @@
NEXT_POS(ppos, bpp);
if (!l) { l = 8; src++; }
}
- FB_WRITEL((end_mask & eorx)^bgx, dst++);
+ fb_writel((end_mask & eorx)^bgx, dst++);
}
- l -= pad;
+ l -= pad;
dst1 += p->fix.line_length;
}
}
|