提交 91c43132 编写于 作者: T Thomas Pfaff 提交者: Linus Torvalds

fbcon: fix color generation for monochrome framebuffer

The current attr_fgcol_ec / attr_bgcol_ec macros do a simple shift of bits
to get the color from vc_video_erase_char.  For a monochrome display
however the attribute does not contain any color, only attribute bits.
Furthermore the reverse bit is lost because it is shifted out, the
resulting color is always 0.

This can bee seen on a monochrome console either directly or by setting it
to inverse mode via "setterm -inversescreen on" .  Text is written with
correct color, fb_fillrects from a bit_clear / bit_clear_margins will get
wrong colors.
Signed-off-by: NThomas Pfaff <tpfaff@pcs.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 e8973637
...@@ -63,7 +63,7 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, ...@@ -63,7 +63,7 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy,
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
struct fb_fillrect region; struct fb_fillrect region;
region.color = attr_bgcol_ec(bgshift, vc); region.color = attr_bgcol_ec(bgshift, vc, info);
region.dx = sx * vc->vc_font.width; region.dx = sx * vc->vc_font.width;
region.dy = sy * vc->vc_font.height; region.dy = sy * vc->vc_font.height;
region.width = width * vc->vc_font.width; region.width = width * vc->vc_font.width;
...@@ -213,7 +213,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, ...@@ -213,7 +213,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
unsigned int bs = info->var.yres - bh; unsigned int bs = info->var.yres - bh;
struct fb_fillrect region; struct fb_fillrect region;
region.color = attr_bgcol_ec(bgshift, vc); region.color = attr_bgcol_ec(bgshift, vc, info);
region.rop = ROP_COPY; region.rop = ROP_COPY;
if (rw && !bottom_only) { if (rw && !bottom_only) {
......
...@@ -334,10 +334,7 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info, ...@@ -334,10 +334,7 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
switch (depth) { switch (depth) {
case 1: case 1:
{ {
int col = ~(0xfff << (max(info->var.green.length, int col = mono_col(info);
max(info->var.red.length,
info->var.blue.length)))) & 0xff;
/* 0 or 1 */ /* 0 or 1 */
int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0; int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0;
int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col; int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col;
......
...@@ -93,10 +93,6 @@ struct fbcon_ops { ...@@ -93,10 +93,6 @@ struct fbcon_ops {
(((s) >> (fgshift)) & 0x0f) (((s) >> (fgshift)) & 0x0f)
#define attr_bgcol(bgshift,s) \ #define attr_bgcol(bgshift,s) \
(((s) >> (bgshift)) & 0x0f) (((s) >> (bgshift)) & 0x0f)
#define attr_bgcol_ec(bgshift,vc) \
((vc) ? (((vc)->vc_video_erase_char >> (bgshift)) & 0x0f) : 0)
#define attr_fgcol_ec(fgshift,vc) \
((vc) ? (((vc)->vc_video_erase_char >> (fgshift)) & 0x0f) : 0)
/* Monochrome */ /* Monochrome */
#define attr_bold(s) \ #define attr_bold(s) \
...@@ -108,6 +104,49 @@ struct fbcon_ops { ...@@ -108,6 +104,49 @@ struct fbcon_ops {
#define attr_blink(s) \ #define attr_blink(s) \
((s) & 0x8000) ((s) & 0x8000)
#define mono_col(info) \
(~(0xfff << (max((info)->var.green.length, \
max((info)->var.red.length, \
(info)->var.blue.length)))) & 0xff)
static inline int attr_col_ec(int shift, struct vc_data *vc,
struct fb_info *info, int is_fg)
{
int is_mono01;
int col;
int fg;
int bg;
if (!vc)
return 0;
if (vc->vc_can_do_color)
return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char)
: attr_bgcol(shift,vc->vc_video_erase_char);
if (!info)
return 0;
col = mono_col(info);
is_mono01 = info->fix.visual == FB_VISUAL_MONO01;
if (attr_reverse(vc->vc_video_erase_char)) {
fg = is_mono01 ? col : 0;
bg = is_mono01 ? 0 : col;
}
else {
fg = is_mono01 ? 0 : col;
bg = is_mono01 ? col : 0;
}
return is_fg ? fg : bg;
}
#define attr_bgcol_ec(bgshift,vc,info) \
attr_col_ec(bgshift,vc,info,0);
#define attr_fgcol_ec(fgshift,vc,info) \
attr_col_ec(fgshift,vc,info,1);
/* Font */ /* Font */
#define REFCOUNT(fd) (((int *)(fd))[-1]) #define REFCOUNT(fd) (((int *)(fd))[-1])
#define FNTSIZE(fd) (((int *)(fd))[-2]) #define FNTSIZE(fd) (((int *)(fd))[-2])
......
...@@ -84,7 +84,7 @@ static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, ...@@ -84,7 +84,7 @@ static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy,
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = GETVYRES(ops->p->scrollmode, info);
region.color = attr_bgcol_ec(bgshift,vc); region.color = attr_bgcol_ec(bgshift,vc,info);
region.dx = sy * vc->vc_font.height; region.dx = sy * vc->vc_font.height;
region.dy = vyres - ((sx + width) * vc->vc_font.width); region.dy = vyres - ((sx + width) * vc->vc_font.width);
region.height = width * vc->vc_font.width; region.height = width * vc->vc_font.width;
...@@ -198,7 +198,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info, ...@@ -198,7 +198,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
struct fb_fillrect region; struct fb_fillrect region;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
region.color = attr_bgcol_ec(bgshift,vc); region.color = attr_bgcol_ec(bgshift,vc,info);
region.rop = ROP_COPY; region.rop = ROP_COPY;
if (rw && !bottom_only) { if (rw && !bottom_only) {
......
...@@ -70,7 +70,7 @@ static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, ...@@ -70,7 +70,7 @@ static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy,
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = GETVXRES(ops->p->scrollmode, info);
region.color = attr_bgcol_ec(bgshift,vc); region.color = attr_bgcol_ec(bgshift,vc,info);
region.dx = vxres - ((sy + height) * vc->vc_font.height); region.dx = vxres - ((sy + height) * vc->vc_font.height);
region.dy = sx * vc->vc_font.width; region.dy = sx * vc->vc_font.width;
region.height = width * vc->vc_font.width; region.height = width * vc->vc_font.width;
...@@ -182,7 +182,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info, ...@@ -182,7 +182,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
struct fb_fillrect region; struct fb_fillrect region;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
region.color = attr_bgcol_ec(bgshift,vc); region.color = attr_bgcol_ec(bgshift,vc,info);
region.rop = ROP_COPY; region.rop = ROP_COPY;
if (rw && !bottom_only) { if (rw && !bottom_only) {
......
...@@ -71,7 +71,7 @@ static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, ...@@ -71,7 +71,7 @@ static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy,
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = GETVYRES(ops->p->scrollmode, info);
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = GETVXRES(ops->p->scrollmode, info);
region.color = attr_bgcol_ec(bgshift,vc); region.color = attr_bgcol_ec(bgshift,vc,info);
region.dy = vyres - ((sy + height) * vc->vc_font.height); region.dy = vyres - ((sy + height) * vc->vc_font.height);
region.dx = vxres - ((sx + width) * vc->vc_font.width); region.dx = vxres - ((sx + width) * vc->vc_font.width);
region.width = width * vc->vc_font.width; region.width = width * vc->vc_font.width;
...@@ -228,7 +228,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info, ...@@ -228,7 +228,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
struct fb_fillrect region; struct fb_fillrect region;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
region.color = attr_bgcol_ec(bgshift,vc); region.color = attr_bgcol_ec(bgshift,vc,info);
region.rop = ROP_COPY; region.rop = ROP_COPY;
if (rw && !bottom_only) { if (rw && !bottom_only) {
......
...@@ -40,8 +40,8 @@ static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy, ...@@ -40,8 +40,8 @@ static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy,
rect.index = vc->vc_video_erase_char & rect.index = vc->vc_video_erase_char &
((vc->vc_hi_font_mask) ? 0x1ff : 0xff); ((vc->vc_hi_font_mask) ? 0x1ff : 0xff);
rect.fg = attr_fgcol_ec(fgshift, vc); rect.fg = attr_fgcol_ec(fgshift, vc, info);
rect.bg = attr_bgcol_ec(bgshift, vc); rect.bg = attr_bgcol_ec(bgshift, vc, info);
rect.sx = sx; rect.sx = sx;
rect.sy = sy; rect.sy = sy;
rect.width = width; rect.width = width;
......
...@@ -150,7 +150,7 @@ static int aafbcon_set_font(struct display *disp, int width, int height) ...@@ -150,7 +150,7 @@ static int aafbcon_set_font(struct display *disp, int width, int height)
{ {
struct aafb_info *info = (struct aafb_info *)disp->fb_info; struct aafb_info *info = (struct aafb_info *)disp->fb_info;
struct aafb_cursor *c = &info->cursor; struct aafb_cursor *c = &info->cursor;
u8 fgc = ~attr_bgcol_ec(disp, disp->conp); u8 fgc = ~attr_bgcol_ec(disp, disp->conp, &info->info);
if (width > 64 || height > 64 || width < 0 || height < 0) if (width > 64 || height > 64 || width < 0 || height < 0)
return -EINVAL; return -EINVAL;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册