Commit 91c4313206e4409871e2ddd13c29508afe1c8834

Authored by Thomas Pfaff
Committed by Linus Torvalds
1 parent e8973637bd

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: Thomas Pfaff <tpfaff@pcs.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 8 changed files with 55 additions and 19 deletions Side-by-side Diff

drivers/video/console/bitblit.c
... ... @@ -63,7 +63,7 @@
63 63 int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
64 64 struct fb_fillrect region;
65 65  
66   - region.color = attr_bgcol_ec(bgshift, vc);
  66 + region.color = attr_bgcol_ec(bgshift, vc, info);
67 67 region.dx = sx * vc->vc_font.width;
68 68 region.dy = sy * vc->vc_font.height;
69 69 region.width = width * vc->vc_font.width;
... ... @@ -213,7 +213,7 @@
213 213 unsigned int bs = info->var.yres - bh;
214 214 struct fb_fillrect region;
215 215  
216   - region.color = attr_bgcol_ec(bgshift, vc);
  216 + region.color = attr_bgcol_ec(bgshift, vc, info);
217 217 region.rop = ROP_COPY;
218 218  
219 219 if (rw && !bottom_only) {
drivers/video/console/fbcon.c
... ... @@ -334,10 +334,7 @@
334 334 switch (depth) {
335 335 case 1:
336 336 {
337   - int col = ~(0xfff << (max(info->var.green.length,
338   - max(info->var.red.length,
339   - info->var.blue.length)))) & 0xff;
340   -
  337 + int col = mono_col(info);
341 338 /* 0 or 1 */
342 339 int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0;
343 340 int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col;
drivers/video/console/fbcon.h
... ... @@ -93,10 +93,6 @@
93 93 (((s) >> (fgshift)) & 0x0f)
94 94 #define attr_bgcol(bgshift,s) \
95 95 (((s) >> (bgshift)) & 0x0f)
96   -#define attr_bgcol_ec(bgshift,vc) \
97   - ((vc) ? (((vc)->vc_video_erase_char >> (bgshift)) & 0x0f) : 0)
98   -#define attr_fgcol_ec(fgshift,vc) \
99   - ((vc) ? (((vc)->vc_video_erase_char >> (fgshift)) & 0x0f) : 0)
100 96  
101 97 /* Monochrome */
102 98 #define attr_bold(s) \
... ... @@ -108,6 +104,49 @@
108 104 #define attr_blink(s) \
109 105 ((s) & 0x8000)
110 106  
  107 +#define mono_col(info) \
  108 + (~(0xfff << (max((info)->var.green.length, \
  109 + max((info)->var.red.length, \
  110 + (info)->var.blue.length)))) & 0xff)
  111 +
  112 +static inline int attr_col_ec(int shift, struct vc_data *vc,
  113 + struct fb_info *info, int is_fg)
  114 +{
  115 + int is_mono01;
  116 + int col;
  117 + int fg;
  118 + int bg;
  119 +
  120 + if (!vc)
  121 + return 0;
  122 +
  123 + if (vc->vc_can_do_color)
  124 + return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char)
  125 + : attr_bgcol(shift,vc->vc_video_erase_char);
  126 +
  127 + if (!info)
  128 + return 0;
  129 +
  130 + col = mono_col(info);
  131 + is_mono01 = info->fix.visual == FB_VISUAL_MONO01;
  132 +
  133 + if (attr_reverse(vc->vc_video_erase_char)) {
  134 + fg = is_mono01 ? col : 0;
  135 + bg = is_mono01 ? 0 : col;
  136 + }
  137 + else {
  138 + fg = is_mono01 ? 0 : col;
  139 + bg = is_mono01 ? col : 0;
  140 + }
  141 +
  142 + return is_fg ? fg : bg;
  143 +}
  144 +
  145 +#define attr_bgcol_ec(bgshift,vc,info) \
  146 + attr_col_ec(bgshift,vc,info,0);
  147 +#define attr_fgcol_ec(fgshift,vc,info) \
  148 + attr_col_ec(fgshift,vc,info,1);
  149 +
111 150 /* Font */
112 151 #define REFCOUNT(fd) (((int *)(fd))[-1])
113 152 #define FNTSIZE(fd) (((int *)(fd))[-2])
drivers/video/console/fbcon_ccw.c
... ... @@ -84,7 +84,7 @@
84 84 int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
85 85 u32 vyres = GETVYRES(ops->p->scrollmode, info);
86 86  
87   - region.color = attr_bgcol_ec(bgshift,vc);
  87 + region.color = attr_bgcol_ec(bgshift,vc,info);
88 88 region.dx = sy * vc->vc_font.height;
89 89 region.dy = vyres - ((sx + width) * vc->vc_font.width);
90 90 region.height = width * vc->vc_font.width;
... ... @@ -198,7 +198,7 @@
198 198 struct fb_fillrect region;
199 199 int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
200 200  
201   - region.color = attr_bgcol_ec(bgshift,vc);
  201 + region.color = attr_bgcol_ec(bgshift,vc,info);
202 202 region.rop = ROP_COPY;
203 203  
204 204 if (rw && !bottom_only) {
drivers/video/console/fbcon_cw.c
... ... @@ -70,7 +70,7 @@
70 70 int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
71 71 u32 vxres = GETVXRES(ops->p->scrollmode, info);
72 72  
73   - region.color = attr_bgcol_ec(bgshift,vc);
  73 + region.color = attr_bgcol_ec(bgshift,vc,info);
74 74 region.dx = vxres - ((sy + height) * vc->vc_font.height);
75 75 region.dy = sx * vc->vc_font.width;
76 76 region.height = width * vc->vc_font.width;
... ... @@ -182,7 +182,7 @@
182 182 struct fb_fillrect region;
183 183 int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
184 184  
185   - region.color = attr_bgcol_ec(bgshift,vc);
  185 + region.color = attr_bgcol_ec(bgshift,vc,info);
186 186 region.rop = ROP_COPY;
187 187  
188 188 if (rw && !bottom_only) {
drivers/video/console/fbcon_ud.c
... ... @@ -71,7 +71,7 @@
71 71 u32 vyres = GETVYRES(ops->p->scrollmode, info);
72 72 u32 vxres = GETVXRES(ops->p->scrollmode, info);
73 73  
74   - region.color = attr_bgcol_ec(bgshift,vc);
  74 + region.color = attr_bgcol_ec(bgshift,vc,info);
75 75 region.dy = vyres - ((sy + height) * vc->vc_font.height);
76 76 region.dx = vxres - ((sx + width) * vc->vc_font.width);
77 77 region.width = width * vc->vc_font.width;
... ... @@ -228,7 +228,7 @@
228 228 struct fb_fillrect region;
229 229 int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
230 230  
231   - region.color = attr_bgcol_ec(bgshift,vc);
  231 + region.color = attr_bgcol_ec(bgshift,vc,info);
232 232 region.rop = ROP_COPY;
233 233  
234 234 if (rw && !bottom_only) {
drivers/video/console/tileblit.c
... ... @@ -40,8 +40,8 @@
40 40  
41 41 rect.index = vc->vc_video_erase_char &
42 42 ((vc->vc_hi_font_mask) ? 0x1ff : 0xff);
43   - rect.fg = attr_fgcol_ec(fgshift, vc);
44   - rect.bg = attr_bgcol_ec(bgshift, vc);
  43 + rect.fg = attr_fgcol_ec(fgshift, vc, info);
  44 + rect.bg = attr_bgcol_ec(bgshift, vc, info);
45 45 rect.sx = sx;
46 46 rect.sy = sy;
47 47 rect.width = width;
drivers/video/pmag-aa-fb.c
... ... @@ -150,7 +150,7 @@
150 150 {
151 151 struct aafb_info *info = (struct aafb_info *)disp->fb_info;
152 152 struct aafb_cursor *c = &info->cursor;
153   - u8 fgc = ~attr_bgcol_ec(disp, disp->conp);
  153 + u8 fgc = ~attr_bgcol_ec(disp, disp->conp, &info->info);
154 154  
155 155 if (width > 64 || height > 64 || width < 0 || height < 0)
156 156 return -EINVAL;