[igt-dev] [PATCH i-g-t] tests/kms_plane_multiple: Add dual display subtest
Karthik B S
karthik.b.s at intel.com
Thu Mar 30 08:50:08 UTC 2023
Add subtest to validate MPO simultaneously on 2 displays.
Signed-off-by: Karthik B S <karthik.b.s at intel.com>
---
tests/kms_plane_multiple.c | 212 ++++++++++++++++++++++++++++---------
1 file changed, 163 insertions(+), 49 deletions(-)
diff --git a/tests/kms_plane_multiple.c b/tests/kms_plane_multiple.c
index 7dd9d586..91cf2c93 100644
--- a/tests/kms_plane_multiple.c
+++ b/tests/kms_plane_multiple.c
@@ -46,10 +46,10 @@ typedef struct {
typedef struct {
int drm_fd;
igt_display_t display;
- igt_crc_t ref_crc;
- igt_pipe_crc_t *pipe_crc;
- igt_plane_t **plane;
- struct igt_fb *fb;
+ igt_crc_t ref_crc1, ref_crc2;
+ igt_pipe_crc_t *pipe_crc1, *pipe_crc2;
+ igt_plane_t **plane1, **plane2;
+ struct igt_fb *fb1, *fb2;
} data_t;
/* Command line parameters. */
@@ -68,14 +68,14 @@ struct {
*/
static void test_init(data_t *data, enum pipe pipe, int n_planes)
{
- data->pipe_crc = igt_pipe_crc_new(data->drm_fd, pipe,
+ data->pipe_crc1 = igt_pipe_crc_new(data->drm_fd, pipe,
IGT_PIPE_CRC_SOURCE_AUTO);
- data->plane = calloc(n_planes, sizeof(*data->plane));
- igt_assert_f(data->plane != NULL, "Failed to allocate memory for planes\n");
+ data->plane1 = calloc(n_planes, sizeof(*data->plane1));
+ igt_assert_f(data->plane1 != NULL, "Failed to allocate memory for planes\n");
- data->fb = calloc(n_planes, sizeof(struct igt_fb));
- igt_assert_f(data->fb != NULL, "Failed to allocate memory for FBs\n");
+ data->fb1 = calloc(n_planes, sizeof(struct igt_fb));
+ igt_assert_f(data->fb1 != NULL, "Failed to allocate memory for FBs\n");
}
static void test_fini(data_t *data, igt_output_t *output, int n_planes)
@@ -83,21 +83,21 @@ static void test_fini(data_t *data, igt_output_t *output, int n_planes)
/* reset the constraint on the pipe */
igt_output_set_pipe(output, PIPE_ANY);
- igt_pipe_crc_free(data->pipe_crc);
- data->pipe_crc = NULL;
+ igt_pipe_crc_free(data->pipe_crc1);
+ data->pipe_crc1 = NULL;
- free(data->plane);
- data->plane = NULL;
+ free(data->plane1);
+ data->plane1 = NULL;
- free(data->fb);
- data->fb = NULL;
+ free(data->fb1);
+ data->fb1 = NULL;
igt_display_reset(&data->display);
}
static void
-get_reference_crc(data_t *data, igt_output_t *output, enum pipe pipe,
- color_t *color, uint64_t modifier)
+get_reference_crc(data_t *data, igt_output_t *output, enum pipe pipe, igt_pipe_crc_t *pipe_crc,
+ color_t *color, igt_plane_t **plane, uint64_t modifier, igt_crc_t *ref_crc)
{
drmModeModeInfo *mode;
igt_plane_t *primary;
@@ -107,7 +107,7 @@ get_reference_crc(data_t *data, igt_output_t *output, enum pipe pipe,
igt_output_set_pipe(output, pipe);
primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
- data->plane[primary->index] = primary;
+ plane[primary->index] = primary;
mode = igt_output_get_mode(output);
@@ -115,21 +115,21 @@ get_reference_crc(data_t *data, igt_output_t *output, enum pipe pipe,
DRM_FORMAT_XRGB8888,
modifier,
color->red, color->green, color->blue,
- &data->fb[primary->index]);
+ &data->fb1[primary->index]);
- igt_plane_set_fb(data->plane[primary->index], &data->fb[primary->index]);
+ igt_plane_set_fb(plane[primary->index], &data->fb1[primary->index]);
ret = igt_display_try_commit2(&data->display, COMMIT_ATOMIC);
igt_skip_on(ret != 0);
- igt_pipe_crc_collect_crc(data->pipe_crc, &data->ref_crc);
+ igt_pipe_crc_collect_crc(pipe_crc, ref_crc);
}
static void
create_fb_for_mode_position(data_t *data, igt_output_t *output, drmModeModeInfo *mode,
color_t *color, int *rect_x, int *rect_y,
int *rect_w, int *rect_h, uint64_t modifier,
- int max_planes)
+ int max_planes, igt_fb_t *fb)
{
unsigned int fb_id;
cairo_t *cr;
@@ -141,16 +141,16 @@ create_fb_for_mode_position(data_t *data, igt_output_t *output, drmModeModeInfo
mode->hdisplay, mode->vdisplay,
DRM_FORMAT_XRGB8888,
modifier,
- &data->fb[primary->index]);
+ &fb[primary->index]);
igt_assert(fb_id);
- cr = igt_get_cairo_ctx(data->drm_fd, &data->fb[primary->index]);
+ cr = igt_get_cairo_ctx(data->drm_fd, &fb[primary->index]);
igt_paint_color(cr, rect_x[0], rect_y[0],
mode->hdisplay, mode->vdisplay,
color->red, color->green, color->blue);
for (int i = 0; i < max_planes; i++) {
- if (data->plane[i]->type == DRM_PLANE_TYPE_PRIMARY)
+ if (data->plane1[i]->type == DRM_PLANE_TYPE_PRIMARY)
continue;
igt_paint_color(cr, rect_x[i], rect_y[i],
rect_w[i], rect_h[i], 0.0, 0.0, 0.0);
@@ -161,8 +161,8 @@ create_fb_for_mode_position(data_t *data, igt_output_t *output, drmModeModeInfo
static void
-prepare_planes(data_t *data, enum pipe pipe_id, color_t *color,
- uint64_t modifier, int max_planes, igt_output_t *output)
+prepare_planes(data_t *data, enum pipe pipe_id, color_t *color, igt_plane_t **plane,
+ uint64_t modifier, int max_planes, igt_output_t *output, igt_fb_t *fb)
{
drmModeModeInfo *mode;
igt_pipe_t *pipe;
@@ -222,15 +222,14 @@ prepare_planes(data_t *data, enum pipe pipe_id, color_t *color,
* Here is made assumption primary plane will have
* index zero.
*/
- igt_plane_t *plane = igt_output_get_plane(output, suffle[i]);
uint32_t plane_format;
uint64_t plane_modifier;
- data->plane[i] = plane;
+ plane[i] = igt_output_get_plane(output, suffle[i]);
- if (plane->type == DRM_PLANE_TYPE_PRIMARY)
+ if (plane[i]->type == DRM_PLANE_TYPE_PRIMARY)
continue;
- else if (plane->type == DRM_PLANE_TYPE_CURSOR)
+ else if (plane[i]->type == DRM_PLANE_TYPE_CURSOR)
size[i] = SIZE_CURSOR;
else
size[i] = SIZE_PLANE;
@@ -238,10 +237,10 @@ prepare_planes(data_t *data, enum pipe pipe_id, color_t *color,
x[i] = rand() % (mode->hdisplay - size[i]);
y[i] = rand() % (mode->vdisplay - size[i]);
- plane_format = data->plane[i]->type == DRM_PLANE_TYPE_CURSOR ? DRM_FORMAT_ARGB8888 : DRM_FORMAT_XRGB8888;
- plane_modifier = data->plane[i]->type == DRM_PLANE_TYPE_CURSOR ? DRM_FORMAT_MOD_LINEAR : modifier;
+ plane_format = plane[i]->type == DRM_PLANE_TYPE_CURSOR ? DRM_FORMAT_ARGB8888 : DRM_FORMAT_XRGB8888;
+ plane_modifier = plane[i]->type == DRM_PLANE_TYPE_CURSOR ? DRM_FORMAT_MOD_LINEAR : modifier;
- igt_skip_on(!igt_plane_has_format_mod(plane, plane_format,
+ igt_skip_on(!igt_plane_has_format_mod(plane[i], plane_format,
plane_modifier));
igt_create_color_fb(data->drm_fd,
@@ -249,17 +248,17 @@ prepare_planes(data_t *data, enum pipe pipe_id, color_t *color,
plane_format,
plane_modifier,
color->red, color->green, color->blue,
- &data->fb[i]);
+ &fb[i]);
- igt_plane_set_position(data->plane[i], x[i], y[i]);
- igt_plane_set_fb(data->plane[i], &data->fb[i]);
+ igt_plane_set_position(plane[i], x[i], y[i]);
+ igt_plane_set_fb(plane[i], &fb[i]);
}
/* primary plane */
- data->plane[primary->index] = primary;
+ plane[primary->index] = primary;
create_fb_for_mode_position(data, output, mode, color, x, y,
- size, size, modifier, max_planes);
- igt_plane_set_fb(data->plane[primary->index], &data->fb[primary->index]);
+ size, size, modifier, max_planes, &fb[primary->index]);
+ igt_plane_set_fb(plane[primary->index], &fb[primary->index]);
free((void*)x);
free((void*)y);
free((void*)size);
@@ -305,12 +304,13 @@ test_plane_position_with_output(data_t *data, enum pipe pipe,
test_init(data, pipe, n_planes);
- get_reference_crc(data, output, pipe, &blue, modifier);
+ get_reference_crc(data, output, pipe, data->pipe_crc1, &blue,
+ data->plane1, modifier, &data->ref_crc1);
/* Find out how many planes are allowed simultaneously */
do {
c++;
- prepare_planes(data, pipe, &blue, modifier, c, output);
+ prepare_planes(data, pipe, &blue, data->plane1, modifier, c, output, data->fb1);
err = igt_display_try_commit2(&data->display, COMMIT_ATOMIC);
for_each_plane_on_pipe(&data->display, pipe, plane)
@@ -320,7 +320,7 @@ test_plane_position_with_output(data_t *data, enum pipe pipe,
igt_display_commit2(&data->display, COMMIT_ATOMIC);
for (int x = 0; x < c; x++)
- igt_remove_fb(data->drm_fd, &data->fb[x]);
+ igt_remove_fb(data->drm_fd, &data->fb1[x]);
} while (!err && c < n_planes);
if (err)
@@ -334,14 +334,14 @@ test_plane_position_with_output(data_t *data, enum pipe pipe,
while (i < iterations || loop_forever) {
/* randomize planes and set up the holes */
- prepare_planes(data, pipe, &blue, modifier, c, output);
+ prepare_planes(data, pipe, &blue, data->plane1, modifier, c, output, data->fb1);
igt_display_commit2(&data->display, COMMIT_ATOMIC);
- igt_pipe_crc_start(data->pipe_crc);
+ igt_pipe_crc_start(data->pipe_crc1);
- igt_pipe_crc_get_current(data->display.drm_fd, data->pipe_crc, &crc);
- igt_assert_crc_equal(&data->ref_crc, &crc);
- igt_pipe_crc_stop(data->pipe_crc);
+ igt_pipe_crc_get_current(data->display.drm_fd, data->pipe_crc1, &crc);
+ igt_assert_crc_equal(&data->ref_crc1, &crc);
+ igt_pipe_crc_stop(data->pipe_crc1);
for_each_plane_on_pipe(&data->display, pipe, plane)
igt_plane_set_fb(plane, NULL);
@@ -350,7 +350,7 @@ test_plane_position_with_output(data_t *data, enum pipe pipe,
igt_display_commit2(&data->display, COMMIT_ATOMIC);
for (int x = 0; x < c; x++)
- igt_remove_fb(data->drm_fd, &data->fb[x]);
+ igt_remove_fb(data->drm_fd, &data->fb1[x]);
i++;
}
@@ -373,6 +373,108 @@ test_plane_position(data_t *data, enum pipe pipe, igt_output_t *output, uint64_t
n_planes, modifier);
}
+static void test_init_2_display(data_t *data, enum pipe pipe1, enum pipe pipe2)
+{
+ data->pipe_crc1 = igt_pipe_crc_new(data->drm_fd, pipe1,
+ IGT_PIPE_CRC_SOURCE_AUTO);
+ data->pipe_crc2 = igt_pipe_crc_new(data->drm_fd, pipe2,
+ IGT_PIPE_CRC_SOURCE_AUTO);
+
+ data->plane1 = calloc(2, sizeof(*data->plane1));
+ igt_assert_f(data->plane1 != NULL, "Failed to allocate memory for planes\n");
+
+ data->plane2 = calloc(2, sizeof(*data->plane2));
+ igt_assert_f(data->plane2 != NULL, "Failed to allocate memory for planes\n");
+
+ data->fb1 = calloc(2, sizeof(struct igt_fb));
+ igt_assert_f(data->fb1 != NULL, "Failed to allocate memory for FBs\n");
+
+ data->fb2 = calloc(2, sizeof(struct igt_fb));
+ igt_assert_f(data->fb2 != NULL, "Failed to allocate memory for FBs\n");
+}
+
+static void test_fini_2_display(data_t *data)
+{
+ igt_pipe_crc_stop(data->pipe_crc1);
+ igt_pipe_crc_stop(data->pipe_crc2);
+
+ igt_display_reset(&data->display);
+}
+
+static void test_plane_position_2_display(data_t *data, enum pipe pipe1, enum pipe pipe2,
+ igt_output_t *output1, igt_output_t *output2)
+{
+ color_t blue = { 0.0f, 0.0f, 1.0f };
+ igt_crc_t crc1, crc2;
+
+ test_init_2_display(data, pipe1, pipe2);
+ get_reference_crc(data, output1, pipe1, data->pipe_crc1, &blue,
+ data->plane1, DRM_FORMAT_MOD_LINEAR, &data->ref_crc1);
+ get_reference_crc(data, output2, pipe2, data->pipe_crc2, &blue,
+ data->plane2, DRM_FORMAT_MOD_LINEAR, &data->ref_crc2);
+
+ prepare_planes(data, pipe1, &blue, data->plane1, DRM_FORMAT_MOD_LINEAR, 2, output1, data->fb1);
+ prepare_planes(data, pipe2, &blue, data->plane2, DRM_FORMAT_MOD_LINEAR, 2, output2, data->fb2);
+
+ igt_display_commit2(&data->display, COMMIT_ATOMIC);
+ igt_pipe_crc_start(data->pipe_crc1);
+ igt_pipe_crc_start(data->pipe_crc2);
+
+ igt_pipe_crc_get_current(data->display.drm_fd, data->pipe_crc1, &crc1);
+ igt_pipe_crc_get_current(data->display.drm_fd, data->pipe_crc2, &crc2);
+
+ igt_assert_crc_equal(&data->ref_crc1, &crc1);
+ igt_assert_crc_equal(&data->ref_crc2, &crc2);
+}
+
+#define for_each_connected_output_local(display, output) \
+ for (int j__ = 0; assert(igt_can_fail()), j__ < (display)->n_outputs; j__++) \
+ for_each_if((((output) = &(display)->outputs[j__]), \
+ igt_output_is_connected((output))))
+
+#define for_each_valid_output_on_pipe_local(display, pipe, output) \
+ for_each_connected_output_local((display), (output)) \
+ for_each_if(igt_pipe_connector_valid((pipe), (output)))
+
+static void run_2_display_test(data_t *data)
+{
+ enum pipe pipe1, pipe2;
+ igt_output_t *output1, *output2;
+ igt_display_t *display = &data->display;
+
+ igt_display_reset(display);
+
+ for_each_pipe(display, pipe1) {
+ for_each_valid_output_on_pipe(display, pipe1, output1) {
+ for_each_pipe(display, pipe2) {
+ if (pipe1 == pipe2)
+ continue;
+
+ for_each_valid_output_on_pipe_local(display, pipe2, output2) {
+ if (output1 == output2)
+ continue;
+
+ igt_display_reset(display);
+
+ igt_output_set_pipe(output1, pipe1);
+ igt_output_set_pipe(output2, pipe2);
+
+ if (!i915_pipe_output_combo_valid(display))
+ continue;
+
+ igt_dynamic_f("pipe-%s-%s-pipe-%s-%s",
+ kmstest_pipe_name(pipe1), output1->name,
+ kmstest_pipe_name(pipe2), output2->name)
+ test_plane_position_2_display(data, pipe1, pipe2,
+ output1, output2);
+
+ test_fini_2_display(data);
+ }
+ }
+ }
+ }
+}
+
static void run_test(data_t *data, uint64_t modifier)
{
enum pipe pipe;
@@ -476,6 +578,18 @@ igt_main_args("", long_options, help_str, opt_handler, NULL)
run_test(&data, subtests[i].modifier);
}
+ igt_subtest_with_dynamic("2x-outputs") {
+ int valid_outputs = 0;
+ igt_output_t *output;
+
+ for_each_connected_output(&data.display, output)
+ valid_outputs++;
+
+ igt_require(valid_outputs > 1);
+
+ run_2_display_test(&data);
+ }
+
igt_fixture {
igt_display_fini(&data.display);
close(data.drm_fd);
--
2.39.1
More information about the igt-dev
mailing list