> 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;
> 
> 

Reply via email to