NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/60696: genfb(4) restores the wrong palette when leaving WSDISPLAYIO_MODE_MAPPED
>Number: 60696
>Category: kern
>Synopsis: genfb(4) restores the wrong palette when leaving WSDISPLAYIO_MODE_MAPPED
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Sep 08 10:40:00 +0000 2026
>Originator: Ray Tran
>Release: 11.0
>Organization:
Diamond Creek Digital
>Environment:
NetBSD/mac68k 11.0
Tested on: Macintosh IIcx (68030, NuBus "Toby" video), Centris 650 (68040, onboard "Wombat" DAFB)
>Description:
genfb keeps one copy of the palette, scp->sc_cmap_red/green/blue[256].
- genfb_putcmap(), the WSDISPLAYIO_PUTCMAP path, writes into it
(dev/wsfb/genfb.c, "memcpy(&scp->sc_cmap_red[index], ...)").
- genfb_restore_palette() reads out of it and pushes it to hardware.
- WSDISPLAYIO_SMODE calls genfb_restore_palette() on the transition back
to WSDISPLAYIO_MODE_EMUL.
So when a program maps the framebuffer, programs its own colours through
WSDISPLAYIO_PUTCMAP and then exits, genfb "restores" that program's
palette onto the console. The console's own palette is gone: nothing
kept a copy of it. The restore is close to a no-op -- it rewrites the
hardware with the values already there.
This affects any genfb attachment whose bus backend supplies a colormap
callback, since without one genfb_putpalreg() does nothing and the
hardware LUT is never touched at all. On an 8-bit display the effect is
obvious: after leaving X the console is drawn with X's colour cube.
>How-To-Repeat:
On a machine whose genfb attachment provides a colormap callback, at
depth 8: note the console colours, run an X server that allocates
colours (i.e. without a static colormap), exit it, and look at the
console. It is drawn with the palette X last installed rather than the
one it had before X started.
>Fix:
Keep a copy of the palette when leaving MODE_EMUL and put it back when
returning, so the console's colours survive a mapped-mode program.
The change is contained in the WSDISPLAYIO_SMODE case plus three arrays
in struct genfb_private, and does not affect a system with no userland
palette changes. The order of the mode callback relative to the restore
is unchanged.
Tested on a Macintosh Centris 650 (DAFB, 640x480x8, colormap callback
provided) running NetBSD 11.0, with an X server that programs the CLUT
and a console driver that installs its own palette. Before, the
console came back wearing X's colours; after, its own palette returns.
Applies with "patch -p1" from the top of usr/src; verified with -F0
(no fuzz) against NetBSD-current 11.99.8 (20260830003849Z) and 11.0.
--- a/sys/dev/wsfb/genfb.c
+++ b/sys/dev/wsfb/genfb.c
@@ -93,6 +93,14 @@
u_char sc_cmap_red[256];
u_char sc_cmap_green[256];
u_char sc_cmap_blue[256];
+ u_char sc_cmap_saved_red[256];
+ u_char sc_cmap_saved_green[256];
+ u_char sc_cmap_saved_blue[256];
bool sc_want_clear;
#ifdef SPLASHSCREEN
struct splash_info sc_splash;
@@ -508,11 +516,33 @@
return error;
if (new_mode != scp->sc_mode) {
+ if (scp->sc_mode == WSDISPLAYIO_MODE_EMUL) {
+ memcpy(scp->sc_cmap_saved_red,
+ scp->sc_cmap_red, 256);
+ memcpy(scp->sc_cmap_saved_green,
+ scp->sc_cmap_green, 256);
+ memcpy(scp->sc_cmap_saved_blue,
+ scp->sc_cmap_blue, 256);
+ }
scp->sc_mode = new_mode;
if (scp->sc_modecb != NULL) {
scp->sc_modecb->gmc_setmode(sc, scp->sc_mode);
}
if (new_mode == WSDISPLAYIO_MODE_EMUL) {
+ memcpy(scp->sc_cmap_red,
+ scp->sc_cmap_saved_red, 256);
+ memcpy(scp->sc_cmap_green,
+ scp->sc_cmap_saved_green, 256);
+ memcpy(scp->sc_cmap_blue,
+ scp->sc_cmap_saved_blue, 256);
genfb_restore_palette(sc);
vcons_redraw_screen(ms);
}
Home |
Main Index |
Thread Index |
Old Index