From dc4d1cf676236b26d3d726bfe307fca34b47d97a Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Tue, 5 May 2026 11:38:46 -0500 Subject: [PATCH 01/10] trace: Use generics to simplify annotation usage Use C's Generic() functionality to make all the annotation usage have a single entrypoint. Signed-off-by: Derek Foreman --- libweston/perfetto/u_perfetto.cc | 32 ++++++++++++++++++++++ libweston/perfetto/u_perfetto.h | 18 +++++++++++++ libweston/renderer-gl/gl-renderer.c | 42 ++++++++++++++--------------- libweston/renderer-gl/gl-shaders.c | 26 +++++++++--------- libweston/surface-state.c | 10 +++---- libweston/weston-trace.h | 42 +++++++++-------------------- 6 files changed, 101 insertions(+), 69 deletions(-) diff --git a/libweston/perfetto/u_perfetto.cc b/libweston/perfetto/u_perfetto.cc index b7a96fd2a..76b6921cf 100644 --- a/libweston/perfetto/u_perfetto.cc +++ b/libweston/perfetto/u_perfetto.cc @@ -227,6 +227,38 @@ util_perfetto_trace_commit_annotate_func_flow(uint64_t id, const char *name, }); } +void +perfetto_annotate_int(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + int value) +{ + annots[count].type = WESTON_DEBUG_ANNOTATION_INT_VAL; + annots[count].ivalue = value; + annots[count].key = key; +} + +void +perfetto_annotate_float(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + float value) +{ + annots[count].type = WESTON_DEBUG_ANNOTATION_FLOAT_VAL; + annots[count].fvalue = value; + annots[count].key = key; +} + +void +perfetto_annotate_string(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + const char *value) +{ + annots[count].type = WESTON_DEBUG_ANNOTATION_STR_VAL; + annots[count].svalue = value; + annots[count].key = key; +} class UtilPerfettoObserver : public perfetto::TrackEventSessionObserver { public: diff --git a/libweston/perfetto/u_perfetto.h b/libweston/perfetto/u_perfetto.h index 4c84b7250..cb1234285 100644 --- a/libweston/perfetto/u_perfetto.h +++ b/libweston/perfetto/u_perfetto.h @@ -92,6 +92,24 @@ uint64_t util_perfetto_next_id(void); uint64_t util_perfetto_new_track(const char *name); +void +perfetto_annotate_int(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + int value); + +void +perfetto_annotate_float(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + float value); + +void +perfetto_annotate_string(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + const char *value); + #else /* HAVE_PERFETTO */ static inline void diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 5eb45f6cd..985845602 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -436,12 +436,12 @@ gl_log_paint_node_bbox_and_region(struct gl_renderer *gr, struct weston_paint_no WESTON_TRACE_BEGIN_ANNOTATION(); - WESTON_TRACE_ANNOTATE_ADD_STR("paint node", pnode->internal_name); - WESTON_TRACE_ANNOTATE_ADD_STR("type", str); - WESTON_TRACE_ANNOTATE_ADD_INT("x", box_x); - WESTON_TRACE_ANNOTATE_ADD_INT("y", box_y); - WESTON_TRACE_ANNOTATE_ADD_INT("box_width", box_width); - WESTON_TRACE_ANNOTATE_ADD_INT("box_height", box_height); + WESTON_TRACE_ANNOTATE_ADD("paint node", pnode->internal_name); + WESTON_TRACE_ANNOTATE_ADD("type", str); + WESTON_TRACE_ANNOTATE_ADD("x", box_x); + WESTON_TRACE_ANNOTATE_ADD("y", box_y); + WESTON_TRACE_ANNOTATE_ADD("box_width", box_width); + WESTON_TRACE_ANNOTATE_ADD("box_height", box_height); WESTON_TRACE_COMMIT_ANNOTATION(&pnode->flow_id); @@ -2364,15 +2364,15 @@ set_blend_state(struct gl_renderer *gr, struct weston_paint_node *pnode, bool st if (state) { glEnable(GL_BLEND); gl_log_paint_node(gr, "\t\tblending enabled\n"); - WESTON_TRACE_ANNOTATE_ADD_STR("blending", "enabled"); + WESTON_TRACE_ANNOTATE_ADD("blending", "enabled"); } else { glDisable(GL_BLEND); gl_log_paint_node(gr, "\t\tblending disabled\n"); - WESTON_TRACE_ANNOTATE_ADD_STR("blending", "disabled"); + WESTON_TRACE_ANNOTATE_ADD("blending", "disabled"); } if (pnode) { - WESTON_TRACE_ANNOTATE_ADD_STR("paint node", pnode->internal_name); + WESTON_TRACE_ANNOTATE_ADD("paint node", pnode->internal_name); WESTON_TRACE_COMMIT_ANNOTATION(&pnode->flow_id); } else { WESTON_TRACE_COMMIT_ANNOTATION(NULL); @@ -2546,7 +2546,7 @@ apply_color_effect(struct gl_renderer *gr, struct weston_paint_node *pnode, stru WESTON_TRACE_FUNC_FLOW(&pnode->flow_id); WESTON_TRACE_BEGIN_ANNOTATION(); - WESTON_TRACE_ANNOTATE_ADD_STR("paint node", pnode->internal_name); + WESTON_TRACE_ANNOTATE_ADD("paint node", pnode->internal_name); weston_assert_f32_eq(compositor, a, 1.0f); @@ -2556,7 +2556,7 @@ apply_color_effect(struct gl_renderer *gr, struct weston_paint_node *pnode, stru *g = 1.0f - *g; *b = 1.0f - *b; gl_log_paint_node(gr, "\t\tcolor effect: inversion\n"); - WESTON_TRACE_ANNOTATE_ADD_STR("color effect", "inversion"); + WESTON_TRACE_ANNOTATE_ADD("color effect", "inversion"); WESTON_TRACE_COMMIT_ANNOTATION(&pnode->flow_id); return; case WESTON_OUTPUT_COLOR_EFFECT_TYPE_GRAYSCALE: @@ -2564,7 +2564,7 @@ apply_color_effect(struct gl_renderer *gr, struct weston_paint_node *pnode, stru *g = *r; *b = *r; gl_log_paint_node(gr, "\t\tcolor effect: grayscale\n"); - WESTON_TRACE_ANNOTATE_ADD_STR("color effect", "greyscale"); + WESTON_TRACE_ANNOTATE_ADD("color effect", "greyscale"); WESTON_TRACE_COMMIT_ANNOTATION(&pnode->flow_id); return; case WESTON_OUTPUT_COLOR_EFFECT_TYPE_CVD_CORRECTION: @@ -2579,7 +2579,7 @@ apply_color_effect(struct gl_renderer *gr, struct weston_paint_node *pnode, stru weston_log_scope_printf(gr->paint_node_scope, "\t\tcolor effect: cvd - %s\n", weston_output_cvd_type_to_str(effect->u.cvd)); - WESTON_TRACE_ANNOTATE_ADD_STR("color effect", + WESTON_TRACE_ANNOTATE_ADD("color effect", weston_output_cvd_type_to_str(effect->u.cvd)); WESTON_TRACE_COMMIT_ANNOTATION(&pnode->flow_id); return; @@ -2646,22 +2646,22 @@ draw_paint_node(struct weston_paint_node *pnode, pixman_region32_init(&repaint); pixman_region32_intersect(&repaint, &pnode->visible, damage); - WESTON_TRACE_ANNOTATE_ADD_STR("paint node", pnode->internal_name); - WESTON_TRACE_ANNOTATE_ADD_STR("label", pnode->surface->label); - WESTON_TRACE_ANNOTATE_ADD_INT("surface id", pnode->surface->s_id); + WESTON_TRACE_ANNOTATE_ADD("paint node", pnode->internal_name); + WESTON_TRACE_ANNOTATE_ADD("label", pnode->surface->label); + WESTON_TRACE_ANNOTATE_ADD("surface id", pnode->surface->s_id); gl_log_paint_node_start(gr, pnode); if (!pixman_region32_not_empty(&repaint)) { gl_log_paint_node(gr, "\t\tskipped repaint: repaint region empty\n"); - WESTON_TRACE_ANNOTATE_ADD_STR("skipped repaint", "repaint region empty"); + WESTON_TRACE_ANNOTATE_ADD("skipped repaint", "repaint region empty"); goto out; } if (pnode->is_fully_transparent) { gl_log_paint_node(gr, "\t\tskipped repaint: paint node transparent\n"); gs->used_in_output_repaint = true; /* sort of */ - WESTON_TRACE_ANNOTATE_ADD_STR("skipped repaint", "paint node transparent"); + WESTON_TRACE_ANNOTATE_ADD("skipped repaint", "paint node transparent"); goto out; } @@ -2669,7 +2669,7 @@ draw_paint_node(struct weston_paint_node *pnode, pnode->valid_transform && (pnode->surf_xform_valid && !pnode->surf_xform.transform)) { gl_log_paint_node(gr, "\t\toptimize: using glClear\n"); - WESTON_TRACE_ANNOTATE_ADD_STR("optimization", "using glClear"); + WESTON_TRACE_ANNOTATE_ADD("optimization", "using glClear"); clear_region(gr, pnode, &repaint); gs->used_in_output_repaint = true; goto out; @@ -2677,13 +2677,13 @@ draw_paint_node(struct weston_paint_node *pnode, if (ensure_surface_buffer_is_ready(gr, gs, pnode) < 0) { gl_log_paint_node(gr, "\t\tskipped repaint: buffer not ready\n"); - WESTON_TRACE_ANNOTATE_ADD_STR("skipped repaint", "buffer not ready"); + WESTON_TRACE_ANNOTATE_ADD("skipped repaint", "buffer not ready"); goto out; } if (!gl_shader_config_init_for_paint_node(&sconf, pnode)) { gl_log_paint_node(gr, "\t\tskipped repaint: shader config failure\n"); - WESTON_TRACE_ANNOTATE_ADD_STR("skipped repaint", "shader config failure"); + WESTON_TRACE_ANNOTATE_ADD("skipped repaint", "shader config failure"); goto out; } diff --git a/libweston/renderer-gl/gl-shaders.c b/libweston/renderer-gl/gl-shaders.c index 8861a69b4..35170db98 100644 --- a/libweston/renderer-gl/gl-shaders.c +++ b/libweston/renderer-gl/gl-shaders.c @@ -856,7 +856,7 @@ gl_shader_load_config(struct gl_renderer *gr, struct weston_paint_node *pnode, WESTON_TRACE_BEGIN_ANNOTATION(); if (pnode) { - WESTON_TRACE_ANNOTATE_ADD_STR("paint node", pnode->internal_name); + WESTON_TRACE_ANNOTATE_ADD("paint node", pnode->internal_name); } glUniformMatrix4fv(shader->proj_uniform, @@ -871,10 +871,10 @@ gl_shader_load_config(struct gl_renderer *gr, struct weston_paint_node *pnode, "\t\tcolor: r: %.2f, g: %.2f, b: %.2f, a: %.2f\n", sconf->unicolor[0], sconf->unicolor[1], sconf->unicolor[2], sconf->unicolor[3]); - WESTON_TRACE_ANNOTATE_ADD_FLOAT("color r", sconf->unicolor[0]); - WESTON_TRACE_ANNOTATE_ADD_FLOAT("color g", sconf->unicolor[1]); - WESTON_TRACE_ANNOTATE_ADD_FLOAT("color b", sconf->unicolor[2]); - WESTON_TRACE_ANNOTATE_ADD_FLOAT("color a", sconf->unicolor[3]); + WESTON_TRACE_ANNOTATE_ADD("color r", sconf->unicolor[0]); + WESTON_TRACE_ANNOTATE_ADD("color g", sconf->unicolor[1]); + WESTON_TRACE_ANNOTATE_ADD("color b", sconf->unicolor[2]); + WESTON_TRACE_ANNOTATE_ADD("color a", sconf->unicolor[3]); glUniform4fv(shader->color_uniform, 1, sconf->unicolor); } if (shader->tint_uniform != -1) { @@ -882,15 +882,15 @@ gl_shader_load_config(struct gl_renderer *gr, struct weston_paint_node *pnode, "\t\ttint: r: %.2f, g: %.2f, b: %.2f, a: %.2f\n", sconf->tint[0], sconf->tint[1], sconf->tint[2], sconf->tint[3]); - WESTON_TRACE_ANNOTATE_ADD_FLOAT("tint r", sconf->tint[0]); - WESTON_TRACE_ANNOTATE_ADD_FLOAT("tint g", sconf->tint[1]); - WESTON_TRACE_ANNOTATE_ADD_FLOAT("tint b", sconf->tint[2]); - WESTON_TRACE_ANNOTATE_ADD_FLOAT("tint a", sconf->tint[3]); + WESTON_TRACE_ANNOTATE_ADD("tint r", sconf->tint[0]); + WESTON_TRACE_ANNOTATE_ADD("tint g", sconf->tint[1]); + WESTON_TRACE_ANNOTATE_ADD("tint b", sconf->tint[2]); + WESTON_TRACE_ANNOTATE_ADD("tint a", sconf->tint[3]); glUniform4fv(shader->tint_uniform, 1, sconf->tint); } weston_log_scope_printf(gr->paint_node_scope, "\t\talpha: %.2f\n", sconf->view_alpha); - WESTON_TRACE_ANNOTATE_ADD_FLOAT("alpha", sconf->view_alpha); + WESTON_TRACE_ANNOTATE_ADD("alpha", sconf->view_alpha); glUniform1f(shader->view_alpha_uniform, sconf->view_alpha); assert(sconf->input_num <= SHADER_INPUT_TEX_MAX); @@ -935,11 +935,11 @@ gl_shader_load_config(struct gl_renderer *gr, struct weston_paint_node *pnode, break; case SHADER_COLOR_EFFECT_INVERSION: weston_log_scope_printf(gr->paint_node_scope, "\t\tcolor effect: inversion\n"); - WESTON_TRACE_ANNOTATE_ADD_STR("color effect", "inversion"); + WESTON_TRACE_ANNOTATE_ADD("color effect", "inversion"); break; case SHADER_COLOR_EFFECT_GRAYSCALE: weston_log_scope_printf(gr->paint_node_scope, "\t\tcolor effect: grayscale\n"); - WESTON_TRACE_ANNOTATE_ADD_STR("color effect", "greyscale"); + WESTON_TRACE_ANNOTATE_ADD("color effect", "greyscale"); break; case SHADER_COLOR_EFFECT_CVD_CORRECTION: weston_assert_int_ne(gr->compositor, shader->cvd_correction_uniform, -1); @@ -948,7 +948,7 @@ gl_shader_load_config(struct gl_renderer *gr, struct weston_paint_node *pnode, glUniformMatrix3fv(shader->cvd_correction_uniform, 1, GL_FALSE, sconf->color_effect.cvd.correction.colmaj); - WESTON_TRACE_ANNOTATE_ADD_STR("color effect", + WESTON_TRACE_ANNOTATE_ADD("color effect", weston_output_cvd_type_to_str(sconf->color_effect.cvd)); break; } diff --git a/libweston/surface-state.c b/libweston/surface-state.c index 1513655d4..a05496887 100644 --- a/libweston/surface-state.c +++ b/libweston/surface-state.c @@ -206,11 +206,11 @@ weston_surface_attach(struct weston_surface *surface, WESTON_TRACE_BEGIN_ANNOTATION(); if (buffer) { - WESTON_TRACE_ANNOTATE_ADD_STR("surface", surface->internal_name); - WESTON_TRACE_ANNOTATE_ADD_STR("format", buffer->pixel_format->drm_format_name); - WESTON_TRACE_ANNOTATE_ADD_STR("modifier", buffer->format_modifier_name); - WESTON_TRACE_ANNOTATE_ADD_INT("width", buffer->width); - WESTON_TRACE_ANNOTATE_ADD_INT("height", buffer->height); + WESTON_TRACE_ANNOTATE_ADD("surface", surface->internal_name); + WESTON_TRACE_ANNOTATE_ADD("format", buffer->pixel_format->drm_format_name); + WESTON_TRACE_ANNOTATE_ADD("modifier", buffer->format_modifier_name); + WESTON_TRACE_ANNOTATE_ADD("width", buffer->width); + WESTON_TRACE_ANNOTATE_ADD("height", buffer->height); } WESTON_TRACE_ANNOTATE_FUNC_FLOW(&surface->flow_id); diff --git a/libweston/weston-trace.h b/libweston/weston-trace.h index b2ba55492..49c207725 100644 --- a/libweston/weston-trace.h +++ b/libweston/weston-trace.h @@ -77,26 +77,16 @@ struct weston_debug_annotation __pd_annots[WESTON_MAX_DEBUG_ANNOTS]; \ unsigned int __pd_i = 0 -#define _WESTON_TRACE_ANNOTATE_ADD_INT(k, v) \ +#define _WESTON_TRACE_ANNOTATE_ADD(k, v) \ weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, __pd_i); \ - __pd_annots[__pd_i].type = WESTON_DEBUG_ANNOTATION_INT_VAL; \ - __pd_annots[__pd_i].ivalue = v; \ - __pd_annots[__pd_i].key = k; \ - __pd_i++ - -#define _WESTON_TRACE_ANNOTATE_ADD_FLOAT(k, v) \ - weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, __pd_i); \ - __pd_annots[__pd_i].type = WESTON_DEBUG_ANNOTATION_FLOAT_VAL; \ - __pd_annots[__pd_i].fvalue = v; \ - __pd_annots[__pd_i].key = k; \ - __pd_i++ - -#define _WESTON_TRACE_ANNOTATE_ADD_STR(k, v) \ - weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, __pd_i); \ - __pd_annots[__pd_i].type = WESTON_DEBUG_ANNOTATION_STR_VAL; \ - __pd_annots[__pd_i].svalue = v; \ - __pd_annots[__pd_i].key = k; \ - __pd_i++ + _Generic((v), \ + int: perfetto_annotate_int, \ + unsigned int: perfetto_annotate_int, \ + float: perfetto_annotate_float, \ + char *: perfetto_annotate_string, \ + const char *: perfetto_annotate_string \ + ) (__pd_annots, __pd_i, k, v); \ + __pd_i++; #define _WESTON_TRACE_COMMIT_ANNOTATION(id, name) \ do { \ @@ -240,9 +230,7 @@ _weston_trace_scope_end(int *scope) #define _WESTON_TRACE_BEGIN_ANNOTATION() #define _WESTON_TRACE_COMMIT_ANNOTATION(id, name) -#define _WESTON_TRACE_ANNOTATE_ADD_INT(k, v) -#define _WESTON_TRACE_ANNOTATE_ADD_FLOAT(k, v) -#define _WESTON_TRACE_ANNOTATE_ADD_STR(k, v) +#define _WESTON_TRACE_ANNOTATE_ADD(k, v) #define _WESTON_TRACE_ANNOTATE_FUNC() #define _WESTON_TRACE_ANNOTATE_FUNC_FLOW(id, name) @@ -261,14 +249,8 @@ _weston_trace_scope_end(int *scope) #define WESTON_TRACE_BEGIN_ANNOTATION() \ _WESTON_TRACE_BEGIN_ANNOTATION() -#define WESTON_TRACE_ANNOTATE_ADD_INT(k, v) \ - _WESTON_TRACE_ANNOTATE_ADD_INT(k, v) - -#define WESTON_TRACE_ANNOTATE_ADD_FLOAT(k, v) \ - _WESTON_TRACE_ANNOTATE_ADD_FLOAT(k, v) - -#define WESTON_TRACE_ANNOTATE_ADD_STR(k, v) \ - _WESTON_TRACE_ANNOTATE_ADD_STR(k, v) +#define WESTON_TRACE_ANNOTATE_ADD(k, v) \ + _WESTON_TRACE_ANNOTATE_ADD(k, v) #define WESTON_TRACE_COMMIT_ANNOTATION(id) \ _WESTON_TRACE_COMMIT_ANNOTATION(id, __func__) From a285379c9a20eb227cf39329f12b22ebc0a876b1 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Tue, 5 May 2026 12:33:33 -0500 Subject: [PATCH 02/10] trace: Add multiple annotations with a single macro Use recursive macro magic to make a single ANNOTATE macro that processes a list of annotations. Signed-off-by: Derek Foreman --- libweston/surface-state.c | 10 +++++----- libweston/weston-trace.h | 25 +++++++++++++++++++++---- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/libweston/surface-state.c b/libweston/surface-state.c index a05496887..c1dc3ac29 100644 --- a/libweston/surface-state.c +++ b/libweston/surface-state.c @@ -206,11 +206,11 @@ weston_surface_attach(struct weston_surface *surface, WESTON_TRACE_BEGIN_ANNOTATION(); if (buffer) { - WESTON_TRACE_ANNOTATE_ADD("surface", surface->internal_name); - WESTON_TRACE_ANNOTATE_ADD("format", buffer->pixel_format->drm_format_name); - WESTON_TRACE_ANNOTATE_ADD("modifier", buffer->format_modifier_name); - WESTON_TRACE_ANNOTATE_ADD("width", buffer->width); - WESTON_TRACE_ANNOTATE_ADD("height", buffer->height); + WESTON_TRACE_ANNOTATE(("surface", surface->internal_name), + ("format", buffer->pixel_format->drm_format_name), + ("modifier", buffer->format_modifier_name), + ("width", buffer->width), + ("height", buffer->height)); } WESTON_TRACE_ANNOTATE_FUNC_FLOW(&surface->flow_id); diff --git a/libweston/weston-trace.h b/libweston/weston-trace.h index 49c207725..9aa78576f 100644 --- a/libweston/weston-trace.h +++ b/libweston/weston-trace.h @@ -77,7 +77,7 @@ struct weston_debug_annotation __pd_annots[WESTON_MAX_DEBUG_ANNOTS]; \ unsigned int __pd_i = 0 -#define _WESTON_TRACE_ANNOTATE_ADD(k, v) \ +#define _WESTON_TRACE_DO_ANNOTATE_ADD(k, v) \ weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, __pd_i); \ _Generic((v), \ int: perfetto_annotate_int, \ @@ -230,7 +230,7 @@ _weston_trace_scope_end(int *scope) #define _WESTON_TRACE_BEGIN_ANNOTATION() #define _WESTON_TRACE_COMMIT_ANNOTATION(id, name) -#define _WESTON_TRACE_ANNOTATE_ADD(k, v) +#define _WESTON_TRACE_DO_ANNOTATE_ADD(k, v) #define _WESTON_TRACE_ANNOTATE_FUNC() #define _WESTON_TRACE_ANNOTATE_FUNC_FLOW(id, name) @@ -249,8 +249,8 @@ _weston_trace_scope_end(int *scope) #define WESTON_TRACE_BEGIN_ANNOTATION() \ _WESTON_TRACE_BEGIN_ANNOTATION() -#define WESTON_TRACE_ANNOTATE_ADD(k, v) \ - _WESTON_TRACE_ANNOTATE_ADD(k, v) +#define WESTON_TRACE_DO_ANNOTATE_ADD(k, v) \ + _WESTON_TRACE_DO_ANNOTATE_ADD(k, v) #define WESTON_TRACE_COMMIT_ANNOTATION(id) \ _WESTON_TRACE_COMMIT_ANNOTATION(id, __func__) @@ -261,4 +261,21 @@ _weston_trace_scope_end(int *scope) #define WESTON_TRACE_ANNOTATE_FUNC_FLOW(id) \ _WESTON_TRACE_ANNOTATE_FUNC_FLOW(id, __func__) +#define FORCE_RECURSE () +#define WESTON_TRACE_ANNOTATE_ADD(k, v) WESTON_TRACE_DO_ANNOTATE_ADD(k, v) +#define WESTON_TRACE_ANNOTATE_PAIR(pair) WESTON_TRACE_ANNOTATE_ADD pair + +/* There is a large but finite limit to the number of options */ +#define EXPAND(arg) EXPAND1(EXPAND1(EXPAND1(EXPAND1(arg)))) +#define EXPAND1(arg) EXPAND2(EXPAND2(EXPAND2(EXPAND2(arg)))) +#define EXPAND2(arg) arg + +#define ITER_HELPER(operation, pair, ...) \ + operation(pair) \ + __VA_OPT__(ITER_AGAIN FORCE_RECURSE (operation, __VA_ARGS__)) +#define ITER_AGAIN() ITER_HELPER + +#define WESTON_TRACE_ANNOTATE(...) \ + __VA_OPT__(EXPAND(ITER_HELPER(WESTON_TRACE_ANNOTATE_PAIR, __VA_ARGS__))) + #endif /* WESTON_TRACE_H */ From c56f2bc7091d720bde09a19b268be20f8122a705 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Tue, 5 May 2026 12:48:52 -0500 Subject: [PATCH 03/10] trace: Have annotation functions return a count This is a step towards annotating larger structs. Signed-off-by: Derek Foreman --- libweston/perfetto/u_perfetto.cc | 12 +++++++++--- libweston/perfetto/u_perfetto.h | 6 +++--- libweston/weston-trace.h | 5 ++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/libweston/perfetto/u_perfetto.cc b/libweston/perfetto/u_perfetto.cc index 76b6921cf..40800c2d2 100644 --- a/libweston/perfetto/u_perfetto.cc +++ b/libweston/perfetto/u_perfetto.cc @@ -227,7 +227,7 @@ util_perfetto_trace_commit_annotate_func_flow(uint64_t id, const char *name, }); } -void +int perfetto_annotate_int(struct weston_debug_annotation *annots, unsigned int count, const char *key, @@ -236,9 +236,11 @@ perfetto_annotate_int(struct weston_debug_annotation *annots, annots[count].type = WESTON_DEBUG_ANNOTATION_INT_VAL; annots[count].ivalue = value; annots[count].key = key; + + return 1; } -void +int perfetto_annotate_float(struct weston_debug_annotation *annots, unsigned int count, const char *key, @@ -247,9 +249,11 @@ perfetto_annotate_float(struct weston_debug_annotation *annots, annots[count].type = WESTON_DEBUG_ANNOTATION_FLOAT_VAL; annots[count].fvalue = value; annots[count].key = key; + + return 1; } -void +int perfetto_annotate_string(struct weston_debug_annotation *annots, unsigned int count, const char *key, @@ -258,6 +262,8 @@ perfetto_annotate_string(struct weston_debug_annotation *annots, annots[count].type = WESTON_DEBUG_ANNOTATION_STR_VAL; annots[count].svalue = value; annots[count].key = key; + + return 1; } class UtilPerfettoObserver : public perfetto::TrackEventSessionObserver { diff --git a/libweston/perfetto/u_perfetto.h b/libweston/perfetto/u_perfetto.h index cb1234285..00570f615 100644 --- a/libweston/perfetto/u_perfetto.h +++ b/libweston/perfetto/u_perfetto.h @@ -92,19 +92,19 @@ uint64_t util_perfetto_next_id(void); uint64_t util_perfetto_new_track(const char *name); -void +int perfetto_annotate_int(struct weston_debug_annotation *annots, unsigned int count, const char *key, int value); -void +int perfetto_annotate_float(struct weston_debug_annotation *annots, unsigned int count, const char *key, float value); -void +int perfetto_annotate_string(struct weston_debug_annotation *annots, unsigned int count, const char *key, diff --git a/libweston/weston-trace.h b/libweston/weston-trace.h index 9aa78576f..9d4b55979 100644 --- a/libweston/weston-trace.h +++ b/libweston/weston-trace.h @@ -79,14 +79,13 @@ #define _WESTON_TRACE_DO_ANNOTATE_ADD(k, v) \ weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, __pd_i); \ - _Generic((v), \ + __pd_i += _Generic((v), \ int: perfetto_annotate_int, \ unsigned int: perfetto_annotate_int, \ float: perfetto_annotate_float, \ char *: perfetto_annotate_string, \ const char *: perfetto_annotate_string \ - ) (__pd_annots, __pd_i, k, v); \ - __pd_i++; + ) (__pd_annots, __pd_i, k, v); #define _WESTON_TRACE_COMMIT_ANNOTATION(id, name) \ do { \ From eacb27b4cf8ad6c778b916cc414505ad9453256f Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Tue, 5 May 2026 14:54:37 -0500 Subject: [PATCH 04/10] trace: Put annotations in a separate file For now just the three we have, but we'll be adding a bunch of complex annotations, so having their own place will be cleaner. Signed-off-by: Derek Foreman --- libweston/meson.build | 2 + libweston/perfetto/annotations.c | 68 ++++++++++++++++++++++++++++++++ libweston/perfetto/annotations.h | 48 ++++++++++++++++++++++ libweston/perfetto/u_perfetto.cc | 39 ------------------ libweston/perfetto/u_perfetto.h | 18 --------- libweston/weston-trace.h | 1 + 6 files changed, 119 insertions(+), 57 deletions(-) create mode 100644 libweston/perfetto/annotations.c create mode 100644 libweston/perfetto/annotations.h diff --git a/libweston/meson.build b/libweston/meson.build index b2a8cac8d..2bc719fb0 100644 --- a/libweston/meson.build +++ b/libweston/meson.build @@ -117,6 +117,8 @@ endif if get_option('perfetto') srcs_libweston += [ + 'perfetto/annotations.c', + 'perfetto/annotations.h', 'perfetto/u_perfetto.cc', 'perfetto/u_perfetto.h', 'timeline-perfetto.c' diff --git a/libweston/perfetto/annotations.c b/libweston/perfetto/annotations.c new file mode 100644 index 000000000..7cee650a3 --- /dev/null +++ b/libweston/perfetto/annotations.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2026 Amazon.com, Inc. or its affiliates + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +#include "perfetto/annotations.h" +#include "weston-trace.h" + +WL_EXPORT int +perfetto_annotate_int(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + int value) +{ + annots[count].type = WESTON_DEBUG_ANNOTATION_INT_VAL; + annots[count].ivalue = value; + annots[count].key = key; + + return 1; +} + +WL_EXPORT int +perfetto_annotate_float(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + float value) +{ + annots[count].type = WESTON_DEBUG_ANNOTATION_FLOAT_VAL; + annots[count].fvalue = value; + annots[count].key = key; + + return 1; +} + +WL_EXPORT int +perfetto_annotate_string(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + const char *value) +{ + annots[count].type = WESTON_DEBUG_ANNOTATION_STR_VAL; + annots[count].svalue = value; + annots[count].key = key; + + return 1; +} diff --git a/libweston/perfetto/annotations.h b/libweston/perfetto/annotations.h new file mode 100644 index 000000000..17a90db4b --- /dev/null +++ b/libweston/perfetto/annotations.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2026 Amazon.com, Inc. or its affiliates + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include + +#include "perfetto/u_perfetto.h" + +int +perfetto_annotate_int(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + int value); + +int +perfetto_annotate_float(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + float value); + +int +perfetto_annotate_string(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + const char *value); diff --git a/libweston/perfetto/u_perfetto.cc b/libweston/perfetto/u_perfetto.cc index 40800c2d2..6a472dcc4 100644 --- a/libweston/perfetto/u_perfetto.cc +++ b/libweston/perfetto/u_perfetto.cc @@ -227,45 +227,6 @@ util_perfetto_trace_commit_annotate_func_flow(uint64_t id, const char *name, }); } -int -perfetto_annotate_int(struct weston_debug_annotation *annots, - unsigned int count, - const char *key, - int value) -{ - annots[count].type = WESTON_DEBUG_ANNOTATION_INT_VAL; - annots[count].ivalue = value; - annots[count].key = key; - - return 1; -} - -int -perfetto_annotate_float(struct weston_debug_annotation *annots, - unsigned int count, - const char *key, - float value) -{ - annots[count].type = WESTON_DEBUG_ANNOTATION_FLOAT_VAL; - annots[count].fvalue = value; - annots[count].key = key; - - return 1; -} - -int -perfetto_annotate_string(struct weston_debug_annotation *annots, - unsigned int count, - const char *key, - const char *value) -{ - annots[count].type = WESTON_DEBUG_ANNOTATION_STR_VAL; - annots[count].svalue = value; - annots[count].key = key; - - return 1; -} - class UtilPerfettoObserver : public perfetto::TrackEventSessionObserver { public: UtilPerfettoObserver() { perfetto::TrackEvent::AddSessionObserver(this); } diff --git a/libweston/perfetto/u_perfetto.h b/libweston/perfetto/u_perfetto.h index 00570f615..4c84b7250 100644 --- a/libweston/perfetto/u_perfetto.h +++ b/libweston/perfetto/u_perfetto.h @@ -92,24 +92,6 @@ uint64_t util_perfetto_next_id(void); uint64_t util_perfetto_new_track(const char *name); -int -perfetto_annotate_int(struct weston_debug_annotation *annots, - unsigned int count, - const char *key, - int value); - -int -perfetto_annotate_float(struct weston_debug_annotation *annots, - unsigned int count, - const char *key, - float value); - -int -perfetto_annotate_string(struct weston_debug_annotation *annots, - unsigned int count, - const char *key, - const char *value); - #else /* HAVE_PERFETTO */ static inline void diff --git a/libweston/weston-trace.h b/libweston/weston-trace.h index 9d4b55979..b8b4f582a 100644 --- a/libweston/weston-trace.h +++ b/libweston/weston-trace.h @@ -10,6 +10,7 @@ #ifndef WESTON_TRACE_H #define WESTON_TRACE_H +#include "perfetto/annotations.h" #include "perfetto/u_perfetto.h" #include From 0d86cd5ce5f7955199baf52f840417629457acba Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Tue, 5 May 2026 15:08:35 -0500 Subject: [PATCH 05/10] trace: Move assertions into individual annotation functions The int, string, and float annotators will become our atoms when we start logging larger structs. The functions for complex annotations will call these many times for a single annotation. So we should assert in the int, string, and float annotators before adding there, so the big functions are implicitly checked. Signed-off-by: Derek Foreman --- libweston/perfetto/annotations.c | 8 ++++++++ libweston/weston-trace.h | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/libweston/perfetto/annotations.c b/libweston/perfetto/annotations.c index 7cee650a3..f383a699f 100644 --- a/libweston/perfetto/annotations.c +++ b/libweston/perfetto/annotations.c @@ -23,9 +23,11 @@ * SOFTWARE. */ +#include "config.h" #include #include "perfetto/annotations.h" +#include "shared/weston-assert.h" #include "weston-trace.h" WL_EXPORT int @@ -34,6 +36,8 @@ perfetto_annotate_int(struct weston_debug_annotation *annots, const char *key, int value) { + weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, count); + annots[count].type = WESTON_DEBUG_ANNOTATION_INT_VAL; annots[count].ivalue = value; annots[count].key = key; @@ -47,6 +51,8 @@ perfetto_annotate_float(struct weston_debug_annotation *annots, const char *key, float value) { + weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, count); + annots[count].type = WESTON_DEBUG_ANNOTATION_FLOAT_VAL; annots[count].fvalue = value; annots[count].key = key; @@ -60,6 +66,8 @@ perfetto_annotate_string(struct weston_debug_annotation *annots, const char *key, const char *value) { + weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, count); + annots[count].type = WESTON_DEBUG_ANNOTATION_STR_VAL; annots[count].svalue = value; annots[count].key = key; diff --git a/libweston/weston-trace.h b/libweston/weston-trace.h index b8b4f582a..f19eae457 100644 --- a/libweston/weston-trace.h +++ b/libweston/weston-trace.h @@ -79,7 +79,6 @@ unsigned int __pd_i = 0 #define _WESTON_TRACE_DO_ANNOTATE_ADD(k, v) \ - weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, __pd_i); \ __pd_i += _Generic((v), \ int: perfetto_annotate_int, \ unsigned int: perfetto_annotate_int, \ From 924f0d2f16a67e7ef83966ab71501b1e73895d8a Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Tue, 5 May 2026 16:49:05 -0500 Subject: [PATCH 06/10] trace: Only add to annotation array if we're tracing Saves some effort when we're not tracing - but if we start tracing in the middle of creating an annotation it could be missing a couple of fields. Signed-off-by: Derek Foreman --- libweston/weston-trace.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/libweston/weston-trace.h b/libweston/weston-trace.h index f19eae457..cf416f2df 100644 --- a/libweston/weston-trace.h +++ b/libweston/weston-trace.h @@ -78,14 +78,16 @@ struct weston_debug_annotation __pd_annots[WESTON_MAX_DEBUG_ANNOTS]; \ unsigned int __pd_i = 0 -#define _WESTON_TRACE_DO_ANNOTATE_ADD(k, v) \ - __pd_i += _Generic((v), \ - int: perfetto_annotate_int, \ - unsigned int: perfetto_annotate_int, \ - float: perfetto_annotate_float, \ - char *: perfetto_annotate_string, \ - const char *: perfetto_annotate_string \ - ) (__pd_annots, __pd_i, k, v); +#define _WESTON_TRACE_DO_ANNOTATE_ADD(k, v) \ + if (unlikely(util_perfetto_is_tracing_enabled())) { \ + __pd_i += _Generic((v), \ + int: perfetto_annotate_int, \ + unsigned int: perfetto_annotate_int, \ + float: perfetto_annotate_float, \ + char *: perfetto_annotate_string, \ + const char *: perfetto_annotate_string \ + ) (__pd_annots, __pd_i, k, v); \ + } #define _WESTON_TRACE_COMMIT_ANNOTATION(id, name) \ do { \ From b8bd3c7c8bded595b683440e0a8cb230b36e406a Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Tue, 5 May 2026 16:50:55 -0500 Subject: [PATCH 07/10] trace: Add a max size for the key Not sure we'll ever hit this, but since we're concatenating strings into a static sized buffer I suppose it's useful to ensure it won't have an unreadable result. Signed-off-by: Derek Foreman --- libweston/weston-trace.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libweston/weston-trace.h b/libweston/weston-trace.h index cf416f2df..db0b72512 100644 --- a/libweston/weston-trace.h +++ b/libweston/weston-trace.h @@ -33,6 +33,9 @@ /* maximum allowed debug annotations */ #define WESTON_MAX_DEBUG_ANNOTS 128 +/* maximum key length */ +#define WESTON_TRACE_MAX_KEY_LENGTH 30 + /* note that util_perfetto_is_tracing_enabled always returns false until * util_perfetto_init is called */ @@ -80,6 +83,7 @@ #define _WESTON_TRACE_DO_ANNOTATE_ADD(k, v) \ if (unlikely(util_perfetto_is_tracing_enabled())) { \ + static_assert(sizeof(k) < WESTON_TRACE_MAX_KEY_LENGTH); \ __pd_i += _Generic((v), \ int: perfetto_annotate_int, \ unsigned int: perfetto_annotate_int, \ From 84891c9e2f11e04b3109ba6ff8d03ca31f281ed4 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Tue, 5 May 2026 16:47:21 -0500 Subject: [PATCH 08/10] trace: Add namespaces to keys and use it for weston_buffer We now track the size of the key string, as well as allow adding empty "container" annotations that are just a name for nested storage. When parents are present, the full key name is created by walking them and prepending them to a string backwards. Use this to implement a buffer annotation helper and use it in the one place we're already logging a buffer. Signed-off-by: Derek Foreman --- libweston/perfetto/annotations.c | 111 ++++++++++++++++++++++++++++--- libweston/perfetto/annotations.h | 10 +++ libweston/perfetto/u_perfetto.cc | 54 ++++++++++++++- libweston/perfetto/u_perfetto.h | 3 + libweston/surface-state.c | 9 +-- libweston/weston-trace.h | 6 +- 6 files changed, 172 insertions(+), 21 deletions(-) diff --git a/libweston/perfetto/annotations.c b/libweston/perfetto/annotations.c index f383a699f..8eccf79f8 100644 --- a/libweston/perfetto/annotations.c +++ b/libweston/perfetto/annotations.c @@ -26,21 +26,55 @@ #include "config.h" #include +#include "libweston/pixel-formats.h" #include "perfetto/annotations.h" #include "shared/weston-assert.h" #include "weston-trace.h" -WL_EXPORT int -perfetto_annotate_int(struct weston_debug_annotation *annots, - unsigned int count, - const char *key, - int value) + +static int +do_perfetto_annotate_int(struct weston_debug_annotation *annots, + unsigned int count, + unsigned int parent, + const char *key, + unsigned int key_size, + int value) { weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, count); annots[count].type = WESTON_DEBUG_ANNOTATION_INT_VAL; annots[count].ivalue = value; + annots[count].parent = parent; annots[count].key = key; + annots[count].key_size = key_size; + return 1; +} + +WL_EXPORT int +perfetto_annotate_int(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + unsigned int key_size, + int value) +{ + return do_perfetto_annotate_int(annots, count, count, key, key_size, value); +} + +static int +do_perfetto_annotate_float(struct weston_debug_annotation *annots, + unsigned int count, + unsigned int parent, + const char *key, + unsigned int key_size, + float value) +{ + weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, count); + + annots[count].type = WESTON_DEBUG_ANNOTATION_FLOAT_VAL; + annots[count].fvalue = value; + annots[count].parent = parent; + annots[count].key = key; + annots[count].key_size = key_size; return 1; } @@ -49,13 +83,27 @@ WL_EXPORT int perfetto_annotate_float(struct weston_debug_annotation *annots, unsigned int count, const char *key, + unsigned int key_size, float value) +{ + return do_perfetto_annotate_float(annots, count, count, key, key_size, value); +} + +static int +do_perfetto_annotate_string(struct weston_debug_annotation *annots, + unsigned int count, + unsigned int parent, + const char *key, + unsigned int key_size, + const char *value) { weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, count); - annots[count].type = WESTON_DEBUG_ANNOTATION_FLOAT_VAL; - annots[count].fvalue = value; + annots[count].type = WESTON_DEBUG_ANNOTATION_STR_VAL; + annots[count].svalue = value; + annots[count].parent = parent; annots[count].key = key; + annots[count].key_size = key_size; return 1; } @@ -64,13 +112,58 @@ WL_EXPORT int perfetto_annotate_string(struct weston_debug_annotation *annots, unsigned int count, const char *key, + unsigned int key_size, const char *value) +{ + return do_perfetto_annotate_string(annots, count, count, key, key_size, value); +} + +static int +perfetto_annotate_container(struct weston_debug_annotation *annots, + unsigned int count, + unsigned int parent, + const char *key, + unsigned int key_size) { weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, count); - annots[count].type = WESTON_DEBUG_ANNOTATION_STR_VAL; - annots[count].svalue = value; + annots[count].type = WESTON_DEBUG_ANNOTATION_CONTAINER; annots[count].key = key; + annots[count].key_size = key_size; + annots[count].parent = parent; return 1; } + +/* Helper macros for the complex annotations */ +#define ADD_STRING(parent, key, value) \ + do_perfetto_annotate_string(annots, count + new_items, parent, key, sizeof(key), value) + +#define ADD_INT(parent, key, value) \ + do_perfetto_annotate_int(annots, count + new_items, parent, key, sizeof(key), value) + +#define ADD_FLOAT(parent, key, value) \ + do_perfetto_annotate_float(annots, count + new_items, parent, key, sizeof(key), value) + +WL_EXPORT int +perfetto_annotate_buffer(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + unsigned int key_size, + const struct weston_buffer *buffer) +{ + int new_items = 0; + int parent = count; + + if (!buffer) + return perfetto_annotate_string(annots, count, key, key_size, "None"); + + new_items += perfetto_annotate_container(annots, count, count, key, key_size); + + new_items += ADD_STRING(parent, "format", buffer->pixel_format->drm_format_name); + new_items += ADD_STRING(parent, "modifier", buffer->format_modifier_name); + new_items += ADD_INT(parent, "width", buffer->width); + new_items += ADD_INT(parent, "height", buffer->height); + + return new_items; +} diff --git a/libweston/perfetto/annotations.h b/libweston/perfetto/annotations.h index 17a90db4b..aaa64e1e0 100644 --- a/libweston/perfetto/annotations.h +++ b/libweston/perfetto/annotations.h @@ -33,16 +33,26 @@ int perfetto_annotate_int(struct weston_debug_annotation *annots, unsigned int count, const char *key, + unsigned int key_size, int value); int perfetto_annotate_float(struct weston_debug_annotation *annots, unsigned int count, const char *key, + unsigned int key_size, float value); int perfetto_annotate_string(struct weston_debug_annotation *annots, unsigned int count, const char *key, + unsigned int key_size, const char *value); + +int +perfetto_annotate_buffer(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + unsigned int key_size, + const struct weston_buffer *buffer); diff --git a/libweston/perfetto/u_perfetto.cc b/libweston/perfetto/u_perfetto.cc index 6a472dcc4..168060e4d 100644 --- a/libweston/perfetto/u_perfetto.cc +++ b/libweston/perfetto/u_perfetto.cc @@ -151,6 +151,29 @@ util_perfetto_next_id(void) return p_atomic_inc_return(&util_perfetto_unique_id); } +static char * +build_key(char *space, size_t size, struct weston_debug_annotation *annots, unsigned int idx) +{ + char *cur = space + size; + + cur -= annots[idx].key_size; + memcpy(cur, annots[idx].key, annots[idx].key_size); + + do { + idx = annots[idx].parent; + + if (space + 2 + annots[idx].key_size - 1 >= cur) + return NULL; + + *(--cur) = ':'; + *(--cur) = ':'; + cur -= annots[idx].key_size - 1; + memcpy(cur, annots[idx].key, annots[idx].key_size - 1); + } while (idx != annots[idx].parent); + + return cur; +} + static void util_perfetto_flush_debug_annotation(perfetto::EventContext *ctx, unsigned int nr_entries, @@ -160,15 +183,40 @@ util_perfetto_flush_debug_annotation(perfetto::EventContext *ctx, return; for (unsigned int idx = 0; idx < nr_entries; idx++) { + const char *key = annots[idx].key; + char keyspace[400]; + bool use_built_key; + + if (annots[idx].type == WESTON_DEBUG_ANNOTATION_CONTAINER) + continue; + + use_built_key = false; + if (annots[idx].parent != idx) { + key = build_key(keyspace, sizeof(keyspace), annots, idx); + if (!key) + continue; + + use_built_key = true; + } + switch (annots[idx].type) { case WESTON_DEBUG_ANNOTATION_INT_VAL: - ctx->AddDebugAnnotation(annots[idx].key, annots[idx].ivalue); + if (use_built_key) + ctx->AddDebugAnnotation(perfetto::DynamicString(key), annots[idx].ivalue); + else + ctx->AddDebugAnnotation(key, annots[idx].ivalue); break; case WESTON_DEBUG_ANNOTATION_FLOAT_VAL: - ctx->AddDebugAnnotation(annots[idx].key, annots[idx].fvalue); + if (use_built_key) + ctx->AddDebugAnnotation(perfetto::DynamicString(key), annots[idx].fvalue); + else + ctx->AddDebugAnnotation(key, annots[idx].fvalue); break; case WESTON_DEBUG_ANNOTATION_STR_VAL: - ctx->AddDebugAnnotation(annots[idx].key, annots[idx].svalue); + if (use_built_key) + ctx->AddDebugAnnotation(perfetto::DynamicString(key), annots[idx].svalue); + else + ctx->AddDebugAnnotation(key, annots[idx].svalue); break; default: break; diff --git a/libweston/perfetto/u_perfetto.h b/libweston/perfetto/u_perfetto.h index 4c84b7250..1ac50124b 100644 --- a/libweston/perfetto/u_perfetto.h +++ b/libweston/perfetto/u_perfetto.h @@ -43,16 +43,19 @@ enum weston_debug_annotation_type { WESTON_DEBUG_ANNOTATION_INT_VAL, WESTON_DEBUG_ANNOTATION_FLOAT_VAL, WESTON_DEBUG_ANNOTATION_STR_VAL, + WESTON_DEBUG_ANNOTATION_CONTAINER, }; struct weston_debug_annotation { const char *key; + size_t key_size; enum weston_debug_annotation_type type; union { int ivalue; float fvalue; const char *svalue; }; + unsigned int parent; }; #ifdef HAVE_PERFETTO diff --git a/libweston/surface-state.c b/libweston/surface-state.c index c1dc3ac29..3e8765841 100644 --- a/libweston/surface-state.c +++ b/libweston/surface-state.c @@ -205,13 +205,8 @@ weston_surface_attach(struct weston_surface *surface, enum weston_paint_node_status pnode_changes = WESTON_PAINT_NODE_CLEAN; WESTON_TRACE_BEGIN_ANNOTATION(); - if (buffer) { - WESTON_TRACE_ANNOTATE(("surface", surface->internal_name), - ("format", buffer->pixel_format->drm_format_name), - ("modifier", buffer->format_modifier_name), - ("width", buffer->width), - ("height", buffer->height)); - } + WESTON_TRACE_ANNOTATE(("surface", surface->internal_name), + ("new buffer", buffer)); WESTON_TRACE_ANNOTATE_FUNC_FLOW(&surface->flow_id); if (!buffer) { diff --git a/libweston/weston-trace.h b/libweston/weston-trace.h index db0b72512..031cb8327 100644 --- a/libweston/weston-trace.h +++ b/libweston/weston-trace.h @@ -89,8 +89,10 @@ unsigned int: perfetto_annotate_int, \ float: perfetto_annotate_float, \ char *: perfetto_annotate_string, \ - const char *: perfetto_annotate_string \ - ) (__pd_annots, __pd_i, k, v); \ + const char *: perfetto_annotate_string, \ + struct weston_buffer *: perfetto_annotate_buffer, \ + const struct weston_buffer *: perfetto_annotate_buffer \ + ) (__pd_annots, __pd_i, k, sizeof(k), v); \ } #define _WESTON_TRACE_COMMIT_ANNOTATION(id, name) \ From a92dd64159f50b316b510abca910bf8aa6d83e87 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Tue, 5 May 2026 21:27:36 -0500 Subject: [PATCH 09/10] trace: Add annotations for solid buffers Added as an example of adding another layer of nesting, to show the entry point for the Generic (which has no parent), and a helper function for nesting inside another structure. Signed-off-by: Derek Foreman --- libweston/perfetto/annotations.c | 36 ++++++++++++++++++++++++++++++++ libweston/perfetto/annotations.h | 7 +++++++ 2 files changed, 43 insertions(+) diff --git a/libweston/perfetto/annotations.c b/libweston/perfetto/annotations.c index 8eccf79f8..f4daeac9b 100644 --- a/libweston/perfetto/annotations.c +++ b/libweston/perfetto/annotations.c @@ -145,6 +145,39 @@ perfetto_annotate_container(struct weston_debug_annotation *annots, #define ADD_FLOAT(parent, key, value) \ do_perfetto_annotate_float(annots, count + new_items, parent, key, sizeof(key), value) +static int +do_perfetto_annotate_solid_buffer_values(struct weston_debug_annotation *annots, + unsigned int count, + unsigned int parent, + const char *key, + unsigned int key_size, + const struct weston_solid_buffer_values *values) +{ + int new_items = 0; + + new_items += perfetto_annotate_container(annots, count, parent, key, key_size); + + new_items += ADD_FLOAT(count, "red", values->r); + new_items += ADD_FLOAT(count, "green", values->g); + new_items += ADD_FLOAT(count, "blue", values->b); + new_items += ADD_FLOAT(count, "alpha", values->a); + + return new_items; +} + +WL_EXPORT int +perfetto_annotate_solid_buffer_values(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + unsigned int key_size, + const struct weston_solid_buffer_values *values) +{ + return do_perfetto_annotate_solid_buffer_values(annots, count, count, key, key_size, values); +} + +#define ADD_SOLID_VALUES(parent, key, value) \ + do_perfetto_annotate_solid_buffer_values(annots, count + new_items, parent, key, sizeof(key), value) + WL_EXPORT int perfetto_annotate_buffer(struct weston_debug_annotation *annots, unsigned int count, @@ -165,5 +198,8 @@ perfetto_annotate_buffer(struct weston_debug_annotation *annots, new_items += ADD_INT(parent, "width", buffer->width); new_items += ADD_INT(parent, "height", buffer->height); + if (buffer->type == WESTON_BUFFER_SOLID) + new_items += ADD_SOLID_VALUES(parent, "solid", &buffer->solid); + return new_items; } diff --git a/libweston/perfetto/annotations.h b/libweston/perfetto/annotations.h index aaa64e1e0..9eeb1c831 100644 --- a/libweston/perfetto/annotations.h +++ b/libweston/perfetto/annotations.h @@ -56,3 +56,10 @@ perfetto_annotate_buffer(struct weston_debug_annotation *annots, const char *key, unsigned int key_size, const struct weston_buffer *buffer); + +int +perfetto_annotate_solid_buffer_values(struct weston_debug_annotation *annots, + unsigned int count, + const char *key, + unsigned int key_size, + const struct weston_solid_buffer_values *values); From c662f9239ac1771e13d06d7c48c6531e6fa0889b Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Wed, 6 May 2026 08:36:57 -0500 Subject: [PATCH 10/10] trace: Have a single macro for a flowed func with annotations Make a WESTON_TRACE_ANNOTATE_FUNC_FLOW that does the preamble, adds the annotations, and flushes it out in a single "statement". Signed-off-by: Derek Foreman --- libweston/surface-state.c | 7 +++---- libweston/weston-trace.h | 4 +++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libweston/surface-state.c b/libweston/surface-state.c index 3e8765841..633497617 100644 --- a/libweston/surface-state.c +++ b/libweston/surface-state.c @@ -204,10 +204,9 @@ weston_surface_attach(struct weston_surface *surface, struct weston_buffer *old_buffer = surface->buffer_ref.buffer; enum weston_paint_node_status pnode_changes = WESTON_PAINT_NODE_CLEAN; - WESTON_TRACE_BEGIN_ANNOTATION(); - WESTON_TRACE_ANNOTATE(("surface", surface->internal_name), - ("new buffer", buffer)); - WESTON_TRACE_ANNOTATE_FUNC_FLOW(&surface->flow_id); + WESTON_TRACE_ANNOTATE_FUNC_FLOW(&surface->flow_id, + ("surface", surface->internal_name), + ("new buffer", buffer)); if (!buffer) { if (weston_surface_is_mapped(surface)) { diff --git a/libweston/weston-trace.h b/libweston/weston-trace.h index 031cb8327..9e1346920 100644 --- a/libweston/weston-trace.h +++ b/libweston/weston-trace.h @@ -265,7 +265,9 @@ _weston_trace_scope_end(int *scope) #define WESTON_TRACE_ANNOTATE_FUNC() \ _WESTON_TRACE_ANNOTATE_FUNC(__func__) -#define WESTON_TRACE_ANNOTATE_FUNC_FLOW(id) \ +#define WESTON_TRACE_ANNOTATE_FUNC_FLOW(id, ...) \ + _WESTON_TRACE_BEGIN_ANNOTATION(); \ + WESTON_TRACE_ANNOTATE(__VA_ARGS__) \ _WESTON_TRACE_ANNOTATE_FUNC_FLOW(id, __func__) #define FORCE_RECURSE ()