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;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/