[igt-dev] [i-g-t V4 6/7] tests/kms_vrr: Add new subtest to switch RR without modeset
Srinivas, Vidya
vidya.srinivas at intel.com
Mon Dec 4 02:35:19 UTC 2023
Tested-by: Vidya Srinivas <vidya.srinivas at intel.com>
> -----Original Message-----
> From: igt-dev <igt-dev-bounces at lists.freedesktop.org> On Behalf Of
> Bhanuprakash Modem
> Sent: Friday, December 1, 2023 7:47 PM
> To: igt-dev at lists.freedesktop.org
> Subject: [igt-dev] [i-g-t V4 6/7] tests/kms_vrr: Add new subtest to switch RR
> without modeset
>
> Add new subtest to switch between low refresh rate to high refresh rate and
> vice versa seamlessly without modeset.
>
> Below are the sequence of operations to perform:
>
> 1. Use High RR mode + VRR On (if panel supports) -> Measure vblank timings
> 2. Switch to Low RR mode -> Measure vblank timings 3. Switch back to High
> RR mode -> Measure vblank timings
>
> Signed-off-by: Bhanuprakash Modem <bhanuprakash.modem at intel.com>
> ---
> tests/kms_vrr.c | 135 ++++++++++++++++++++++++++++++++++++++++++++---
> -
> 1 file changed, 124 insertions(+), 11 deletions(-)
>
> diff --git a/tests/kms_vrr.c b/tests/kms_vrr.c index 422d89073..8b89d1a87
> 100644
> --- a/tests/kms_vrr.c
> +++ b/tests/kms_vrr.c
> @@ -53,6 +53,10 @@
> * SUBTEST: flipline
> * Description: Make sure that flips happen at flipline decision boundary.
> *
> + * SUBTEST: seamless-rr-switch
> + * Description: Test to switch RR seamlessly without modeset.
> + * Functionality: adaptive_sync, drrs, lrr
> + *
> * SUBTEST: negative-basic
> * Description: Make sure that VRR should not be enabled on the Non-VRR
> panel.
> */
> @@ -70,7 +74,14 @@ enum {
> TEST_DPMS = 1 << 1,
> TEST_SUSPEND = 1 << 2,
> TEST_FLIPLINE = 1 << 3,
> - TEST_NEGATIVE = 1 << 4,
> + TEST_SEAMLESS_RR = 1 << 4,
> + TEST_NEGATIVE = 1 << 5,
> +};
> +
> +enum {
> + HIGH_RR_MODE,
> + LOW_RR_MODE,
> + RR_MODES_COUNT,
> };
>
> typedef struct range {
> @@ -85,6 +96,7 @@ typedef struct data {
> igt_fb_t fb0;
> igt_fb_t fb1;
> range_t range;
> + drmModeModeInfo switch_modes[RR_MODES_COUNT];
> } data_t;
>
> typedef struct vtest_ns {
> @@ -166,6 +178,24 @@ output_mode_with_maxrate(igt_output_t *output,
> unsigned int vrr_max)
> return mode;
> }
>
> +static drmModeModeInfo
> +low_rr_mode_with_same_res(igt_output_t *output, unsigned int vrr_min) {
> + int i;
> + drmModeConnectorPtr connector = output->config.connector;
> + drmModeModeInfo mode = *igt_output_get_mode(output);
> +
> + for (i = 0; i < connector->count_modes; i++)
> + /* TODO: Improve checks for downclock */
> + if (connector->modes[i].hdisplay == mode.hdisplay &&
> + connector->modes[i].vdisplay == mode.vdisplay &&
> + connector->modes[i].vrefresh < mode.vrefresh &&
> + connector->modes[i].vrefresh >= vrr_min)
> + mode = connector->modes[i];
> +
> + return mode;
> +}
> +
> /* Read min and max vrr range from the connector debugfs. */ static range_t
> get_vrr_range(data_t *data, igt_output_t *output) @@ -380,6 +410,9 @@
> test_basic(data_t *data, enum pipe pipe, igt_output_t *output, uint32_t flags)
> igt_info("VRR Test execution on %s, PIPE_%s with VRR range: (%u-%u)
> Hz\n",
> output->name, kmstest_pipe_name(pipe), range.min,
> range.max);
>
> + igt_info("Override Mode: ");
> + kmstest_dump_mode(&data->switch_modes[HIGH_RR_MODE]);
> +
> set_vrr_on_pipe(data, pipe, true);
>
> /*
> @@ -456,7 +489,9 @@ test_basic(data_t *data, enum pipe pipe, igt_output_t
> *output, uint32_t flags)
>
> static void test_cleanup(data_t *data, enum pipe pipe, igt_output_t *output)
> {
> - igt_pipe_set_prop_value(&data->display, pipe,
> IGT_CRTC_VRR_ENABLED, false);
> + if (vrr_capable(output))
> + igt_pipe_set_prop_value(&data->display, pipe,
> IGT_CRTC_VRR_ENABLED,
> +false);
> +
> igt_plane_set_fb(data->primary, NULL);
> igt_output_set_pipe(output, PIPE_NONE);
> igt_output_override_mode(output, NULL); @@ -466,9 +501,71 @@
> static void test_cleanup(data_t *data, enum pipe pipe, igt_output_t *output)
> igt_remove_fb(data->drm_fd, &data->fb0); }
>
> -static bool output_constraint(data_t *data, igt_output_t *output)
> +static void
> +test_seamless_rr_basic(data_t *data, enum pipe pipe, igt_output_t
> +*output, uint32_t flags)
> {
> - drmModeModeInfo mode;
> + uint32_t result;
> + vtest_ns_t vtest_ns;
> + uint64_t rate;
> + bool vrr = vrr_capable(output);
> +
> + igt_info("Use HIGH_RR Mode as default (VRR: %s): ", vrr ? "ON" :
> "OFF");
> + kmstest_dump_mode(&data->switch_modes[HIGH_RR_MODE]);
> +
> + prepare_test(data, output, pipe);
> + vtest_ns = get_test_rate_ns(data->range);
> +
> + if (vrr) {
> + igt_pipe_set_prop_value(&data->display, pipe,
> IGT_CRTC_VRR_ENABLED, true);
> + igt_assert(igt_display_try_commit_atomic(&data->display, 0,
> NULL) == 0);
> + }
> +
> + rate = vtest_ns.max;
> + result = flip_and_measure(data, output, pipe, rate,
> TEST_DURATION_NS);
> + igt_assert_f(result > 75,
> + "Refresh rate (%u Hz) %"PRIu64"ns: Target VRR %s
> threshold not reached, result was %u%%\n",
> + data->range.max, rate, vrr ? "on" : "off", result);
> +
> + /* Switch to low rr mode without modeset. */
> + igt_info("Switch to LOW_RR Mode (VRR: %s): ", vrr ? "ON" : "OFF");
> + kmstest_dump_mode(&data->switch_modes[LOW_RR_MODE]);
> + igt_output_override_mode(output, &data-
> >switch_modes[LOW_RR_MODE]);
> + igt_assert(igt_display_try_commit_atomic(&data->display, 0, NULL) ==
> +0);
> +
> + rate = vtest_ns.min;
> + result = flip_and_measure(data, output, pipe, rate,
> TEST_DURATION_NS);
> + igt_assert_f(result > 75,
> + "Refresh rate (%u Hz) %"PRIu64"ns: Target VRR %s
> threshold not reached, result was %u%%\n",
> + data->range.min, rate, vrr ? "on" : "off", result);
> +
> + /* Switch back to high rr mode without modeset. */
> + igt_info("Switch back to HIGH_RR Mode (VRR: %s): ", vrr ? "ON" :
> "OFF");
> + kmstest_dump_mode(&data->switch_modes[HIGH_RR_MODE]);
> + igt_output_override_mode(output, &data-
> >switch_modes[HIGH_RR_MODE]);
> + igt_assert(igt_display_try_commit_atomic(&data->display, 0, NULL) ==
> +0);
> +
> + rate = vtest_ns.mid;
> + result = flip_and_measure(data, output, pipe, rate,
> TEST_DURATION_NS);
> + igt_assert_f(vrr ? (result > 75) : (result < 10),
> + "Refresh rate (%u Hz) %"PRIu64"ns: Target VRR %s
> threshold %s, result was %u%%\n",
> + ((data->range.max + data->range.min) / 2), rate,
> + vrr ? "on" : "off", vrr ? "not reached" : "exceeded", result); }
> +
> +static bool output_constraint(data_t *data, igt_output_t *output,
> +uint32_t flags) {
> + if ((flags & TEST_SEAMLESS_RR) &&
> + output->config.connector->connector_type !=
> DRM_MODE_CONNECTOR_eDP)
> + return false;
> +
> + /*
> + * FIXME: Read the DRRS capability, currently assuming:
> + * - Panel should contain 2 modes only
> + * - Both modes should have the same resolution but different RR
> + */
> + if ((flags & TEST_SEAMLESS_RR) &&
> + !vrr_capable(output) && output->config.connector->count_modes
> != 2)
> + return false;
>
> /* Reset output */
> igt_display_reset(&data->display);
> @@ -481,16 +578,22 @@ static bool output_constraint(data_t *data,
> igt_output_t *output)
> * - vrr_min range should be less than the override mode vrefresh.
> * - Limit the vrr_max range with the override mode vrefresh.
> */
> - mode = output_mode_with_maxrate(output, data->range.max);
> - if (mode.vrefresh < data->range.min)
> + data->switch_modes[HIGH_RR_MODE] =
> output_mode_with_maxrate(output, data->range.max);
> + if (data->switch_modes[HIGH_RR_MODE].vrefresh < data-
> >range.min)
> return false;
>
> - data->range.max = mode.vrefresh;
> + data->range.max = data->switch_modes[HIGH_RR_MODE].vrefresh;
> + igt_output_override_mode(output, &data-
> >switch_modes[HIGH_RR_MODE]);
>
> - igt_info("Override Mode: ");
> - kmstest_dump_mode(&mode);
> + /* Search for a low refresh rate mode. */
> + if (!(flags & TEST_SEAMLESS_RR))
> + return true;
> +
> + data->switch_modes[LOW_RR_MODE] =
> low_rr_mode_with_same_res(output, data->range.min);
> + if (data->switch_modes[LOW_RR_MODE].vrefresh == data-
> >switch_modes[HIGH_RR_MODE].vrefresh)
> + return false;
>
> - igt_output_override_mode(output, &mode);
> + data->range.min = data->switch_modes[LOW_RR_MODE].vrefresh;
>
> return true;
> }
> @@ -500,6 +603,9 @@ static bool config_constraint(data_t *data,
> igt_output_t *output, uint32_t flags
> if (!has_vrr(output))
> return false;
>
> + if (flags & TEST_SEAMLESS_RR)
> + goto out;
> +
> /* For Negative tests, panel should be non-vrr. */
> if ((flags & TEST_NEGATIVE) && vrr_capable(output))
> return false;
> @@ -507,7 +613,8 @@ static bool config_constraint(data_t *data,
> igt_output_t *output, uint32_t flags
> if ((flags & ~TEST_NEGATIVE) && !vrr_capable(output))
> return false;
>
> - if (!output_constraint(data, output))
> +out:
> + if (!output_constraint(data, output, flags))
> return false;
>
> return true;
> @@ -583,6 +690,12 @@ igt_main
> igt_subtest_with_dynamic("negative-basic")
> run_vrr_test(&data, test_basic, TEST_NEGATIVE);
>
> + igt_describe("Test to switch RR seamlessly without modeset.");
> + igt_subtest_with_dynamic("seamless-rr-switch") {
> + igt_require_intel(data.drm_fd);
> + run_vrr_test(&data, test_seamless_rr_basic,
> TEST_SEAMLESS_RR);
> + }
> +
> igt_fixture {
> igt_display_fini(&data.display);
> drm_close_driver(data.drm_fd);
> --
> 2.40.0
More information about the igt-dev
mailing list