mirror of
https://github.com/labwc/labwc.git
synced 2026-03-29 07:58:10 -04:00
scaled-scene-buffer: reduce unnecessary renderings
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.
This commit is contained in:
parent
cc838e79ed
commit
5db953aa89
6 changed files with 69 additions and 23 deletions
|
|
@ -36,6 +36,12 @@ int font_height(struct font *font);
|
||||||
*/
|
*/
|
||||||
int font_width(struct font *font, const char *string);
|
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
|
* font_buffer_create - Create ARGB8888 lab_data_buffer using pango
|
||||||
* @buffer: buffer pointer
|
* @buffer: buffer pointer
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,17 @@ struct scaled_scene_buffer *scaled_scene_buffer_create(
|
||||||
const struct scaled_scene_buffer_impl *implementation,
|
const struct scaled_scene_buffer_impl *implementation,
|
||||||
struct wl_list *cached_buffers, bool drop_buffer);
|
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 */
|
/* Private */
|
||||||
struct scaled_scene_buffer_cache_entry {
|
struct scaled_scene_buffer_cache_entry {
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,18 @@ font_width(struct font *font, const char *string)
|
||||||
return rectangle.width;
|
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
|
void
|
||||||
font_buffer_create(struct lab_data_buffer **buffer, int max_width,
|
font_buffer_create(struct lab_data_buffer **buffer, int max_width,
|
||||||
const char *text, struct font *font, const float *color,
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PangoRectangle text_extents = font_extents(font, text);
|
int width, height;
|
||||||
|
font_get_buffer_size(max_width, text, font, &width, &height);
|
||||||
|
|
||||||
if (max_width > 0 && text_extents.width > max_width) {
|
*buffer = buffer_create_cairo(width, height, scale);
|
||||||
text_extents.width = max_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
*buffer = buffer_create_cairo(text_extents.width, text_extents.height, scale);
|
|
||||||
if (!*buffer) {
|
if (!*buffer) {
|
||||||
wlr_log(WLR_ERROR, "Failed to create font buffer");
|
wlr_log(WLR_ERROR, "Failed to create font buffer");
|
||||||
return;
|
return;
|
||||||
|
|
@ -127,7 +136,7 @@ font_buffer_create(struct lab_data_buffer **buffer, int max_width,
|
||||||
|
|
||||||
PangoLayout *layout = pango_cairo_create_layout(cairo);
|
PangoLayout *layout = pango_cairo_create_layout(cairo);
|
||||||
pango_context_set_round_glyph_positions(pango_layout_get_context(layout), false);
|
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_text(layout, text, -1);
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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->color, color, sizeof(self->color));
|
||||||
memcpy(self->bg_color, bg_color, sizeof(self->bg_color));
|
memcpy(self->bg_color, bg_color, sizeof(self->bg_color));
|
||||||
|
|
||||||
/* Invalidate cache and force a new render */
|
/* Calculate the size of font buffer and request re-rendering */
|
||||||
scaled_scene_buffer_invalidate_cache(self->scaled_buffer);
|
font_get_buffer_size(self->max_width, self->text, &self->font,
|
||||||
|
&self->width, &self->height);
|
||||||
/* Ensure the height / width is up-to-date */
|
scaled_scene_buffer_request_update(self->scaled_buffer,
|
||||||
self->width = self->scaled_buffer->width;
|
self->width, self->height);
|
||||||
self->height = self->scaled_buffer->height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
scaled_font_buffer_set_max_width(struct scaled_font_buffer *self, int max_width)
|
scaled_font_buffer_set_max_width(struct scaled_font_buffer *self, int max_width)
|
||||||
{
|
{
|
||||||
self->max_width = max_width;
|
self->max_width = max_width;
|
||||||
scaled_scene_buffer_invalidate_cache(self->scaled_buffer);
|
|
||||||
|
|
||||||
/* Ensure the height / width is up-to-date */
|
font_get_buffer_size(self->max_width, self->text, &self->font,
|
||||||
self->width = self->scaled_buffer->width;
|
&self->width, &self->height);
|
||||||
self->height = self->scaled_buffer->height;
|
scaled_scene_buffer_request_update(self->scaled_buffer,
|
||||||
|
self->width, self->height);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,8 @@ struct scaled_rect_buffer *scaled_rect_buffer_create(
|
||||||
memcpy(self->fill_color, fill_color, sizeof(self->fill_color));
|
memcpy(self->fill_color, fill_color, sizeof(self->fill_color));
|
||||||
memcpy(self->border_color, border_color, sizeof(self->border_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;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,11 @@ scaled_scene_buffer_create(struct wlr_scene_tree *parent,
|
||||||
}
|
}
|
||||||
|
|
||||||
self->impl = impl;
|
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;
|
self->drop_buffer = drop_buffer;
|
||||||
wl_list_init(&self->cache);
|
wl_list_init(&self->cache);
|
||||||
|
|
||||||
|
|
@ -254,7 +258,8 @@ scaled_scene_buffer_create(struct wlr_scene_tree *parent,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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);
|
assert(self);
|
||||||
struct scaled_scene_buffer_cache_entry *cache_entry, *cache_entry_tmp;
|
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);
|
_cache_entry_destroy(cache_entry, self->drop_buffer);
|
||||||
}
|
}
|
||||||
assert(wl_list_empty(&self->cache));
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue