mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-02-05 08:50:34 +01:00
Merge branch 'wip/mvlad/cache-str-values' into 'main'
compositor: Cache weston buffer, surface and view properties as strings See merge request wayland/weston!1907
This commit is contained in:
commit
3e2f6efbd5
5 changed files with 289 additions and 116 deletions
|
|
@ -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;
|
||||
|
|
@ -1588,6 +1596,8 @@ struct weston_buffer {
|
|||
|
||||
const struct pixel_format_info *pixel_format;
|
||||
uint64_t format_modifier;
|
||||
|
||||
struct weston_cached_string scene_graph_record;
|
||||
};
|
||||
|
||||
enum weston_buffer_reference_type {
|
||||
|
|
@ -1771,6 +1781,8 @@ struct weston_view {
|
|||
|
||||
bool is_mapped;
|
||||
struct weston_log_pacer subsurface_parent_log_pacer;
|
||||
|
||||
struct weston_cached_string scene_graph_record;
|
||||
};
|
||||
|
||||
enum weston_surface_status {
|
||||
|
|
@ -2042,6 +2054,7 @@ struct weston_surface {
|
|||
|
||||
/** commit_timing_v1 */
|
||||
struct weston_commit_timer *commit_timer;
|
||||
struct weston_cached_string scene_graph_record;
|
||||
};
|
||||
|
||||
struct weston_subsurface {
|
||||
|
|
@ -2822,6 +2835,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
|
||||
|
|
|
|||
|
|
@ -104,6 +104,9 @@
|
|||
|
||||
#define DEFAULT_REPAINT_WINDOW 7 /* milliseconds */
|
||||
|
||||
static struct weston_layer *
|
||||
get_view_layer(struct weston_view *view);
|
||||
|
||||
static void
|
||||
weston_output_transform_scale_init(struct weston_output *output,
|
||||
uint32_t transform, uint32_t scale);
|
||||
|
|
@ -376,6 +379,29 @@ paint_node_update_late(struct weston_paint_node *pnode)
|
|||
paint_node_validate_ready(pnode);
|
||||
}
|
||||
|
||||
static void
|
||||
weston_paint_node_debug_string_regenerate(FILE *fp, void *data)
|
||||
{
|
||||
struct weston_paint_node *pnode = data;
|
||||
struct weston_view *view = NULL;
|
||||
struct weston_output *output = NULL;
|
||||
|
||||
if (!pnode) {
|
||||
fprintf(fp, "\t\t\tpaint node [pending repaint]:\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(fp, "\t\t\tpaint node %p:\n", pnode);
|
||||
|
||||
view = pnode->view;
|
||||
output = pnode->output;
|
||||
|
||||
fprintf(fp, "\t\t\t\toutput: %d (%s)%s\n",
|
||||
output->id, output->name,
|
||||
(view->output == output) ? " (primary)" : "");
|
||||
|
||||
}
|
||||
|
||||
static struct weston_paint_node *
|
||||
weston_paint_node_create(struct weston_surface *surface,
|
||||
struct weston_view *view,
|
||||
|
|
@ -429,6 +455,9 @@ weston_paint_node_create(struct weston_surface *surface,
|
|||
pnode->status =
|
||||
WESTON_PAINT_NODE_ALL_DIRTY & ~WESTON_PAINT_NODE_PLANE_DIRTY;
|
||||
|
||||
pnode->scene_graph_record.regen =
|
||||
weston_paint_node_debug_string_regenerate;
|
||||
|
||||
return pnode;
|
||||
}
|
||||
|
||||
|
|
@ -480,6 +509,7 @@ weston_paint_node_destroy(struct weston_paint_node *pnode)
|
|||
pixman_region32_fini(&pnode->visible);
|
||||
pixman_region32_fini(&pnode->visible_previous);
|
||||
pixman_region32_fini(&pnode->clipped_view);
|
||||
free(pnode->scene_graph_record.cached_str);
|
||||
free(pnode);
|
||||
}
|
||||
|
||||
|
|
@ -733,6 +763,39 @@ weston_output_mode_switch_to_temporary(struct weston_output *output,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
weston_view_debug_string_regenerate(FILE *fp, void *data)
|
||||
{
|
||||
struct weston_view *ev = data;
|
||||
pixman_box32_t *box;
|
||||
|
||||
if (!weston_view_is_mapped(ev))
|
||||
fprintf(fp, "\t[view is not mapped!]\n");
|
||||
if (wl_list_empty(&ev->layer_link.link)) {
|
||||
if (!get_view_layer(ev))
|
||||
fprintf(fp, "\t[view is not part of any layer]\n");
|
||||
else
|
||||
fprintf(fp, "\t[view is under parent view layer]\n");
|
||||
}
|
||||
|
||||
box = pixman_region32_extents(&ev->transform.boundingbox);
|
||||
fprintf(fp, "\t\tposition: (%d, %d) -> (%d, %d)\n",
|
||||
box->x1, box->y1, box->x2, box->y2);
|
||||
box = pixman_region32_extents(&ev->transform.opaque);
|
||||
|
||||
if (weston_view_is_opaque(ev, &ev->transform.boundingbox)) {
|
||||
fprintf(fp, "\t\t[fully opaque]\n");
|
||||
} else if (!pixman_region32_not_empty(&ev->transform.opaque)) {
|
||||
fprintf(fp, "\t\t[not opaque]\n");
|
||||
} else {
|
||||
fprintf(fp, "\t\t[opaque: (%d, %d) -> (%d, %d)]\n",
|
||||
box->x1, box->y1, box->x2, box->y2);
|
||||
}
|
||||
|
||||
if (ev->alpha < 1.0)
|
||||
fprintf(fp, "\t\talpha: %f\n", ev->alpha);
|
||||
}
|
||||
|
||||
static struct weston_view *
|
||||
weston_view_create_internal(struct weston_surface *surface)
|
||||
{
|
||||
|
|
@ -765,6 +828,9 @@ weston_view_create_internal(struct weston_surface *surface)
|
|||
pixman_region32_init(&view->geometry.scissor);
|
||||
pixman_region32_init(&view->transform.boundingbox);
|
||||
view->transform.dirty = 1;
|
||||
|
||||
view->scene_graph_record.regen =
|
||||
weston_view_debug_string_regenerate;
|
||||
weston_view_update_transform(view);
|
||||
|
||||
return view;
|
||||
|
|
@ -962,6 +1028,33 @@ 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",
|
||||
weston_surface_get_role(surface), pid, surface_id, desc);
|
||||
|
||||
if (!weston_surface_is_mapped(surface))
|
||||
fprintf(fp, "\t[surface is not mapped!]\n");
|
||||
}
|
||||
|
||||
WL_EXPORT struct weston_surface *
|
||||
weston_surface_create(struct weston_compositor *compositor)
|
||||
{
|
||||
|
|
@ -1029,6 +1122,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;
|
||||
}
|
||||
|
||||
|
|
@ -1958,6 +2054,8 @@ weston_view_update_transform_internal(struct weston_view *view)
|
|||
geometry.parent_link) {
|
||||
weston_view_update_transform(child);
|
||||
}
|
||||
|
||||
weston_cached_str_invalidate(&view->scene_graph_record);
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
|
|
@ -2593,6 +2691,7 @@ weston_view_unmap(struct weston_view *view)
|
|||
}
|
||||
|
||||
weston_view_destroy_paint_nodes(view);
|
||||
weston_cached_str_invalidate(&view->scene_graph_record);
|
||||
|
||||
wl_signal_emit_mutable(&view->unmap_signal, view);
|
||||
view->surface->compositor->view_list_needs_rebuild = true;
|
||||
|
|
@ -2605,6 +2704,8 @@ static void weston_surface_start_mapping(struct weston_surface *surface)
|
|||
surface->is_mapping = true;
|
||||
surface->is_mapped = true;
|
||||
surface->compositor->view_list_needs_rebuild = true;
|
||||
|
||||
weston_cached_str_invalidate(&surface->scene_graph_record);
|
||||
wl_signal_emit_mutable(&surface->map_signal, surface);
|
||||
}
|
||||
|
||||
|
|
@ -2628,6 +2729,8 @@ weston_surface_unmap(struct weston_surface *surface)
|
|||
wl_list_for_each(view, &surface->views, surface_link)
|
||||
weston_view_unmap(view);
|
||||
surface->output = NULL;
|
||||
|
||||
weston_cached_str_invalidate(&surface->scene_graph_record);
|
||||
wl_signal_emit_mutable(&surface->unmap_signal, surface);
|
||||
}
|
||||
|
||||
|
|
@ -2660,6 +2763,7 @@ weston_view_destroy(struct weston_view *view)
|
|||
|
||||
wl_list_remove(&view->surface_link);
|
||||
|
||||
free(view->scene_graph_record.cached_str);
|
||||
free(view);
|
||||
}
|
||||
|
||||
|
|
@ -2747,6 +2851,7 @@ weston_surface_unref(struct weston_surface *surface)
|
|||
|
||||
wl_list_remove(&surface->fifo_barrier_link);
|
||||
|
||||
free(surface->scene_graph_record.cached_str);
|
||||
free(surface);
|
||||
}
|
||||
|
||||
|
|
@ -2808,9 +2913,60 @@ weston_buffer_destroy_handler(struct wl_listener *listener, void *data)
|
|||
return;
|
||||
|
||||
wl_signal_emit_mutable(&buffer->destroy_signal, buffer);
|
||||
free(buffer->scene_graph_record.cached_str);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
weston_buffer_debug_string_regenerate(FILE *fp, void *data)
|
||||
{
|
||||
struct weston_buffer *buffer = data;
|
||||
char *modifier_name;
|
||||
|
||||
switch (buffer->type) {
|
||||
case WESTON_BUFFER_SHM:
|
||||
fprintf(fp, "\t\tSHM buffer\n");
|
||||
break;
|
||||
case WESTON_BUFFER_DMABUF:
|
||||
fprintf(fp, "\t\tdmabuf buffer\n");
|
||||
break;
|
||||
case WESTON_BUFFER_SOLID:
|
||||
fprintf(fp, "\t\tsolid-colour buffer\n");
|
||||
fprintf(fp, "\t\t\t[R %f, G %f, B %f, A %f]\n",
|
||||
buffer->solid.r, buffer->solid.g, buffer->solid.b,
|
||||
buffer->solid.a);
|
||||
break;
|
||||
case WESTON_BUFFER_RENDERER_OPAQUE:
|
||||
fprintf(fp, "\t\tEGL buffer:\n");
|
||||
fprintf(fp, "\t\t\t[format may be inaccurate]\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (buffer->pixel_format) {
|
||||
fprintf(fp, "\t\t\tformat: 0x%lx %s\n",
|
||||
(unsigned long) buffer->pixel_format->format,
|
||||
buffer->pixel_format->drm_format_name);
|
||||
} else {
|
||||
fprintf(fp, "\t\t\t[unknown format]\n");
|
||||
}
|
||||
|
||||
modifier_name = pixel_format_get_modifier(buffer->format_modifier);
|
||||
fprintf(fp, "\t\t\tmodifier: %s\n",
|
||||
modifier_name ?
|
||||
modifier_name : "Failed to convert to a modifier name");
|
||||
free(modifier_name);
|
||||
|
||||
fprintf(fp, "\t\t\twidth: %d, height: %d\n",
|
||||
buffer->width, buffer->height);
|
||||
if (buffer->buffer_origin == ORIGIN_BOTTOM_LEFT)
|
||||
fprintf(fp, "\t\t\tbottom-left origin\n");
|
||||
|
||||
if (buffer->direct_display)
|
||||
fprintf(fp, "\t\t\tdirect-display buffer (no renderer access)\n");
|
||||
}
|
||||
|
||||
|
||||
WL_EXPORT struct weston_buffer *
|
||||
weston_buffer_from_resource(struct weston_compositor *ec,
|
||||
struct wl_resource *resource)
|
||||
|
|
@ -2833,6 +2989,8 @@ weston_buffer_from_resource(struct weston_compositor *ec,
|
|||
return NULL;
|
||||
|
||||
buffer->resource = resource;
|
||||
buffer->scene_graph_record.regen =
|
||||
weston_buffer_debug_string_regenerate;
|
||||
wl_signal_init(&buffer->destroy_signal);
|
||||
buffer->destroy_listener.notify = weston_buffer_destroy_handler;
|
||||
wl_resource_add_destroy_listener(resource, &buffer->destroy_listener);
|
||||
|
|
@ -2901,6 +3059,7 @@ weston_buffer_from_resource(struct weston_compositor *ec,
|
|||
|
||||
fail:
|
||||
wl_list_remove(&buffer->destroy_listener.link);
|
||||
free(buffer->scene_graph_record.cached_str);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -2958,6 +3117,7 @@ weston_buffer_reference(struct weston_buffer_reference *ref,
|
|||
!old_ref.buffer->resource) {
|
||||
wl_signal_emit_mutable(&old_ref.buffer->destroy_signal,
|
||||
old_ref.buffer);
|
||||
free(old_ref.buffer->scene_graph_record.cached_str);
|
||||
free(old_ref.buffer);
|
||||
}
|
||||
}
|
||||
|
|
@ -3049,6 +3209,8 @@ weston_buffer_create_solid_rgba(struct weston_compositor *compositor,
|
|||
buffer->solid.g = g;
|
||||
buffer->solid.b = b;
|
||||
buffer->solid.a = a;
|
||||
buffer->scene_graph_record.regen =
|
||||
weston_buffer_debug_string_regenerate;
|
||||
|
||||
if (a == 1.0) {
|
||||
buffer->pixel_format =
|
||||
|
|
@ -5389,6 +5551,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
|
||||
|
|
@ -9422,31 +9586,13 @@ static void
|
|||
debug_scene_view_print_buffer(FILE *fp, struct weston_view *view)
|
||||
{
|
||||
struct weston_buffer *buffer = view->surface->buffer_ref.buffer;
|
||||
char *modifier_name;
|
||||
|
||||
if (!buffer) {
|
||||
fprintf(fp, "\t\t[buffer not available]\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (buffer->type) {
|
||||
case WESTON_BUFFER_SHM:
|
||||
fprintf(fp, "\t\tSHM buffer\n");
|
||||
break;
|
||||
case WESTON_BUFFER_DMABUF:
|
||||
fprintf(fp, "\t\tdmabuf buffer\n");
|
||||
break;
|
||||
case WESTON_BUFFER_SOLID:
|
||||
fprintf(fp, "\t\tsolid-colour buffer\n");
|
||||
fprintf(fp, "\t\t\t[R %f, G %f, B %f, A %f]\n",
|
||||
buffer->solid.r, buffer->solid.g, buffer->solid.b,
|
||||
buffer->solid.a);
|
||||
break;
|
||||
case WESTON_BUFFER_RENDERER_OPAQUE:
|
||||
fprintf(fp, "\t\tEGL buffer:\n");
|
||||
fprintf(fp, "\t\t\t[format may be inaccurate]\n");
|
||||
break;
|
||||
}
|
||||
fputs(weston_cached_str_get(&buffer->scene_graph_record, buffer), fp);
|
||||
|
||||
if (buffer->busy_count > 0) {
|
||||
fprintf(fp, "\t\t\t[%d references may use buffer content]\n",
|
||||
|
|
@ -9455,27 +9601,6 @@ debug_scene_view_print_buffer(FILE *fp, struct weston_view *view)
|
|||
fprintf(fp, "\t\t\t[buffer has been released to client]\n");
|
||||
}
|
||||
|
||||
if (buffer->pixel_format) {
|
||||
fprintf(fp, "\t\t\tformat: 0x%lx %s\n",
|
||||
(unsigned long) buffer->pixel_format->format,
|
||||
buffer->pixel_format->drm_format_name);
|
||||
} else {
|
||||
fprintf(fp, "\t\t\t[unknown format]\n");
|
||||
}
|
||||
|
||||
modifier_name = pixel_format_get_modifier(buffer->format_modifier);
|
||||
fprintf(fp, "\t\t\tmodifier: %s\n",
|
||||
modifier_name ?
|
||||
modifier_name : "Failed to convert to a modifier name");
|
||||
free(modifier_name);
|
||||
|
||||
fprintf(fp, "\t\t\twidth: %d, height: %d\n",
|
||||
buffer->width, buffer->height);
|
||||
if (buffer->buffer_origin == ORIGIN_BOTTOM_LEFT)
|
||||
fprintf(fp, "\t\t\tbottom-left origin\n");
|
||||
|
||||
if (buffer->direct_display)
|
||||
fprintf(fp, "\t\t\tdirect-display buffer (no renderer access)\n");
|
||||
}
|
||||
|
||||
static const struct weston_enum_map transforms[] = {
|
||||
|
|
@ -9552,22 +9677,15 @@ debug_scene_view_print_paint_node(FILE *fp,
|
|||
struct weston_paint_node *pnode;
|
||||
|
||||
pnode = weston_view_find_paint_node(view, output);
|
||||
if (!pnode)
|
||||
fprintf(fp, "\t\t\tpaint node [pending repaint]:\n");
|
||||
else
|
||||
fprintf(fp, "\t\t\tpaint node %p:\n", pnode);
|
||||
|
||||
fprintf(fp, "\t\t\t\toutput: %d (%s)%s\n",
|
||||
output->id, output->name,
|
||||
(view->output == output) ? " (primary)" : "");
|
||||
fputs(weston_cached_str_get(&pnode->scene_graph_record, pnode), fp);
|
||||
|
||||
if (!pnode)
|
||||
return;
|
||||
|
||||
fprintf(fp, "\t\t\t\tBuffer to output transform: ");
|
||||
if (!pnode->valid_transform)
|
||||
if (!pnode->valid_transform) {
|
||||
fprintf(fp, "Free form\n");
|
||||
else {
|
||||
} else {
|
||||
const char *tform;
|
||||
|
||||
tform = weston_transform_to_string(pnode->transform);
|
||||
|
|
@ -9575,11 +9693,10 @@ debug_scene_view_print_paint_node(FILE *fp,
|
|||
}
|
||||
|
||||
if (pnode->try_view_on_plane_failure_reasons) {
|
||||
char *fr_str = bits_to_str(pnode->try_view_on_plane_failure_reasons,
|
||||
weston_plane_failure_reasons_to_str);
|
||||
fprintf(fp, "\t\t\t\tPlane failure reasons: %s\n", fr_str);
|
||||
|
||||
free(fr_str);
|
||||
fprintf(fp, "\t\t\t\tPlane failure reasons: ");
|
||||
bits_to_str_stream(pnode->try_view_on_plane_failure_reasons,
|
||||
weston_plane_failure_reasons_to_str, fp);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9588,53 +9705,12 @@ 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);
|
||||
}
|
||||
fprintf(fp, "\tView %d (%s %p):\n", view_idx,
|
||||
weston_cached_str_get(&view->surface->scene_graph_record, view->surface),
|
||||
view);
|
||||
|
||||
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);
|
||||
|
||||
if (!weston_view_is_mapped(view))
|
||||
fprintf(fp, "\t[view is not mapped!]\n");
|
||||
if (!weston_surface_is_mapped(view->surface))
|
||||
fprintf(fp, "\t[surface is not mapped!]\n");
|
||||
if (wl_list_empty(&view->layer_link.link)) {
|
||||
if (!get_view_layer(view))
|
||||
fprintf(fp, "\t[view is not part of any layer]\n");
|
||||
else
|
||||
fprintf(fp, "\t[view is under parent view layer]\n");
|
||||
}
|
||||
|
||||
box = pixman_region32_extents(&view->transform.boundingbox);
|
||||
fprintf(fp, "\t\tposition: (%d, %d) -> (%d, %d)\n",
|
||||
box->x1, box->y1, box->x2, box->y2);
|
||||
box = pixman_region32_extents(&view->transform.opaque);
|
||||
|
||||
if (weston_view_is_opaque(view, &view->transform.boundingbox)) {
|
||||
fprintf(fp, "\t\t[fully opaque]\n");
|
||||
} else if (!pixman_region32_not_empty(&view->transform.opaque)) {
|
||||
fprintf(fp, "\t\t[not opaque]\n");
|
||||
} else {
|
||||
fprintf(fp, "\t\t[opaque: (%d, %d) -> (%d, %d)]\n",
|
||||
box->x1, box->y1, box->x2, box->y2);
|
||||
}
|
||||
|
||||
if (view->alpha < 1.0)
|
||||
fprintf(fp, "\t\talpha: %f\n", view->alpha);
|
||||
fputs(weston_cached_str_get(&view->scene_graph_record, view), fp);
|
||||
|
||||
if (view->output_mask != 0) {
|
||||
fprintf(fp, "\t\tpaint nodes:\n");
|
||||
|
|
@ -9708,6 +9784,8 @@ weston_compositor_print_scene_graph(struct weston_compositor *ec)
|
|||
size_t len;
|
||||
int err;
|
||||
|
||||
WESTON_TRACE_FUNC();
|
||||
|
||||
fp = open_memstream(&ret, &len);
|
||||
assert(fp);
|
||||
|
||||
|
|
@ -10920,3 +10998,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)
|
||||
{
|
||||
WESTON_TRACE_FUNC();
|
||||
s->is_up_to_date = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -750,6 +750,8 @@ struct weston_paint_node {
|
|||
*/
|
||||
bool need_hole;
|
||||
uint32_t psf_flags; /* presentation-feedback flags */
|
||||
|
||||
struct weston_cached_string scene_graph_record;
|
||||
};
|
||||
|
||||
struct weston_paint_node *
|
||||
|
|
|
|||
|
|
@ -3398,6 +3398,7 @@ gl_renderer_fill_buffer_info(struct weston_compositor *ec,
|
|||
|
||||
buffer->renderer_private = gb;
|
||||
gb->destroy_listener.notify = handle_buffer_destroy;
|
||||
weston_cached_str_invalidate(&buffer->scene_graph_record);
|
||||
wl_signal_add(&buffer->destroy_signal, &gb->destroy_listener);
|
||||
return true;
|
||||
|
||||
|
|
|
|||
|
|
@ -130,12 +130,42 @@ str_printf(char **str_out, const char *fmt, ...)
|
|||
}
|
||||
|
||||
/**
|
||||
* Utility to print combination of enum values as string
|
||||
* Utility to print combination of enum values as string. Use an opened FILE
|
||||
* stream to write data.
|
||||
*
|
||||
* Only works for enum whose values are defined as power of two. Given a bitmask
|
||||
* in which each bit represents an enum value and a function that maps each enum
|
||||
* value to a string, this function returns a string (comma separated) with all
|
||||
* the enum values that are present in the bitmask.
|
||||
* \param bits The bitmask of enum values.
|
||||
* \param map Function that maps enum values to string.
|
||||
* \param fp an opened FILE stream
|
||||
*/
|
||||
static inline void
|
||||
bits_to_str_stream(uint32_t bits, const char *(*map)(uint32_t), FILE *fp)
|
||||
{
|
||||
unsigned i;
|
||||
const char *sep = "";
|
||||
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
for (i = 0; bits; i++) {
|
||||
uint32_t bitmask = 1u << i;
|
||||
|
||||
if (bits & bitmask) {
|
||||
fprintf(fp, "%s%s", sep, map(bitmask));
|
||||
sep = ", ";
|
||||
}
|
||||
|
||||
bits &= ~bitmask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to print combination of enum values as string.
|
||||
* Uses bits_to_str_stream() helper.
|
||||
*
|
||||
* Only works for enum whose values are defined as power of two. Given a
|
||||
* bitmask in which each bit represents an enum value and a function that maps
|
||||
* each enum value to a string, this function returns a string (comma
|
||||
* separated) with all the enum values that are present in the bitmask.
|
||||
*
|
||||
* \param bits The bitmask of enum values.
|
||||
* \param map Function that maps enum values to string.
|
||||
|
|
@ -148,23 +178,13 @@ bits_to_str(uint32_t bits, const char *(*map)(uint32_t))
|
|||
FILE *fp;
|
||||
char *str = NULL;
|
||||
size_t size = 0;
|
||||
unsigned i;
|
||||
const char *sep = "";
|
||||
|
||||
fp = open_memstream(&str, &size);
|
||||
if (!fp)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; bits; i++) {
|
||||
uint32_t bitmask = 1u << i;
|
||||
bits_to_str_stream(bits, map, fp);
|
||||
|
||||
if (bits & bitmask) {
|
||||
fprintf(fp, "%s%s", sep, map(bitmask));
|
||||
sep = ", ";
|
||||
}
|
||||
|
||||
bits &= ~bitmask;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
return str;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue