timeline: convert vblank timestamp to MONOTONIC
authorPekka Paalanen <pekka.paalanen@collabora.com>
Thu, 28 May 2020 08:34:04 +0000 (11:34 +0300)
committerPekka Paalanen <pekka.paalanen@collabora.com>
Thu, 28 May 2020 13:34:48 +0000 (16:34 +0300)
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 <pekka.paalanen@collabora.com>
libweston/compositor.c
libweston/timeline.c

index 5fda943..283f3f6 100644 (file)
@@ -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,
index 9da8b5e..d5738f4 100644 (file)
@@ -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;