summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/kms_flip.c68
1 files changed, 67 insertions, 1 deletions
diff --git a/tests/kms_flip.c b/tests/kms_flip.c
index b30e07c9..9829b355 100644
--- a/tests/kms_flip.c
+++ b/tests/kms_flip.c
@@ -26,6 +26,7 @@
#endif
#include "igt.h"
+
#include <cairo.h>
#include <errno.h>
#include <fcntl.h>
@@ -43,6 +44,7 @@
#include <time.h>
#include <pthread.h>
+#include "igt_stats.h"
#define TEST_DPMS (1 << 0)
#define TEST_WITH_DUMMY_BCS (1 << 1)
@@ -1301,6 +1303,70 @@ static void free_test_output(struct test_output *o)
}
}
+static void calibrate_ts(struct test_output *o, int crtc_idx)
+{
+#define CALIBRATE_TS_STEPS 16
+ drmVBlank wait;
+ igt_stats_t stats;
+ uint32_t last_seq;
+ uint64_t last_timestamp;
+ double expected;
+ double mean;
+ double stddev;
+ int n;
+
+ memset(&wait, 0, sizeof(wait));
+ wait.request.type = kmstest_get_vbl_flag(crtc_idx);
+ wait.request.type |= DRM_VBLANK_ABSOLUTE | DRM_VBLANK_NEXTONMISS;
+ do_or_die(drmWaitVBlank(drm_fd, &wait));
+
+ last_seq = wait.reply.sequence;
+ last_timestamp = wait.reply.tval_sec;
+ last_timestamp *= 1000000;
+ last_timestamp += wait.reply.tval_usec;
+
+ memset(&wait, 0, sizeof(wait));
+ wait.request.type = kmstest_get_vbl_flag(crtc_idx);
+ wait.request.type |= DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+ wait.request.sequence = last_seq;
+ for (n = 0; n < CALIBRATE_TS_STEPS; n++) {
+ ++wait.request.sequence;
+ do_or_die(drmWaitVBlank(drm_fd, &wait));
+ }
+
+ igt_stats_init_with_size(&stats, CALIBRATE_TS_STEPS);
+ for (n = 0; n < CALIBRATE_TS_STEPS; n++) {
+ struct drm_event_vblank ev;
+ uint64_t now;
+
+ igt_assert(read(drm_fd, &ev, sizeof(ev)) == sizeof(ev));
+ igt_assert_eq(ev.sequence, last_seq + 1);
+
+ now = ev.tv_sec;
+ now *= 1000000;
+ now += ev.tv_usec;
+
+ igt_stats_push(&stats, now - last_timestamp);
+
+ last_timestamp = now;
+ last_seq = ev.sequence;
+ }
+
+ expected = frame_time(o);
+
+ mean = igt_stats_get_mean(&stats);
+ stddev = igt_stats_get_std_deviation(&stats);
+
+ igt_info("Expected frametime: %.0fus; measured %.1fus +- %.3fus accuracy %.2f%%\n",
+ expected, mean, stddev, 100 * 6 * stddev / mean);
+ igt_assert(6 * stddev / mean < 0.005); /* 99% accuracy within 0.5% */
+
+ igt_require_f(fabs(mean - expected) < 2*stddev,
+ "vblank interval differs from modeline! expected %.1fus, measured %1.fus +- %.3fus, difference %.1fus (%.1f sigma)\n",
+ expected, mean, stddev,
+ fabs(mean - expected), fabs(mean - expected) / stddev);
+}
+
static void run_test_on_crtc_set(struct test_output *o, int *crtc_idxs,
int crtc_count, int duration_ms)
{
@@ -1404,7 +1470,7 @@ static void run_test_on_crtc_set(struct test_output *o, int *crtc_idxs,
/* quiescent the hw a bit so ensure we don't miss a single frame */
if (o->flags & TEST_CHECK_TS)
- sleep(1);
+ calibrate_ts(o, crtc_idxs[0]);
igt_assert_eq(do_page_flip(o, o->fb_ids[1], true), 0);
wait_for_events(o);