[PATCH] Use correct erase colour for clearing in fbcon

Helge Deller deller at gmx.de
Mon Feb 3 19:42:41 UTC 2025


On 2/2/25 21:33, Kajtár Zsolt wrote:
> 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 at c64.rulez.org>


applied for further testing to fbdev git tree.

Helge

> ---
>   drivers/video/fbdev/core/bitblit.c   |  5 ++--
>   drivers/video/fbdev/core/fbcon.c     | 10 +++++---
>   drivers/video/fbdev/core/fbcon.h     | 38 +---------------------------
>   drivers/video/fbdev/core/fbcon_ccw.c |  5 ++--
>   drivers/video/fbdev/core/fbcon_cw.c  |  5 ++--
>   drivers/video/fbdev/core/fbcon_ud.c  |  5 ++--
>   drivers/video/fbdev/core/tileblit.c  |  8 +++---
>   7 files changed, 18 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
> index 3ff1b2a86..f9475c14f 100644
> --- a/drivers/video/fbdev/core/bitblit.c
> +++ b/drivers/video/fbdev/core/bitblit.c
> @@ -59,12 +59,11 @@ static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy,
>   }
>
>   static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy,
> -		      int sx, int height, int width)
> +		      int sx, int height, int width, int fg, int bg)
>   {
> -	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
>   	struct fb_fillrect region;
>
> -	region.color = attr_bgcol_ec(bgshift, vc, info);
> +	region.color = bg;
>   	region.dx = sx * vc->vc_font.width;
>   	region.dy = sy * vc->vc_font.height;
>   	region.width = width * vc->vc_font.width;
> diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
> index e8b4e8c11..07d127110 100644
> --- a/drivers/video/fbdev/core/fbcon.c
> +++ b/drivers/video/fbdev/core/fbcon.c
> @@ -1258,7 +1258,7 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
>   {
>   	struct fb_info *info = fbcon_info_from_console(vc->vc_num);
>   	struct fbcon_ops *ops = info->fbcon_par;
> -
> +	int fg, bg;
>   	struct fbcon_display *p = &fb_display[vc->vc_num];
>   	u_int y_break;
>
> @@ -1279,16 +1279,18 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
>   		fbcon_clear_margins(vc, 0);
>   	}
>
> +	fg = get_color(vc, info, vc->vc_video_erase_char, 1);
> +	bg = get_color(vc, info, vc->vc_video_erase_char, 0);
>   	/* Split blits that cross physical y_wrap boundary */
>
>   	y_break = p->vrows - p->yscroll;
>   	if (sy < y_break && sy + height - 1 >= y_break) {
>   		u_int b = y_break - sy;
> -		ops->clear(vc, info, real_y(p, sy), sx, b, width);
> +		ops->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg);
>   		ops->clear(vc, info, real_y(p, sy + b), sx, height - b,
> -				 width);
> +				 width, fg, bg);
>   	} else
> -		ops->clear(vc, info, real_y(p, sy), sx, height, width);
> +		ops->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg);
>   }
>
>   static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
> diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
> index df70ea5ec..4d97e6d8a 100644
> --- a/drivers/video/fbdev/core/fbcon.h
> +++ b/drivers/video/fbdev/core/fbcon.h
> @@ -55,7 +55,7 @@ struct fbcon_ops {
>   	void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy,
>   		      int sx, int dy, int dx, int height, int width);
>   	void (*clear)(struct vc_data *vc, struct fb_info *info, int sy,
> -		      int sx, int height, int width);
> +		      int sx, int height, int width, int fb, int bg);
>   	void (*putcs)(struct vc_data *vc, struct fb_info *info,
>   		      const unsigned short *s, int count, int yy, int xx,
>   		      int fg, int bg);
> @@ -116,42 +116,6 @@ static inline int mono_col(const struct fb_info *info)
>   	return (~(0xfff << max_len)) & 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)
> -
>       /*
>        *  Scroll Method
>        */
> diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c
> index f9b794ff7..89ef4ba7e 100644
> --- a/drivers/video/fbdev/core/fbcon_ccw.c
> +++ b/drivers/video/fbdev/core/fbcon_ccw.c
> @@ -78,14 +78,13 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
>   }
>
>   static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy,
> -		     int sx, int height, int width)
> +		     int sx, int height, int width, int fg, int bg)
>   {
>   	struct fbcon_ops *ops = info->fbcon_par;
>   	struct fb_fillrect region;
> -	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
>   	u32 vyres = GETVYRES(ops->p, info);
>
> -	region.color = attr_bgcol_ec(bgshift,vc,info);
> +	region.color = bg;
>   	region.dx = sy * vc->vc_font.height;
>   	region.dy = vyres - ((sx + width) * vc->vc_font.width);
>   	region.height = width * vc->vc_font.width;
> diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c
> index 903f6fc17..b9dac7940 100644
> --- a/drivers/video/fbdev/core/fbcon_cw.c
> +++ b/drivers/video/fbdev/core/fbcon_cw.c
> @@ -63,14 +63,13 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
>   }
>
>   static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy,
> -		     int sx, int height, int width)
> +		     int sx, int height, int width, int fg, int bg)
>   {
>   	struct fbcon_ops *ops = info->fbcon_par;
>   	struct fb_fillrect region;
> -	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
>   	u32 vxres = GETVXRES(ops->p, info);
>
> -	region.color = attr_bgcol_ec(bgshift,vc,info);
> +	region.color = bg;
>   	region.dx = vxres - ((sy + height) * vc->vc_font.height);
>   	region.dy = sx *  vc->vc_font.width;
>   	region.height = width * vc->vc_font.width;
> diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c
> index 594331936..0af7913a2 100644
> --- a/drivers/video/fbdev/core/fbcon_ud.c
> +++ b/drivers/video/fbdev/core/fbcon_ud.c
> @@ -64,15 +64,14 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy,
>   }
>
>   static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy,
> -		     int sx, int height, int width)
> +		     int sx, int height, int width, int fg, int bg)
>   {
>   	struct fbcon_ops *ops = info->fbcon_par;
>   	struct fb_fillrect region;
> -	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
>   	u32 vyres = GETVYRES(ops->p, info);
>   	u32 vxres = GETVXRES(ops->p, info);
>
> -	region.color = attr_bgcol_ec(bgshift,vc,info);
> +	region.color = bg;
>   	region.dy = vyres - ((sy + height) * vc->vc_font.height);
>   	region.dx = vxres - ((sx + width) *  vc->vc_font.width);
>   	region.width = width * vc->vc_font.width;
> diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c
> index eff7ec4da..45b0828fa 100644
> --- a/drivers/video/fbdev/core/tileblit.c
> +++ b/drivers/video/fbdev/core/tileblit.c
> @@ -32,16 +32,14 @@ static void tile_bmove(struct vc_data *vc, struct fb_info *info, int sy,
>   }
>
>   static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy,
> -		       int sx, int height, int width)
> +		       int sx, int height, int width, int fg, int bg)
>   {
>   	struct fb_tilerect rect;
> -	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
> -	int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
>
>   	rect.index = vc->vc_video_erase_char &
>   		((vc->vc_hi_font_mask) ? 0x1ff : 0xff);
> -	rect.fg = attr_fgcol_ec(fgshift, vc, info);
> -	rect.bg = attr_bgcol_ec(bgshift, vc, info);
> +	rect.fg = fg;
> +	rect.bg = bg;
>   	rect.sx = sx;
>   	rect.sy = sy;
>   	rect.width = width;



More information about the dri-devel mailing list