Resent-Date: Wed, 21 Oct 1998 10:43:24 +0200 (MET DST)
To: linux-m68k@lists.linux-m68k.org
Subject: Fbcon display bug
X-Yow: Yes, but will I see the EASTER BUNNY in skintight leather
 at an IRON MAIDEN concert?
From: Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
Date: 21 Oct 1998 10:43:47 +0200
Resent-From: linux-m68k@phil.uni-sb.de

There is a display bug in the fbcon driver if the screen height is not
evenly divisible by the font height and panning is used for scrolling.  In
this case the extra screen lines at the bottom are never cleared.  I don't
know how this can be fixed, since the interface to the frame buffer driver
is completely based on character cells.

But here is a patch to fix the iplan drivers so that they can cope with
font heights that are not a power of two.

Andreas.

----------------------------------------------------------------------
--- drivers/video/fbcon-iplan2p2.c.~1~	Tue Sep  1 18:06:06 1998
+++ drivers/video/fbcon-iplan2p2.c	Tue Oct 20 20:40:48 1998
@@ -169,18 +169,25 @@
 	/*  Special (but often used) case: Moving whole lines can be
 	 *  done with memmove()
 	 */
-	mymemmove(p->screen_base + ((dy * p->next_line) << fontheightlog(p)),
-		  p->screen_base + ((sy * p->next_line) << fontheightlog(p)),
-		  (p->next_line * height) << fontheightlog(p));
+	mymemmove(p->screen_base + dy * p->next_line * fontheight(p),
+		  p->screen_base + sy * p->next_line * fontheight(p),
+		  p->next_line * height * fontheight(p));
     } else {
 	int rows, cols;
 	u8 *src;
 	u8 *dst;
 	int bytes = p->next_line;
-	int linesize = bytes << fontheightlog(p);
-	u_int colsize  = height << fontheightlog(p);
+	int linesize;
+	u_int colsize;
 	u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
 
+	if (fontheightlog(p)) {
+	    linesize = bytes << fontheightlog(p);
+	    colsize = height << fontheightlog(p);
+	} else {
+	    linesize = bytes * fontheight(p);
+	    colsize = height * fontheight(p);
+	}
 	if ((sx & 1) == (dx & 1)) {
 	    /* odd->odd or even->even */
 	    if (upwards) {
@@ -258,19 +265,30 @@
     u8 *start;
     int rows;
     int bytes = p->next_line;
-    int lines = height << fontheightlog(p);
+    int lines;
     u32 size;
     u32 cval;
     u16 pcval;
 
     cval = expand2l (COLOR_2P (attr_bgcol_ec(p,conp)));
 
+    if (fontheightlog(p))
+	lines = height << fontheightlog(p);
+    else
+	lines = height * fontheight(p);
+
     if (sx == 0 && width * 2 == bytes) {
-	offset = (sy * bytes) << fontheightlog(p);
+	if (fontheightlog(p))
+	    offset = (sy * bytes) << fontheightlog(p);
+	else
+	    offset = sy * bytes * fontheight(p);
 	size = lines * bytes;
 	memset_even_2p(p->screen_base+offset, size, cval);
     } else {
-	offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*4 + (sx & 1);
+	if (fontheightlog(p))
+	    offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*4 + (sx & 1);
+	else
+	    offset = sy * bytes * fontheight(p) + (sx>>1)*4 + (sx & 1);
 	start = p->screen_base + offset;
 	pcval = expand2w(COLOR_2P(attr_bgcol_ec(p,conp)));
 
@@ -306,8 +324,15 @@
     int bytes = p->next_line;
     u16 eorx, fgx, bgx, fdx;
 
-    dest = p->screen_base + ((yy * bytes) << fontheightlog(p)) + (xx>>1)*4 + (xx & 1);
-    cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
+    if (fontheightlog(p)) {
+	dest = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
+		(xx>>1)*4 + (xx & 1));
+	cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
+    } else {
+	dest = (p->screen_base + yy * bytes * fontheight(p) +
+		(xx>>1)*4 + (xx & 1));
+	cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+    }
 
     fgx = expand2w(COLOR_2P(attr_fgcol(p,c)));
     bgx = expand2w(COLOR_2P(attr_bgcol(p,c)));
@@ -330,14 +355,22 @@
     u16 eorx, fgx, bgx, fdx;
 
     bytes = p->next_line;
-    dest0 = p->screen_base + ((yy * bytes) << fontheightlog(p)) + (xx>>1)*4 + (xx & 1);
+    if (fontheightlog(p))
+	dest0 = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
+		 (xx>>1)*4 + (xx & 1));
+    else
+	dest0 = (p->screen_base + yy * bytes * fontheight(p) +
+		 (xx>>1)*4 + (xx & 1));
     fgx = expand2w(COLOR_2P(attr_fgcol(p,*s)));
     bgx = expand2w(COLOR_2P(attr_bgcol(p,*s)));
     eorx = fgx ^ bgx;
 
     while (count--) {
 	c = *s++ & p->charmask;
-	cdat  = p->fontdata + (c << fontheightlog(p));
+	if (fontheightlog(p))
+	    cdat = p->fontdata + (c << fontheightlog(p));
+	else
+	    cdat = p->fontdata + c * fontheight(p);
 
 	for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
 	    fdx = dup2w(*cdat++);
@@ -353,8 +386,12 @@
     int j;
     int bytes;
 
-    dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
-	    (xx>>1)*4 + (xx & 1));
+    if (fontheightlog(p))
+	dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
+		(xx>>1)*4 + (xx & 1));
+    else
+	dest = (p->screen_base + yy * p->next_line * fontheight(p) +
+		(xx>>1)*4 + (xx & 1));
     j = fontheight(p);
     bytes = p->next_line;
     while (j--) {
--- drivers/video/fbcon-iplan2p4.c.~1~	Tue Sep  1 18:06:17 1998
+++ drivers/video/fbcon-iplan2p4.c	Tue Oct 20 20:40:57 1998
@@ -177,18 +177,25 @@
 	/*  Special (but often used) case: Moving whole lines can be
 	 *done with memmove()
 	 */
-	mymemmove(p->screen_base + ((dy * p->next_line) << fontheightlog(p)),
-		  p->screen_base + ((sy * p->next_line) << fontheightlog(p)),
-		  (p->next_line * height) << fontheightlog(p));
+	mymemmove(p->screen_base + dy * p->next_line * fontheight(p),
+		  p->screen_base + sy * p->next_line * fontheight(p),
+		  p->next_line * height * fontheight(p));
     } else {
 	int rows, cols;
 	u8 *src;
 	u8 *dst;
 	int bytes = p->next_line;
-	int linesize = bytes << fontheightlog(p);
-	u_int colsize  = height << fontheightlog(p);
+	int linesize;
+	u_int colsize;
 	u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
 
+	if (fontheightlog(p)) {
+	    linesize = bytes << fontheightlog(p);
+	    colsize = height << fontheightlog(p);
+	} else {
+	    linesize = bytes * fontheight(p);
+	    colsize = height * fontheight(p);
+	}
 	if ((sx & 1) == (dx & 1)) {
 	    /* odd->odd or even->even */
 
@@ -269,18 +276,29 @@
     u8 *start;
     int rows;
     int bytes = p->next_line;
-    int lines = height << fontheightlog(p);
+    int lines;
     u32 size;
     u32 cval1, cval2, pcval;
 
     expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
 
+    if (fontheightlog(p))
+	lines = height << fontheightlog(p);
+    else
+	lines = height * fontheight(p);
+
     if (sx == 0 && width * 4 == bytes) {
-	offset = (sy * bytes) << fontheightlog(p);
+	if (fontheightlog(p))
+	    offset = (sy * bytes) << fontheightlog(p);
+	else
+	    offset = sy * bytes * fontheight(p);
 	size = lines * bytes;
 	memset_even_4p(p->screen_base+offset, size, cval1, cval2);
     } else {
-	offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*8 + (sx & 1);
+	if (fontheightlog(p))
+	    offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*8 + (sx & 1);
+	else
+	    offset = sy * bytes * fontheight(p) + (sx>>1)*8 + (sx & 1);
 	start = p->screen_base + offset;
 	pcval = expand4l(attr_bgcol_ec(p,conp));
 
@@ -316,8 +334,15 @@
     int bytes = p->next_line;
     u32 eorx, fgx, bgx, fdx;
 
-    dest = p->screen_base + ((yy * bytes) << fontheightlog(p)) + (xx>>1)*8 + (xx & 1);
-    cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
+    if (fontheightlog(p)) {
+	dest = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
+		(xx>>1)*8 + (xx & 1));
+	cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
+    } else {
+	dest = (p->screen_base + yy * bytes * fontheight(p) +
+		(xx>>1)*8 + (xx & 1));
+	cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+    }
 
     fgx = expand4l(attr_fgcol(p,c));
     bgx = expand4l(attr_bgcol(p,c));
@@ -340,7 +365,12 @@
     u32 eorx, fgx, bgx, fdx;
 
     bytes = p->next_line;
-    dest0 = p->screen_base + ((yy * bytes) << fontheightlog(p)) + (xx>>1)*8 + (xx & 1);
+    if (fontheightlog(p))
+	dest0 = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
+		 (xx>>1)*8 + (xx & 1));
+    else
+	dest0 = (p->screen_base + yy * bytes * fontheight(p) +
+		 (xx>>1)*8 + (xx & 1));
     fgx = expand4l(attr_fgcol(p,*s));
     bgx = expand4l(attr_bgcol(p,*s));
     eorx = fgx ^ bgx;
@@ -354,7 +384,10 @@
 	*/
 
 	c = *s++ & p->charmask;
-	cdat  = p->fontdata + (c << fontheightlog(p));
+	if (fontheightlog(p))
+	    cdat = p->fontdata + (c << fontheightlog(p));
+	else
+	    cdat = p->fontdata + c * fontheight(p);
 
 	for(rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
 	    fdx = dup4l(*cdat++);
@@ -370,8 +403,12 @@
     int j;
     int bytes;
 
-    dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
-	    (xx>>1)*8 + (xx & 1));
+    if (fontheightlog(p))
+	dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
+		(xx>>1)*8 + (xx & 1));
+    else
+	dest = (p->screen_base + yy * p->next_line * fontheight(p) +
+		(xx>>1)*8 + (xx & 1));
     j = fontheight(p);
     bytes = p->next_line;
 
--- drivers/video/fbcon-iplan2p8.c.~1~	Tue Sep  1 18:06:28 1998
+++ drivers/video/fbcon-iplan2p8.c	Tue Oct 20 20:40:51 1998
@@ -209,18 +209,25 @@
 	/*  Special (but often used) case: Moving whole lines can be
 	 *  done with memmove()
 	 */
-	fast_memmove(p->screen_base + ((dy * p->next_line) << fontheightlog(p)),
-		     p->screen_base + ((sy * p->next_line) << fontheightlog(p)),
-		     (p->next_line * height) << fontheightlog(p));
+	fast_memmove(p->screen_base + dy * p->next_line * fontheight(p),
+		     p->screen_base + sy * p->next_line * fontheight(p),
+		     p->next_line * height * fontheight(p));
      } else {
 	int rows, cols;
 	u8 *src;
 	u8 *dst;
 	int bytes = p->next_line;
-	int linesize = bytes << fontheightlog(p);
-	u_int colsize = height << fontheightlog(p);
+	int linesize;
+	u_int colsize;
 	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
 
+	if (fontheightlog(p)) {
+	    linesize = bytes << fontheightlog(p);
+	    colsize = height << fontheightlog(p);
+	} else {
+	    linesize = bytes * fontheight(p);
+	    colsize = height * fontheight(p);
+	}
 	if ((sx & 1) == (dx & 1)) {
 	    /* odd->odd or even->even */
 
@@ -301,18 +308,29 @@
     u8 *start;
     int rows;
     int bytes = p->next_line;
-    int lines = height << fontheightlog(p);
+    int lines;
     u32 size;
     u32 cval1, cval2, cval3, cval4, pcval1, pcval2;
 
     expand8ql(attr_bgcol_ec(p,conp), &cval1, &cval2, &cval3, &cval4);
 
+    if (fontheightlog(p))
+	lines = height << fontheightlog(p);
+    else
+	lines = height * fontheight(p);
+
     if (sx == 0 && width * 8 == bytes) {
-	offset = (sy * bytes) << fontheightlog(p);
+	if (fontheightlog(p))
+	    offset = (sy * bytes) << fontheightlog(p);
+	else
+	    offset = sy * bytes * fontheight(p);
 	size    = lines * bytes;
 	memset_even_8p(p->screen_base+offset, size, cval1, cval2, cval3, cval4);
     } else {
-	offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*16 + (sx & 1);
+	if (fontheightlog(p))
+	    offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*16 + (sx & 1);
+	else
+	    offset = sy * bytes * fontheight(p) + (sx>>1)*16 + (sx & 1);
 	start = p->screen_base + offset;
 	expand8dl(attr_bgcol_ec(p,conp), &pcval1, &pcval2);
 
@@ -348,8 +366,15 @@
     int bytes = p->next_line;
     u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
 
-    dest = p->screen_base + ((yy * bytes) << fontheightlog(p)) + (xx>>1)*16 + (xx & 1);
-    cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
+    if (fontheightlog(p)) {
+	dest = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
+		(xx>>1)*16 + (xx & 1));
+	cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
+    } else {
+	dest = (p->screen_base + yy * bytes * fontheight(p) +
+		(xx>>1)*16 + (xx & 1));
+	cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+    }
 
     expand8dl(attr_fgcol(p,c), &fgx1, &fgx2);
     expand8dl(attr_bgcol(p,c), &bgx1, &bgx2);
@@ -372,8 +397,12 @@
     u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
 
     bytes = p->next_line;
-    dest0 = p->screen_base + ((yy * bytes) << fontheightlog(p)) + (xx>>1)*16 +
-	    (xx & 1);
+    if (fontheightlog(p))
+	dest0 = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
+		 (xx>>1)*16 + (xx & 1));
+    else
+	dest0 = (p->screen_base + yy * bytes * fontheight(p) +
+		 (xx>>1)*16 + (xx & 1));
 
     expand8dl(attr_fgcol(p,*s), &fgx1, &fgx2);
     expand8dl(attr_bgcol(p,*s), &bgx1, &bgx2);
@@ -389,7 +418,10 @@
 	*/
 
 	c = *s++ & p->charmask;
-	cdat  = p->fontdata + (c << fontheightlog(p));
+	if (fontheightlog(p))
+	    cdat = p->fontdata + (c << fontheightlog(p));
+	else
+	    cdat = p->fontdata + c * fontheight(p);
 
 	for(rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
 	    fdx = dup4l(*cdat++);
@@ -405,8 +437,12 @@
     int j;
     int bytes;
 
-    dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
-	    (xx>>1)*16 + (xx & 1));
+    if (fontheightlog(p))
+	dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
+		(xx>>1)*16 + (xx & 1));
+    else
+	dest = (p->screen_base + yy * p->next_line * fontheight(p) +
+		(xx>>1)*16 + (xx & 1));
     j = fontheight(p);
     bytes = p->next_line;
 

-- 
Andreas Schwab                                      "And now for something
schwab@issan.cs.uni-dortmund.de                      completely different"
schwab@gnu.org

