Commit 91c4313206e4409871e2ddd13c29508afe1c8834
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; |