]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
fbcon: Use correct erase colour for clearing in fbcon
authorZsolt Kajtar <soci@c64.rulez.org>
Sun, 2 Feb 2025 20:33:46 +0000 (21:33 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 4 Jun 2025 12:36:59 +0000 (14:36 +0200)
[ Upstream commit 892c788d73fe4a94337ed092cb998c49fa8ecaf4 ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/video/fbdev/core/bitblit.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbcon.h
drivers/video/fbdev/core/fbcon_ccw.c
drivers/video/fbdev/core/fbcon_cw.c
drivers/video/fbdev/core/fbcon_ud.c
drivers/video/fbdev/core/tileblit.c

index 8e095b0982db4dab46761c8fd9b1c126f3970aa6..bb821b68f88c088e4a5e1f845fda4cabf6ca6309 100644 (file)
@@ -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;
index 6d58c8a5cb446dcd168b762cea2f0dd5cdddea22..080b615a55810e9a627caacd6ffcb79e442cea20 100644 (file)
@@ -1266,7 +1266,7 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
 {
        struct fb_info *info = registered_fb[con2fb_map[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;
 
@@ -1287,16 +1287,18 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
                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_putcs(struct vc_data *vc, const unsigned short *s,
index 0f16cbc99e6a4f483018a46928f9e957917f9179..3e1ec454b8aa39126d3d2859c68126aa2791484e 100644 (file)
@@ -57,7 +57,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);
@@ -118,42 +118,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
      */
index f75b24c32d497e27fdb6c56b512b68e92349b9a2..40c7d5793ccfeedba8fb8aab84e50dade2f7e6ee 100644 (file)
@@ -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;
index cf03dc62f35d37869fd6aac1bb679285527a9f97..933e4ed52d393db739b9a524fd3996f86ef9d270 100644 (file)
@@ -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;
index c5d2da731d68629b2a2fc4ce15fcdc5d654ced21..abd23f37815f59d532de7a0bef1fe6f7e55122a5 100644 (file)
@@ -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;
index 628fe5e010c08264af89ce6157a46901eb969dda..82e43e82f488eb3912fc1f8a97d98fb8325e08ac 100644 (file)
@@ -33,16 +33,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;