Thread (10 messages) 10 messages, 4 authors, 2003-02-17

Re: [Linux-fbdev-devel] Re: New logo code (fwd)

From: Antonino Daplas <hidden>
Date: 2003-02-06 07:20:33
Also in: lkml

On Wed, 2003-02-05 at 20:37, Geert Uytterhoeven wrote:
On Tue, 28 Jan 2003, Geert Uytterhoeven wrote:
quoted
On Sun, 12 Jan 2003, Geert Uytterhoeven wrote:
quoted
The current logo code is messy, complex, and inflexible. So I decided to
rewrite it. My goals were:
  - Logos must be accessible easily by an image editor (currently: hex C source
    data must be converted to another format first)
  - Logos must be stored in ASCII-form in the source tree
  - Support arbitrary logo sizes (currently: fixed 80x80)
  - Allow the logo to be selected statically (at compile time) and/or
    dynamically (at run-time, based on machine type) (currently: at compile
    time only).
  - Allow simple adition of new logos
  - Support grayscale logos (not used yet)

The patch achieves all of these. Logos are stored in ASCII PNM format in
drivers/video/logo/, and automatically converted to hex C source arrays using
scripts/pnmtologo. I chose ASCII PNM because (a) it's ASCII, (b) it's very
simple to parse without an external library (XPM is more difficult to parse),
and (c) it can be handled by many image manipulation programs.

Code that wants to display a logo just calls fb_find_logo(), specifying the
wanted logo type, and receives a pointer to a suitable logo (or NULL).

I also modified fb_show_logo() to return the number of scanlines that are used
by the logo, so fbcon knows how many lines to reserve.
I put a new version at

    http://home.tvd.be/cr26864/Linux/fbdev/linux-logo-2.5.59.diff.bz2

Changes:
  - Merge with 2.5.59
  - New logo (CLUT224 only) for PA-RISC
  - Let hgafb and newport_con include logo sources directly, since they need
    access to the logos in non-init code

All comments are welcomed! Thanks!
Come on, is there really no one to comment on this??
Actually, I tried the patch before, but it was erased so fast that I
never got to see the logo :-)

Anyway, I think it's because logo_lines require logo_height in
fbcon_set_display().  logo_height is returned by fb_show_logo(), however
fb_show_logo() is called after computing logo_lines.

So, how about breaking up fb_show_logo() into fb_prepare_logo() and
fb_show_logo()?  We can call fb_prepare_logo() to get the logo height
for the logo_lines, then do an fb_show_logo() for the actual drawing.

Also I noticed that the type of logo depends solely on the framebuffer
depth.  This is not necessarily correct.  DirectColor at <24bpp 
requires a 4-bit logo.

Overall, I like it, though it does add some kilobytes to the kernel
image size.

Tony

BTW: Do you know of any logo images that are compatible with your patch?
I'm beginning to get tired of seeing Tux always:-)

diff -Naur linux-2.5.59-gu/drivers/video/console/fbcon.c linux/drivers/video/console/fbcon.c
--- linux-2.5.59-gu/drivers/video/console/fbcon.c	2003-02-05 06:37:49.000000000 +0000
+++ linux/drivers/video/console/fbcon.c	2003-02-05 06:38:52.000000000 +0000
@@ -958,6 +958,7 @@
 		int cnt;
 		int step;
 
+		logo_height = fb_prepare_logo(info);
 		logo_lines = (logo_height + vc->vc_font.height - 1) /
 			     vc->vc_font.height;
 		q = (unsigned short *) (vc->vc_origin +
@@ -1944,8 +1945,7 @@
 		accel_clear_margins(vc, p, 0);
 	if (logo_shown == -2) {
 		logo_shown = fg_console;
-		/* This is protected above by initmem_freed */
-		logo_height = fb_show_logo(info);
+		fb_show_logo(info);	/* This is protected above by initmem_freed */
 		update_region(fg_console,
 			      vc->vc_origin + vc->vc_size_row * vc->vc_top,
 			      vc->vc_size_row * (vc->vc_bottom -
diff -Naur linux-2.5.59-gu/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- linux-2.5.59-gu/drivers/video/fbmem.c	2003-02-05 06:33:48.000000000 +0000
+++ linux/drivers/video/fbmem.c	2003-02-05 06:36:03.000000000 +0000
@@ -511,101 +511,119 @@
  * We isolate each bit and expand each into a byte. The "needs_logo" flag will
  * be set to 1.
  */
-int fb_show_logo(struct fb_info *info)
-{
-	unsigned char *fb = info->screen_base, *logo_new = NULL;
-	u32 *palette = NULL, *saved_pseudo_palette = NULL;
-	int needs_directpalette = 0;
-	int needs_truepalette = 0;
-	int needs_cmapreset = 0;
-	struct fb_image image;
-	const struct linux_logo *logo = 0;
+static struct logo_data {
+	int depth;
+	int needs_logo;
+	int needs_directpalette;
+	int needs_truepalette;
+	int needs_cmapreset;
 	int type;
-	int needs_logo = 0;
-	int done = 0, x;
-
-	/* Return if the frame buffer is not mapped */
-	if (!fb || !info->fbops->fb_imageblit)
-		return 0;
+	const struct linux_logo *logo;
+} fb_logo;
 
-	image.depth = info->var.bits_per_pixel;
-
-	/* reasonable default */
-	if (image.depth >= 8)
-		type = LINUX_LOGO_CLUT224;
-	else if (image.depth >= 4)
-		type = LINUX_LOGO_VGA16;
-	else
-		type = LINUX_LOGO_MONO;
-
-	/* Return if no suitable logo was found */
-	logo = fb_find_logo(type);
-	if (!logo || logo->height > info->var.yres)
-		return 0;
+int fb_prepare_logo(struct fb_info *info)
+{
+	memset(&fb_logo, 0, sizeof(struct logo_data));
 
-	image.data = logo->data;
+	fb_logo.depth = info->var.bits_per_pixel;
 
 	switch (info->fix.visual) {
 	case FB_VISUAL_TRUECOLOR:
-		needs_truepalette = 1;
-		if (image.depth >= 4 && image.depth <= 8)
-			needs_logo = 4;
-		else if (image.depth < 4)
-			needs_logo = 1;
+		if (fb_logo.depth > 8) {
+			fb_logo.needs_truepalette = 1;
+			fb_logo.needs_logo = 8;
+		} else if (fb_logo.depth >= 4 && fb_logo.depth <= 8)
+			fb_logo.needs_logo = 4;
+		else 
+			fb_logo.needs_logo = 1;
 		break;
 	case FB_VISUAL_DIRECTCOLOR:
-		if (image.depth >= 24) {
-			needs_directpalette = 1;
-			needs_cmapreset = 1;
+		if (fb_logo.depth >= 24) {
+			fb_logo.needs_directpalette = 1;
+			fb_logo.needs_cmapreset = 1;
+			fb_logo.needs_logo = 8;
 		}
 		/* 16 colors */
-		else if (image.depth >= 16)
-			needs_logo = 4;
+		else if (fb_logo.depth >= 16)
+			fb_logo.needs_logo = 4;
 		/* 2 colors */
 		else
-			needs_logo = 1;
+			fb_logo.needs_logo = 1;
 		break;
 	case FB_VISUAL_MONO01:
 		/* reversed 0 = fg, 1 = bg */
-		needs_logo = ~1;
+		fb_logo.needs_logo = ~1;
 		break;
 	case FB_VISUAL_MONO10:
-		needs_logo = 1;
+		fb_logo.needs_logo = 1;
 		break;
 	case FB_VISUAL_PSEUDOCOLOR:
 	default:
-		if (image.depth >= 8)
-			needs_cmapreset = 1;
+		if (fb_logo.depth >= 8) {
+			fb_logo.needs_cmapreset = 1;
+			fb_logo.needs_logo = 8;
+		}
 		/* fall through */
 	case FB_VISUAL_STATIC_PSEUDOCOLOR:
 		/* 16 colors */
-		if (image.depth >= 4 && image.depth < 8)
-			needs_logo = 4;
+		if (fb_logo.depth >= 4 && fb_logo.depth < 8)
+			fb_logo.needs_logo = 4;
 		/* 2 colors */
-		else if (image.depth < 4)
-			needs_logo = 1;
+		else if (fb_logo.depth < 4)
+			fb_logo.needs_logo = 1;
 		break;
 	}
 
-	if (needs_cmapreset)
-		fb_set_logocmap(info, logo);
+	if (fb_logo.needs_logo >= 8)
+		fb_logo.type = LINUX_LOGO_CLUT224;
+	else if (fb_logo.needs_logo >= 4)
+		fb_logo.type = LINUX_LOGO_VGA16;
+	else
+		fb_logo.type = LINUX_LOGO_MONO;
 
-	if (needs_truepalette || needs_directpalette) {
+	/* Return if no suitable logo was found */
+	fb_logo.logo = fb_find_logo(fb_logo.type);
+	if (!fb_logo.logo || fb_logo.logo->height > info->var.yres)
+		return 0;
+	return fb_logo.logo->height;
+}
+
+int fb_show_logo(struct fb_info *info)
+{
+	unsigned char *fb = info->screen_base, *logo_new = NULL;
+	u32 *palette = NULL, *saved_pseudo_palette = NULL;
+	struct fb_image image;
+	int done = 0, x;
+
+	/* Return if the frame buffer is not mapped */
+	if (!fb || !info->fbops->fb_imageblit ||
+	    !fb_logo.depth)
+		return 0;
+
+	image.depth = fb_logo.depth;
+	image.data = fb_logo.logo->data;
+
+	if (fb_logo.needs_cmapreset)
+		fb_set_logocmap(info, fb_logo.logo);
+
+	if (fb_logo.needs_truepalette || 
+	    fb_logo.needs_directpalette) {
 		palette = kmalloc(256 * 4, GFP_KERNEL);
 		if (palette == NULL)
 			return 0;
 
-		if (needs_truepalette)
-			fb_set_logo_truepalette(info, logo, palette);
+		if (fb_logo.needs_truepalette)
+			fb_set_logo_truepalette(info, fb_logo.logo, palette);
 		else
-			fb_set_logo_directpalette(info, logo, palette);
+			fb_set_logo_directpalette(info, fb_logo.logo, palette);
 
 		saved_pseudo_palette = info->pseudo_palette;
 		info->pseudo_palette = palette;
 	}
 
-	if (needs_logo) {
-		logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);
+	if (fb_logo.needs_logo != 8) {
+		logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height, 
+				   GFP_KERNEL);
 		if (logo_new == NULL) {
 			if (palette)
 				kfree(palette);
@@ -615,27 +633,27 @@
 		}
 
 		image.data = logo_new;
-		fb_set_logo(info, logo, logo_new, needs_logo);
+		fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.needs_logo);
 	}
 
-	image.width = logo->width;
-	image.height = logo->height;
+	image.width = fb_logo.logo->width;
+	image.height = fb_logo.logo->height;
 	image.dy = 0;
 
-	for (x = 0; x < num_online_cpus() * (logo->width + 8) &&
-	     x <= info->var.xres-logo->width; x += (logo->width + 8)) {
+	for (x = 0; x < num_online_cpus() * (fb_logo.logo->width + 8) &&
+	     x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) {
 		image.dx = x;
 		info->fbops->fb_imageblit(info, &image);
 		done = 1;
 	}
-
+	
 	if (palette != NULL)
 		kfree(palette);
 	if (saved_pseudo_palette != NULL)
 		info->pseudo_palette = saved_pseudo_palette;
 	if (logo_new != NULL)
 		kfree(logo_new);
-	return logo->height;
+	return fb_logo.logo->height;
 }
 
 static int fbmem_read_proc(char *buf, char **start, off_t offset,
@@ -1213,6 +1231,7 @@
 EXPORT_SYMBOL(num_registered_fb);
 EXPORT_SYMBOL(registered_fb);
 EXPORT_SYMBOL(fb_show_logo);
+EXPORT_SYMBOL(fb_prepare_logo);
 EXPORT_SYMBOL(fb_set_var);
 EXPORT_SYMBOL(fb_blank);
 EXPORT_SYMBOL(fb_pan_display);
diff -Naur linux-2.5.59-gu/include/linux/fb.h linux/include/linux/fb.h
--- linux-2.5.59-gu/include/linux/fb.h	2003-02-05 06:39:34.000000000 +0000
+++ linux/include/linux/fb.h	2003-02-05 06:40:30.000000000 +0000
@@ -464,6 +464,7 @@
 /* drivers/video/fbmem.c */
 extern int register_framebuffer(struct fb_info *fb_info);
 extern int unregister_framebuffer(struct fb_info *fb_info);
+extern int fb_prepare_logo(struct fb_info *fb_info);
 extern int fb_show_logo(struct fb_info *fb_info);
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help