mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
config: tweak.surface-bit-depth now defaults to 'auto'
When set to 'auto', use 10-bit surfaces if gamma-correct blending is enabled, and 8-bit surfaces otherwise. Note that we may still fallback to 8-bit surfaces (without disabling gamma-correct blending) if the compositor does not support 10-bit surfaces. Closes #2082
This commit is contained in:
parent
7ced397089
commit
2a8948a3f3
13 changed files with 108 additions and 71 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
|
@ -64,14 +64,27 @@
|
|||
|
||||
## Unreleased
|
||||
### Added
|
||||
|
||||
* `auto` to the `tweak.surface-bit-depth` option.
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
* `gamma-correct-blending` now defaults to `no` instead of `yes`.
|
||||
* `tweak.surface-bit-depth` default value changed to `auto`; uses
|
||||
10-bit surfaces when `gamma-correct-blending=yes`, and 8-bit
|
||||
surfaces otherwise.
|
||||
|
||||
|
||||
### Deprecated
|
||||
### Removed
|
||||
### Fixed
|
||||
|
||||
* Inaccurate colors when `gamma-correct-blending=yes` ([#2082][2082]).
|
||||
|
||||
[2082]: https://codeberg.org/dnkl/foot/issues/2082
|
||||
|
||||
|
||||
### Security
|
||||
### Contributors
|
||||
|
||||
|
|
|
|||
4
config.c
4
config.c
|
|
@ -2771,7 +2771,7 @@ parse_section_tweak(struct context *ctx)
|
|||
|
||||
return value_to_enum(
|
||||
ctx,
|
||||
(const char *[]){"8-bit", "10-bit", NULL},
|
||||
(const char *[]){"auto", "8-bit", "10-bit", NULL},
|
||||
(int *)&conf->tweak.surface_bit_depth);
|
||||
}
|
||||
|
||||
|
|
@ -3419,7 +3419,7 @@ config_load(struct config *conf, const char *conf_path,
|
|||
.box_drawing_solid_shades = true,
|
||||
.font_monospace_warn = true,
|
||||
.sixel = true,
|
||||
.surface_bit_depth = 8,
|
||||
.surface_bit_depth = SHM_BITS_AUTO,
|
||||
},
|
||||
|
||||
.touch = {
|
||||
|
|
|
|||
8
config.h
8
config.h
|
|
@ -131,6 +131,12 @@ struct custom_regex {
|
|||
struct config_spawn_template launch;
|
||||
};
|
||||
|
||||
enum shm_bit_depth {
|
||||
SHM_BITS_AUTO,
|
||||
SHM_BITS_8,
|
||||
SHM_BITS_10
|
||||
};
|
||||
|
||||
struct config {
|
||||
char *term;
|
||||
char *shell;
|
||||
|
|
@ -408,7 +414,7 @@ struct config {
|
|||
bool box_drawing_solid_shades;
|
||||
bool font_monospace_warn;
|
||||
bool sixel;
|
||||
enum { SHM_8_BIT, SHM_10_BIT } surface_bit_depth;
|
||||
enum shm_bit_depth surface_bit_depth;
|
||||
} tweak;
|
||||
|
||||
struct {
|
||||
|
|
|
|||
|
|
@ -220,12 +220,13 @@ empty string to be set, but it must be quoted: *KEY=""*)
|
|||
than intended when rendered with gamma-correct blending, since the
|
||||
font designer set the font weight based on incorrect rendering.
|
||||
|
||||
Note that some colors (especially dark ones) may be slightly
|
||||
off. The reason for this is loss of color precision, due to foot
|
||||
using 8-bit surfaces (i.e. each color channel is 8 bits). In all
|
||||
known cases, the difference is small enough not to be noticed
|
||||
though. The amount of errors can be reduced by using 10-bit
|
||||
surfaces; see *tweak.surface-bit-depth*.
|
||||
In order to represent colors faithfully, higher precision image
|
||||
buffers are required. By default, foot will use 10-bit color
|
||||
channels, if available, when gamma-correct blending is
|
||||
enabled. However, the high precision buffers are slow; if you want
|
||||
to use gamma-correct blending, but prefer speed (throughput and
|
||||
input latency) over accurate colors, you can force 8-bit color
|
||||
channels by setting *tweak.surface-bit-depth=8-bit*.
|
||||
|
||||
Default: _no_.
|
||||
|
||||
|
|
@ -1974,23 +1975,25 @@ any of these options.
|
|||
|
||||
*surface-bit-depth*
|
||||
Selects which RGB bit depth to use for image buffers. One of
|
||||
*8-bit*, or *10-bit*.
|
||||
*auto*, *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.
|
||||
*auto* chooses bit depth depending on other settings, and
|
||||
availability.
|
||||
|
||||
When *gamma-correct-blending* is enabled, you may want to enable
|
||||
10-bit surfaces, as that improves color precision. 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.
|
||||
*8-bit*, uses 8 bits for each color channel, alpha included. This
|
||||
is the default when *gamma-correct-blending=no*.
|
||||
|
||||
You should also note that 10-bit surface is much slower. This will
|
||||
increase input latency and decrease rendering throughput.
|
||||
*10-bit* uses 10 bits for each RGB channel, and 2 bits for the
|
||||
alpha channel. Thus, it provides higher precision color channels,
|
||||
but a lower precision alpha channel. It is the default when
|
||||
*gamma-correct-blending=yes*, if supported by the compositor.
|
||||
|
||||
Default: _8-bit_
|
||||
Note that *10-bit* is much slower than *8-bit*; if you want to use
|
||||
gamma-correct blending, and if you prefer speed (throughput and
|
||||
input latency) over accurate colors, you can set
|
||||
*surface-bit-depth=8-bit* explicitly.
|
||||
|
||||
Default: _auto_
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ render_worker_thread(void *_ctx)
|
|||
}
|
||||
|
||||
bool
|
||||
render_do_linear_blending(const struct terminal *term)
|
||||
wayl_do_linear_blending(const struct wayland *wayl, const struct config *conf)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -201,11 +201,12 @@ void urls_reset(struct terminal *term) {}
|
|||
|
||||
void shm_unref(struct buffer *buf) {}
|
||||
void shm_chain_free(struct buffer_chain *chain) {}
|
||||
enum shm_bit_depth shm_chain_bit_depth(const struct buffer_chain *chain) { return SHM_BITS_8; }
|
||||
|
||||
struct buffer_chain *
|
||||
shm_chain_new(
|
||||
struct wayland *wayl, bool scrollable, size_t pix_instances,
|
||||
bool ten_bit_it_if_capable)
|
||||
enum shm_bit_depth desired_bit_depth)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
31
render.c
31
render.c
|
|
@ -626,7 +626,7 @@ draw_cursor(const struct terminal *term, const struct cell *cell,
|
|||
pixman_color_t cursor_color;
|
||||
pixman_color_t text_color;
|
||||
cursor_colors_for_cell(term, cell, fg, bg, &cursor_color, &text_color,
|
||||
render_do_linear_blending(term));
|
||||
wayl_do_linear_blending(term->wl, term->conf));
|
||||
|
||||
if (unlikely(!term->kbd_focus)) {
|
||||
switch (term->conf->cursor.unfocused_style) {
|
||||
|
|
@ -820,7 +820,7 @@ render_cell(struct terminal *term, pixman_image_t *pix,
|
|||
if (cell->attrs.blink && term->blink.state == BLINK_OFF)
|
||||
_fg = color_blend_towards(_fg, 0x00000000, term->conf->dim.amount);
|
||||
|
||||
const bool gamma_correct = render_do_linear_blending(term);
|
||||
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
|
||||
pixman_color_t fg = color_hex_to_pixman(_fg, gamma_correct);
|
||||
pixman_color_t bg = color_hex_to_pixman_with_alpha(_bg, alpha, gamma_correct);
|
||||
|
||||
|
|
@ -1180,7 +1180,8 @@ static void
|
|||
render_urgency(struct terminal *term, struct buffer *buf)
|
||||
{
|
||||
uint32_t red = term->colors.table[1];
|
||||
pixman_color_t bg = color_hex_to_pixman(red, render_do_linear_blending(term));
|
||||
pixman_color_t bg = color_hex_to_pixman(
|
||||
red, wayl_do_linear_blending(term->wl, term->conf));
|
||||
|
||||
int width = min(min(term->margins.left, term->margins.right),
|
||||
min(term->margins.top, term->margins.bottom));
|
||||
|
|
@ -1211,7 +1212,7 @@ render_margin(struct terminal *term, struct buffer *buf,
|
|||
const int bmargin = term->height - term->margins.bottom;
|
||||
const int line_count = end_line - start_line;
|
||||
|
||||
const bool gamma_correct = render_do_linear_blending(term);
|
||||
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
|
||||
const uint32_t _bg = !term->reverse ? term->colors.bg : term->colors.fg;
|
||||
uint16_t alpha = term->colors.alpha;
|
||||
|
||||
|
|
@ -1699,7 +1700,7 @@ render_ime_preedit_for_seat(struct terminal *term, struct seat *seat,
|
|||
if (unlikely(term->is_searching))
|
||||
return;
|
||||
|
||||
const bool gamma_correct = render_do_linear_blending(term);
|
||||
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
|
||||
|
||||
/* Adjust cursor position to viewport */
|
||||
struct coord cursor;
|
||||
|
|
@ -1970,7 +1971,8 @@ render_overlay(struct terminal *term)
|
|||
case OVERLAY_FLASH:
|
||||
color = color_hex_to_pixman_with_alpha(
|
||||
term->conf->colors.flash,
|
||||
term->conf->colors.flash_alpha, render_do_linear_blending(term));
|
||||
term->conf->colors.flash_alpha,
|
||||
wayl_do_linear_blending(term->wl, term->conf));
|
||||
break;
|
||||
|
||||
case OVERLAY_NONE:
|
||||
|
|
@ -2312,7 +2314,7 @@ render_osd(struct terminal *term, const struct wayl_sub_surface *sub_surf,
|
|||
pixman_image_set_clip_region32(buf->pix[0], &clip);
|
||||
pixman_region32_fini(&clip);
|
||||
|
||||
const bool gamma_correct = render_do_linear_blending(term);
|
||||
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
|
||||
uint16_t alpha = _bg >> 24 | (_bg >> 24 << 8);
|
||||
pixman_color_t bg = color_hex_to_pixman_with_alpha(_bg, alpha, gamma_correct);
|
||||
pixman_image_fill_rectangles(
|
||||
|
|
@ -2453,7 +2455,7 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx,
|
|||
if (info->width == 0 || info->height == 0)
|
||||
return;
|
||||
|
||||
const bool gamma_correct = render_do_linear_blending(term);
|
||||
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
|
||||
|
||||
{
|
||||
/* Fully transparent - no need to do a color space transform */
|
||||
|
|
@ -2542,7 +2544,7 @@ get_csd_button_fg_color(const struct terminal *term)
|
|||
}
|
||||
|
||||
return color_hex_to_pixman_with_alpha(
|
||||
_color, alpha, render_do_linear_blending(term));
|
||||
_color, alpha, wayl_do_linear_blending(term->wl, term->conf));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2819,7 +2821,7 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx,
|
|||
if (!term->visual_focus)
|
||||
_color = color_dim(term, _color);
|
||||
|
||||
const bool gamma_correct = render_do_linear_blending(term);
|
||||
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
|
||||
pixman_color_t color = color_hex_to_pixman_with_alpha(_color, alpha, gamma_correct);
|
||||
render_csd_part(term, surf->surf, buf, info->width, info->height, &color);
|
||||
|
||||
|
|
@ -3678,7 +3680,7 @@ render_search_box(struct terminal *term)
|
|||
: term->conf->colors.use_custom.search_box_no_match;
|
||||
|
||||
/* Background - yellow on empty/match, red on mismatch (default) */
|
||||
const bool gamma_correct = render_do_linear_blending(term);
|
||||
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
|
||||
const pixman_color_t color = color_hex_to_pixman(
|
||||
is_match
|
||||
? (custom_colors
|
||||
|
|
@ -5247,10 +5249,3 @@ render_xcursor_set(struct seat *seat, struct terminal *term,
|
|||
seat->pointer.xcursor_pending = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
render_do_linear_blending(const struct terminal *term)
|
||||
{
|
||||
return term->conf->gamma_correct &&
|
||||
term->wl->color_management.img_description != NULL;
|
||||
}
|
||||
|
|
|
|||
2
render.h
2
render.h
|
|
@ -47,5 +47,3 @@ struct csd_data {
|
|||
};
|
||||
|
||||
struct csd_data get_csd_data(const struct terminal *term, enum csd_surface surf_idx);
|
||||
|
||||
bool render_do_linear_blending(const struct terminal *term);
|
||||
|
|
|
|||
15
shm.c
15
shm.c
|
|
@ -972,7 +972,7 @@ shm_unref(struct buffer *_buf)
|
|||
|
||||
struct buffer_chain *
|
||||
shm_chain_new(struct wayland *wayl, bool scrollable, size_t pix_instances,
|
||||
bool ten_bit_if_capable)
|
||||
enum shm_bit_depth desired_bit_depth)
|
||||
{
|
||||
pixman_format_code_t pixman_fmt_without_alpha = PIXMAN_x8r8g8b8;
|
||||
enum wl_shm_format shm_fmt_without_alpha = WL_SHM_FORMAT_XRGB8888;
|
||||
|
|
@ -982,8 +982,7 @@ shm_chain_new(struct wayland *wayl, bool scrollable, size_t pix_instances,
|
|||
|
||||
static bool have_logged = false;
|
||||
|
||||
|
||||
if (ten_bit_if_capable) {
|
||||
if (desired_bit_depth == SHM_BITS_10) {
|
||||
if (wayl->shm_have_argb2101010 && wayl->shm_have_xrgb2101010) {
|
||||
pixman_fmt_without_alpha = PIXMAN_x2r10g10b10;
|
||||
shm_fmt_without_alpha = WL_SHM_FORMAT_XRGB2101010;
|
||||
|
|
@ -1058,3 +1057,13 @@ shm_chain_free(struct buffer_chain *chain)
|
|||
|
||||
free(chain);
|
||||
}
|
||||
|
||||
enum shm_bit_depth
|
||||
shm_chain_bit_depth(const struct buffer_chain *chain)
|
||||
{
|
||||
const pixman_format_code_t fmt = chain->pixman_fmt_with_alpha;
|
||||
|
||||
return (fmt == PIXMAN_a2r10g10b10 || fmt == PIXMAN_a2b10g10r10)
|
||||
? SHM_BITS_10
|
||||
: SHM_BITS_8;
|
||||
}
|
||||
|
|
|
|||
5
shm.h
5
shm.h
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <tllist.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "wayland.h"
|
||||
|
||||
struct damage;
|
||||
|
|
@ -46,9 +47,11 @@ void shm_set_max_pool_size(off_t max_pool_size);
|
|||
struct buffer_chain;
|
||||
struct buffer_chain *shm_chain_new(
|
||||
struct wayland *wayl, bool scrollable, size_t pix_instances,
|
||||
bool ten_bit_it_if_capable);
|
||||
enum shm_bit_depth desired_bit_depth);
|
||||
void shm_chain_free(struct buffer_chain *chain);
|
||||
|
||||
enum shm_bit_depth shm_chain_bit_depth(const struct buffer_chain *chain);
|
||||
|
||||
/*
|
||||
* Returns a single buffer.
|
||||
*
|
||||
|
|
|
|||
4
sixel.c
4
sixel.c
|
|
@ -110,10 +110,10 @@ sixel_init(struct terminal *term, int p1, int p2, int p3)
|
|||
term->sixel.image.height = 0;
|
||||
term->sixel.image.alloc_height = 0;
|
||||
term->sixel.image.bottom_pixel = 0;
|
||||
term->sixel.linear_blending = render_do_linear_blending(term);
|
||||
term->sixel.linear_blending = wayl_do_linear_blending(term->wl, term->conf);
|
||||
term->sixel.pixman_fmt = PIXMAN_a8r8g8b8;
|
||||
|
||||
if (term->conf->tweak.surface_bit_depth == SHM_10_BIT) {
|
||||
if (term->conf->tweak.surface_bit_depth == SHM_BITS_10) {
|
||||
if (term->wl->shm_have_argb2101010 && term->wl->shm_have_xrgb2101010) {
|
||||
term->sixel.use_10bit = true;
|
||||
term->sixel.pixman_fmt = PIXMAN_a2r10g10b10;
|
||||
|
|
|
|||
42
terminal.c
42
terminal.c
|
|
@ -1073,19 +1073,16 @@ reload_fonts(struct terminal *term, bool resize_grid)
|
|||
|
||||
options->scaling_filter = conf->tweak.fcft_filter;
|
||||
options->color_glyphs.format = PIXMAN_a8r8g8b8;
|
||||
options->color_glyphs.srgb_decode = render_do_linear_blending(term);
|
||||
options->color_glyphs.srgb_decode =
|
||||
wayl_do_linear_blending(term->wl, term->conf);
|
||||
|
||||
if (conf->tweak.surface_bit_depth == SHM_10_BIT) {
|
||||
if ((term->wl->shm_have_argb2101010 && term->wl->shm_have_xrgb2101010) ||
|
||||
(term->wl->shm_have_abgr2101010 && term->wl->shm_have_xbgr2101010))
|
||||
{
|
||||
/*
|
||||
* Use a high-res buffer type for emojis. We don't want to
|
||||
* use an a2r10g0b10 type of surface, since we need more
|
||||
* than 2 bits for alpha.
|
||||
*/
|
||||
options->color_glyphs.format = PIXMAN_rgba_float;
|
||||
}
|
||||
if (shm_chain_bit_depth(term->render.chains.grid) >= SHM_BITS_10) {
|
||||
/*
|
||||
* Use a high-res buffer type for emojis. We don't want to use
|
||||
* an a2r10g0b10 type of surface, since we need more than 2
|
||||
* bits for alpha.
|
||||
*/
|
||||
options->color_glyphs.format = PIXMAN_rgba_float;
|
||||
}
|
||||
|
||||
struct fcft_font *fonts[4];
|
||||
|
|
@ -1260,7 +1257,10 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
goto err;
|
||||
}
|
||||
|
||||
const bool ten_bit_surfaces = conf->tweak.surface_bit_depth == SHM_10_BIT;
|
||||
const enum shm_bit_depth desired_bit_depth =
|
||||
conf->tweak.surface_bit_depth == SHM_BITS_AUTO
|
||||
? wayl_do_linear_blending(wayl, conf) ? SHM_BITS_10 : SHM_BITS_8
|
||||
: conf->tweak.surface_bit_depth;
|
||||
|
||||
/* Initialize configure-based terminal attributes */
|
||||
*term = (struct terminal) {
|
||||
|
|
@ -1346,13 +1346,13 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
.render = {
|
||||
.chains = {
|
||||
.grid = shm_chain_new(wayl, true, 1 + conf->render_worker_count,
|
||||
ten_bit_surfaces),
|
||||
.search = shm_chain_new(wayl, false, 1 ,ten_bit_surfaces),
|
||||
.scrollback_indicator = shm_chain_new(wayl, false, 1, ten_bit_surfaces),
|
||||
.render_timer = shm_chain_new(wayl, false, 1, ten_bit_surfaces),
|
||||
.url = shm_chain_new(wayl, false, 1, ten_bit_surfaces),
|
||||
.csd = shm_chain_new(wayl, false, 1, ten_bit_surfaces),
|
||||
.overlay = shm_chain_new(wayl, false, 1, ten_bit_surfaces),
|
||||
desired_bit_depth),
|
||||
.search = shm_chain_new(wayl, false, 1 ,desired_bit_depth),
|
||||
.scrollback_indicator = shm_chain_new(wayl, false, 1, desired_bit_depth),
|
||||
.render_timer = shm_chain_new(wayl, false, 1, desired_bit_depth),
|
||||
.url = shm_chain_new(wayl, false, 1, desired_bit_depth),
|
||||
.csd = shm_chain_new(wayl, false, 1, desired_bit_depth),
|
||||
.overlay = shm_chain_new(wayl, false, 1, desired_bit_depth),
|
||||
},
|
||||
.scrollback_lines = conf->scrollback.lines,
|
||||
.app_sync_updates.timer_fd = app_sync_updates_fd,
|
||||
|
|
@ -1495,7 +1495,7 @@ term_window_configured(struct terminal *term)
|
|||
xassert(term->window->is_configured);
|
||||
fdm_add(term->fdm, term->ptmx, EPOLLIN, &fdm_ptmx, term);
|
||||
|
||||
const bool gamma_correct = render_do_linear_blending(term);
|
||||
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
|
||||
LOG_INFO("gamma-correct blending: %s", gamma_correct ? "enabled" : "disabled");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2640,3 +2640,10 @@ wayl_activate(struct wayland *wayl, struct wl_window *win, const char *token)
|
|||
|
||||
xdg_activation_v1_activate(wayl->xdg_activation, token, win->surface.surf);
|
||||
}
|
||||
|
||||
bool
|
||||
wayl_do_linear_blending(const struct wayland *wayl, const struct config *conf)
|
||||
{
|
||||
return conf->gamma_correct &&
|
||||
wayl->color_management.img_description != NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <fcft/fcft.h>
|
||||
#include <tllist.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "cursor-shape.h"
|
||||
#include "fdm.h"
|
||||
|
||||
|
|
@ -539,3 +540,4 @@ bool wayl_get_activation_token(
|
|||
struct wl_window *win, activation_token_cb_t cb, void *cb_data);
|
||||
void wayl_activate(struct wayland *wayl, struct wl_window *win, const char *token);
|
||||
|
||||
bool wayl_do_linear_blending(const struct wayland *wayl, const struct config *conf);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue