]> git.mdlowis.com Git - proto/labwc.git/commitdiff
scaled-scene-buffer: reduce unnecessary renderings
authortokyo4j <hrak1529@gmail.com>
Tue, 3 Dec 2024 07:18:52 +0000 (16:18 +0900)
committerHiroaki Yamamoto <hrak1529@gmail.com>
Wed, 18 Dec 2024 08:21:29 +0000 (17:21 +0900)
Prior to this commit, a backing buffer with scale 1 was always created for
a scaled_scene_buffer before showing it, and backing buffers for specific
scales were created on output_enter events.

This commit removes this redundant re-renderings by calling
wlr_scene_buffer_set_dest_size() upon scaled_scene_buffer creation just to
receive output_enter events and delaying the first rendering to the first
output_enter event.

I needed to add font_get_buffer_size() to obtain the size of a font buffer
without actually creating it.

include/common/font.h
include/common/scaled-scene-buffer.h
src/common/font.c
src/common/scaled-font-buffer.c
src/common/scaled-rect-buffer.c
src/common/scaled-scene-buffer.c

index ea7342297ff3d46b9026dfa39a8980c4b64c0e47..c9e9c179803fa0564f9b2d30cdc5441b2164100b 100644 (file)
@@ -36,6 +36,12 @@ int font_height(struct font *font);
  */
 int font_width(struct font *font, const char *string);
 
+/**
+ * font_get_buffer_size - dry-run font_buffer_create() to get buffer size
+ */
+void font_get_buffer_size(int max_width, const char *text, struct font *font,
+       int *width, int *height);
+
 /**
  * font_buffer_create - Create ARGB8888 lab_data_buffer using pango
  * @buffer: buffer pointer
index 5c36559587ae95b9c7fbab6340deafd10722dad0..f1c1d1249c57ce735275b32dd83405a90436cab1 100644 (file)
@@ -96,8 +96,17 @@ struct scaled_scene_buffer *scaled_scene_buffer_create(
        const struct scaled_scene_buffer_impl *implementation,
        struct wl_list *cached_buffers, bool drop_buffer);
 
-/* Clear the cache of existing buffers, useful in case the content changes */
-void scaled_scene_buffer_invalidate_cache(struct scaled_scene_buffer *self);
+/**
+ * scaled_scene_buffer_request_update - mark the buffer that needs to be
+ * updated
+ * @width: the width of the buffer to be rendered, in scene coordinates
+ * @height: the height of the buffer to be rendered, in scene coordinates
+ *
+ * This function should be called when the states bound to the buffer are
+ * updated and ready for rendering.
+ */
+void scaled_scene_buffer_request_update(struct scaled_scene_buffer *self,
+       int width, int height);
 
 /* Private */
 struct scaled_scene_buffer_cache_entry {
index 4c406c420dbbbbfe0dd17b550eac7b2284b8d598..0014eaf107e62e417cdb6d1d7a33a4fe75bf3fef 100644 (file)
@@ -79,6 +79,18 @@ font_width(struct font *font, const char *string)
        return rectangle.width;
 }
 
+void
+font_get_buffer_size(int max_width, const char *text, struct font *font,
+       int *width, int *height)
+{
+       PangoRectangle text_extents = font_extents(font, text);
+       if (max_width > 0 && text_extents.width > max_width) {
+               text_extents.width = max_width;
+       }
+       *width = text_extents.width;
+       *height = text_extents.height;
+}
+
 void
 font_buffer_create(struct lab_data_buffer **buffer, int max_width,
        const char *text, struct font *font, const float *color,
@@ -88,13 +100,10 @@ font_buffer_create(struct lab_data_buffer **buffer, int max_width,
                return;
        }
 
-       PangoRectangle text_extents = font_extents(font, text);
-
-       if (max_width > 0 && text_extents.width > max_width) {
-               text_extents.width = max_width;
-       }
+       int width, height;
+       font_get_buffer_size(max_width, text, font, &width, &height);
 
-       *buffer = buffer_create_cairo(text_extents.width, text_extents.height, scale);
+       *buffer = buffer_create_cairo(width, height, scale);
        if (!*buffer) {
                wlr_log(WLR_ERROR, "Failed to create font buffer");
                return;
@@ -127,7 +136,7 @@ font_buffer_create(struct lab_data_buffer **buffer, int max_width,
 
        PangoLayout *layout = pango_cairo_create_layout(cairo);
        pango_context_set_round_glyph_positions(pango_layout_get_context(layout), false);
-       pango_layout_set_width(layout, text_extents.width * PANGO_SCALE);
+       pango_layout_set_width(layout, width * PANGO_SCALE);
        pango_layout_set_text(layout, text, -1);
        pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
 
index 78849b722f110e52948816c572d551e068ca0595..e8a9b0a5741695ff836e818370e582eaac953d5a 100644 (file)
@@ -116,21 +116,20 @@ scaled_font_buffer_update(struct scaled_font_buffer *self, const char *text,
        memcpy(self->color, color, sizeof(self->color));
        memcpy(self->bg_color, bg_color, sizeof(self->bg_color));
 
-       /* Invalidate cache and force a new render */
-       scaled_scene_buffer_invalidate_cache(self->scaled_buffer);
-
-       /* Ensure the height / width is up-to-date */
-       self->width = self->scaled_buffer->width;
-       self->height = self->scaled_buffer->height;
+       /* Calculate the size of font buffer and request re-rendering */
+       font_get_buffer_size(self->max_width, self->text, &self->font,
+               &self->width, &self->height);
+       scaled_scene_buffer_request_update(self->scaled_buffer,
+               self->width, self->height);
 }
 
 void
 scaled_font_buffer_set_max_width(struct scaled_font_buffer *self, int max_width)
 {
        self->max_width = max_width;
-       scaled_scene_buffer_invalidate_cache(self->scaled_buffer);
 
-       /* Ensure the height / width is up-to-date */
-       self->width = self->scaled_buffer->width;
-       self->height = self->scaled_buffer->height;
+       font_get_buffer_size(self->max_width, self->text, &self->font,
+               &self->width, &self->height);
+       scaled_scene_buffer_request_update(self->scaled_buffer,
+               self->width, self->height);
 }
index 10457cd9fe063fb77072a10268733a1b965675b1..04b5e6d7dd708ca5ffaf0280c486ff60e269a590 100644 (file)
@@ -110,7 +110,8 @@ struct scaled_rect_buffer *scaled_rect_buffer_create(
        memcpy(self->fill_color, fill_color, sizeof(self->fill_color));
        memcpy(self->border_color, border_color, sizeof(self->border_color));
 
-       scaled_scene_buffer_invalidate_cache(scaled_buffer);
+       scaled_scene_buffer_request_update(scaled_buffer,
+               self->width, self->height);
 
        return self;
 }
index cb6bf14a48a1f190fcdcca475af636e9173971ad..6a19891aa425d6fe8bae78d33079daa1c54676e9 100644 (file)
@@ -228,7 +228,11 @@ scaled_scene_buffer_create(struct wlr_scene_tree *parent,
        }
 
        self->impl = impl;
-       self->active_scale = 1;
+       /*
+        * Set active scale to zero so that we always render a new buffer when
+        * entering the first output
+        */
+       self->active_scale = 0;
        self->drop_buffer = drop_buffer;
        wl_list_init(&self->cache);
 
@@ -254,7 +258,8 @@ scaled_scene_buffer_create(struct wlr_scene_tree *parent,
 }
 
 void
-scaled_scene_buffer_invalidate_cache(struct scaled_scene_buffer *self)
+scaled_scene_buffer_request_update(struct scaled_scene_buffer *self,
+               int width, int height)
 {
        assert(self);
        struct scaled_scene_buffer_cache_entry *cache_entry, *cache_entry_tmp;
@@ -262,5 +267,22 @@ scaled_scene_buffer_invalidate_cache(struct scaled_scene_buffer *self)
                _cache_entry_destroy(cache_entry, self->drop_buffer);
        }
        assert(wl_list_empty(&self->cache));
-       _update_buffer(self, self->active_scale);
+
+       /*
+        * Tell wlroots about the buffer size so we can receive output_enter
+        * events even when the actual backing buffer is not set yet.
+        * The buffer size set here is updated when the backing buffer is
+        * created in _update_buffer().
+        */
+       wlr_scene_buffer_set_dest_size(self->scene_buffer, width, height);
+       self->width = width;
+       self->height = height;
+
+       /*
+        * Skip re-rendering if the buffer is not shown yet
+        * TODO: don't re-render also when the buffer is temporarily invisible
+        */
+       if (self->active_scale > 0) {
+               _update_buffer(self, self->active_scale);
+       }
 }