[i-g-t V2 1/2] tests/kms_vrr: New subtest to swith RR without modeset
Bhanuprakash Modem
bhanuprakash.modem at intel.com
Mon Nov 27 11:09:54 UTC 2023
V2: - Add DRRS seamless support
Signed-off-by: Bhanuprakash Modem <bhanuprakash.modem at intel.com>
---
tests/kms_vrr.c | 185 +++++++++++++++++++++++++++++++++++++++---------
1 file changed, 152 insertions(+), 33 deletions(-)
diff --git a/tests/kms_vrr.c b/tests/kms_vrr.c
index 13b347631..14c585600 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.
*/
@@ -65,19 +69,19 @@
*/
#define TEST_DURATION_NS (5000000000ull)
-#define DRM_MODE_FMT "\"%s\": %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x"
-#define DRM_MODE_ARG(m) \
- (m)->name, (m)->vrefresh, (m)->clock, \
- (m)->hdisplay, (m)->hsync_start, (m)->hsync_end, (m)->htotal, \
- (m)->vdisplay, (m)->vsync_start, (m)->vsync_end, (m)->vtotal, \
- (m)->type, (m)->flags
+enum {
+ HIGH_RR_MODE,
+ LOW_RR_MODE,
+ RR_MODES_COUNT,
+};
enum {
TEST_BASIC = 1 << 0,
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,
};
typedef struct range {
@@ -92,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 {
@@ -162,15 +167,11 @@ output_mode_with_maxrate(igt_output_t *output, unsigned int vrr_max)
drmModeConnectorPtr connector = output->config.connector;
drmModeModeInfo mode = *igt_output_get_mode(output);
- igt_debug("Default Mode " DRM_MODE_FMT "\n", DRM_MODE_ARG(&mode));
-
for (i = 0; i < connector->count_modes; i++)
if (connector->modes[i].vrefresh > mode.vrefresh &&
connector->modes[i].vrefresh <= vrr_max)
mode = connector->modes[i];
- igt_debug("Override Mode " DRM_MODE_FMT "\n", DRM_MODE_ARG(&mode));
-
return mode;
}
@@ -238,19 +239,7 @@ static void prepare_test(data_t *data, igt_output_t *output, enum pipe pipe)
drmModeModeInfo mode;
cairo_t *cr;
- /* Reset output */
- igt_display_reset(&data->display);
- igt_output_set_pipe(output, pipe);
-
- /* Capture VRR range */
- data->range = get_vrr_range(data, output);
-
- /* Override mode with max vrefresh.
- * - 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);
- igt_require(mode.vrefresh > data->range.min);
+ mode = data->switch_modes[HIGH_RR_MODE];
data->range.max = mode.vrefresh;
igt_output_override_mode(output, &mode);
@@ -340,7 +329,7 @@ flip_and_measure(data_t *data, igt_output_t *output, enum pipe pipe,
*/
event_ns = get_kernel_event_ns(data, DRM_EVENT_FLIP_COMPLETE);
- igt_debug("event_ns - last_event_ns: %"PRIu64"\n",
+ igt_info("event_ns - last_event_ns: %"PRIu64"\n",
(event_ns - last_event_ns));
/*
@@ -485,6 +474,136 @@ test_basic(data_t *data, enum pipe pipe, igt_output_t *output, uint32_t flags)
igt_remove_fb(data->drm_fd, &data->fb0);
}
+static void
+test_seamless_rr_basic(data_t *data, enum pipe pipe, igt_output_t *output, uint32_t flags)
+{
+ uint32_t result;
+ vtest_ns_t vtest_ns;
+ range_t range;
+ uint64_t rate;
+
+ igt_info("Use HIGH_RR Mode as default: ");
+ kmstest_dump_mode(&data->switch_modes[HIGH_RR_MODE]);
+
+ prepare_test(data, output, pipe);
+ range = data->range;
+ vtest_ns = get_test_rate_ns(range);
+
+ rate = vtest_ns.max;
+ result = flip_and_measure(data, output, pipe, rate, TEST_DURATION_NS);
+ igt_info("Refresh rate (%u Hz) %"PRIu64"ns: %u%%\n", range.max, rate, result);
+
+ /* Switch to low rr mode without modeset. */
+ igt_info("Override with LOW_RR Mode: ");
+ 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_info("Refresh rate (%u Hz) %"PRIu64"ns: %u%%\n", range.min, rate, result);
+
+ /* Switch back to high rr mode without modeset. */
+ igt_info("Override with HIGH_RR Mode: ");
+ 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);
+
+ /* 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);
+}
+
+static bool output_constraint(data_t *data, igt_output_t *output, uint32_t flags)
+{
+ /* Reset output */
+ igt_display_reset(&data->display);
+
+ /* Capture VRR range */
+ data->range = get_vrr_range(data, output);
+
+ /* Override mode with max vrefresh.
+ * - vrr_min range should be less than the override mode vrefresh.
+ * - Limit the vrr_max range with the override mode vrefresh.
+ */
+ 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;
+
+ if (!(flags & TEST_SEAMLESS_RR))
+ return true;
+
+ /* Search for a low refresh rate mode */
+ for_each_connector_mode(output) {
+ drmModeModeInfo mode = output->config.connector->modes[j__];
+
+ /* TODO: improve checks for downclock */
+ if (mode.hdisplay != data->switch_modes[HIGH_RR_MODE].hdisplay ||
+ mode.vdisplay != data->switch_modes[HIGH_RR_MODE].vdisplay)
+ continue;
+
+ if (mode.vrefresh >= data->switch_modes[HIGH_RR_MODE].vrefresh ||
+ mode.vrefresh < data->range.min)
+ continue;
+
+ data->switch_modes[LOW_RR_MODE] = mode;
+
+ return true;
+ }
+
+ return false;
+}
+
+static bool drrs_capable(data_t *data, igt_output_t *output)
+{
+ if (output->config.connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+ return false;
+
+ /*
+ * FIXME to read the DRRS capability, currently assuming:
+ * - Panel should contain 2 modes only
+ * - Both modes should have the same resolution but different RR
+ */
+ if (output->config.connector->count_modes != 2)
+ return false;
+
+ data->switch_modes[HIGH_RR_MODE] = output->config.connector->modes[0];
+ data->switch_modes[LOW_RR_MODE] = output->config.connector->modes[1];
+
+ if (data->switch_modes[HIGH_RR_MODE].hdisplay != data->switch_modes[LOW_RR_MODE].hdisplay ||
+ data->switch_modes[HIGH_RR_MODE].vdisplay != data->switch_modes[LOW_RR_MODE].vdisplay ||
+ data->switch_modes[HIGH_RR_MODE].vrefresh <= data->switch_modes[LOW_RR_MODE].vrefresh)
+ return false;
+
+ return true;
+}
+
+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) && !vrr_capable(output))
+ return drrs_capable(data, output);
+
+ /* For Negative tests, panel should be non-vrr. */
+ if ((flags & TEST_NEGATIVE) && vrr_capable(output))
+ return false;
+
+ if (!(flags & TEST_NEGATIVE) && !vrr_capable(output))
+ return false;
+
+ if (!output_constraint(data, output, flags))
+ return false;
+
+ return true;
+}
+
/* Runs tests on outputs that are VRR capable. */
static void
run_vrr_test(data_t *data, test_t test, uint32_t flags)
@@ -494,14 +613,7 @@ run_vrr_test(data_t *data, test_t test, uint32_t flags)
for_each_connected_output(&data->display, output) {
enum pipe pipe;
- if (!has_vrr(output))
- continue;
-
- /* For Negative tests, panel should be non-vrr. */
- if ((flags & TEST_NEGATIVE) && vrr_capable(output))
- continue;
-
- if ((flags & ~TEST_NEGATIVE) && !vrr_capable(output))
+ if (!config_constraint(data, output, flags))
continue;
for_each_pipe(&data->display, pipe) {
@@ -509,6 +621,7 @@ run_vrr_test(data_t *data, test_t test, uint32_t flags)
igt_display_reset(&data->display);
igt_output_set_pipe(output, pipe);
+ igt_output_override_mode(output, &data->switch_modes[HIGH_RR_MODE]);
if (!intel_pipe_output_combo_valid(&data->display))
continue;
@@ -558,6 +671,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 Intel-gfx-trybot
mailing list