[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