mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-24 18:08:15 +02:00
timeline: Add support for weston_input_event
And with it include a dedicated track in Perfetto to display the event timestamp on that a weston_seat. This includes support for timeline and for timeline Perfetto. Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
This commit is contained in:
parent
9ce3759bc5
commit
a1ac3c2e8d
8 changed files with 161 additions and 2 deletions
|
|
@ -609,6 +609,7 @@ enum weston_pointer_motion_mask {
|
|||
struct weston_input_event {
|
||||
struct timespec ts;
|
||||
struct weston_seat *seat;
|
||||
uint64_t flow_id;
|
||||
};
|
||||
|
||||
struct weston_pointer_motion_event {
|
||||
|
|
@ -1247,6 +1248,7 @@ struct weston_seat {
|
|||
struct wl_list tablet_tool_list;
|
||||
struct wl_list tablet_seat_resource_list;
|
||||
struct wl_signal tablet_tool_added_signal;
|
||||
uint64_t track_id;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
|||
|
|
@ -5972,6 +5972,10 @@ weston_input_event_init(struct weston_input_event *ievent, struct timespec *ts,
|
|||
{
|
||||
ievent->ts = *ts;
|
||||
ievent->seat = seat;
|
||||
ievent->flow_id = 0;
|
||||
|
||||
WESTON_TRACE_FUNC_FLOW(&ievent->flow_id);
|
||||
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
|
|
|
|||
|
|
@ -145,6 +145,32 @@ util_perfetto_counter_set(const char *name, double value)
|
|||
perfetto::DynamicString(name), value);
|
||||
}
|
||||
|
||||
void
|
||||
util_perfetto_trace_instant_timestamp(const char *name, uint64_t track_id, uint64_t id, clockid_t clock, uint64_t ts)
|
||||
{
|
||||
if (id) {
|
||||
TRACE_EVENT_INSTANT(UTIL_PERFETTO_CATEGORY_DEFAULT_STR,
|
||||
nullptr,
|
||||
perfetto::Track(track_id),
|
||||
perfetto::TraceTimestamp{clockid_to_perfetto_clock(clock), ts},
|
||||
perfetto::Flow::ProcessScoped(id),
|
||||
[&](perfetto::EventContext ctx) {
|
||||
ctx.event()->set_name(name);
|
||||
ctx.AddDebugAnnotation(name, ts);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE_EVENT_INSTANT(UTIL_PERFETTO_CATEGORY_DEFAULT_STR,
|
||||
nullptr,
|
||||
perfetto::Track(track_id),
|
||||
perfetto::TraceTimestamp{clockid_to_perfetto_clock(clock), ts},
|
||||
[&](perfetto::EventContext ctx) {
|
||||
ctx.event()->set_name(name);
|
||||
ctx.AddDebugAnnotation(name, ts);
|
||||
});
|
||||
}
|
||||
|
||||
uint64_t
|
||||
util_perfetto_next_id(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -96,6 +96,9 @@ void util_perfetto_trace_commit_annotate_func(const char *name,
|
|||
void util_perfetto_trace_commit_annotate_func_flow(uint64_t id, const char *name,
|
||||
struct weston_debug_annotations *annots);
|
||||
|
||||
void util_perfetto_trace_instant_timestamp(const char *name, uint64_t track_id,
|
||||
uint64_t id, clockid_t clock, uint64_t ts);
|
||||
|
||||
uint64_t util_perfetto_next_id(void);
|
||||
|
||||
uint64_t util_perfetto_new_track(const char *name);
|
||||
|
|
@ -155,6 +158,12 @@ util_perfetto_trace_commit_annotate_func_flow(uint64_t id, const char *name,
|
|||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
util_perfetto_trace_instant_timestamp(const char *name, uint64_t track_id,
|
||||
clockid_t clock, uint64_t ts)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void util_perfetto_counter_set(const char *name, double value)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,14 @@ build_track_name(struct weston_surface *surface, char *name, int size)
|
|||
snprintf(name, size, "%s #%d", surface->label, surface->s_id);
|
||||
}
|
||||
|
||||
static void
|
||||
build_seat_track_name(struct weston_seat *seat, char *name, int size)
|
||||
{
|
||||
assert(seat->track_id == 0);
|
||||
|
||||
snprintf(name, size, "seat: %s", seat->seat_name);
|
||||
}
|
||||
|
||||
static void
|
||||
weston_perfetto_ensure_surface_id(struct weston_surface *surface)
|
||||
{
|
||||
|
|
@ -77,6 +85,19 @@ weston_perfetto_ensure_surface_id(struct weston_surface *surface)
|
|||
surface->damage_track_id = util_perfetto_new_track(track_name);
|
||||
}
|
||||
|
||||
static void
|
||||
weston_perfetto_ensure_seat_id(struct weston_seat *seat)
|
||||
{
|
||||
char track_name[600];
|
||||
|
||||
if (seat->track_id)
|
||||
return;
|
||||
|
||||
build_seat_track_name(seat, track_name, sizeof(track_name));
|
||||
|
||||
seat->track_id = util_perfetto_new_track(track_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a timeline point for perfetto.
|
||||
*
|
||||
|
|
@ -94,9 +115,10 @@ weston_timeline_perfetto(struct weston_log_scope *timeline_scope,
|
|||
{
|
||||
struct weston_output *output = NULL;
|
||||
struct weston_surface *surface = NULL;
|
||||
struct weston_input_event *ievent = NULL;
|
||||
struct timespec ts;
|
||||
uint64_t now_ns;
|
||||
uint64_t vblank_ns = 0, gpu_ns = 0;
|
||||
uint64_t vblank_ns = 0, gpu_ns = 0, kernel_input_ts = 0;
|
||||
va_list argp;
|
||||
|
||||
if (!util_perfetto_is_tracing_enabled())
|
||||
|
|
@ -130,6 +152,11 @@ weston_timeline_perfetto(struct weston_log_scope *timeline_scope,
|
|||
case TLT_GPU:
|
||||
gpu_ns = timespec_to_nsec(obj);
|
||||
break;
|
||||
case TLT_INPUT_EVENT:
|
||||
ievent = obj;
|
||||
weston_perfetto_ensure_seat_id(ievent->seat);
|
||||
kernel_input_ts = timespec_to_nsec(&ievent->ts);
|
||||
break;
|
||||
default:
|
||||
assert(!"not reached");
|
||||
}
|
||||
|
|
@ -170,6 +197,9 @@ weston_timeline_perfetto(struct weston_log_scope *timeline_scope,
|
|||
case TLP_RENDERER_GPU_END:
|
||||
WESTON_TRACE_TIMESTAMP_END("Active", output->gpu_track_id, CLOCK_MONOTONIC, gpu_ns);
|
||||
break;
|
||||
case TLP_INPUT_KERNEL_TS:
|
||||
WESTON_TRACE_INSTANT_TIMESTAMP("event ts", ievent->seat->track_id, ievent->flow_id, CLOCK_MONOTONIC, kernel_input_ts);
|
||||
break;
|
||||
default:
|
||||
assert(!"not reached");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,6 +222,24 @@ weston_timeline_subscription_surface_ensure(struct weston_timeline_subscription
|
|||
return sub_obj;
|
||||
}
|
||||
|
||||
static struct weston_timeline_subscription_object *
|
||||
weston_timeline_subscription_seat_ensure(struct weston_timeline_subscription *tl_sub,
|
||||
struct weston_seat *seat)
|
||||
{
|
||||
struct weston_timeline_subscription_object *sub_obj;
|
||||
|
||||
sub_obj = weston_timeline_subscription_search(tl_sub, seat);
|
||||
if (!sub_obj) {
|
||||
sub_obj = weston_timeline_subscription_object_create(seat, tl_sub);
|
||||
|
||||
sub_obj->destroy_listener.notify =
|
||||
weston_timeline_destroy_subscription_object_notify;
|
||||
wl_signal_add(&seat->destroy_signal,
|
||||
&sub_obj->destroy_listener);
|
||||
}
|
||||
return sub_obj;
|
||||
}
|
||||
|
||||
static void
|
||||
fprint_quoted_string(struct weston_log_subscription *sub, const char *str)
|
||||
{
|
||||
|
|
@ -265,6 +283,36 @@ emit_weston_output(struct timeline_emit_context *ctx, void *obj)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
emit_weston_seat_print_id(struct weston_log_subscription *sub,
|
||||
struct weston_timeline_subscription_object *sub_obj,
|
||||
const char *name)
|
||||
{
|
||||
if (!weston_timeline_check_object_refresh(sub_obj))
|
||||
return;
|
||||
|
||||
weston_log_subscription_printf(sub, "{ \"id\":%u, "
|
||||
"\"type\":\"weston_seat\", \"name\":", sub_obj->id);
|
||||
fprint_quoted_string(sub, name);
|
||||
weston_log_subscription_printf(sub, " }\n");
|
||||
}
|
||||
|
||||
static int
|
||||
common_emit_seat(struct timeline_emit_context *ctx, struct weston_seat *seat)
|
||||
{
|
||||
struct weston_log_subscription *sub = ctx->subscription;
|
||||
struct weston_timeline_subscription_object *sub_obj;
|
||||
struct weston_timeline_subscription *tl_sub;
|
||||
|
||||
tl_sub = weston_log_subscription_get_data(sub);
|
||||
sub_obj = weston_timeline_subscription_seat_ensure(tl_sub, seat);
|
||||
emit_weston_seat_print_id(sub, sub_obj, seat->seat_name);
|
||||
|
||||
assert(sub_obj->id != 0);
|
||||
fprintf(ctx->cur, "\"seat\":%u", sub_obj->id);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct weston_timeline_subscription_object *
|
||||
check_weston_surface_description(struct weston_log_subscription *sub,
|
||||
|
|
@ -342,6 +390,21 @@ emit_gpu_timestamp(struct timeline_emit_context *ctx, void *obj)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
emit_input_event(struct timeline_emit_context *ctx, void *obj)
|
||||
{
|
||||
struct weston_input_event *ievent = obj;
|
||||
struct timespec ts = ievent->ts;
|
||||
struct weston_seat *seat = ievent->seat;
|
||||
|
||||
common_emit_seat(ctx, seat);
|
||||
|
||||
fprintf(ctx->cur, ", \"event ts\":[%" PRId64 ", %ld]",
|
||||
(int64_t)ts.tv_sec, ts.tv_nsec);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct weston_timeline_subscription_object *
|
||||
weston_timeline_get_subscription_object(struct weston_log_subscription *sub,
|
||||
void *object)
|
||||
|
|
@ -392,6 +455,7 @@ static const type_func type_dispatch[] = {
|
|||
[TLT_SURFACE] = emit_weston_surface,
|
||||
[TLT_VBLANK] = emit_vblank_timestamp,
|
||||
[TLT_GPU] = emit_gpu_timestamp,
|
||||
[TLT_INPUT_EVENT] = emit_input_event,
|
||||
};
|
||||
|
||||
static const char *
|
||||
|
|
@ -420,6 +484,8 @@ tlp_to_string(enum timeline_point_name tlp)
|
|||
return "renderer_gpu_begin";
|
||||
case TLP_RENDERER_GPU_END:
|
||||
return "renderer_gpu_end";
|
||||
case TLP_INPUT_KERNEL_TS:
|
||||
return "event ts";
|
||||
}
|
||||
assert(!"not reached");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ enum timeline_type {
|
|||
TLT_SURFACE,
|
||||
TLT_VBLANK,
|
||||
TLT_GPU,
|
||||
TLT_INPUT_EVENT,
|
||||
};
|
||||
|
||||
enum timeline_point_name {
|
||||
|
|
@ -56,7 +57,8 @@ enum timeline_point_name {
|
|||
TLP_CORE_REPAINT_ENTER_LOOP,
|
||||
TLP_CORE_COMMIT_DAMAGE,
|
||||
TLP_RENDERER_GPU_BEGIN,
|
||||
TLP_RENDERER_GPU_END
|
||||
TLP_RENDERER_GPU_END,
|
||||
TLP_INPUT_KERNEL_TS,
|
||||
};
|
||||
|
||||
/** Timeline subscription created for each subscription
|
||||
|
|
@ -96,6 +98,7 @@ struct weston_timeline_subscription_object {
|
|||
#define TLP_SURFACE(s) TLT_SURFACE, TYPEVERIFY(struct weston_surface *, (s))
|
||||
#define TLP_VBLANK(t) TLT_VBLANK, TYPEVERIFY(const struct timespec *, (t))
|
||||
#define TLP_GPU(t) TLT_GPU, TYPEVERIFY(const struct timespec *, (t))
|
||||
#define TLP_INPUT_EVENT(t) TLT_INPUT_EVENT, TYPEVERIFY(const struct weston_input_event *, (t))
|
||||
|
||||
/** This macro is used to add timeline points.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -152,6 +152,12 @@
|
|||
#define _WESTON_TRACE_ANNOTATE_PAIR(pair) _WESTON_TRACE_ANNOTATE_ADD_GENERIC pair
|
||||
|
||||
/* end of helper section */
|
||||
#define _WESTON_TRACE_INSTANT_TIMESTAMP(name, track_id, id, clock, timestamp) \
|
||||
do { \
|
||||
if (unlikely(util_perfetto_is_tracing_enabled())) \
|
||||
_weston_trace_instant_timestamp(name, track_id, id, \
|
||||
clock, timestamp); \
|
||||
} while (0)
|
||||
|
||||
#if __has_attribute(cleanup) && __has_attribute(unused)
|
||||
|
||||
|
|
@ -255,6 +261,15 @@ _weston_trace_annotate_func_begin_flow(const char *name, uint64_t *id,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
_weston_trace_instant_timestamp(const char *name, uint64_t track_id, uint64_t id,
|
||||
clock_t clock, uint64_t ts)
|
||||
{
|
||||
weston_assert_u64_gt(NULL, id, 0);
|
||||
util_perfetto_trace_instant_timestamp(name, track_id, id, clock, ts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_weston_trace_scope_end(int *scope)
|
||||
{
|
||||
|
|
@ -276,6 +291,7 @@ _weston_trace_scope_end(int *scope)
|
|||
#define _WESTON_TRACE_SET_COUNTER(name, value)
|
||||
#define _WESTON_TRACE_TIMESTAMP_BEGIN(name, track_id, flow_id, clock, timestamp)
|
||||
#define _WESTON_TRACE_TIMESTAMP_END(name, track_id, clock, timestamp)
|
||||
#define _WESTON_TRACE_INSTANT_TIMESTAMP(name, track_id, id, clock, timestamp)
|
||||
|
||||
#define _WESTON_TRACE_BEGIN_ANNOTATION()
|
||||
#define _WESTON_TRACE_COMMIT_ANNOTATION(id, name)
|
||||
|
|
@ -294,6 +310,9 @@ _weston_trace_scope_end(int *scope)
|
|||
_WESTON_TRACE_TIMESTAMP_BEGIN(name, track_id, flow_id, clock, timestamp)
|
||||
#define WESTON_TRACE_TIMESTAMP_END(name, track_id, clock, timestamp) \
|
||||
_WESTON_TRACE_TIMESTAMP_END(name, track_id, clock, timestamp)
|
||||
#define WESTON_TRACE_INSTANT_TIMESTAMP(name, track_id, id, clock, timestamp) \
|
||||
_WESTON_TRACE_INSTANT_TIMESTAMP(name, track_id, id, clock, timestamp)
|
||||
|
||||
|
||||
#define WESTON_TRACE_BEGIN_ANNOTATION() \
|
||||
_WESTON_TRACE_BEGIN_ANNOTATION()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue