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

@ -159,6 +159,7 @@ wl_proto_xml = [
wayland_protocols_datadir / 'staging/fractional-scale/fractional-scale-v1.xml',
wayland_protocols_datadir / 'unstable/tablet/tablet-unstable-v2.xml', # required by cursor-shape-v1
wayland_protocols_datadir / 'staging/cursor-shape/cursor-shape-v1.xml',
wayland_protocols_datadir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
]
foreach prot : wl_proto_xml

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;

View file

@ -2195,7 +2195,9 @@ term_font_size_reset(struct terminal *term)
bool
term_fractional_scaling(const struct terminal *term)
{
return term->wl->fractional_scale_manager != NULL && term->window->scale > 0.;
return term->wl->fractional_scale_manager != NULL &&
term->wl->viewporter != NULL &&
term->window->scale > 0.;
}
bool

View file

@ -1320,6 +1320,16 @@ handle_global(void *data, struct wl_registry *registry,
wayl->registry, name, &wp_cursor_shape_manager_v1_interface, required);
}
else if (streq(interface, wp_single_pixel_buffer_manager_v1_interface.name)) {
const uint32_t required = 1;
if (!verify_iface_version(interface, version, required))
return;
wayl->single_pixel_manager = wl_registry_bind(
wayl->registry, name,
&wp_single_pixel_buffer_manager_v1_interface, required);
}
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
else if (streq(interface, zwp_text_input_manager_v3_interface.name)) {
const uint32_t required = 1;
@ -1636,6 +1646,8 @@ wayl_destroy(struct wayland *wayl)
zwp_text_input_manager_v3_destroy(wayl->text_input_manager);
#endif
if (wayl->single_pixel_manager != NULL)
wp_single_pixel_buffer_manager_v1_destroy(wayl->single_pixel_manager);
if (wayl->fractional_scale_manager != NULL)
wp_fractional_scale_manager_v1_destroy(wayl->fractional_scale_manager);
if (wayl->viewporter != NULL)
@ -2058,6 +2070,7 @@ surface_scale_explicit_width_height(
}
}
xassert(surf->viewport != NULL);
wl_surface_set_buffer_scale(surf->surf, 1);
wp_viewport_set_destination(
surf->viewport, roundf(width / scale), roundf(height / scale));
@ -2204,7 +2217,7 @@ wayl_win_subsurface_new_with_custom_parent(
}
struct wp_viewport *viewport = NULL;
if (wayl->fractional_scale_manager != NULL && wayl->viewporter != NULL) {
if (wayl->viewporter != NULL) {
viewport = wp_viewporter_get_viewport(wayl->viewporter, main_surface);
if (viewport == NULL) {
LOG_ERR("failed to instantiate viewport for sub-surface");

View file

@ -12,6 +12,7 @@
#include <fractional-scale-v1.h>
#include <presentation-time.h>
#include <primary-selection-unstable-v1.h>
#include <single-pixel-buffer-v1.h>
#include <text-input-unstable-v3.h>
#include <viewporter.h>
#include <xdg-activation-v1.h>
@ -439,10 +440,12 @@ struct wayland {
struct wp_cursor_shape_manager_v1 *cursor_shape_manager;
struct wp_single_pixel_buffer_manager_v1 *single_pixel_manager;
bool presentation_timings;
struct wp_presentation *presentation;
uint32_t presentation_clock_id;
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
struct zwp_text_input_manager_v3 *text_input_manager;
#endif