From a276db50f8ada5da268671a97fd4999f57becd72 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Thu, 14 May 2026 11:20:03 +0300 Subject: [PATCH] input: Add support for tracking input events on egress side This includes an additional _double variant for _Generics and a bool one. Similarly, _WESTON_TRACE_ANNOTATE_FUNC_FLOW gets a _Generics macro variant to handle the case were we have a integer flow ID, rather than an a pointer. Finally we always have a flow ID set when weston_input_event gets initalized. Signed-off-by: Marius Vlad --- libweston/input.c | 149 +++++++++++++++++++++++++++---- libweston/perfetto/annotations.c | 51 +++++++++++ libweston/perfetto/annotations.h | 11 +++ libweston/perfetto/u_perfetto.cc | 6 ++ libweston/perfetto/u_perfetto.h | 8 +- libweston/weston-trace.h | 27 ++++-- 6 files changed, 227 insertions(+), 25 deletions(-) diff --git a/libweston/input.c b/libweston/input.c index 951a4c558..265dd0834 100644 --- a/libweston/input.c +++ b/libweston/input.c @@ -53,6 +53,7 @@ #include "input-timestamps-unstable-v1-server-protocol.h" #include "tablet-unstable-v2-server-protocol.h" #include "timeline.h" +#include "weston-trace.h" enum pointer_constraint_type { POINTER_CONSTRAINT_TYPE_LOCK, @@ -565,13 +566,34 @@ pointer_send_relative_motion(struct weston_pointer *pointer, struct wl_list *resource_list; struct wl_resource *resource; - if (!pointer->focus_client) + if (!pointer->focus_client) { + WESTON_TRACE_ANNOTATE_FUNC_FLOW(event->base.flow_id, + ("discard relative pointer motion", + "missing focus client"), + ("internal_name", pointer->focus->internal_name), + ("label", pointer->focus->surface->label), + ("pointer sx", pointer->sx), + ("pointer sy", pointer->sy)); return; + } - if (!weston_pointer_motion_to_rel(pointer, event, - &rel, - &rel_unaccel)) + if (!weston_pointer_motion_to_rel(pointer, event, &rel, &rel_unaccel)) { + WESTON_TRACE_ANNOTATE_FUNC_FLOW(event->base.flow_id, + ("discard relative pointer motion", + "invalid relative data"), + ("internal_name", pointer->focus->internal_name), + ("label", pointer->focus->surface->label), + ("pointer sx", pointer->sx), + ("pointer sy", pointer->sy)); return; + } + + WESTON_TRACE_ANNOTATE_FUNC_FLOW(event->base.flow_id, + ("send", "relative pointer motion"), + ("internal_name", pointer->focus->internal_name), + ("label", pointer->focus->surface->label), + ("pointer sx", pointer->sx), + ("pointer sy", pointer->sy)); resource_list = &pointer->focus_client->relative_pointer_resources; time_usec = timespec_to_usec(&event->base.ts); @@ -589,9 +611,8 @@ pointer_send_relative_motion(struct weston_pointer *pointer, } static void -pointer_send_motion(struct weston_pointer *pointer, - const struct timespec *ts, - wl_fixed_t sx, wl_fixed_t sy) +pointer_send_motion(struct weston_pointer *pointer, wl_fixed_t sx, wl_fixed_t sy, + const struct weston_pointer_motion_event *event) { struct wl_list *resource_list; struct wl_resource *resource; @@ -600,12 +621,19 @@ pointer_send_motion(struct weston_pointer *pointer, if (!pointer->focus_client) return; + WESTON_TRACE_ANNOTATE_FUNC_FLOW(event->base.flow_id, + ("send", "relative pointer motion"), + ("internal_name", pointer->focus->internal_name), + ("label", pointer->focus->surface->label), + ("pointer sx", sx), + ("pointer sy", sy)); + resource_list = &pointer->focus_client->pointer_resources; - msecs = timespec_to_msec(ts); + msecs = timespec_to_msec(&event->base.ts); wl_resource_for_each(resource, resource_list) { send_timestamps_for_input_resource(resource, &pointer->timestamps_list, - ts); + &event->base.ts); wl_pointer_send_motion(resource, msecs, sx, sy); } } @@ -614,6 +642,8 @@ WL_EXPORT void weston_pointer_send_motion(struct weston_pointer *pointer, const struct weston_pointer_motion_event *event) { + WESTON_TRACE_FUNC_FLOW(&event->base.flow_id); + wl_fixed_t old_sx; wl_fixed_t old_sy; struct weston_view *old_focus = pointer->focus; @@ -640,7 +670,7 @@ weston_pointer_send_motion(struct weston_pointer *pointer, if (pointer->focus && old_focus == pointer->focus && (old_sx != pointer->sx || old_sy != pointer->sy)) { - pointer_send_motion(pointer, &event->base.ts, pointer->sx, pointer->sy); + pointer_send_motion(pointer, pointer->sx, pointer->sy, event); } pointer_send_relative_motion(pointer, event); @@ -692,8 +722,20 @@ weston_pointer_send_button(struct weston_pointer *pointer, uint32_t button = button_event->button; enum wl_pointer_button_state state = button_event->button_state; - if (!weston_pointer_has_focus_resource(pointer)) + if (!weston_pointer_has_focus_resource(pointer)) { + WESTON_TRACE_ANNOTATE_FUNC_FLOW(button_event->base.flow_id, + ("discard button", "missing focus resource"), + ("state", button_event->button_state), + ("button", button_event->button)); return; + } + + WESTON_TRACE_ANNOTATE_FUNC_FLOW(button_event->base.flow_id, + ("send", "button"), + ("internal_name", pointer->focus->internal_name), + ("label", pointer->focus->surface->label), + ("state", button_event->button_state), + ("button", button_event->button)); resource_list = &pointer->focus_client->pointer_resources; serial = wl_display_next_serial(display); @@ -743,8 +785,24 @@ weston_pointer_send_axis(struct weston_pointer *pointer, struct wl_list *resource_list; uint32_t msecs; - if (!weston_pointer_has_focus_resource(pointer)) + if (!weston_pointer_has_focus_resource(pointer)) { + WESTON_TRACE_ANNOTATE_FUNC_FLOW(event->base.flow_id, + ("discard axis", "missing focus resource"), + ("axis", event->axis), + ("value", event->value), + ("has_discrete", event->has_discrete), + ("discrete", event->discrete)); return; + } + + WESTON_TRACE_ANNOTATE_FUNC_FLOW(event->base.flow_id, + ("send", "axis"), + ("internal_name", pointer->focus->internal_name), + ("label", pointer->focus->surface->label), + ("axis", event->axis), + ("value", event->value), + ("has_discrete", event->has_discrete), + ("discrete", event->discrete)); resource_list = &pointer->focus_client->pointer_resources; msecs = timespec_to_msec(&event->base.ts); @@ -904,12 +962,28 @@ weston_touch_send_down(const struct weston_touch_event *event) struct weston_coord_surface surf_pos; uint32_t msecs; - if (!weston_touch_has_focus_resource(touch)) + if (!weston_touch_has_focus_resource(touch)) { + WESTON_TRACE_ANNOTATE_FUNC_FLOW(event->base.flow_id, + ("discard touch down", "missing focus resource"), + ("touch pos x", event->pos.c.x), + ("touch pos y", event->pos.c.y), + ("touch id", event->touch_id)); return; + } surf_pos = weston_coord_global_to_surface(touch->focus, event->pos); weston_view_update_transform(touch->focus); + WESTON_TRACE_ANNOTATE_FUNC_FLOW(event->base.flow_id, + ("send", "touch down"), + ("internal_name", touch->focus->internal_name), + ("label", touch->focus->surface->label), + ("touch pos x", event->pos.c.x), + ("touch pos y", event->pos.c.y), + ("surface pos x", surf_pos.c.x), + ("surface pos y", surf_pos.c.y), + ("touch id", event->touch_id)); + resource_list = &touch->focus_resource_list; serial = wl_display_next_serial(display); msecs = timespec_to_msec(&event->base.ts); @@ -949,8 +1023,18 @@ weston_touch_send_up(const struct weston_touch_event *event) struct wl_list *resource_list; uint32_t msecs; - if (!weston_touch_has_focus_resource(touch)) + if (!weston_touch_has_focus_resource(touch)) { + WESTON_TRACE_ANNOTATE_FUNC_FLOW(event->base.flow_id, + ("discard touch up", "missing focus resource"), + ("touch id", event->touch_id)); return; + } + + WESTON_TRACE_ANNOTATE_FUNC_FLOW(event->base.flow_id, + ("send", "touch up"), + ("internal_name", touch->focus->internal_name), + ("label", touch->focus->surface->label), + ("touch id", event->touch_id)); resource_list = &touch->focus_resource_list; serial = wl_display_next_serial(display); @@ -986,12 +1070,26 @@ weston_touch_send_motion(const struct weston_touch_event *event) struct weston_coord_surface surf_pos; struct weston_touch *touch = event->base.seat->touch_state; - if (!weston_touch_has_focus_resource(touch)) + if (!weston_touch_has_focus_resource(touch)) { + WESTON_TRACE_ANNOTATE_FUNC_FLOW(event->base.flow_id, + ("discard touch motion", "missing focus resource"), + ("touch pos x", event->pos.c.x), + ("touch pos y", event->pos.c.y), + ("touch id", event->touch_id)); return; + } surf_pos = weston_coord_global_to_surface(touch->focus, event->pos); weston_view_update_transform(touch->focus); + WESTON_TRACE_ANNOTATE_FUNC_FLOW(event->base.flow_id, + ("send", "touch motion"), + ("internal_name", touch->focus->internal_name), + ("label", touch->focus->surface->label), + ("touch pos x", event->pos.c.x), + ("touch pos y", event->pos.c.y), + ("touch id", event->touch_id)); + resource_list = &touch->focus_resource_list; msecs = timespec_to_msec(&event->base.ts); wl_resource_for_each(resource, resource_list) { @@ -1089,12 +1187,27 @@ weston_keyboard_send_key(struct weston_keyboard *keyboard, uint32_t key = key_event->key; enum wl_keyboard_key_state state = key_event->key_state; - if (!weston_keyboard_has_focus_resource(keyboard)) + if (!weston_keyboard_has_focus_resource(keyboard)) { + WESTON_TRACE_ANNOTATE_FUNC_FLOW(key_event->base.flow_id, + ("discard send key", "missing touch resource"), + ("key", key), + ("state", state), + ("update state", key_event->key_update_state)); return; + } resource_list = &keyboard->focus_resource_list; serial = wl_display_next_serial(display); msecs = timespec_to_msec(&time); + + WESTON_TRACE_ANNOTATE_FUNC_FLOW(key_event->base.flow_id, + ("send", "key"), + ("internal_name", keyboard->focus->internal_name), + ("label", keyboard->focus->label), + ("key", key), + ("state", state), + ("update state", key_event->key_update_state)); + wl_resource_for_each(resource, resource_list) { send_timestamps_for_input_resource(resource, &keyboard->timestamps_list, @@ -5650,6 +5763,8 @@ static void confined_pointer_grab_pointer_motion(struct weston_pointer_grab *grab, const struct weston_pointer_motion_event *event) { + WESTON_TRACE_FUNC_FLOW(&event->base.flow_id); + struct weston_pointer_constraint *constraint = container_of(grab, struct weston_pointer_constraint, grab); struct weston_pointer *pointer = grab->pointer; @@ -5679,7 +5794,7 @@ confined_pointer_grab_pointer_motion(struct weston_pointer_grab *grab, pointer->sy = wl_fixed_from_double(surf_pos.c.y); if (old_sx != pointer->sx || old_sy != pointer->sy) { - pointer_send_motion(pointer, &event->base.ts, pointer->sx, pointer->sy); + pointer_send_motion(pointer, pointer->sx, pointer->sy, event); } pointer_send_relative_motion(pointer, event); diff --git a/libweston/perfetto/annotations.c b/libweston/perfetto/annotations.c index 818800be1..6c2d28241 100644 --- a/libweston/perfetto/annotations.c +++ b/libweston/perfetto/annotations.c @@ -73,6 +73,33 @@ perfetto_annotate_int(struct weston_debug_annotations *annots, do_annotate_int(annots, annots->count, key, key_size, value); } +static void +do_annotate_bool(struct weston_debug_annotations *annots, + unsigned char parent, + const char *key, + unsigned char key_size, bool value) +{ + weston_assert_u8_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, annots->count); + struct weston_debug_annotation *annot = &annots->annots[annots->count]; + + annot->type = WESTON_DEBUG_ANNOTATION_STR_VAL; + annot->svalue = value ? " true" : "false"; + annot->parent = parent; + annot->key = key; + annot->key_size = key_size; + + annots->count++; +} + +WL_EXPORT void +perfetto_annotate_bool(struct weston_debug_annotations *annots, + const char *key, + unsigned char key_size, + bool value) +{ + do_annotate_bool(annots, annots->count, key, key_size, value); +} + static void do_annotate_float(struct weston_debug_annotations *annots, unsigned char parent, @@ -101,6 +128,30 @@ perfetto_annotate_float(struct weston_debug_annotations *annots, do_annotate_float(annots, annots->count, key, key_size, value); } +static void +do_annotate_double(struct weston_debug_annotations *annots, + unsigned char parent, const char *key, + unsigned char key_size, double value) +{ + weston_assert_u8_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, annots->count); + struct weston_debug_annotation *annot = &annots->annots[annots->count]; + + annot->type = WESTON_DEBUG_ANNOTATION_DOUBLE_VAL; + annot->fvalue = value; + annot->parent = parent; + annot->key = key; + annot->key_size = key_size; + + annots->count++; +} + +WL_EXPORT void +perfetto_annotate_double(struct weston_debug_annotations *annots, + const char *key, unsigned char key_size, + double value) +{ + do_annotate_double(annots, annots->count, key, key_size, value); +} static void do_annotate_string(struct weston_debug_annotations *annots, unsigned char parent, diff --git a/libweston/perfetto/annotations.h b/libweston/perfetto/annotations.h index bc92c7209..cf0e88bc5 100644 --- a/libweston/perfetto/annotations.h +++ b/libweston/perfetto/annotations.h @@ -35,11 +35,22 @@ perfetto_annotate_int(struct weston_debug_annotations *annots, unsigned char key_size, int value); +void +perfetto_annotate_bool(struct weston_debug_annotations *annots, + const char *key, + unsigned char key_size, + bool value); + void perfetto_annotate_float(struct weston_debug_annotations *annots, const char *key, unsigned char key_size, float value); +void +perfetto_annotate_double(struct weston_debug_annotations *annots, + const char *key, + unsigned char key_size, + double value); void perfetto_annotate_string(struct weston_debug_annotations *annots, diff --git a/libweston/perfetto/u_perfetto.cc b/libweston/perfetto/u_perfetto.cc index dbf163c9e..09f6a4ab5 100644 --- a/libweston/perfetto/u_perfetto.cc +++ b/libweston/perfetto/u_perfetto.cc @@ -241,6 +241,12 @@ util_perfetto_flush_debug_annotation(perfetto::EventContext *ctx, else ctx->AddDebugAnnotation(key, annot->fvalue); break; + case WESTON_DEBUG_ANNOTATION_DOUBLE_VAL: + if (use_built_key) + ctx->AddDebugAnnotation(perfetto::DynamicString(key), annot->dvalue); + else + ctx->AddDebugAnnotation(key, annot->dvalue); + break; case WESTON_DEBUG_ANNOTATION_STR_VAL: if (use_built_key) ctx->AddDebugAnnotation(perfetto::DynamicString(key), annot->svalue); diff --git a/libweston/perfetto/u_perfetto.h b/libweston/perfetto/u_perfetto.h index 131d0e889..8251f4174 100644 --- a/libweston/perfetto/u_perfetto.h +++ b/libweston/perfetto/u_perfetto.h @@ -40,9 +40,10 @@ extern "C" { #endif enum weston_debug_annotation_type { - WESTON_DEBUG_ANNOTATION_INT_VAL, - WESTON_DEBUG_ANNOTATION_FLOAT_VAL, - WESTON_DEBUG_ANNOTATION_STR_VAL, + WESTON_DEBUG_ANNOTATION_INT_VAL, + WESTON_DEBUG_ANNOTATION_FLOAT_VAL, + WESTON_DEBUG_ANNOTATION_DOUBLE_VAL, + WESTON_DEBUG_ANNOTATION_STR_VAL, WESTON_DEBUG_ANNOTATION_CONTAINER, }; @@ -51,6 +52,7 @@ struct weston_debug_annotation { union { int ivalue; float fvalue; + double dvalue; const char *svalue; }; unsigned char type; diff --git a/libweston/weston-trace.h b/libweston/weston-trace.h index 322dc1b30..beb16f478 100644 --- a/libweston/weston-trace.h +++ b/libweston/weston-trace.h @@ -35,7 +35,7 @@ #define WESTON_MAX_DEBUG_ANNOTS 128 /* maximum key length */ -#define WESTON_TRACE_MAX_KEY_LENGTH 30 +#define WESTON_TRACE_MAX_KEY_LENGTH 40 /* note that util_perfetto_is_tracing_enabled always returns false until * util_perfetto_init is called @@ -90,8 +90,10 @@ static_assert(sizeof(k) < WESTON_TRACE_MAX_KEY_LENGTH); \ _Generic((v), \ int: perfetto_annotate_int, \ + bool: perfetto_annotate_bool, \ unsigned int: perfetto_annotate_int, \ float: perfetto_annotate_float, \ + double: perfetto_annotate_double, \ char *: perfetto_annotate_string, \ const char *: perfetto_annotate_string, \ struct weston_buffer *: perfetto_annotate_buffer, \ @@ -190,10 +192,13 @@ __attribute__((cleanup(_weston_trace_scope_end), unused)) = \ _weston_trace_annotate_func_begin(name, &__pd_annots) -#define _WESTON_TRACE_ANNOTATE_FUNC_FLOW(id, name) \ - int _WESTON_TRACE_SCOPE_VAR(__LINE__) \ - __attribute__((cleanup(_weston_trace_scope_end), unused)) = \ - _weston_trace_annotate_func_begin_flow(name, id, &__pd_annots) +#define _WESTON_TRACE_ANNOTATE_FUNC_FLOW(id, name) \ + int _WESTON_TRACE_SCOPE_VAR(__LINE__) \ + __attribute__((cleanup(_weston_trace_scope_end), unused)) = \ + _Generic((id), \ + uint64_t *: _weston_trace_annotate_func_begin_flow, \ + uint64_t : _weston_trace_annotate_func_begin_const_flow \ + )(name, id, &__pd_annots) static inline int _weston_trace_scope_begin(const char *name) @@ -270,6 +275,18 @@ _weston_trace_instant_timestamp(const char *name, uint64_t track_id, uint64_t id return 0; } +static inline int +_weston_trace_annotate_func_begin_const_flow(const char *name, uint64_t id, + struct weston_debug_annotations *annots) +{ + weston_assert_u64_gt(NULL, id, 0); + _WESTON_TRACE_ANNOTATE_FUNC_BEGIN_FLOW(name, id, annots); + + annots->count = 0; + return 0; +} + + static inline void _weston_trace_scope_end(int *scope) {