Bug 261751 - vt mouse pointer background display bug
Summary: vt mouse pointer background display bug
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: Unspecified
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-bugs (Nobody)
URL: https://reviews.freebsd.org/D34412
Keywords: vt
Depends on:
Blocks:
 
Reported: 2022-02-06 17:21 UTC by Stefan B.
Modified: 2022-03-07 16:33 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Stefan B. 2022-02-06 17:21:46 UTC
How to reproduce:

1. Configure system to use vt newcons.
2. Run any application that uses dialog(1).
3. Move the mouse cursor onto the blue background area of the dialog(1) screen.

You'll observe that the character boxes under the mouse cursor are no longer blue, but _red_.

Looks strange and rather buggy.
This happens on all graphics cards on which I tested vt.
It can be observed _only_ when using vt newcons.

On sc console or X terminal emulators the mouse cursor background looks perfectly normal.
Comment 1 Ed Maste freebsd_committer freebsd_triage 2022-02-09 04:17:09 UTC
I cannot reproduce this.
Comment 2 Ed Maste freebsd_committer freebsd_triage 2022-02-20 20:06:14 UTC
Can you please attach a screenshot demonstrating the issue?
Comment 3 Stefan B. 2022-03-02 05:58:56 UTC
I have made a photo, sorry for the bad quality. I can make other photos or vbox screenshots if needed for better quality.

https://postimg.cc/CRxSJ3RK

Please zoom into the upper-left corner and look at the red box surrounding the mouse cursor, below the letters "unk".
This can be reproduced on any program that uses dialog, for example bsdinstall.

The color background of all character boxes intersecting with the mouse cursor is affected.
So the shape of the "red box" varies as you move the mouse, causing a less-than-ideal first impression of FreeBSD.

I have not yet encountered any hardware on which this artifact does not happen.
With the SC console, I have never seen this.
So I am quite sure that it is not a hardware issue, but a vt newcons issue.

BTW, as you can see, ensuring functional suspend/resume by autoconfiguring the "correct console to use" caused some substantial work for me while writing the Skunk Installer.
It would be awesome if from some FreeBSD RELEASE version onward the Skunk Installer would no longer have to revert the computer to using the SC console.

Thus I highly appreciate your work on fixing/improving vt newcons! Thank you very much!
Comment 4 Ed Maste freebsd_committer freebsd_triage 2022-03-02 13:40:57 UTC
Thank you for the photo, I have an idea what's happening here and why I don't see it. I believe this issue is reproducible with vt_vga only, not with an EFI framebuffer.

In sys/dev/vt/hw/vga/vt_vga.c:vga_bitblt_one_text_pixels_block() there is an optimized special case for a "pixel block" having only two colours, and a more general case for n colours. In the case in your photo we are using the general case.

I suspect the general case has the R and B channels swapped.  If you can easily try a patch we could confirm this by disabling the optimization. For example,

diff --git a/sys/dev/vt/hw/vga/vt_vga.c b/sys/dev/vt/hw/vga/vt_vga.c
index 563867399e53..c8041f1dac8b 100644
--- a/sys/dev/vt/hw/vga/vt_vga.c
+++ b/sys/dev/vt/hw/vga/vt_vga.c
@@ -770,7 +770,7 @@ vga_bitblt_one_text_pixels_block(struct vt_device *vd,
         * The pixels block is completed, we can now draw it on the
         * screen.
         */
-       if (used_colors == 2)
+       if (0 && used_colors == 2)
                vga_bitblt_pixels_block_2colors(vd, pattern_2colors, fg, bg,
                    x, y, vf->vf_height);
        else

If I am correct this would result in a display that is consistently incorrect -- the entire dialog background would be red, not just the location of the mouse cursor.
Comment 5 Ed Maste freebsd_committer freebsd_triage 2022-03-02 13:44:33 UTC
Looking further I think this may be fallout from 5e251aec86367747ac1d7086dcbb05f18ef0f167.

This untested patch may fix it:

diff --git a/sys/dev/vt/hw/vga/vt_vga.c b/sys/dev/vt/hw/vga/vt_vga.c
index 563867399e53..0cb5f356a70a 100644
--- a/sys/dev/vt/hw/vga/vt_vga.c
+++ b/sys/dev/vt/hw/vga/vt_vga.c
@@ -582,7 +582,7 @@ vga_bitblt_pixels_block_ncolors(struct vt_device *vd, const uint8_t *masks,
                                /* The pixel "j" uses color "color". */
                                for (plan = 0; plan < 4; ++plan)
                                        plans[i * 4 + plan] |=
-                                           ((color >> plan) & 0x1) << (7 - j);
+                                           ((cons_to_vga_colors[color] >> plan) & 0x1) << (7 - j);
                        }
                }
        }
Comment 6 Ed Maste freebsd_committer freebsd_triage 2022-03-02 16:42:22 UTC
Review opened at https://reviews.freebsd.org/D34412
Comment 7 commit-hook freebsd_committer freebsd_triage 2022-03-03 00:09:37 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=f266082f113a6a110c28034c64693c2cc216fd9d

commit f266082f113a6a110c28034c64693c2cc216fd9d
Author:     Ed Maste <emaste@FreeBSD.org>
AuthorDate: 2022-03-02 16:40:00 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2022-03-03 00:07:20 +0000

    vt_vga: fix colour in pixel blocks with more than 4 colours

    VGA hardware provides many different graphics and data access modes,
    each with different capabilities and limitations.

    VGA vt(4) graphics mode operates on blocks of pixels at a time.  When a
    given pixel block contains only two colours the vt_vga driver uses write
    mode 3.  When the block contains more than two colours it uses write
    mode 0.  This is done because two-colour write mode 3 is much more
    efficient.

    In practice write mode 3 is used most of the time, as there is often a
    single foreground colour and single background colour across the entire
    console.  One common exception requiring the use of mode 0 is when the
    mouse cursor is drawn over a background other than black, as we need
    black and white for the cursor in addition to the background colour.

    VGA's default 16-colour palette provides the same set of colours as the
    system console, but in a different order.  Previously we configured a
    non-default VGA palette that had the same colours at the same indexes.
    However, this caused anything drawn before the kernel started (drawn by
    the loader, for instance) to change colours once the kernel configured
    the new, non-default palette.

    In 5e251aec8636 we switched to leaving the default VGA palette in place,
    translating console colour indexes to VGA colour indexes as necessary.
    This translation was missed for the write mode 0 case for pixel blocks
    with more than two colours.

    PR:             261751
    Reviewed by:    adrian
    MFC after:      1 week
    Fixes:          5e251aec8636 ("vt(4): Use default VGA palette")
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D34412

 sys/dev/vt/hw/vga/vt_vga.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
Comment 8 Stefan B. 2022-03-03 10:12:57 UTC
Built both the first patch, and the patch posted in the phabricator review.
Looks fine so far.
The strange red background box seems gone, didn't reappear at my quick test.
Comment 9 commit-hook freebsd_committer freebsd_triage 2022-03-07 16:26:49 UTC
A commit in branch stable/13 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=eb40c0f2f2ce5d83707bef2f9c8259312da852d1

commit eb40c0f2f2ce5d83707bef2f9c8259312da852d1
Author:     Ed Maste <emaste@FreeBSD.org>
AuthorDate: 2022-03-02 16:40:00 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2022-03-07 16:25:21 +0000

    vt_vga: fix colour in pixel blocks with more than 4 colours

    VGA hardware provides many different graphics and data access modes,
    each with different capabilities and limitations.

    VGA vt(4) graphics mode operates on blocks of pixels at a time.  When a
    given pixel block contains only two colours the vt_vga driver uses write
    mode 3.  When the block contains more than two colours it uses write
    mode 0.  This is done because two-colour write mode 3 is much more
    efficient.

    In practice write mode 3 is used most of the time, as there is often a
    single foreground colour and single background colour across the entire
    console.  One common exception requiring the use of mode 0 is when the
    mouse cursor is drawn over a background other than black, as we need
    black and white for the cursor in addition to the background colour.

    VGA's default 16-colour palette provides the same set of colours as the
    system console, but in a different order.  Previously we configured a
    non-default VGA palette that had the same colours at the same indexes.
    However, this caused anything drawn before the kernel started (drawn by
    the loader, for instance) to change colours once the kernel configured
    the new, non-default palette.

    In 5e251aec8636 we switched to leaving the default VGA palette in place,
    translating console colour indexes to VGA colour indexes as necessary.
    This translation was missed for the write mode 0 case for pixel blocks
    with more than two colours.

    PR:             261751
    Reviewed by:    adrian
    MFC after:      1 week
    Fixes:          5e251aec8636 ("vt(4): Use default VGA palette")
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D34412

    (cherry picked from commit f266082f113a6a110c28034c64693c2cc216fd9d)

 sys/dev/vt/hw/vga/vt_vga.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
Comment 10 commit-hook freebsd_committer freebsd_triage 2022-03-07 16:26:53 UTC
A commit in branch stable/12 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=4e4e477d89fd0333425ed4623858082bdb58ffe7

commit 4e4e477d89fd0333425ed4623858082bdb58ffe7
Author:     Ed Maste <emaste@FreeBSD.org>
AuthorDate: 2022-03-02 16:40:00 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2022-03-07 16:25:58 +0000

    vt_vga: fix colour in pixel blocks with more than 4 colours

    VGA hardware provides many different graphics and data access modes,
    each with different capabilities and limitations.

    VGA vt(4) graphics mode operates on blocks of pixels at a time.  When a
    given pixel block contains only two colours the vt_vga driver uses write
    mode 3.  When the block contains more than two colours it uses write
    mode 0.  This is done because two-colour write mode 3 is much more
    efficient.

    In practice write mode 3 is used most of the time, as there is often a
    single foreground colour and single background colour across the entire
    console.  One common exception requiring the use of mode 0 is when the
    mouse cursor is drawn over a background other than black, as we need
    black and white for the cursor in addition to the background colour.

    VGA's default 16-colour palette provides the same set of colours as the
    system console, but in a different order.  Previously we configured a
    non-default VGA palette that had the same colours at the same indexes.
    However, this caused anything drawn before the kernel started (drawn by
    the loader, for instance) to change colours once the kernel configured
    the new, non-default palette.

    In 5e251aec8636 we switched to leaving the default VGA palette in place,
    translating console colour indexes to VGA colour indexes as necessary.
    This translation was missed for the write mode 0 case for pixel blocks
    with more than two colours.

    PR:             261751
    Reviewed by:    adrian
    MFC after:      1 week
    Fixes:          5e251aec8636 ("vt(4): Use default VGA palette")
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D34412

    (cherry picked from commit f266082f113a6a110c28034c64693c2cc216fd9d)

 sys/dev/vt/hw/vga/vt_vga.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)