render: use single-pixel buffers for overlays, when possible

The unicode-mode, and flash overlays are single color buffers. This
means we can use the single-pixel buffer protocol.

It's undefined whether the compositor will release the buffer or not;
to make things easier, simply destroy the buffer as soon as we've
committed it.

Note that since compositors don't necessarily release single-pixel
buffers, we can't plug them into our own buffer interface. This means
we can't use buffer pointers to check if we can re-use the previous
buffer (i.e. we can skip comitting a new buffer), or if we have to
create a new one.

It's _almost_ enough to just check if the last overlay style is the
same as the current one. Except that that doesn't take window resizes
into account...
This commit is contained in:
Daniel Eklöf 2024-05-21 16:09:34 +02:00
parent 6944d5f901
commit 3c96d0b68e
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
5 changed files with 92 additions and 11 deletions

View file

@ -1559,6 +1559,58 @@ render_ime_preedit(struct terminal *term, struct buffer *buf)
#endif
}
static void
render_overlay_single_pixel(struct terminal *term, enum overlay_style style,
pixman_color_t color)
{
struct wayland *wayl = term->wl;
struct wayl_sub_surface *overlay = &term->window->overlay;
/*
* Note: we currently do *not* re-use the overlay buffer
*
* This means we'll re-create the buffer each time we render a new
* frame. This shouldn't be a problem in any of the cases where we
* use single-pixel buffers (unicode-input, and flash).
*
* Note: it's _almost_ enough to just check if
* style' == last_overlay_style
* except that doesn't take window resizes into account...
*/
assert(style == OVERLAY_UNICODE_MODE || style == OVERLAY_FLASH);
assert(wayl->single_pixel_manager != NULL);
assert(overlay->surface.viewport != NULL);
struct wl_buffer *buf =
wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(
term->wl->single_pixel_manager,
(double)color.red / 0xffff * 0xffffffff,
(double)color.green / 0xffff * 0xffffffff,
(double)color.blue / 0xffff * 0xffffffff,
(double)color.alpha / 0xffff * 0xffffffff);
wl_surface_set_buffer_scale(overlay->surface.surf, 1);
wp_viewport_set_destination(
overlay->surface.viewport,
roundf(term->width / term->scale),
roundf(term->height / term->scale));
quirk_weston_subsurface_desync_on(overlay->sub);
wl_subsurface_set_position(overlay->sub, 0, 0);
wl_surface_attach(overlay->surface.surf, buf, 0, 0);
wl_surface_damage_buffer(
overlay->surface.surf, 0, 0, term->width, term->height);
wl_surface_commit(overlay->surface.surf);
quirk_weston_subsurface_desync_off(overlay->sub);
term->render.last_overlay_style = style;
wl_buffer_destroy(buf);
}
static void
render_overlay(struct terminal *term)
{
@ -1586,17 +1638,9 @@ render_overlay(struct terminal *term)
return;
}
struct buffer *buf = shm_get_buffer(
term->render.chains.overlay, term->width, term->height, true);
pixman_image_set_clip_region32(buf->pix[0], NULL);
pixman_color_t color;
switch (style) {
case OVERLAY_NONE:
break;
case OVERLAY_SEARCH:
case OVERLAY_UNICODE_MODE:
color = (pixman_color_t){0, 0, 0, 0x7fff};
@ -1607,8 +1651,26 @@ render_overlay(struct terminal *term)
term->conf->colors.flash,
term->conf->colors.flash_alpha);
break;
case OVERLAY_NONE:
xassert(false);
break;
}
const bool single_pixel =
(style == OVERLAY_UNICODE_MODE || style == OVERLAY_FLASH) &&
term->wl->single_pixel_manager != NULL &&
overlay->surface.viewport != NULL;
if (single_pixel) {
render_overlay_single_pixel(term, style, color);
return;
}
struct buffer *buf = shm_get_buffer(
term->render.chains.overlay, term->width, term->height, true);
pixman_image_set_clip_region32(buf->pix[0], NULL);
/* Bounding rectangle of damaged areas - for wl_surface_damage_buffer() */
pixman_box32_t damage_bounds;