[igt-dev] [i-g-t 2/2] tests/kms_vrr: New subtest for CMRR
Bhanuprakash Modem
bhanuprakash.modem at intel.com
Mon Nov 20 08:24:59 UTC 2023
CMRR is an variation of VRR where it varies Vtotal slightly
(between additional 0 and 1 Vtotal scanlines) to match content
rate exactly without frame drops using the adaptive sync framework.
This patch creates a new subtest to validate the CMRR as below:
- Request flips with the refresh_rate * 1.001
- Flips should happen at the frequency of refresh_rate.
Signed-off-by: Bhanuprakash Modem <bhanuprakash.modem at intel.com>
---
tests/kms_vrr.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/tests/kms_vrr.c b/tests/kms_vrr.c
index 741a13be6..351645da5 100644
--- a/tests/kms_vrr.c
+++ b/tests/kms_vrr.c
@@ -29,6 +29,14 @@
* Category: Display
* Description: Test to validate diffent features of VRR
*
+ * SUBTEST: cmrr
+ * Description: Test to validate the content rate to exactly match with the
+ * requested rate without any frame drops.
+ * Driver requirement: i915, xe
+ * Functionality: adaptive_sync
+ * Mega feature: VRR
+ * Test category: functionality test
+ *
* SUBTEST: flip-basic
* Description: Tests that VRR is enabled and that the difference between flip
* timestamps converges to the requested rate
@@ -83,6 +91,8 @@
(m)->vdisplay, (m)->vsync_start, (m)->vsync_end, (m)->vtotal, \
(m)->type, (m)->flags
+#define CMRR_FACTOR 1.001
+
enum {
TEST_BASIC = 1 << 0,
TEST_DPMS = 1 << 1,
@@ -332,6 +342,57 @@ do_flip(data_t *data, igt_fb_t *fb)
igt_reset_timeout();
}
+static uint32_t
+flip_and_measure_cmrr(data_t *data, igt_output_t *output, enum pipe pipe,
+ unsigned int refresh_rate, uint64_t duration_ns)
+{
+ uint64_t start_ns, last_event_ns, event_ns;
+ uint32_t total_flip = 0, total_pass = 0;
+ bool front = false;
+ drmModeModeInfoPtr mode = igt_output_get_mode(output);
+ uint64_t req_rate_ns = rate_from_refresh(refresh_rate * CMRR_FACTOR);
+ uint64_t exp_rate_ns = rate_from_refresh(refresh_rate);
+ uint64_t threshold_ns = exp_rate_ns / mode->vdisplay; /* Upto 1 scan line. */
+
+ igt_info("CMRR on: requested rate: %"PRIu64" ns (%f Hz) "
+ "expected rate: %"PRIu64" ns - %"PRIu64" ns (%f-%f Hz)\n",
+ req_rate_ns, refresh_rate * CMRR_FACTOR,
+ (exp_rate_ns - threshold_ns), (exp_rate_ns + threshold_ns),
+ (float)NSECS_PER_SEC / (exp_rate_ns + threshold_ns),
+ (float)NSECS_PER_SEC / (exp_rate_ns - threshold_ns));
+
+ do_flip(data, &data->fb0);
+ start_ns = last_event_ns = get_kernel_event_ns(data, DRM_EVENT_FLIP_COMPLETE);
+ do {
+ int64_t target_ns, wait_ns, diff_ns = exp_rate_ns;
+
+ front = !front;
+ do_flip(data, front ? &data->fb1 : &data->fb0);
+
+ event_ns = get_kernel_event_ns(data, DRM_EVENT_VBLANK);
+ igt_debug("event_ns - last_event_ns: %"PRIu64" ns (%f Hz)\n",
+ event_ns - last_event_ns, (float)NSECS_PER_SEC / (event_ns - last_event_ns));
+
+ diff_ns -= event_ns - last_event_ns;
+ if (llabs(diff_ns) <= threshold_ns)
+ total_pass += 1;
+ total_flip += 1;
+
+ diff_ns = event_ns - start_ns;
+ wait_ns = ((diff_ns + req_rate_ns - 1) / req_rate_ns) * req_rate_ns;
+ wait_ns -= diff_ns;
+ target_ns = event_ns + wait_ns;
+ while (get_time_ns() < target_ns - 10);
+
+ last_event_ns = get_time_ns();
+ } while (event_ns - start_ns <= duration_ns);
+
+ igt_info("Completed %u flips, %u vblanks were in threshold for (%u Hz) %"PRIu64"ns.\n",
+ total_flip, total_pass, refresh_rate, req_rate_ns);
+
+ return total_flip ? ((total_pass * 100) / total_flip) : 0;
+}
+
/*
* Flips at the given rate and measures against the expected value.
* Returns the pass rate as a percentage from 0 - 100.
@@ -414,6 +475,34 @@ flip_and_measure(data_t *data, igt_output_t *output, enum pipe pipe,
return total_flip ? ((total_pass * 100) / total_flip) : 0;
}
+static void
+test_cmrr(data_t *data, enum pipe pipe, igt_output_t *output, uint32_t flags)
+{
+ uint32_t result;
+ range_t range;
+
+ prepare_test(data, output, pipe);
+ range = data->range;
+
+ igt_info("CMRR test execution on %s, PIPE_%s with VRR range: (%u-%u) Hz\n",
+ output->name, kmstest_pipe_name(pipe), range.min, range.max);
+
+ result = flip_and_measure_cmrr(data, output, pipe, range.max, TEST_DURATION_NS);
+
+ /* Clean-up */
+ igt_plane_set_fb(data->primary, NULL);
+ igt_output_set_pipe(output, PIPE_NONE);
+ igt_output_override_mode(output, NULL);
+ igt_display_commit2(&data->display, COMMIT_ATOMIC);
+
+ igt_remove_fb(data->drm_fd, &data->fb1);
+ igt_remove_fb(data->drm_fd, &data->fb0);
+
+ igt_assert_f(result > 75,
+ "Refresh rate (%u Hz) %"PRIu64"ns: Target CMRR on threshold not reached, result was %u%%\n",
+ range.max, rate_from_refresh(range.max), result);
+}
+
/* Basic VRR flip functionality test - enable, measure, disable, measure */
static void
test_basic(data_t *data, enum pipe pipe, igt_output_t *output, uint32_t flags)
@@ -587,6 +676,14 @@ igt_main
igt_subtest_with_dynamic("negative-basic")
run_vrr_test(&data, test_basic, TEST_NEGATIVE);
+ igt_describe("Test to validate the the content rate exactly match with the "
+ "requested rate without any frame drops.");
+ igt_subtest_with_dynamic("cmrr") {
+ igt_require(is_intel_device(data.drm_fd) &&
+ intel_display_ver(intel_get_drm_devid(data.drm_fd)) >= 20);
+ run_vrr_test(&data, test_cmrr, TEST_BASIC);
+ }
+
igt_fixture {
igt_display_fini(&data.display);
drm_close_driver(data.drm_fd);
--
2.40.0
More information about the igt-dev
mailing list