linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Antonino Daplas <adaplas@pol.net>
To: Linux Fbdev development list <linux-fbdev-devel@lists.sourceforge.net>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [PATCH] FBDev: fix for fbcon Oops
Date: 28 Nov 2002 12:24:46 +0500	[thread overview]
Message-ID: <1038468191.1092.48.camel@localhost.localdomain> (raw)

[-- Attachment #1: Type: text/plain, Size: 781 bytes --]

Hi,

Attached is a patch against 2.5.49 + James Simmons' latest fbdev.diff.

This fixes fbcon oopsing at load time which is due to the fb_cursor's
palette index entries being improperly updated.

A new kind of 'emacs glitch'  appeared, though. This can be described as
a block of text that is incompletely  copied, ie when "tabbing" a line
of text.  This is present with all hardware I tested, soft accel and
hardware accel, which indicates a problem in the higher layers (probably
fbcon). vgacon works okay.  

Other changes:

1. optimization of fbcon_accel_putcs()
2. enabling logo displays at all packed pixel formats (as long as
fb_imageblit is supported)
3. Various fbcon_accel_cursor() fixes which would have resulted in
wrong cursor colors or an invisible cursor.



Tony



[-- Attachment #2: fbcon.c.diff --]
[-- Type: text/x-patch, Size: 9458 bytes --]

diff -Naur linux-2.5.49/drivers/video/Makefile linux/drivers/video/Makefile
--- linux-2.5.49/drivers/video/Makefile	2002-11-28 06:29:45.000000000 +0000
+++ linux/drivers/video/Makefile	2002-11-28 06:30:35.000000000 +0000
@@ -69,7 +69,7 @@
 obj-$(CONFIG_FB_TX3912)           += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 
 obj-$(CONFIG_FB_MATROX)		  += matrox/
-obj-$(CONFIG_FB_RIVA)		  += riva/
+obj-$(CONFIG_FB_RIVA)		  += riva/ cfbfillrect.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_SIS)		  += sis/
 obj-$(CONFIG_FB_ATY)		  += aty/ cfbimgblt.o
 
diff -Naur linux-2.5.49/drivers/video/console/fbcon.c linux/drivers/video/console/fbcon.c
--- linux-2.5.49/drivers/video/console/fbcon.c	2002-11-28 06:30:09.000000000 +0000
+++ linux/drivers/video/console/fbcon.c	2002-11-28 06:33:39.000000000 +0000
@@ -153,6 +153,8 @@
 static int cursor_on;
 static int cursor_blink_rate;
 
+static u8 fbcon_pixmap[8192];
+
 static inline void cursor_undrawn(void)
 {
 	vbl_cursor_cnt = 0;
@@ -353,7 +355,8 @@
 {
 	struct fb_info *info = p->fb_info;
 	unsigned short charmask = p->charmask;
-	unsigned int width = ((vc->vc_font.width + 7) >> 3);
+	unsigned int width = ((vc->vc_font.width + 7)/8);
+	unsigned int cellsize = vc->vc_font.height * width;
 	struct fb_image image;
 	u16 c = scr_readw(s);
 
@@ -361,16 +364,37 @@
 	image.bg_color = attr_bgcol(p, c);
 	image.dx = xx * vc->vc_font.width;
 	image.dy = yy * vc->vc_font.height;
-	image.width = vc->vc_font.width;
 	image.height = vc->vc_font.height;
 	image.depth = 1;
 
-	while (count--) {
-		image.data = p->fontdata + 
-			(scr_readw(s++) & charmask) * vc->vc_font.height * width;
+	if (!(vc->vc_font.width & 7) && fbcon_pixmap != NULL) {
+		unsigned int pitch = width * count, i, j;
+		char *src, *dst, *dst0;
+
+		dst0 = fbcon_pixmap;
+		image.width = vc->vc_font.width * count;
+		image.data = fbcon_pixmap;
+		while (count--) {
+			src = p->fontdata + (scr_readw(s++) & charmask) * cellsize;
+			dst = dst0;
+			for (i = image.height; i--; ) {
+				for (j = 0; j < width; j++) 
+					dst[j] = *src++;
+				dst += pitch;
+			}
+			dst0 += width;
+		}
 		info->fbops->fb_imageblit(info, &image);
-		image.dx += vc->vc_font.width;
-	}	
+	}
+	else {
+		image.width = vc->vc_font.width;
+		while (count--) {
+			image.data = p->fontdata + 
+				(scr_readw(s++) & charmask) * vc->vc_font.height * width;
+			info->fbops->fb_imageblit(info, &image);
+			image.dx += vc->vc_font.width;
+		}	
+	}
 }
 
 void fbcon_accel_clear_margins(struct vc_data *vc, struct display *p,
@@ -425,7 +449,7 @@
 
 	if ((vc->vc_cursor_type & 0x0f) != shape) {
 		shape = vc->vc_cursor_type & 0x0f;
-		cursor.set |= FB_CUR_SETSIZE;
+		cursor.set |= FB_CUR_SETSHAPE;
 	}
 
 	c = scr_readw((u16 *) vc->vc_pos);
@@ -435,10 +459,7 @@
 		fgcolor = (int) attr_fgcol(p, c);
 		bgcolor = (int) attr_bgcol(p, c);
 		cursor.set |= FB_CUR_SETCMAP;
-		cursor.image.bg_color = bgcolor;
-		cursor.image.fg_color = fgcolor;
 	}
-
 	c &= p->charmask;
 	font = p->fontdata + (c * ((width + 7) / 8) * height);
 	if (font != dest) {
@@ -453,7 +474,7 @@
 
 	if (cursor.set & FB_CUR_SETSIZE) {
 		memset(image, 0xff, 64);
-		cursor.set |= FB_CUR_SETSIZE;
+		cursor.set |= FB_CUR_SETSHAPE;
 	}		
 
 	if (cursor.set & FB_CUR_SETSHAPE) {
@@ -497,6 +518,8 @@
 	cursor.image.dy = yy * height;
 	cursor.image.depth = 1;
 	cursor.image.data = image;
+	cursor.image.bg_color = bgcolor;
+	cursor.image.fg_color = fgcolor;
 	cursor.mask = mask;
 	cursor.dest = dest;
 	cursor.rop = ROP_XOR;
@@ -2487,20 +2510,16 @@
 	struct display *p = &fb_display[fg_console];	/* draw to vt in foreground */
 	struct fb_info *info = p->fb_info;
 	struct vc_data *vc = info->display_fg;
-#ifdef CONFIG_FBCON_ACCEL
 	struct fb_image image;
 	u32 *palette = NULL, *saved_palette = NULL;
-#endif
 	int depth = info->var.bits_per_pixel;
-	int line = info->fix.line_length;
 	unsigned char *fb = info->screen_base;
-	unsigned char *logo;
-	unsigned char *dst, *src;
-	int i, j, n, x1, y1, x;
+	unsigned char *logo, *logo_new = NULL;
+	int i, j, n, x;
 	int logo_depth, done = 0;
 
 	/* Return if the frame buffer is not mapped */
-	if (!fb)
+	if (!fb || !info->fbops->fb_imageblit)
 		return 0;
 
 	/*
@@ -2543,65 +2562,114 @@
 		logo_depth = 1;
 	}
 
-#if defined(CONFIG_FBCON_ACCEL)
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		unsigned char mask[9] =
-		    { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
+    {
+	    int needs_truepalette = 0;
+	    int needs_directpalette = 0;
+	    int needs_logo = 0;
+
+	    switch (info->fix.visual) {
+	    case FB_VISUAL_TRUECOLOR:
+		    needs_truepalette = 1;
+		    break;
+	    case FB_VISUAL_DIRECTCOLOR:
+		    if (depth >= 24) 
+			    needs_directpalette = 1;
+		    /* 16 colors */
+		    else if (depth >= 16)
+			    needs_logo = 4;
+		    /* 2 colors */
+		    else
+			    needs_logo = 1;
+		    break;
+	    case FB_VISUAL_PSEUDOCOLOR:
+	    default:
+		    /* 16 colors */
+		    if (depth >= 4 && depth < 8)
+			    needs_logo = 4;
+		    /* 4 colors */
+		    else if (depth < 4)
+			    needs_logo = 1;
+		    break;
+	    }		    
+	if (needs_truepalette || needs_directpalette) {
+		unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
 		unsigned char redmask, greenmask, bluemask;
 		int redshift, greenshift, blueshift;
 
-		/* Bug: Doesn't obey msb_right ... (who needs that?) */
-		redmask =
-		    mask[info->var.red.length <
-			 8 ? info->var.red.length : 8];
-		greenmask =
-		    mask[info->var.green.length <
-			 8 ? info->var.green.length : 8];
-		bluemask =
-		    mask[info->var.blue.length <
-			 8 ? info->var.blue.length : 8];
-		redshift =
-		    info->var.red.offset - (8 - info->var.red.length);
-		greenshift =
-		    info->var.green.offset - (8 - info->var.green.length);
-		blueshift =
-		    info->var.blue.offset - (8 - info->var.blue.length);
-
 		/*
-		 * We have to create a temporary palette since console palette is only
+	 	 * We have to create a temporary palette since console palette is only
 		 * 16 colors long.
-		 */
+	 	 */
 		palette = kmalloc(256 * 4, GFP_KERNEL);
 		if (palette == NULL)
-			return (LOGO_H + vc->vc_font.height - 1)/vc->vc_font.height;
+			return 1;
+
+		if (needs_truepalette) {
+			/* Bug: Doesn't obey msb_right ... (who needs that?) */
+			redmask   = mask[info->var.red.length   < 8 ? info->var.red.length   : 8];
+			greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
+			bluemask  = mask[info->var.blue.length  < 8 ? info->var.blue.length  : 8];
+			redshift   = info->var.red.offset   - (8 - info->var.red.length);
+			greenshift = info->var.green.offset - (8 - info->var.green.length);
+			blueshift  = info->var.blue.offset  - (8 - info->var.blue.length);
+
 
-		for (i = 0; i < LINUX_LOGO_COLORS; i++) {
-			palette[i + 32] =
-			    (safe_shift
-			     ((linux_logo_red[i] & redmask),
-			      redshift) | safe_shift((linux_logo_green[i] &
-						      greenmask),
-						     greenshift) |
-			     safe_shift((linux_logo_blue[i] & bluemask),
-					blueshift));
+			for ( i = 0; i < LINUX_LOGO_COLORS; i++) {
+				palette[i+32] = (safe_shift((linux_logo_red[i]   & redmask), redshift) |
+						 safe_shift((linux_logo_green[i] & greenmask), greenshift) |
+						 safe_shift((linux_logo_blue[i]  & bluemask), blueshift));
+			}
+		}
+		else {
+			redshift = info->var.red.offset;
+			greenshift = info->var.green.offset;
+			blueshift = info->var.blue.offset;
+
+			for (i = 32; i < LINUX_LOGO_COLORS; i++) 
+				palette[i] = i << redshift | i << greenshift | i << blueshift;
 		}
 		saved_palette = info->pseudo_palette;
 		info->pseudo_palette = palette;
 	}
+	if (needs_logo) {
+		logo_new = kmalloc(LOGO_W * LOGO_H, GFP_KERNEL);
+		if (logo_new == NULL)
+			return 1;
+
+		logo = logo_new;
+		switch (needs_logo) {
+		case 4:
+		{
+			for (i = 0; i < (LOGO_W * LOGO_H)/2; i++) {
+				logo_new[i*2] = linux_logo16[i] >> 4;
+				logo_new[(i*2)+1] = linux_logo16[i] & 0xf;
+			}
+		}
+		break;
+		case 1:
+		default:
+		{
+			int j;
+			for (i = 0; i < (LOGO_W * LOGO_H)/8; i++) 
+				for (j = 0; j < 8; j++) 
+					logo_new[i*2] = linux_logo_bw[i] &  (7 - j);
+		}
+		break;
+		} 
+	}
 	image.width = LOGO_W;
 	image.height = LOGO_H;
 	image.depth = depth;
 	image.data = logo;
 	image.dy = 0;
-#endif
+    }
 
 	for (x = 0; x < num_online_cpus() * (LOGO_W + 8) &&
 	     x < info->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {
-#if defined (CONFIG_FBCON_ACCEL)
 		image.dx = x;
 		info->fbops->fb_imageblit(info, &image);
 		done = 1;
-#endif
+#if 0 /* Turn off, should be removed soon enough... */
 #if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_ILBM) || \
     defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P4) || \
     defined(CONFIG_FBCON_IPLAN2P8)
@@ -2733,14 +2801,14 @@
 			done = 1;
 		}
 #endif
+#endif /* Turn off for now... */
 	}
-
-#if defined (CONFIG_FBCON_ACCEL)
 	if (palette != NULL)
 		kfree(palette);
 	if (saved_palette != NULL)
 		info->pseudo_palette = saved_palette;
-#endif
+	if (logo_new != NULL)
+		kfree(logo_new);
 	/* Modes not yet supported: packed pixels with depth != 8 (does such a
 	 * thing exist in reality?) */
 

             reply	other threads:[~2002-11-28  7:24 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-11-28  7:24 Antonino Daplas [this message]
2002-12-02 21:15 ` [Linux-fbdev-devel] [PATCH] FBDev: fix for fbcon Oops James Simmons

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1038468191.1092.48.camel@localhost.localdomain \
    --to=adaplas@pol.net \
    --cc=linux-fbdev-devel@lists.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).