summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJuha-Pekka Heikkila <juhapekka.heikkila@gmail.com>2018-11-30 15:34:36 +0200
committerJuha-Pekka Heikkila <juhapekka.heikkila@gmail.com>2018-12-04 13:26:38 +0200
commit14c1b132c8f829637c55fb071a9a2e5ce00e7ed8 (patch)
tree41e77c4c4856771828c4a4adcc5f60e1b9d14eb7 /tests
parent333f1386dcfc8d94830cf6458393cefdee6d4663 (diff)
tests/kms_rotation_crc: Add multi plane tests
Add three new tests which try primary and sprite planes next to each other with different plane formats, rotations and tiling modes. multiplane-rotation subtest run test through with both planes fully visible. multiplane-rotation-cropping-top will crop primary plane to left/top corner and sprite plane to right/top corner while running rotation tests. multiplane-rotation-cropping-bottom will crop primary plane to left/bottom corner and sprite plane to right/bottom corner while running rotation tests. v2 (Nautiyal, Ankit K): Use rectangular figures instead of square figures and fix associated code to perform correctly. Adjust plane positions according to screen size to avoid putting planes outside screen. v3 (Nautiyal, Ankit K): Minor detail fix. Signed-off-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com> Reviewed-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/kms_rotation_crc.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/tests/kms_rotation_crc.c b/tests/kms_rotation_crc.c
index 366c2546e..369936f94 100644
--- a/tests/kms_rotation_crc.c
+++ b/tests/kms_rotation_crc.c
@@ -26,6 +26,25 @@
#include <math.h>
#define MAX_FENCES 32
+#define MAXMULTIPLANESAMOUNT 2
+
+struct p_struct {
+ igt_plane_t *plane;
+ struct igt_fb fb;
+};
+
+enum p_pointorigo {
+ p_top = 1 << 0,
+ p_bottom = 1 << 1,
+ p_left = 1 << 2,
+ p_right = 1 << 3
+};
+
+struct p_point{
+ enum p_pointorigo origo;
+ float_t x;
+ float_t y;
+};
typedef struct {
int gfx_fd;
@@ -43,6 +62,9 @@ typedef struct {
uint32_t override_fmt;
uint64_t override_tiling;
int devid;
+
+ struct p_struct *multiplaneoldview;
+ struct p_point planepos[MAXMULTIPLANESAMOUNT];
} data_t;
typedef struct {
@@ -395,6 +417,194 @@ static void test_plane_rotation(data_t *data, int plane_type, bool test_bad_form
}
}
+typedef struct {
+ int32_t x1, y1;
+ uint64_t width, height, tiling, planetype, format;
+ igt_rotation_t rotation_sw, rotation_hw;
+} planeinfos;
+
+static void get_multiplane_crc(data_t *data, igt_output_t *output,
+ igt_crc_t *crc_output, planeinfos *planeinfo,
+ int numplanes)
+{
+ uint32_t w, h;
+ igt_display_t *display = &data->display;
+ struct p_struct *planes, *oldplanes;
+ int c, ret;
+
+ oldplanes = data->multiplaneoldview;
+ planes = malloc(sizeof(*planes) * numplanes);
+
+ for (c = 0; c < numplanes; c++) {
+ planes[c].plane = igt_output_get_plane_type(output,
+ planeinfo[c].planetype);
+
+ w = planeinfo[c].width;
+ h = planeinfo[c].height;
+
+ if (planeinfo[c].rotation_sw & (IGT_ROTATION_90 | IGT_ROTATION_270))
+ igt_swap(w, h);
+
+ igt_create_fb(data->gfx_fd, w, h, planeinfo[c].format,
+ planeinfo[c].tiling, &planes[c].fb);
+
+ paint_squares(data, planeinfo[c].rotation_sw, &planes[c].fb, 1.0f);
+ igt_plane_set_fb(planes[c].plane, &planes[c].fb);
+
+ if (planeinfo[c].rotation_hw & (IGT_ROTATION_90 | IGT_ROTATION_270))
+ igt_plane_set_size(planes[c].plane, h, w);
+
+ igt_plane_set_position(planes[c].plane, planeinfo[c].x1, planeinfo[c].y1);
+ igt_plane_set_rotation(planes[c].plane, planeinfo[c].rotation_hw);
+ }
+
+ ret = igt_display_try_commit2(display, COMMIT_ATOMIC);
+ igt_assert_eq(ret, 0);
+
+ igt_pipe_crc_get_current(data->gfx_fd, data->pipe_crc, crc_output);
+
+ for (c = 0; c < numplanes && oldplanes; c++)
+ igt_remove_fb(data->gfx_fd, &oldplanes[c].fb);
+
+ free(oldplanes);
+ data->multiplaneoldview = (void*)planes;
+}
+
+static void pointlocation(data_t *data, planeinfos *p, drmModeModeInfo *mode,
+ int c)
+{
+ p[c].x1 = (int32_t)(data->planepos[c].x * mode->hdisplay)
+ + ((data->planepos[c].origo & p_right) ? mode->hdisplay : 0);
+ p[c].y1 = (int32_t)(data->planepos[c].y * mode->vdisplay)
+ + ((data->planepos[c].origo & p_bottom) ? mode->vdisplay : 0);
+}
+
+/*
+ * Here is pipe parameter which is now used only for first pipe.
+ * It is left here if this test ever was wanted to be run on
+ * different pipes.
+ */
+static void test_multi_plane_rotation(data_t *data, enum pipe pipe)
+{
+ igt_display_t *display = &data->display;
+ igt_output_t *output;
+ igt_crc_t retcrc_sw, retcrc_hw;
+ planeinfos p[2];
+ int c;
+ struct p_struct *oldplanes;
+ drmModeModeInfo *mode;
+
+ const static struct {
+ igt_rotation_t rotation;
+ float_t width;
+ float_t height;
+ uint64_t tiling;
+ } planeconfigs[] = {
+ {IGT_ROTATION_0, .2f, .4f, LOCAL_DRM_FORMAT_MOD_NONE },
+ {IGT_ROTATION_0, .2f, .4f, LOCAL_I915_FORMAT_MOD_X_TILED },
+ {IGT_ROTATION_0, .2f, .4f, LOCAL_I915_FORMAT_MOD_Y_TILED },
+ {IGT_ROTATION_0, .2f, .4f, LOCAL_I915_FORMAT_MOD_Yf_TILED },
+ {IGT_ROTATION_90, .2f, .4f, LOCAL_I915_FORMAT_MOD_Y_TILED },
+ {IGT_ROTATION_90, .2f, .4f, LOCAL_I915_FORMAT_MOD_Yf_TILED },
+ {IGT_ROTATION_180, .2f, .4f, LOCAL_DRM_FORMAT_MOD_NONE },
+ {IGT_ROTATION_180, .2f, .4f, LOCAL_I915_FORMAT_MOD_X_TILED },
+ {IGT_ROTATION_180, .2f, .4f, LOCAL_I915_FORMAT_MOD_Y_TILED },
+ {IGT_ROTATION_180, .2f, .4f, LOCAL_I915_FORMAT_MOD_Yf_TILED },
+ {IGT_ROTATION_270, .2f, .4f, LOCAL_I915_FORMAT_MOD_Y_TILED },
+ {IGT_ROTATION_270, .2f, .4f, LOCAL_I915_FORMAT_MOD_Yf_TILED },
+ };
+
+ /*
+ * These are those modes which are tested. For testing feel interesting
+ * case with tiling are 2 byte wide and 4 byte wide.
+ *
+ * TODO:
+ * Built support for NV12 here.
+ */
+ const static uint32_t formatlist[] = {DRM_FORMAT_RGB565,
+ DRM_FORMAT_XRGB8888};
+
+ for_each_valid_output_on_pipe(display, pipe, output) {
+ int i, j, k, l;
+ igt_output_set_pipe(output, pipe);
+ mode = igt_output_get_mode(output);
+ igt_display_require_output(display);
+ igt_display_commit2(display, COMMIT_ATOMIC);
+
+ data->pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe,
+ INTEL_PIPE_CRC_SOURCE_AUTO);
+ igt_pipe_crc_start(data->pipe_crc);
+
+ for (i = 0; i < ARRAY_SIZE(planeconfigs); i++) {
+ p[0].planetype = DRM_PLANE_TYPE_PRIMARY;
+ p[0].width = (uint64_t)(planeconfigs[i].width * mode->hdisplay);
+ p[0].height = (uint64_t)(planeconfigs[i].height * mode->vdisplay);
+ p[0].tiling = planeconfigs[i].tiling;
+ pointlocation(data, (planeinfos *)&p, mode, 0);
+
+ for (k = 0; k < ARRAY_SIZE(formatlist); k++) {
+ p[0].format = formatlist[k];
+
+ for (j = 0; j < ARRAY_SIZE(planeconfigs); j++) {
+ p[1].planetype = DRM_PLANE_TYPE_OVERLAY;
+ p[1].width = (uint64_t)(planeconfigs[j].width * mode->hdisplay);
+ p[1].height = (uint64_t)(planeconfigs[j].height * mode->vdisplay);
+ p[1].tiling = planeconfigs[j].tiling;
+ pointlocation(data, (planeinfos *)&p,
+ mode, 1);
+
+ for (l = 0; l < ARRAY_SIZE(formatlist); l++) {
+ p[1].format = formatlist[l];
+
+ /*
+ * RGB565 90/270 degrees rotation is supported
+ * from gen11 onwards.
+ */
+ if (p[0].format == DRM_FORMAT_RGB565 &&
+ (planeconfigs[i].rotation & (IGT_ROTATION_90 | IGT_ROTATION_270))
+ && intel_gen(data->devid) < 11)
+ continue;
+
+ if (p[1].format == DRM_FORMAT_RGB565 &&
+ (planeconfigs[j].rotation & (IGT_ROTATION_90 | IGT_ROTATION_270))
+ && intel_gen(data->devid) < 11)
+ continue;
+
+ p[0].rotation_sw = planeconfigs[i].rotation;
+ p[0].rotation_hw = IGT_ROTATION_0;
+ p[1].rotation_sw = planeconfigs[j].rotation;
+ p[1].rotation_hw = IGT_ROTATION_0;
+ get_multiplane_crc(data, output, &retcrc_sw,
+ (planeinfos *)&p, MAXMULTIPLANESAMOUNT);
+
+ igt_swap(p[0].rotation_sw, p[0].rotation_hw);
+ igt_swap(p[1].rotation_sw, p[1].rotation_hw);
+ get_multiplane_crc(data, output, &retcrc_hw,
+ (planeinfos *)&p, MAXMULTIPLANESAMOUNT);
+
+ igt_assert_crc_equal(&retcrc_sw, &retcrc_hw);
+ }
+ }
+ }
+ }
+ igt_pipe_crc_stop(data->pipe_crc);
+ igt_pipe_crc_free(data->pipe_crc);
+ igt_output_set_pipe(output, PIPE_ANY);
+ }
+
+ /*
+ * Old fbs are deleted only after new ones are set on planes.
+ * This is done to speed up the test
+ */
+ oldplanes = data->multiplaneoldview;
+ for (c = 0; c < MAXMULTIPLANESAMOUNT && oldplanes; c++)
+ igt_remove_fb(data->gfx_fd, &oldplanes[c].fb);
+
+ free(oldplanes);
+ data->multiplaneoldview = NULL;
+ data->pipe_crc = NULL;
+}
+
static void test_plane_rotation_exhaust_fences(data_t *data,
enum pipe pipe,
igt_output_t *output,
@@ -595,6 +805,42 @@ igt_main
}
}
+ igt_subtest_f("multiplane-rotation") {
+ igt_require(gen >= 9);
+ cleanup_crtc(&data);
+ data.planepos[0].origo = p_top | p_left;
+ data.planepos[0].x = .2f;
+ data.planepos[0].y = .1f;
+ data.planepos[1].origo = p_top | p_right;
+ data.planepos[1].x = -.4f;
+ data.planepos[1].y = .1f;
+ test_multi_plane_rotation(&data, 0);
+ }
+
+ igt_subtest_f("multiplane-rotation-cropping-top") {
+ igt_require(gen >= 9);
+ cleanup_crtc(&data);
+ data.planepos[0].origo = p_top | p_left;
+ data.planepos[0].x = -.05f;
+ data.planepos[0].y = -.15f;
+ data.planepos[1].origo = p_top | p_right;
+ data.planepos[1].x = -.15f;
+ data.planepos[1].y = -.15f;
+ test_multi_plane_rotation(&data, 0);
+ }
+
+ igt_subtest_f("multiplane-rotation-cropping-bottom") {
+ igt_require(gen >= 9);
+ cleanup_crtc(&data);
+ data.planepos[0].origo = p_bottom | p_left;
+ data.planepos[0].x = -.05f;
+ data.planepos[0].y = -.20f;
+ data.planepos[1].origo = p_bottom | p_right;
+ data.planepos[1].x = -.15f;
+ data.planepos[1].y = -.20f;
+ test_multi_plane_rotation(&data, 0);
+ }
+
/*
* exhaust-fences should be last test, if it fails we may OOM in
* the following subtests otherwise.