[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