NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
17.6k stars 13.75k forks source link

Enable extra fonts in kernel configuration #210070

Closed 9ary closed 1 year ago

9ary commented 1 year ago

Issue description

NixOS's default kernel configuration only enables the 8x8 and 8x16 fonts. This is not ideal, because they are too small for high-resolution displays. The current workaround used by config.hardware.video.hidpi.enable is to set console.font = lib.mkDefault "${pkgs.terminus_font}/share/consolefonts/ter-v32n.psf.gz". There are problems with this however:

The kernel is actually able to select an appropriate font for the current resolution using a simple heuristic since mid-2019 (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=dfd19a5004eff03755967086aa04254c3d91b8ec). This bypasses the problems listed above and ensures a good font is always selected after resolution switches. The only requirement appears to be that the fonts must be built into the kernel.

Technical details

Font-related kconfig options as configured by NixOS:

CONFIG_FONT_SUPPORT=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y

Arch Linux:

CONFIG_FONT_SUPPORT=y
CONFIG_FONTS=y
# CONFIG_FONT_8x8 is not set
CONFIG_FONT_8x16=y
# CONFIG_FONT_6x11 is not set
# CONFIG_FONT_7x14 is not set
# CONFIG_FONT_PEARL_8x8 is not set
# CONFIG_FONT_ACORN_8x8 is not set
# CONFIG_FONT_MINI_4x6 is not set
# CONFIG_FONT_6x10 is not set
# CONFIG_FONT_10x18 is not set
# CONFIG_FONT_SUN8x16 is not set
# CONFIG_FONT_SUN12x22 is not set
CONFIG_FONT_TER16x32=y
# CONFIG_FONT_6x8 is not set

So Arch enables the default 8x16 and Terminus 16x32 (the same font that the hidpi module sets). The observed behavior on Arch is that it seamlessly switches fonts after mode switches, and I've never seen this break since it has been enabled.

GrabbenD commented 1 year ago

Same issue here with a NVIDIA card and a 3840x1600 monitor. tty0 console text covers the entire screen. I couldn't resolve this issue manually with boot.initrd.availableKernelModules = [ "nvidia" ]; and boot.kernelParams = [ "video=DP-3:3840x1600@60" ]; (DP-3 is my monitor).

Setting the font manually to the default value (console.font = "Lat2-Terminus16";) gives the right font size but this particular font doesn't have antialiasing which looks quite bad on a HIDPI monitor.

9ary commented 1 year ago

There's no antialiasing in console fonts, they're all bitmap fonts.

GrabbenD commented 1 year ago

Gotcha, thanks.

On side note, I looked for a different consolefont and came up with this. Looks a lot better now :smile:

# For reference, boot.loader.grub.font affects console.font. 20px in GRUB and 16px in console gives a smooth transition (otherwise it looks like the font is resizing)

boot.initrd.systemd.enable = true; # [Experimental] SystemD as PID1 for faster Plymouth and TTY resolution initialization

boot.loader.grub = {
  # ... Rest of GRUB2 config ...

  font = "${pkgs.tamzen}/share/fonts/misc/Tamzen10x20r.otb"; # (pf2/otb/ttf) Invalid font breaks TTY resolution
  fontSize = 20; # Size should match bitmap font size

  gfxpayloadEfi = "3840x1600x32"; # TTY resolution (grub > videoinfo)
  gfxmodeEfi = "auto"; # Grub resolution (overridden by console mode)
  extraConfig = "
    terminal_input console
    terminal_output console
  ";
};

console = {
  earlySetup = true;
  font = "${pkgs.tamzen}/share/consolefonts/Tamzen8x16.psf";
  packages = with pkgs; [ tamzen ];
};