Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fbcon: Use correct erase colour for clearing in fbcon

The erase colour calculation for fbcon clearing should use get_color instead
of attr_col_ec, like everything else. The latter is similar but is not correct.
For example it's missing the depth dependent remapping and doesn't care about
blanking.

The problem can be reproduced by setting up the background colour to grey
(vt.color=0x70) and having an fbcon console set to 2bpp (4 shades of gray).
Now the background attribute should be 1 (dark gray) on the console.

If the screen is scrolled when pressing enter in a shell prompt at the bottom
line then the new line is cleared using colour 7 instead of 1. That's not
something fillrect likes (at 2bbp it expect 0-3) so the result is interesting.

This patch switches to get_color with vc_video_erase_char to determine the
erase colour from attr_col_ec. That makes the latter function redundant as
no other users were left.

Use correct erase colour for clearing in fbcon

Signed-off-by: Zsolt Kajtar <soci@c64.rulez.org>
Signed-off-by: Helge Deller <deller@gmx.de>

authored by

Zsolt Kajtar and committed by
Helge Deller
892c788d 76d3ca89

+18 -58
+2 -3
drivers/video/fbdev/core/bitblit.c
··· 59 59 } 60 60 61 61 static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, 62 - int sx, int height, int width) 62 + int sx, int height, int width, int fg, int bg) 63 63 { 64 - int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; 65 64 struct fb_fillrect region; 66 65 67 - region.color = attr_bgcol_ec(bgshift, vc, info); 66 + region.color = bg; 68 67 region.dx = sx * vc->vc_font.width; 69 68 region.dy = sy * vc->vc_font.height; 70 69 region.width = width * vc->vc_font.width;
+6 -4
drivers/video/fbdev/core/fbcon.c
··· 1258 1258 { 1259 1259 struct fb_info *info = fbcon_info_from_console(vc->vc_num); 1260 1260 struct fbcon_ops *ops = info->fbcon_par; 1261 - 1261 + int fg, bg; 1262 1262 struct fbcon_display *p = &fb_display[vc->vc_num]; 1263 1263 u_int y_break; 1264 1264 ··· 1279 1279 fbcon_clear_margins(vc, 0); 1280 1280 } 1281 1281 1282 + fg = get_color(vc, info, vc->vc_video_erase_char, 1); 1283 + bg = get_color(vc, info, vc->vc_video_erase_char, 0); 1282 1284 /* Split blits that cross physical y_wrap boundary */ 1283 1285 1284 1286 y_break = p->vrows - p->yscroll; 1285 1287 if (sy < y_break && sy + height - 1 >= y_break) { 1286 1288 u_int b = y_break - sy; 1287 - ops->clear(vc, info, real_y(p, sy), sx, b, width); 1289 + ops->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg); 1288 1290 ops->clear(vc, info, real_y(p, sy + b), sx, height - b, 1289 - width); 1291 + width, fg, bg); 1290 1292 } else 1291 - ops->clear(vc, info, real_y(p, sy), sx, height, width); 1293 + ops->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg); 1292 1294 } 1293 1295 1294 1296 static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
+1 -37
drivers/video/fbdev/core/fbcon.h
··· 55 55 void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, 56 56 int sx, int dy, int dx, int height, int width); 57 57 void (*clear)(struct vc_data *vc, struct fb_info *info, int sy, 58 - int sx, int height, int width); 58 + int sx, int height, int width, int fb, int bg); 59 59 void (*putcs)(struct vc_data *vc, struct fb_info *info, 60 60 const unsigned short *s, int count, int yy, int xx, 61 61 int fg, int bg); ··· 115 115 max_len = max(info->var.blue.length, max_len); 116 116 return (~(0xfff << max_len)) & 0xff; 117 117 } 118 - 119 - static inline int attr_col_ec(int shift, struct vc_data *vc, 120 - struct fb_info *info, int is_fg) 121 - { 122 - int is_mono01; 123 - int col; 124 - int fg; 125 - int bg; 126 - 127 - if (!vc) 128 - return 0; 129 - 130 - if (vc->vc_can_do_color) 131 - return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char) 132 - : attr_bgcol(shift,vc->vc_video_erase_char); 133 - 134 - if (!info) 135 - return 0; 136 - 137 - col = mono_col(info); 138 - is_mono01 = info->fix.visual == FB_VISUAL_MONO01; 139 - 140 - if (attr_reverse(vc->vc_video_erase_char)) { 141 - fg = is_mono01 ? col : 0; 142 - bg = is_mono01 ? 0 : col; 143 - } 144 - else { 145 - fg = is_mono01 ? 0 : col; 146 - bg = is_mono01 ? col : 0; 147 - } 148 - 149 - return is_fg ? fg : bg; 150 - } 151 - 152 - #define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0) 153 - #define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1) 154 118 155 119 /* 156 120 * Scroll Method
+2 -3
drivers/video/fbdev/core/fbcon_ccw.c
··· 78 78 } 79 79 80 80 static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, 81 - int sx, int height, int width) 81 + int sx, int height, int width, int fg, int bg) 82 82 { 83 83 struct fbcon_ops *ops = info->fbcon_par; 84 84 struct fb_fillrect region; 85 - int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; 86 85 u32 vyres = GETVYRES(ops->p, info); 87 86 88 - region.color = attr_bgcol_ec(bgshift,vc,info); 87 + region.color = bg; 89 88 region.dx = sy * vc->vc_font.height; 90 89 region.dy = vyres - ((sx + width) * vc->vc_font.width); 91 90 region.height = width * vc->vc_font.width;
+2 -3
drivers/video/fbdev/core/fbcon_cw.c
··· 63 63 } 64 64 65 65 static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, 66 - int sx, int height, int width) 66 + int sx, int height, int width, int fg, int bg) 67 67 { 68 68 struct fbcon_ops *ops = info->fbcon_par; 69 69 struct fb_fillrect region; 70 - int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; 71 70 u32 vxres = GETVXRES(ops->p, info); 72 71 73 - region.color = attr_bgcol_ec(bgshift,vc,info); 72 + region.color = bg; 74 73 region.dx = vxres - ((sy + height) * vc->vc_font.height); 75 74 region.dy = sx * vc->vc_font.width; 76 75 region.height = width * vc->vc_font.width;
+2 -3
drivers/video/fbdev/core/fbcon_ud.c
··· 64 64 } 65 65 66 66 static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, 67 - int sx, int height, int width) 67 + int sx, int height, int width, int fg, int bg) 68 68 { 69 69 struct fbcon_ops *ops = info->fbcon_par; 70 70 struct fb_fillrect region; 71 - int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; 72 71 u32 vyres = GETVYRES(ops->p, info); 73 72 u32 vxres = GETVXRES(ops->p, info); 74 73 75 - region.color = attr_bgcol_ec(bgshift,vc,info); 74 + region.color = bg; 76 75 region.dy = vyres - ((sy + height) * vc->vc_font.height); 77 76 region.dx = vxres - ((sx + width) * vc->vc_font.width); 78 77 region.width = width * vc->vc_font.width;
+3 -5
drivers/video/fbdev/core/tileblit.c
··· 32 32 } 33 33 34 34 static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy, 35 - int sx, int height, int width) 35 + int sx, int height, int width, int fg, int bg) 36 36 { 37 37 struct fb_tilerect rect; 38 - int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; 39 - int fgshift = (vc->vc_hi_font_mask) ? 9 : 8; 40 38 41 39 rect.index = vc->vc_video_erase_char & 42 40 ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); 43 - rect.fg = attr_fgcol_ec(fgshift, vc, info); 44 - rect.bg = attr_bgcol_ec(bgshift, vc, info); 41 + rect.fg = fg; 42 + rect.bg = bg; 45 43 rect.sx = sx; 46 44 rect.sy = sy; 47 45 rect.width = width;