Commit 37709b41 authored by Antonino Daplas's avatar Antonino Daplas Committed by Linus Torvalds

[PATCH] fbcon: ifferentiate bits_per_pixel from color depth

1. If you remember this thread (HP300 support checked in), one concern
   was how to support framebuffers with bpp == 8 but color depth < 8
   (chunky layout).  I suggested to use the fields in var->{red|green|blue}
   to differentiate between bits_per_pixel and depth.  Included is a patch
   that does that.

   (The above assumes background/foreground of 0/1.  If hardware needs a
   different value, such as 0 - black, 0xff - white, just indicate
   TRUECOLOR or DIRECTCOLOR and set info->pseudopalette correctly in
   xxxfb_setcolreg().)

   The patch will break the following drivers when in monochrome since
   they do not set the proper color bitfields.  I've included a fix in
   patch #2.

   68328fb
   bw2fb
   cirrusfb
   dnfb
   macfb
   stifb
   tx3912fb

2. Besides the change above, support for the inverse and underline
   attribute is added in monochrome mode.  One should get text which are
   underlined/reversed if the corresponding attribute is set.

3. Because vt.c uses a 16-color palette, use fbcon_default_cmap if
   framebuffer can do less than 16 colors.  In 4 colors, display will be
   grayscaled.  In 8 colors, display should have the same colors as a
   16-color console but will lack brightness/ intensity.

4. Fix monochrome logo drawing.

5. Reduce code of fbcon_putc so it just calls fbcon_putcs.
Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ed4a3514
......@@ -600,6 +600,17 @@ static inline void save_screen(int currcons)
* Redrawing of screen
*/
static void clear_buffer_attributes(int currcons)
{
unsigned short *p = (unsigned short *) origin;
int count = screenbuf_size/2;
int mask = hi_font_mask | 0xff;
for (; count > 0; count--, p++) {
scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p);
}
}
void redraw_screen(int new_console, int is_switch)
{
int redraw = 1;
......@@ -637,9 +648,21 @@ void redraw_screen(int new_console, int is_switch)
if (redraw) {
int update;
int old_was_color = vc_cons[currcons].d->vc_can_do_color;
set_origin(currcons);
update = sw->con_switch(vc_cons[currcons].d);
set_palette(currcons);
/*
* If console changed from mono<->color, the best we can do
* is to clear the buffer attributes. As it currently stands,
* rebuilding new attributes from the old buffer is not doable
* without overly complex code.
*/
if (old_was_color != vc_cons[currcons].d->vc_can_do_color) {
update_attr(currcons);
clear_buffer_attributes(currcons);
}
if (update && vcmode != KD_GRAPHICS)
do_update_region(currcons, origin, screenbuf_size/2);
}
......@@ -2653,17 +2676,6 @@ int __init vty_init(void)
#ifndef VT_SINGLE_DRIVER
static void clear_buffer_attributes(int currcons)
{
unsigned short *p = (unsigned short *) origin;
int count = screenbuf_size/2;
int mask = hi_font_mask | 0xff;
for (; count > 0; count--, p++) {
scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p);
}
}
/*
* If we support more console drivers, this function is used
* when a driver wants to take over some existing consoles
......
......@@ -325,7 +325,7 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
else
slow_imageblit(image, p, dst1, fgcolor, bgcolor,
start_index, pitch_index);
} else if (image->depth <= bpp)
} else
color_imageblit(image, p, dst1, start_index, pitch_index);
}
......
This diff is collapsed.
......@@ -431,6 +431,25 @@ int num_registered_fb;
static int ofonly __initdata = 0;
#endif
/*
* Helpers
*/
int fb_get_color_depth(struct fb_info *info)
{
struct fb_var_screeninfo *var = &info->var;
if (var->green.length == var->blue.length &&
var->green.length == var->red.length &&
!var->green.offset && !var->blue.offset &&
!var->red.offset)
return var->green.length;
else
return (var->green.length + var->red.length +
var->blue.length);
}
EXPORT_SYMBOL(fb_get_color_depth);
/*
* Drawing helpers.
*/
......@@ -650,9 +669,12 @@ static void fb_set_logo(struct fb_info *info,
const struct linux_logo *logo, u8 *dst,
int depth)
{
int i, j, shift;
int i, j, k, fg = 1;
const u8 *src = logo->data;
u8 d, xor = 0;
u8 d, xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
if (fb_get_color_depth(info) == 3)
fg = 7;
switch (depth) {
case 4:
......@@ -666,17 +688,14 @@ static void fb_set_logo(struct fb_info *info,
}
}
break;
case ~1:
xor = 0xff;
case 1:
for (i = 0; i < logo->height; i++) {
shift = 7;
d = *src++ ^ xor;
for (j = 0; j < logo->width; j++) {
*dst++ = (d >> shift) & 1;
shift = (shift-1) & 7;
if (shift == 7)
d = *src++ ^ xor;
for (j = 0; j < logo->width; src++) {
d = *src ^ xor;
for (k = 7; k >= 0; k--) {
*dst++ = ((d >> k) & 1) ? fg : 0;
j++;
}
}
}
break;
......@@ -738,7 +757,7 @@ int fb_prepare_logo(struct fb_info *info)
}
/* Return if no suitable logo was found */
fb_logo.logo = fb_find_logo(info->var.bits_per_pixel);
fb_logo.logo = fb_find_logo(fb_get_color_depth(info));
if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) {
fb_logo.logo = NULL;
......@@ -765,7 +784,7 @@ int fb_show_logo(struct fb_info *info)
if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING)
return 0;
image.depth = fb_logo.depth;
image.depth = 8;
image.data = fb_logo.logo->data;
if (fb_logo.needs_cmapreset)
......@@ -786,7 +805,7 @@ int fb_show_logo(struct fb_info *info)
info->pseudo_palette = palette;
}
if (fb_logo.depth == 4) {
if (fb_logo.depth <= 4) {
logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height,
GFP_KERNEL);
if (logo_new == NULL) {
......
......@@ -380,6 +380,8 @@ struct fb_cursor {
__u16 set; /* what to set */
__u16 enable; /* cursor on/off */
__u16 rop; /* bitop operation */
__u16 ul; /* underlined? */
__u16 rev; /* reversed? */
const char *mask; /* cursor mask bits */
struct fbcurpos hot; /* cursor hot spot */
struct fb_image image; /* Cursor image */
......@@ -687,6 +689,7 @@ extern void fb_sysmove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
u32 height);
extern void fb_load_cursor_image(struct fb_info *);
extern void fb_set_suspend(struct fb_info *info, int state);
extern int fb_get_color_depth(struct fb_info *info);
extern struct fb_info *registered_fb[FB_MAX];
extern int num_registered_fb;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment