[igt-dev] [PATCH i-g-t v4 05/11] tests/amdgpu/amd_plane: Create mpo panning test
Stylon Wang
stylon.wang at amd.com
Mon Dec 6 09:02:02 UTC 2021
From: Bhawanpreet Lakha <Bhawanpreet.Lakha at amd.com>
[Why]
Moving the MPO window is a common usecase (video window being moved).
This test creates a MPO window and moves it horizontally, vertically and
diagonally
[How]
Create common video resolution windows and move them across the
displays. Test pass is determined by getting a crc of window location
using a single plane, then recreating this scenario using overlay.
Test panes from Start->End1, Start->End2 and Start->End3
CRTC#1
Start
+--------+--------+--------+
|Primary | --> |Primary | End1
+--------+ +--------+
| | \ Overlay |
| v * |
+--------+ \ +--------+
|Primary | |Primary | End2
+--------+--------+--------+
End3
Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha at amd.com>
---
tests/amdgpu/amd_plane.c | 261 +++++++++++++++++++++++++++++++++++++++
1 file changed, 261 insertions(+)
diff --git a/tests/amdgpu/amd_plane.c b/tests/amdgpu/amd_plane.c
index 5666b9e7..09fcf3eb 100644
--- a/tests/amdgpu/amd_plane.c
+++ b/tests/amdgpu/amd_plane.c
@@ -26,6 +26,13 @@
/* Maximum pipes on any AMD ASIC. */
#define MAX_PIPES 6
+#define DISPLAYS_TO_TEST 2
+
+/* (De)gamma LUT. */
+typedef struct lut {
+ struct drm_color_lut *data;
+ uint32_t size;
+} lut_t;
/* Common test data. */
typedef struct data {
@@ -79,6 +86,63 @@ static const drmModeModeInfo test_mode_2 = {
.vscan = 0,
};
+static const drmModeModeInfo test_mode_3 = {
+ .name = "3840x2160 Test",
+ .vrefresh = 60,
+ .clock = 594000,
+ .hdisplay = 3840,
+ .hsync_start = 4016,
+ .hsync_end = 4104,
+ .htotal = 4400,
+ .vdisplay = 2160,
+ .vsync_start = 2168,
+ .vsync_end = 2178,
+ .vtotal = 2250,
+ .type = DRM_MODE_TYPE_DRIVER,
+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+ .hskew = 0,
+ .vscan = 0,
+};
+
+static void lut_init(lut_t *lut, uint32_t size)
+{
+ igt_assert(size > 0);
+ lut->size = size;
+ lut->data = malloc(size * sizeof(struct drm_color_lut));
+ igt_assert(lut);
+}
+static void lut_gen(lut_t *lut)
+{
+ uint32_t i;
+ /* 10% threshold */
+ uint32_t threshold = (256 * 10) / 100;
+
+ for (i = 0; i < threshold; ++i) {
+ uint32_t v = 0;
+ lut->data[i].red = v;
+ lut->data[i].blue = v;
+ lut->data[i].green = v;
+ }
+ for (i = threshold; i < lut->size; ++i) {
+ uint32_t v = 0xffff;
+ lut->data[i].red = v;
+ lut->data[i].blue = v;
+ lut->data[i].green = v;
+ }
+}
+static void lut_free(lut_t *lut)
+{
+ if (lut->data) {
+ free(lut->data);
+ lut->data = NULL;
+ }
+ lut->size = 0;
+}
+
+enum test {
+ MPO_SINGLE_PAN
+};
+
static void test_init(data_t *data)
{
igt_display_t *display = &data->display;
@@ -174,10 +238,205 @@ static void draw_color_alpha(igt_fb_t *fb, int x, int y, int w, int h,
double r, double g, double b, double a)
{
cairo_t *cr = igt_get_cairo_ctx(fb->fd, fb);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
igt_paint_color_alpha(cr, x, y, w, h, r, g, b, a);
igt_put_cairo_ctx(cr);
}
+struct fbc {
+ igt_fb_t ref_primary;
+ igt_fb_t test_primary;
+ igt_fb_t test_overlay;
+ igt_crc_t ref_crc;
+};
+
+/* Sets the regamma LUT. */
+static void set_regamma_lut(data_t *data, lut_t const *lut, int n)
+{
+ size_t size = lut ? sizeof(lut->data) * lut->size : 0;
+ const void *ptr = lut ? lut->data : NULL;
+ igt_pipe_obj_replace_prop_blob(data->pipe[n], IGT_CRTC_GAMMA_LUT, ptr,
+ size);
+}
+
+/*
+ * Compares the result of white backgroud with white window with and without MPO
+ *
+ * Reference crc:
+ * Draws a White background of size (pw,ph).
+ *
+ * Test crc:
+ * Draws a White Overlay of size (pw,ph) then creates a cutout of size (p,w) at location (x,y)
+ * Draws a White Primary plane of size (p,w) at location (x,y) (under the overlay)
+ *
+ * NOTE: The reason for using White+White is to speed up the crc (reuse the ref crc for all cases vs taking
+ * a ref crc per flip)
+ */
+static void test_plane(data_t *data, int n, int x, int y, int w, int h, int pw, int ph, struct fbc *fbc){
+
+ igt_crc_t test_crc;
+ igt_display_t *display = &data->display;
+
+ /* Reference: */
+
+ igt_plane_set_fb(data->primary[n], &fbc[n].ref_primary);
+
+ igt_plane_set_position(data->primary[n], 0, 0);
+ igt_plane_set_size(data->primary[n], pw, ph);
+
+ igt_display_commit_atomic(display, 0, 0);
+
+ /* Test: */
+ /* Draw a white overlay with a cutout */
+ draw_color_alpha(&fbc[n].test_overlay, 0, 0, pw, ph, 1.0, 1.0, 1.0, 1.00);
+ draw_color_alpha(&fbc[n].test_overlay, x, y, w, h, 0.0, 0.0, 0.0, 0.0);
+
+ igt_plane_set_fb(data->primary[n], &fbc[n].test_primary);
+ igt_plane_set_fb(data->overlay[n], &fbc[n].test_overlay);
+
+ /* Move the overlay to cover the cutout */
+ igt_plane_set_position(data->primary[n], x, y);
+ igt_plane_set_size(data->primary[n], w, h);
+
+ igt_display_commit_atomic(display, 0, 0);
+ igt_pipe_crc_collect_crc(data->pipe_crc[n], &test_crc);
+ igt_plane_set_fb(data->overlay[n], NULL);
+
+ igt_assert_crc_equal(&fbc[n].ref_crc, &test_crc);
+
+ /* Set window to white, this is to avoid flashing between black/white after each flip */
+ draw_color_alpha(&fbc[n].ref_primary, 0, 0, pw, ph, 1.0, 1.0, 1.0, 1.00);
+ igt_plane_set_fb(data->primary[n], &fbc[n].ref_primary);
+ igt_plane_set_position(data->primary[n], 0, 0);
+ igt_plane_set_size(data->primary[n], pw, ph);
+ igt_display_commit_atomic(display, 0, 0);
+
+
+}
+/*
+ * MPO_SINGLE_PAN: This test moves the window (w,h) horizontally, vertically and diagonally
+ * Horizontal: from top-left (0,0) to top-right (pw-w,0)
+ * Vertical: from top-left (0,0) to bottom-left (0,ph-h)
+ * Diagonal: from top-left (0,0) to bottom-right (pw-w, ph-h)
+ */
+static void test_panning_1_display(data_t *data, int display_count, int w, int h, struct fbc *fb)
+{
+ /* x and y movements */
+ int dir[3][2]= {
+ {0,1}, /* Only Y */
+ {1,0}, /* Only X */
+ {1,1}, /* Both X and Y */
+
+ };
+
+ /* # of iterations to use to move from one side to the other */
+ int it = 3;
+
+ for (int n = 0; n < display_count; n++) {
+
+ int pw = data->w[n];
+ int ph = data->h[n];
+ int dx = (pw-w)/it;
+ int dy = (ph-h)/it;
+
+ for (int i = 0; i < ARRAY_SIZE(dir); i++){
+ for (int j = 0; j <= it; j++){
+
+ int x = dx*j*dir[i][0];
+ int y = dy*j*dir[i][1];
+
+ /* No need to pan a overley that is bigger than the display */
+ if (pw <= w && ph <= h)
+ break;
+
+ test_plane(data, n, x, y, w, h, pw, ph, fb);
+
+ }
+ }
+ }
+
+ return;
+
+
+}
+
+
+/*
+ * Setup and runner for panning test. Creates common video sizes and pans them across the display
+ */
+static void test_display_mpo(data_t *data, enum test test, uint32_t format, int display_count)
+{
+
+ igt_display_t *display = &data->display;
+ uint32_t regamma_lut_size;
+ lut_t lut;
+ struct fbc fb[4];
+ int videos[][2]= {
+ {426, 240},
+ {640, 360},
+ {854, 480},
+ {1280, 720},
+ {1920, 1080},
+ {2560, 1440},
+ {3840, 2160},
+ };
+
+ test_init(data);
+
+ regamma_lut_size = igt_pipe_obj_get_prop(data->pipe[0], IGT_CRTC_GAMMA_LUT_SIZE);
+ igt_assert_lt(0, regamma_lut_size);
+ lut_init(&lut, regamma_lut_size);
+ lut_gen(&lut);
+
+ for (int n = 0; n < display_count; n++) {
+ int w = data->w[n];
+ int h = data->h[n];
+
+ if (w == 0) {
+ force_output_mode(data, data->output[n], &test_mode_3);
+ w = data->w[n] = test_mode_3.hdisplay;
+ h = data->h[n] = test_mode_3.vdisplay;
+ }
+
+ igt_output_set_pipe(data->output[n], data->pipe_id[n]);
+
+ igt_create_fb(data->fd, w, h, DRM_FORMAT_XRGB8888, 0, &fb[n].ref_primary);
+ igt_create_color_fb(data->fd, w, h, DRM_FORMAT_XRGB8888, 0, 1.0, 1.0, 1.0, &fb[n].ref_primary);
+ igt_create_fb(data->fd, w, h, DRM_FORMAT_ARGB8888, 0, &fb[n].test_overlay);
+
+ igt_plane_set_fb(data->primary[n], &fb[n].ref_primary);
+
+ if (format == DRM_FORMAT_NV12)
+ set_regamma_lut(data, &lut, n);
+ }
+
+ igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET, 0);
+
+ for (int n = 0; n < display_count; n++)
+ igt_pipe_crc_collect_crc(data->pipe_crc[n], &fb[n].ref_crc);
+
+ for (int i = 0; i < ARRAY_SIZE(videos); ++i) {
+
+ for (int n = 0; n < display_count; n++)
+ igt_create_color_fb(data->fd, videos[i][0], videos[i][1],
+ format, 0, 1.0, 1.0, 1.0, &fb[n].test_primary);
+
+ if (test == MPO_SINGLE_PAN)
+ test_panning_1_display(data, display_count, videos[i][0], videos[i][1], fb);
+
+ for (int n = 0; n < display_count; n++)
+ igt_remove_fb(data->fd, &fb[n].test_primary);
+ }
+
+ test_fini(data);
+
+ lut_free(&lut);
+
+ for (int n = 0; n < display_count; n++) {
+ igt_remove_fb(data->fd, &fb[n].ref_primary);
+ igt_remove_fb(data->fd, &fb[n].test_overlay);
+ }
+}
/*
* Compares a white 4K reference FB against a white 4K primary FB and a
* white 4K overlay with an RGBA (0, 0, 0, 0) cutout in the center.
@@ -395,6 +654,8 @@ igt_main
igt_subtest("mpo-swizzle-toggle") test_mpo_swizzle_toggle(&data);
igt_subtest("mpo-swizzle-toggle-multihead")
test_mpo_swizzle_toggle_multihead(&data);
+ igt_subtest("mpo-pan-rgb") test_display_mpo(&data, MPO_SINGLE_PAN, DRM_FORMAT_XRGB8888, DISPLAYS_TO_TEST);
+ igt_subtest("mpo-pan-nv12") test_display_mpo(&data, MPO_SINGLE_PAN, DRM_FORMAT_NV12, DISPLAYS_TO_TEST);
igt_fixture
{
--
2.33.1
More information about the igt-dev
mailing list