libweston: Introduce weston_cached_string

And plug-it in into weston_surface for the time being.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
This commit is contained in:
Marius Vlad 2025-12-04 12:13:45 +02:00
parent 7c8b745249
commit 5346432aba
2 changed files with 101 additions and 17 deletions

View file

@ -80,6 +80,14 @@ struct weston_commit_timing_target {
struct timespec time;
};
struct weston_cached_string {
bool is_up_to_date;
char *cached_str;
/* assumes FP opened, use it to (re-)compose the string */
void (*regen)(FILE *fp, void *data);
};
struct weston_compositor;
struct weston_surface;
struct weston_buffer;
@ -2019,6 +2027,7 @@ struct weston_surface {
/** commit_timing_v1 */
struct weston_commit_timer *commit_timer;
struct weston_cached_string scene_graph_record;
};
struct weston_subsurface {
@ -2799,6 +2808,12 @@ weston_output_get_supported_color_formats(struct weston_output *output);
void
weston_output_set_ready(struct weston_output *output);
const char *
weston_cached_str_get(struct weston_cached_string *s, void *data);
void
weston_cached_str_invalidate(struct weston_cached_string *s);
#ifdef __cplusplus
}
#endif

View file

@ -951,6 +951,30 @@ weston_surface_update_preferred_color_profile(struct weston_surface *surface)
weston_surface_send_preferred_image_description_changed(surface);
}
static void
weston_surface_debug_string_regenerate(FILE *fp, void *data)
{
struct weston_surface *surface = data;
uint32_t surface_id = 0;
pid_t pid = 0;
char desc[512];
if (surface->resource) {
struct wl_resource *resource = surface->resource;
wl_client_get_credentials(wl_resource_get_client(resource),
&pid, NULL, NULL);
surface_id = wl_resource_get_id(surface->resource);
}
if (!surface->get_label ||
surface->get_label(surface, desc, sizeof(desc)) < 0) {
strcpy(desc, "[no description available]");
}
fprintf(fp, "role %s, PID %d, surface ID %u, %s",
surface->role_name, pid, surface_id, desc);
}
WL_EXPORT struct weston_surface *
weston_surface_create(struct weston_compositor *compositor)
{
@ -1016,6 +1040,9 @@ weston_surface_create(struct weston_compositor *compositor)
wl_list_init(&surface->fifo_barrier_link);
surface->scene_graph_record.regen =
weston_surface_debug_string_regenerate;
return surface;
}
@ -2734,6 +2761,7 @@ weston_surface_unref(struct weston_surface *surface)
wl_list_remove(&surface->fifo_barrier_link);
free(surface->scene_graph_record.cached_str);
free(surface);
}
@ -5354,6 +5382,8 @@ weston_surface_set_label_func(struct weston_surface *surface,
surface->get_label = desc;
weston_timeline_refresh_subscription_objects(surface->compositor,
surface);
weston_cached_str_invalidate(&surface->scene_graph_record);
}
/** Get the size of surface contents
@ -9531,25 +9561,11 @@ debug_scene_view_print(FILE *fp, struct weston_view *view, int view_idx)
{
struct weston_compositor *ec = view->surface->compositor;
struct weston_output *output;
char desc[512];
pixman_box32_t *box;
uint32_t surface_id = 0;
pid_t pid = 0;
if (view->surface->resource) {
struct wl_resource *resource = view->surface->resource;
wl_client_get_credentials(wl_resource_get_client(resource),
&pid, NULL, NULL);
surface_id = wl_resource_get_id(view->surface->resource);
}
if (!view->surface->get_label ||
view->surface->get_label(view->surface, desc, sizeof(desc)) < 0) {
strcpy(desc, "[no description available]");
}
fprintf(fp, "\tView %d (role %s, PID %d, surface ID %u, %s, %p):\n",
view_idx, view->surface->role_name, pid, surface_id,
desc, view);
fprintf(fp, "\tView %d (%s %p):\n", view_idx,
weston_cached_str_get(&view->surface->scene_graph_record, view->surface),
view);
if (!weston_view_is_mapped(view))
fprintf(fp, "\t[view is not mapped!]\n");
@ -10852,3 +10868,56 @@ weston_output_set_ready(struct weston_output *output)
weston_output_schedule_repaint(output);
}
}
/**
* Returns a cached string value held up by a pointer to a struct
* weston_cached_string or regenerates the string in case the cached value has
* been invalidated. This is useful for caching object's properties as a string
* value. Users should use weston_cached_str_invalidate in combination with
* this function to denote when it is time to regenerate the string cached
* value.
*
* Note that over-invalidation would actually hurt performance so this is ideal
* for (object) properties that do *not* change each frame.
*
* \param s a pointer to struct weston_cached_string
* \param data generic pointer to be passed to the regen function
* \sa weston_cached_str_invalidate
*
*/
WL_EXPORT const char *
weston_cached_str_get(struct weston_cached_string *s, void *data)
{
if (!s->is_up_to_date) {
char *str = NULL;
size_t size = 0;
FILE *fp;
free(s->cached_str);
fp = open_memstream(&str, &size);
abort_oom_if_null(fp);
s->regen(fp, data);
if (fclose(fp) == 0) {
s->cached_str = str;
} else {
free(str);
s->cached_str = xstrdup("[error]");
}
s->is_up_to_date = true;
}
return s->cached_str;
}
/** Invalidates the cached string value and forces weston_cached_str_get() to
* call the regen callback associated with that particular weston_cached_string
*
* \param s a pointer to struct weston_cached_string
*
*/
WL_EXPORT void
weston_cached_str_invalidate(struct weston_cached_string *s)
{
s->is_up_to_date = false;
}