Teaching kmscon output-rotation à la xrandr

Posted by in Uncategorized

Focus is paramount

Because of my slightly uncommon monitor-setup (two 24″ LCDs locked in portrait orientation side by side) using the VTs under Linux is very cumbersome. That has got to be a developer quirk. But because of that, I like to work on VTs exclusively from time to time… this helps with focus. I even turn off Xorg and/or wayland-based environments.

So what can I use to solve this issue with wrongly orientated text-output? xrandr obviously does not work in such a situation? There is an interesting – sadly abandoned – project on freedesktop: kmscon, which has the potential for being the foundation of a possible solution.

You have to know that kmscon is based on kernel-mode-setting, drm, EGL, pango and a few other bits and pieces. So with that in mind the desire to “teach kmscon output-rotation `a la xrandr” quickly turns into “how OpenGL-knowledge comes in handy for some system-programming” 🙂

Writing the patch

The design of kmscon provides switchable rendering engines/backends. There is one using fbdev… meh, a pixman one… oh venerable pixman and an OpenGL-based backend… STRIKE! This last one is going to be my playground for extension!

The OpenGL-backend needs to transform its output before anything get drawn to the EGL-surface. That is done by transforming the glyph-quads in the vertex-shader for the obvious four cases:

  • normal (0° rotation)
  • right (90° rotation clock-wise)
  • inverted (180° rotation clock-wise)
  • left (-90° rotation counter-clock-wise)

Another adjustment that needs to take place is the handling of the different aspect-ratio and changed number of columns and rows for the right and left orientation cases.

Since the kmscon project is dormant since 2014 or so, its way of taking results from eglChooseConfig() is causing to only work on a single machine (my oldest one). I added a more strict method to pick the right EGL-config, taking the attributes into account. This avoids the EGL_BAD_MATCH error, causing kmscon to exit.

Finally add an additional command-line option and update the man-page to reflect the additional feature and the patch is complete.

Testing and the elephant in the room

I tested it on my five machines, ranging from an intel Skylake GT iGPU up to an AMD Radeon Vega64. All systems run under Ubuntu 20.04, 22.04 or Fedora Workstation 37.

More testing hands are always welcome, since the phrase “It works on my system.” is no recommended quality metric 🙂

What or who is the “elephant in the room” you might wonder? That is nvidia of course and their proprietary driver. They do not support EGL in the same way as everybody else does. What libgbm is for the OpenSource/Mesa side of things, is called EGLstreams on nvidia’s side, if I am not mistaken. I do no longer own any nvidia-based GPUs, so cannot code against their special EGL-API.

Edit: Thanks to some insight provided by user Eighth_Doctor on #fedora-devel (IRC, Libra.Chat) my info about nvidia’s stance towards libgbm was not up-to-date. They actually do support it now and EGLstreams is dead. If the nvidia-driver get initialized with drm, it will use libgbm. Thus this patched kmscon should work with the proprietary driver too. Nice!

The nouveau driver should work fine with my version of kmscon. But I would like some people with such hardare/driver combinations to verify this and provide feedback.

To upstream or not to upstream

Well, that is not really a question. I would gladly send a pull-request to the upstream developer of kmscon. That seems to be David Herrmann as far as I can tell. Or at least a RFC-ish thing to discuss how/if my change is seen as a valuable addition.

Before I consider this I rather have some feedback from curious testers, who try it out on their systems and strange monitor setups.

Sourcecode, binary packages etc

How to actually run it

After you installed it on your machine. Nothing will happen or change by itself. The binary packages do not touch any of your system-files or service-scripts. You have to manually kick things off to run kmscon.

Before you issue any of the commands starting kmscon as shown below, be sure to switch to a VT, login in there and kill off your graphical environment. That’s usually done with a command like…

$> sudo systemctl stop gdm.service 

Here are a few examples…

$> sudo kmscon --vt 1 --rotate normal --drm --hwaccel --render-engine gltex -t linux --xkb-layout de --xkb-model pc102 --font-name "Ubuntu Mono" --font-size 18 

If you want a fancy fps-counter to see your directory listings fly by at 60, 120 or 144 Hz use this…

$> sudo GALLIUM_HUD_PERIOD=0.1 GALLIUM_HUD=".w320.h200.x1570.y10.d.c1000fps+cpu" kmscon --vt 1 --rotate normal --drm --hwaccel --render-engine gltex -t linux --xkb-layout de --xkb-model pc102 --font-name "Ubuntu Mono" --font-size 18 

You have to change the –xkb-layout, –font-name and –font-size to fit you needs and system setup. Also read the man-page of kmscon… especially the section about –rotate. Only use monospaced TrueType fonts.