From 708ca3d650dc16372eeed5f1c6bed62d01c5c408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 22 May 2024 13:38:13 +0200 Subject: [PATCH] render: single-pixel: minor optimization Don't re-create the single-pixel buffer, unless necessary. The buffer itself doesn't have a size. That means we can re-use the buffer if the last frame's overlay style matches the current frame's style. What we *do not* know is whether the current frame's size is the same as the last frame's. This means we still have to set the viewport destination, and commit the surface. --- render.c | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/render.c b/render.c index 7d9baa1e..fd7e743a 100644 --- a/render.c +++ b/render.c @@ -1565,41 +1565,55 @@ render_overlay_single_pixel(struct terminal *term, enum overlay_style style, { struct wayland *wayl = term->wl; struct wayl_sub_surface *overlay = &term->window->overlay; + struct wl_buffer *buf = NULL; /* - * Note: we currently do *not* re-use the overlay buffer + * In an ideal world, we'd only update the surface (i.e. commit + * any changes) if anything has actually changed. * - * 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). + * For technical reasons, we can't do that, since we can't + * determine whether the last committed buffer is still valid + * (i.e. does it correspond to the current overlay style, *and* + * does last frame's size match the current size?) * - * Note: it's _almost_ enough to just check if - * style' == last_overlay_style - * except that doesn't take window resizes into account... + * What we _can_ do is use the fact that single-pixel buffers + * don't have a size; you have to use a viewport to "size" them. + * + * This means we can check if the last frame's overlay style is + * the same as the current size. If so, then we *know* that the + * currently attached buffer is valid, and we *don't* have to + * create a new single-pixel buffer. + * + * What we do *not* know if the *size* is still valid. This means + * we do have to do the viewport calls, and a surface commit. + * + * This is still better than *always* creating a new buffer. */ 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, + quirk_weston_subsurface_desync_on(overlay->sub); + + if (style != term->render.last_overlay_style) { + buf = wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer( + wayl->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); + wl_surface_set_buffer_scale(overlay->surface.surf, 1); + wl_surface_attach(overlay->surface.surf, buf, 0, 0); + } + 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); @@ -1608,7 +1622,10 @@ render_overlay_single_pixel(struct terminal *term, enum overlay_style style, quirk_weston_subsurface_desync_off(overlay->sub); term->render.last_overlay_style = style; - wl_buffer_destroy(buf); + + if (buf != NULL) { + wl_buffer_destroy(buf); + } } static void