fractional scaling: another round(!) of rounding fixes

* Ensure buffer sizes are valid. That is, ensure that
  size / scale * scale == size.
* Do size calculation of the window geometry in the same way we
  calculate the CSD offsets.
This commit is contained in:
Daniel Eklöf 2023-07-28 15:28:10 +02:00
parent 753c4b5d4f
commit 1782474481
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 73 additions and 66 deletions

132
render.c
View file

@ -2386,6 +2386,7 @@ render_csd(struct terminal *term)
if (term->window->is_fullscreen) if (term->window->is_fullscreen)
return; return;
const float scale = term->scale;
struct csd_data infos[CSD_SURF_COUNT]; struct csd_data infos[CSD_SURF_COUNT];
int widths[CSD_SURF_COUNT]; int widths[CSD_SURF_COUNT];
int heights[CSD_SURF_COUNT]; int heights[CSD_SURF_COUNT];
@ -2413,11 +2414,7 @@ render_csd(struct terminal *term)
widths[i] = width; widths[i] = width;
heights[i] = height; heights[i] = height;
wl_subsurface_set_position(sub, roundf(x / scale), roundf(y / scale));
wl_subsurface_set_position(
sub,
(int32_t)roundf(x / term->scale),
(int32_t)roundf(y / term->scale));
} }
struct buffer *bufs[CSD_SURF_COUNT]; struct buffer *bufs[CSD_SURF_COUNT];
@ -2518,16 +2515,14 @@ render_scrollback_position(struct terminal *term)
break; break;
} }
const int iscale = (int)ceilf(term->scale); const float scale = term->scale;
const int margin = (int)roundf(3. * term->scale); const int margin = (int)roundf(3. * scale);
int width = margin + cell_count * term->cell_width + margin; int width = margin + cell_count * term->cell_width + margin;
int height = margin + term->cell_height + margin; int height = margin + term->cell_height + margin;
if (!term_fractional_scaling(term)) { width = roundf(scale * ceilf(width / scale));
width = (width + iscale - 1) / iscale * iscale; height = roundf(scale * ceilf(height / scale));
height = (height + iscale - 1) / iscale * iscale;
}
/* *Where* to render - parent relative coordinates */ /* *Where* to render - parent relative coordinates */
int surf_top = 0; int surf_top = 0;
@ -2558,10 +2553,8 @@ render_scrollback_position(struct terminal *term)
int x = term->width - margin - width; int x = term->width - margin - width;
int y = term->margins.top + surf_top; int y = term->margins.top + surf_top;
if (!term_fractional_scaling(term)) { x = roundf(scale * ceilf(x / scale));
x = (x + iscale - 1) / iscale * iscale; y = roundf(scale * ceilf(y / scale));
y = (y + iscale - 1) / iscale * iscale;
}
if (y + height > term->height) { if (y + height > term->height) {
wl_surface_attach(win->scrollback_indicator.surface.surf, NULL, 0, 0); wl_surface_attach(win->scrollback_indicator.surface.surf, NULL, 0, 0);
@ -2573,9 +2566,7 @@ render_scrollback_position(struct terminal *term)
struct buffer *buf = shm_get_buffer(chain, width, height); struct buffer *buf = shm_get_buffer(chain, width, height);
wl_subsurface_set_position( wl_subsurface_set_position(
win->scrollback_indicator.sub, win->scrollback_indicator.sub, roundf(x / scale), roundf(y / scale));
(int32_t)roundf(x / term->scale),
(int32_t)roundf(y / term->scale));
uint32_t fg = term->colors.table[0]; uint32_t fg = term->colors.table[0];
uint32_t bg = term->colors.table[8 + 4]; uint32_t bg = term->colors.table[8 + 4];
@ -2604,25 +2595,23 @@ render_render_timer(struct terminal *term, struct timespec render_time)
char32_t text[256]; char32_t text[256];
mbstoc32(text, usecs_str, ALEN(text)); mbstoc32(text, usecs_str, ALEN(text));
const int iscale = (int)ceilf(term->scale); const float scale = term->scale;
const int cell_count = c32len(text); const int cell_count = c32len(text);
const int margin = (int)roundf(3. * term->scale); const int margin = (int)roundf(3. * scale);
int width = margin + cell_count * term->cell_width + margin; int width = margin + cell_count * term->cell_width + margin;
int height = margin + term->cell_height + margin; int height = margin + term->cell_height + margin;
if (!term_fractional_scaling(term)) { width = roundf(scale * ceilf(width / scale));
width = (width + iscale - 1) / iscale * iscale; height = roundf(scale * ceilf(height / scale));
height = (height + iscale - 1) / iscale * iscale;
}
struct buffer_chain *chain = term->render.chains.render_timer; struct buffer_chain *chain = term->render.chains.render_timer;
struct buffer *buf = shm_get_buffer(chain, width, height); struct buffer *buf = shm_get_buffer(chain, width, height);
wl_subsurface_set_position( wl_subsurface_set_position(
win->render_timer.sub, win->render_timer.sub,
(int32_t)roundf(margin / term->scale), roundf(margin / scale),
(int32_t)roundf((term->margins.top + term->cell_height - margin) / term->scale)); roundf((term->margins.top + term->cell_height - margin) / scale));
render_osd( render_osd(
term, term,
@ -3167,24 +3156,22 @@ render_search_box(struct terminal *term)
const size_t total_cells = c32swidth(text, text_len); const size_t total_cells = c32swidth(text, text_len);
const size_t wanted_visible_cells = max(20, total_cells); const size_t wanted_visible_cells = max(20, total_cells);
xassert(term->scale >= 1.); const float scale = term->scale;
const size_t margin = (size_t)roundf(3 * term->scale); xassert(scale >= 1.);
const size_t margin = (size_t)roundf(3 * scale);
const size_t width = term->width - 2 * margin;
size_t visible_width = min(
term->width - 2 * margin,
margin + wanted_visible_cells * term->cell_width + margin);
size_t width = term->width - 2 * margin;
size_t height = min( size_t height = min(
term->height - 2 * margin, term->height - 2 * margin,
margin + 1 * term->cell_height + margin); margin + 1 * term->cell_height + margin);
if (!term_fractional_scaling(term)) { width = roundf(scale * ceilf((term->width - 2 * margin) / scale));
const int iscale = (int)ceilf(term->scale); height = roundf(scale * ceilf(height / scale));
visible_width = (visible_width + iscale - 1) / iscale * iscale;
height = (height + iscale - 1) / iscale * iscale; size_t visible_width = min(
} term->width - 2 * margin,
margin + wanted_visible_cells * term->cell_width + margin);
const size_t visible_cells = (visible_width - 2 * margin) / term->cell_width; const size_t visible_cells = (visible_width - 2 * margin) / term->cell_width;
size_t glyph_offset = term->render.search_glyph_offset; size_t glyph_offset = term->render.search_glyph_offset;
@ -3430,10 +3417,10 @@ render_search_box(struct terminal *term)
/* TODO: this is only necessary on a window resize */ /* TODO: this is only necessary on a window resize */
wl_subsurface_set_position( wl_subsurface_set_position(
term->window->search.sub, term->window->search.sub,
(int32_t)roundf(margin / term->scale), roundf(margin / scale),
(int32_t)roundf(max(0, (int32_t)term->height - height - margin) / term->scale)); roundf(max(0, (int32_t)term->height - height - margin) / scale));
wayl_surface_scale(term->window, &term->window->search.surface, buf, term->scale); wayl_surface_scale(term->window, &term->window->search.surface, buf, scale);
wl_surface_attach(term->window->search.surface.surf, buf->wl_buf, 0, 0); wl_surface_attach(term->window->search.surface.surf, buf->wl_buf, 0, 0);
wl_surface_damage_buffer(term->window->search.surface.surf, 0, 0, width, height); wl_surface_damage_buffer(term->window->search.surface.surf, 0, 0, width, height);
@ -3460,8 +3447,9 @@ render_urls(struct terminal *term)
struct wl_window *win = term->window; struct wl_window *win = term->window;
xassert(tll_length(win->urls) > 0); xassert(tll_length(win->urls) > 0);
const int x_margin = (int)roundf(2 * term->scale); const float scale = term->scale;
const int y_margin = (int)roundf(1 * term->scale); const int x_margin = (int)roundf(2 * scale);
const int y_margin = (int)roundf(1 * scale);
/* Calculate view start, counted from the *current* scrollback start */ /* Calculate view start, counted from the *current* scrollback start */
const int scrollback_end const int scrollback_end
@ -3634,11 +3622,8 @@ render_urls(struct terminal *term)
int width = x_margin + cols * term->cell_width + x_margin; int width = x_margin + cols * term->cell_width + x_margin;
int height = y_margin + term->cell_height + y_margin; int height = y_margin + term->cell_height + y_margin;
if (!term_fractional_scaling(term)) { width = roundf(scale * ceilf(width / scale));
const int iscale = (int)ceilf(term->scale); height = roundf(scale * ceilf(height / scale));
width = (width + iscale - 1) / iscale * iscale;
height = (height + iscale - 1) / iscale * iscale;
}
info[render_count].url = &it->item; info[render_count].url = &it->item;
info[render_count].text = xc32dup(label); info[render_count].text = xc32dup(label);
@ -3674,8 +3659,8 @@ render_urls(struct terminal *term)
wl_subsurface_set_position( wl_subsurface_set_position(
sub_surf->sub, sub_surf->sub,
(int32_t)roundf((term->margins.left + x) / term->scale), roundf((term->margins.left + x) / scale),
(int32_t)roundf((term->margins.top + y) / term->scale)); roundf((term->margins.top + y) / scale));
render_osd( render_osd(
term, sub_surf, term->fonts[0], bufs[i], label, term, sub_surf, term->fonts[0], bufs[i], label,
@ -3974,8 +3959,8 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
const int min_rows = 1; const int min_rows = 1;
/* Minimum window size (must be divisible by the scaling factor)*/ /* Minimum window size (must be divisible by the scaling factor)*/
const int min_width = (min_cols * term->cell_width + scale - 1) / scale * scale; const int min_width = roundf(scale * ceilf((min_cols * term->cell_width) / scale));
const int min_height = (min_rows * term->cell_height + scale - 1) / scale * scale; const int min_height = roundf(scale * ceilf((min_rows * term->cell_height) / scale));
width = max(width, min_width); width = max(width, min_width);
height = max(height, min_height); height = max(height, min_height);
@ -4235,22 +4220,43 @@ damage_view:
const bool title_shown = wayl_win_csd_titlebar_visible(term->window); const bool title_shown = wayl_win_csd_titlebar_visible(term->window);
const bool border_shown = wayl_win_csd_borders_visible(term->window); const bool border_shown = wayl_win_csd_borders_visible(term->window);
const int title_height = const int title = title_shown
title_shown ? term->conf->csd.title_height : 0; ? roundf(term->conf->csd.title_height * scale)
const int border_width = : 0;
border_shown ? term->conf->csd.border_width_visible : 0; const int border = border_shown
? roundf(term->conf->csd.border_width_visible * scale)
: 0;
/* Must use surface logical coordinates (same calculations as
in get_csd_data(), but with different inputs) */
const int toplevel_min_width = roundf(border / scale) +
roundf(min_width / scale) +
roundf(border / scale);
const int toplevel_min_height = roundf(border / scale) +
roundf(title / scale) +
roundf(min_height / scale) +
roundf(border / scale);
const int toplevel_width = roundf(border / scale) +
roundf(term->width / scale) +
roundf(border / scale);
const int toplevel_height = roundf(border / scale) +
roundf(title / scale) +
roundf(term->height / scale) +
roundf(border / scale);
const int x = roundf(-border / scale);
const int y = roundf(-title / scale) - roundf(border / scale);
xdg_toplevel_set_min_size( xdg_toplevel_set_min_size(
term->window->xdg_toplevel, term->window->xdg_toplevel,
min_width / scale + 2 * border_width, toplevel_min_width, toplevel_min_height);
min_height / scale + title_height + 2 * border_width);
xdg_surface_set_window_geometry( xdg_surface_set_window_geometry(
term->window->xdg_surface, term->window->xdg_surface,
-border_width, x, y, toplevel_width, toplevel_height);
-title_height - border_width,
term->width / term->scale + 2 * border_width,
term->height / term->scale + title_height + 2 * border_width);
} }
tll_free(term->normal.scroll_damage); tll_free(term->normal.scroll_damage);

View file

@ -2010,11 +2010,12 @@ wayl_surface_scale_explicit_width_height(
LOG_DBG("scaling by a factor of %.2f using fractional scaling " LOG_DBG("scaling by a factor of %.2f using fractional scaling "
"(width=%d, height=%d) ", scale, width, height); "(width=%d, height=%d) ", scale, width, height);
xassert((int)roundf(scale * (int)roundf(width / scale)) == width);
xassert((int)roundf(scale * (int)roundf(height / scale)) == height);
wl_surface_set_buffer_scale(surf->surf, 1); wl_surface_set_buffer_scale(surf->surf, 1);
wp_viewport_set_destination( wp_viewport_set_destination(
surf->viewport, surf->viewport, roundf(width / scale), roundf(height / scale));
(int32_t)roundf((float)width / scale),
(int32_t)roundf((float)height / scale));
#else #else
BUG("wayl_fraction_scaling() returned true, " BUG("wayl_fraction_scaling() returned true, "
"but fractional scaling was not available at compile time"); "but fractional scaling was not available at compile time");