From 50aa3a76c0c6fa8598a48acb641f77a1e3916664 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Thu, 28 May 2020 11:34:04 +0300 Subject: [PATCH] timeline: convert vblank timestamp to MONOTONIC All timeline event timestamps are in CLOCK_MONOTONIC already. DRM KMS timestamps are practically guaranteed to be CLOCK_MONOTONIC too, even though presentation clock could theoretically be something else. For other backends, the presentation clock is likely CLOCK_MONOTONIC_RAW due to weston_compositor_set_presentation_clock_software(). This patch ensures that the recorded vblank timestamp is in CLOCK_MONOTONIC. Otherwise interpreting the timeline traces might be difficult to do accurately, since it would be hard to recover the relationship between the presentation clock and timeline event timestamps. The time conversion routine is the simplest possible, I don't think we need any more accurate conversion for timeline purposes. Besides, DRM-backend is the only backend where the timings actually matter, the other backends are software-timed anyway. Since the clock domain of the "vblank" attribute potentially changes, the attribute is renamed. Wesgr never used this attribute. Signed-off-by: Pekka Paalanen --- libweston/compositor.c | 40 ++++++++++++++++++++++++++++++++++++++-- libweston/timeline.c | 2 +- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/libweston/compositor.c b/libweston/compositor.c index 5fda9432..283f3f68 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -2938,6 +2938,39 @@ output_repaint_timer_handler(void *data) return 0; } +/** Convert a presentation timestamp to another clock domain + * + * \param compositor The compositor defines the presentation clock domain. + * \param presentation_stamp The timestamp in presentation clock domain. + * \param presentation_now Current time in presentation clock domain. + * \param target_clock Defines the target clock domain. + * + * This approximation relies on presentation_stamp to be close to current time. + * The further it is from current time and the bigger the speed difference + * between the two clock domains, the bigger the conversion error. + * + * Conversion error due to system load is biased and unbounded. + */ +static struct timespec +convert_presentation_time_now(struct weston_compositor *compositor, + const struct timespec *presentation_stamp, + const struct timespec *presentation_now, + clockid_t target_clock) +{ + struct timespec target_now = {}; + struct timespec target_stamp; + int64_t delta_ns; + + if (compositor->presentation_clock == target_clock) + return *presentation_stamp; + + clock_gettime(target_clock, &target_now); + delta_ns = timespec_sub_to_nsec(presentation_stamp, presentation_now); + timespec_add_nsec(&target_stamp, &target_now, delta_ns); + + return target_stamp; +} + /** * \ingroup output */ @@ -2949,9 +2982,9 @@ weston_output_finish_frame(struct weston_output *output, struct weston_compositor *compositor = output->compositor; int32_t refresh_nsec; struct timespec now; + struct timespec vblank_monotonic; int64_t msec_rel; - assert(output->repaint_status == REPAINT_AWAITING_COMPLETION); assert(stamp || (presented_flags & WP_PRESENTATION_FEEDBACK_INVALID)); @@ -2965,8 +2998,11 @@ weston_output_finish_frame(struct weston_output *output, goto out; } + vblank_monotonic = convert_presentation_time_now(compositor, + stamp, &now, + CLOCK_MONOTONIC); TL_POINT(compositor, "core_repaint_finished", TLP_OUTPUT(output), - TLP_VBLANK(stamp), TLP_END); + TLP_VBLANK(&vblank_monotonic), TLP_END); refresh_nsec = millihz_to_nsec(output->current_mode->refresh); weston_presentation_feedback_present_list(&output->feedback_list, diff --git a/libweston/timeline.c b/libweston/timeline.c index 9da8b5e3..d5738f48 100644 --- a/libweston/timeline.c +++ b/libweston/timeline.c @@ -324,7 +324,7 @@ emit_vblank_timestamp(struct timeline_emit_context *ctx, void *obj) { struct timespec *ts = obj; - fprintf(ctx->cur, "\"vblank\":[%" PRId64 ", %ld]", + fprintf(ctx->cur, "\"vblank_monotonic\":[%" PRId64 ", %ld]", (int64_t)ts->tv_sec, ts->tv_nsec); return 1;