render: gamma-correct blending

This implements gamma-correct blending, which mainly affects font
rendering.

The implementation requires compile-time availability of the new
color-management protocol (available in wayland-protocols >= 1.41),
and run-time support for the same in the compositor (specifically, the
EXT_LINEAR TF function and sRGB primaries).

How it works: all colors are decoded from sRGB to linear (using a
lookup table, generated in the exact same way pixman generates it's
internal conversion tables) before being used by pixman. The resulting
image buffer is thus in decoded/linear format. We use the
color-management protocol to inform the compositor of this, by tagging
the wayland surfaces with the 'ext_linear' image attribute.

Sixes: all colors are sRGB internally, and decoded to linear before
being used in any sixels. Thus, the image buffers will contain linear
colors. This is important, since otherwise there would be a
decode/encode penalty every time a sixel is blended to the grid.

Emojis: we require fcft >= 3.2, which adds support for sRGB decoding
color glyphs. Meaning, the emoji pixman surfaces can be blended
directly to the grid, just like sixels.

Gamma-correct blending is enabled by default *when the compositor
supports it*. There's a new option to explicitly enable/disable it:
gamma-correct-blending=no|yes. If set to 'yes', and the compositor
does not implement the required color-management features, warning
logs are emitted.

There's a loss of precision when storing linear pixels in 8-bit
channels. For this reason, this patch also adds supports for 10-bit
surfaces. For now, this is disabled by default since such surfaces
only have 2 bits for alpha. It can be enabled with
tweak.surface-bit-depth=10-bit.

Perhaps, in the future, we can enable it by default if:

* gamma-correct blending is enabled
* the user has not enabled a transparent background
This commit is contained in:
Daniel Eklöf 2025-02-21 11:01:29 +01:00
parent 6d39f66eb7
commit ccf625b991
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
20 changed files with 746 additions and 101 deletions

View file

@ -198,6 +198,35 @@ empty string to be set, but it must be quoted: *KEY=""*)
Default: _unset_
*gamma-correct-blending*
Boolean. When enabled, foot will do gamma-correct blending in
linear color space. This is how font glyphs are supposed to be
rendered, but since nearly no applications or toolkits are doing
it on Linux, the result may not look like you are used to.
Compared to the default (disabled), bright glyphs on a dark
background will appear thicker, and dark glyphs on a light
background will appear thinner.
Also be aware that many fonts have been developed on systems that
do not do gamma-correct blending, and may therefore look thicker
than intended when rendered with gamma-correct blending, since the
font designer set the font weight based on incorrect rendering.
FreeType can limit the effect of the latter, with a technique
called stem darkening. It is only available for CFF fonts
(OpenType, .otf) and disabled by default (in FreeType). You can
enable it by setting the environment variable
*FREETYPE_PROPERTIES="cff:no-stem-darkening=0"* before starting
foot.
You may also want to enable 10-bit image buffers when
gamma-correct blending is enabled. Though probably only if you do
not use a transparent background (with 10-bit buffers, you only
get 2 bits alpha). See *tweak.surface-bit-depth*.
Default: enabled when compositor support is available
*box-drawings-uses-font-glyphs*
Boolean. When disabled, foot generates box/line drawing characters
itself. The are several advantages to doing this instead of using
@ -1917,6 +1946,23 @@ any of these options.
*bold-text-in-bright* is set to *yes* (the *palette-based* variant
is not affected by this option). Default: _1.3_.
*surface-bit-depth*
Selects which RGB bit depth to use for image buffers. One of
*8-bit*, or *10-bit*.
The default, *8-bit*, uses 8 bits for all channels, alpha
included. When *gamma-correct-blending* is disabled, this is the
best option.
When *gamma-correct-blending* is enabled, you may want to enable
10-bit surfaces, as that improves the color resolution. Be aware
however, that in this mode, the alpha channel is only 2 bits
instead of 8 bits. Thus, if you are using a transparent
background, you may want to use the default, *8-bit*, even if you
have gamma-correct blending enabled.
Default: _8-bit_
# SEE ALSO
*foot*(1), *footclient*(1)