(While I was writing this, I was reminded of your screen blanking issues on the terminal console. Do check
man 4 console_codes and specifically
printf '\033[9;Xm\033[14;Xm', especially with
X set to zero.)
It doesn't actually change the fbcon source, it adds other kernel modules.
Oh, it does; it adds the decor hooks to drivers/video/fbdev/core/fbcon.c.
Anyway, I don't really understand how it works.
fbcon is a kernel-side blitter, which renders the console terminal contents to the framebuffer. You can use kernel command line parameters to map specific consoles to specific framebuffer devices.
fbterm is an old user-space framebuffer virtual terminal, that does the same thing in userspace.
fbcon does support display rotation, by blitting the characters rotated to the framebuffer. By default, it does not keep any kind of a background image, it just blits text with attributes to the framebuffer, and moves data around when scrolling, just like the Linux console terminal does. It is much more efficient if
CONFIG_FB_TILEBLITTING is set. It uses hardware panning and wrapping if available, falling back to hardware 2D blitting, and to
software blitting if nothing else is available, so it should always be set.
If you use getty for your terminal, then standard input, output, and error are directed to the
/dev/ttyN. The kernel interprets the standard escape sequences, and keeps the terminal contents in
/dev/vcsN (text only),
/dev/vcsuN (Unicode glyphs), and
/dev/vcsaN (text and attributes). Kernel console drivers like fbcon use a
include/linux/console.h:struct consw to register a set of callbacks that the kernel terminal console uses to render them to any other backing.
In userspace, fbterm and others can work in two different ways. One is to provide a virtual terminal (pseudoterminal pair), interpreting the escape sequences (listed in
man 4 console_codes), and keeping the virtual terminal contents in its own buffers, rendering them however one wants. When used instead/as a getty, they read input from the terminal (because that's where they get the keyboard input), but might not use the terminal console for output at all.
The other is to use the terminal console, but scan
/dev/vcsuN (and optionally
/dev/vcsaN) for changes, and updating any changes to the actual output device. The latter is used by screen readers and tools that mirror the terminal console contents to a separate device even when it is not active/foreground. (For example, you can do an X/Wayland application that displays their contents as a read-only window. It will need elevated privileges to access the
/dev/vcsaN and
/dev/vcsuN, however.
If one wanted to layer text and framebuffer contents to the actual display device, one option would be to create an fbcon derivative that also provides a synthetic framebuffer device (see
auxdisplay framebuffer drivers for simple implementations), using say 16-bit ZRGB1555 format, with Z=0 shown beneath the text, and Z=1 above the text. While the console terminal does have support for 24-bit RGB color (just try it:
printf '\033[38;2;255;204;153mThis is #FFCC99.\033[0m\n'), it does not have an escape code to define RGBA, so the only way to define the opacities of the 16 standard colors is to use the
FBIOPUTCMAP/
FBIOGETCMAP ioctl on the framebuffer device, which is a bit oddish.
Then, the derivative kernel module would composite the currently active console terminal (if any) with the synthetic framebuffer data, to the actual framebuffer device.
The downside is the extra memory use, and the slowness. A 1024×768 ZRGB1555 takes 1.5MBytes, and compositing the display contents with say a 8×12 fixed font (128×64 text window) takes its own lookup tables to do efficiently. Some hardware can do something similar by themselves, of course.
If you have read this far, you'll now have a good idea why one of my hobby projects is a small IPS display panel "controller" that internally composites 3-4 such framebuffer layers; one full-color background one, and 3-4 indexed color (pseudocolor, 4-bit or 8-bit pixels, a 256-entry ARGB palette per layer). It just opens up so many new
shenanigans. Well,
old ones, because that what was made arcade and early home game consoles so visually powerful when processors and microprocessors just didn't have the grunt we have available today. Doing it in software is somewhat taxing, so shortcuts and optimizations are quite important for performance. I haven't tried implementing it as a pixel shader for OpenGL ES or similar, but I do believe it would be possible; on any Linux SBC with Mali or other supported OpenGL ES implementation the GPU hardware would do it once per display update (60 - 70 times per second).