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..f4daeac9b --- /dev/null +++ b/libweston/perfetto/annotations.c @@ -0,0 +1,205 @@ +/* + * 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 "config.h" +#include + +#include "libweston/pixel-formats.h" +#include "perfetto/annotations.h" +#include "shared/weston-assert.h" +#include "weston-trace.h" + + +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; +} + +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_STR_VAL; + annots[count].svalue = value; + annots[count].parent = parent; + annots[count].key = key; + annots[count].key_size = key_size; + + return 1; +} + +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_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) + +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, + 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); + + 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 new file mode 100644 index 000000000..9eeb1c831 --- /dev/null +++ b/libweston/perfetto/annotations.h @@ -0,0 +1,65 @@ +/* + * 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, + 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); + +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); diff --git a/libweston/perfetto/u_perfetto.cc b/libweston/perfetto/u_perfetto.cc index b7a96fd2a..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; @@ -227,7 +275,6 @@ util_perfetto_trace_commit_annotate_func_flow(uint64_t id, const char *name, }); } - 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 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/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..633497617 100644 --- a/libweston/surface-state.c +++ b/libweston/surface-state.c @@ -204,15 +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(); - 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_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 b2ba55492..9e1346920 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 @@ -32,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 */ @@ -77,26 +81,19 @@ struct weston_debug_annotation __pd_annots[WESTON_MAX_DEBUG_ANNOTS]; \ unsigned int __pd_i = 0 -#define _WESTON_TRACE_ANNOTATE_ADD_INT(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++ +#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, \ + float: perfetto_annotate_float, \ + char *: perfetto_annotate_string, \ + 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) \ do { \ @@ -240,9 +237,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_DO_ANNOTATE_ADD(k, v) #define _WESTON_TRACE_ANNOTATE_FUNC() #define _WESTON_TRACE_ANNOTATE_FUNC_FLOW(id, name) @@ -261,14 +256,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_DO_ANNOTATE_ADD(k, v) \ + _WESTON_TRACE_DO_ANNOTATE_ADD(k, v) #define WESTON_TRACE_COMMIT_ANNOTATION(id) \ _WESTON_TRACE_COMMIT_ANNOTATION(id, __func__) @@ -276,7 +265,26 @@ _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 () +#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 */