summaryrefslogtreecommitdiff
path: root/tests/kms_setmode.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2016-10-24 11:06:00 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2016-10-25 22:01:53 +0100
commit37c9be1db3966e1fee87ec3942da25980201ee1b (patch)
tree5956b883c51390e5384020c281858c44fa092f3d /tests/kms_setmode.c
parent128d27a01cce753f19e82844fead910f10ec13b3 (diff)
igt/kms_setmode: Test that the vblank interval matches the dotclock
As we allow userspace to set the dotclock, we should try to respect it! Userpsace will try to set its frametimings based upon the dotclock, so ideally it should match the measured vblank interval. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'tests/kms_setmode.c')
-rw-r--r--tests/kms_setmode.c75
1 files changed, 73 insertions, 2 deletions
diff --git a/tests/kms_setmode.c b/tests/kms_setmode.c
index 64e21cd1..9dafca00 100644
--- a/tests/kms_setmode.c
+++ b/tests/kms_setmode.c
@@ -71,6 +71,7 @@ enum test_flags {
TEST_SINGLE_CRTC_CLONE = 0x04,
TEST_EXCLUSIVE_CRTC_CLONE = 0x08,
TEST_STEALING = 0x10,
+ TEST_TIMINGS = 0x20,
};
struct test_config {
@@ -411,6 +412,75 @@ static int test_stealing(int fd, struct crtc_config *crtc, uint32_t *ids)
return ret;
}
+static double frame_time(const drmModeModeInfo *kmode)
+{
+ return 1000.0 * kmode->htotal * kmode->vtotal / kmode->clock;
+}
+
+static void check_timings(int crtc_idx, const drmModeModeInfo *kmode)
+{
+#define CALIBRATE_TS_STEPS 120 /* ~2s has to be less than 128! */
+ 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(kmode);
+
+ 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_assert_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 test_crtc_config(const struct test_config *tconf,
struct crtc_config *crtcs, int crtc_count)
{
@@ -473,8 +543,8 @@ static void test_crtc_config(const struct test_config *tconf,
igt_assert(config_failed == !!(tconf->flags & TEST_INVALID));
- if (ret == 0 && connector_connected && !(tconf->flags & TEST_INVALID))
- sleep(5);
+ if (ret == 0 && connector_connected && tconf->flags & TEST_TIMINGS)
+ check_timings(crtcs[0].crtc_idx, &crtcs[0].mode);
for (i = 0; i < crtc_count; i++) {
if (crtcs[i].fb_info.fb_id) {
@@ -730,6 +800,7 @@ int main(int argc, char **argv)
enum test_flags flags;
const char *name;
} tests[] = {
+ { TEST_TIMINGS, "basic" },
{ TEST_CLONE | TEST_SINGLE_CRTC_CLONE,
"basic-clone-single-crtc" },
{ TEST_INVALID | TEST_CLONE | TEST_SINGLE_CRTC_CLONE,