> Date: Thu, 14 May 2020 19:20:00 +1000
> From: Jonathan Gray <[email protected]>
>
> On Wed, May 13, 2020 at 11:11:56PM -0700, [email protected] wrote:
> > On a system with VGA graphics, like a VirtualBox:
> >
> > Boot to X.
> > ctrl-alt-F1 back to text mode.
> > As root:
> > wsfontload -h 8 -e ibm /usr/share/misc/pcvtfonts/vt220l.808
> > wsconscfg -dF 1
> > wsconscfg -t 80x50 1
> > ctrl-alt-F2 to see the second screen in 80x50 mode
> > (takes a while for the getty to restart).
> > ctrl-alt-F5 to go back to graphics mode with X.
> > ctrl-alt-F2 to go back to the 80x50 text mode.
> >
> > The custom font has not been reloaded, so the screen is full of trash.
> >
> > Inserting a restore in vga.c:824 fixes it:
> > vga_setfont(vc, scr);
> > + vga_restore_fonts(vc);
> > vga_restore_palette(vc);
> >
> > This does cause the font to be uploaded on every virtual screen switch,
> > but it is only there if a custom font has already been loaded, and is
> > tiny in any case.
> >
> > The vga_restore_fonts() function is currently only called in vga_ioctl()
> > for WSDISPLAYIO_SMODE when going from graphics to WSDISPLAYIO_MODE_EMUL,
> > which should be optimal, but this never happens -- that vga_ioctl()
> > happens once after boot to go into graphics mode, but never gets called
> > again when switching back to text mode. Maybe something with the
> > integration of kms drivers changed the call semantics?
>
> Thanks for the report.
>
> In xenocara/xserver/hw/xfree86/os-support/bsd/bsd_init.c
> xf86OpenConsole() does the ioctl with WSDISPLAYIO_MODE_MAPPED
> xf86CloseConsole() does the ioctl with WSDISPLAYIO_MODE_EMUL
>
> however these aren't currently done for switching when xorg is running
>
> Testing here xf86VTSwitchAway() is called when switching from xorg to VT
> xf86VTSwitchTo() is called when switching back to xorg.
>
> Adding the ioctl to these functions makes the steps you've given end in
> a non trashed VT.
>
> This is clearly a dark corner of the xserver code and suffers from
> trying to support multiple systems and be compatible with USL ioctls.
I don't think this is the right approach. Having X involved in the VT
switch has always been a bit of an issue. Can't be avoided completely
since X somehow needs to be told to stop messing with the display
hardware behind our back. But I think it is best if the kernel can do
all the necessary repair by itself. Then, if X crashes, you can still
VT-switch to another screen and have things work.
So I think John's suggestion makes sense. The only thing that seems a
bit wrong is that the current font is set before the fonts are
actually restored.
Restoring the fonts on every VT-switch isn't a very big issue.
Nothing will happen if you didn't explicitly load an alternative font.
But if the overhead is noticable we could only do the restore when
switching away from a screen that has the SCR_GRAPHICS flag set to a
screen that doesn't.
> Index: xserver/hw/xfree86/os-support/bsd/bsd_VTsw.c
> ===================================================================
> RCS file: /cvs/xenocara/xserver/hw/xfree86/os-support/bsd/bsd_VTsw.c,v
> retrieving revision 1.5
> diff -u -p -r1.5 bsd_VTsw.c
> --- xserver/hw/xfree86/os-support/bsd/bsd_VTsw.c 2 Apr 2016 14:25:10
> -0000 1.5
> +++ xserver/hw/xfree86/os-support/bsd/bsd_VTsw.c 14 May 2020 08:44:33
> -0000
> @@ -72,13 +72,20 @@ xf86VTSwitchAway(void)
> {
> #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) \
> || defined(WSCONS_SUPPORT)
> + int mode;
> +
> if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT ||
> xf86Info.consType == WSCONS) {
> xf86Info.vtRequestsPending = FALSE;
> if (ioctl(xf86Info.consoleFd, VT_RELDISP, 1) < 0)
> return FALSE;
> - else
> - return TRUE;
> +
> +#ifdef WSCONS_SUPPORT
> + mode = WSDISPLAYIO_MODE_EMUL;
> + ioctl(xf86Info.consoleFd, WSDISPLAYIO_SMODE, &mode);
> +#endif
> +
> + return TRUE;
> }
> #endif
> return FALSE;
> @@ -89,13 +96,20 @@ xf86VTSwitchTo(void)
> {
> #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) \
> || defined(WSCONS_SUPPORT)
> + int mode;
> +
> if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT ||
> xf86Info.consType == WSCONS) {
> xf86Info.vtRequestsPending = FALSE;
> if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0)
> return FALSE;
> - else
> - return TRUE;
> +
> +#ifdef WSCONS_SUPPORT
> + mode = WSDISPLAYIO_MODE_MAPPED;
> + ioctl(xf86Info.consoleFd, WSDISPLAYIO_SMODE, &mode);
> +#endif
> +
> + return TRUE;
> }
> #endif
> return TRUE;
>
>