[igt-dev] [PATCH 3/4] tests/amdgpu/amd_psr: use double framebuffers to emulate MPO case

David Zhang dingchen.zhang at amd.com
Thu May 5 21:32:25 UTC 2022


[why]
Current implementation to emulate the MPO video playback is via
creating 20 framebuffers (FB) and each FB has a colorful strip
pattern in a different position. From usrmode's view, in general
it would not create so many FBs for primary plane. Instead, it
only creates double or tripple buffers.

[how]
- drop the 20 framebuffers in current implementation
- use the double primary plane framebuffers defined in data struct
  and update the strip pattern alternatively on the double FBs and
  do page flip for each iteration

Cc: Rodrigo Siqueira <rodrigo.siqueira at amd.com>
Cc: Harry Wentland <harry.wentland at amd.com>
Cc: Leo Li <sunpeng.li at amd.com>
Cc: Jay Pillai <aurabindo.pillai at amd.com>
Cc: Wayne Lin <wayne.lin at amd.com>

Signed-off-by: David Zhang <dingchen.zhang at amd.com>
---
 tests/amdgpu/amd_psr.c | 76 +++++++++++++++++++++++++++---------------
 1 file changed, 49 insertions(+), 27 deletions(-)

diff --git a/tests/amdgpu/amd_psr.c b/tests/amdgpu/amd_psr.c
index 29982605..81ebebd3 100644
--- a/tests/amdgpu/amd_psr.c
+++ b/tests/amdgpu/amd_psr.c
@@ -40,10 +40,11 @@ IGT_TEST_DESCRIPTION("Basic test for enabling Panel Self Refresh for eDP display
 #define N_FLIPS 6
 /* DMCUB takes some time to actually enable PSR. Worst case delay is 4 seconds */
 #define PSR_SETTLE_DELAY 4
-/* # of framebuffers for PSR-SU MPO test case to emulate video playback */
-#ifndef N_MPO_TEST_RECT_FB
-#define N_MPO_TEST_RECT_FB 20
-#endif
+
+typedef struct {
+	int x, y;
+	int w, h;
+} pos_t;
 
 /* Common test data. */
 typedef struct data {
@@ -138,6 +139,29 @@ static void draw_color_cursor(igt_fb_t *fb, int size, double r, double g, double
 	igt_put_cairo_ctx(cr);
 }
 
+/* update the given framebuffer and draw colorful strip in new position */
+static void update_color_strip(igt_fb_t *fb, pos_t *old, pos_t *new, double r, double g, double b)
+{
+	cairo_t *cr;
+
+	if (!fb || !new || !old)
+		return;
+
+	cr = igt_get_cairo_ctx(fb->fd, fb);
+	igt_assert_f(cr, "Failed to get cairo context\n");
+
+	/**
+	 * we'd draw the strip in the new position w/ given color
+	 * and make the background of the framebuffer as black
+	 * - render black BG in the old position of strip instead of rendering the whole FB
+	 * - render colorful strip in the new position
+	 */
+	igt_paint_color(cr, old->x, old->y, old->w, old->h, .0, .0, .0);
+	igt_paint_color(cr, new->x, new->y, new->w, new->h, r, g, b);
+
+	igt_put_cairo_ctx(cr);
+}
+
 /* Common test setup. */
 static void test_init(data_t *data)
 {
@@ -314,12 +338,12 @@ static void run_check_psr(data_t *data, bool test_null_crtc) {
 static void run_check_psr_su_mpo(data_t *data)
 {
 	int edp_idx = check_conn_type(data, DRM_MODE_CONNECTOR_eDP);
-	igt_fb_t rect_fb[N_MPO_TEST_RECT_FB]; 	/* rectangle fbs for primary, emulate as video playback region */
 	igt_fb_t ref_fb;	/* reference fb */
 	igt_fb_t *flip_fb;
 	int ret;
 	const int run_sec = 5;
 	int frame_rate = 0;
+	pos_t old[2], new;
 
 	/* skip the test run if no eDP sink detected */
 	igt_skip_on_f(edp_idx == -1, "no eDP connector found\n");
@@ -327,6 +351,10 @@ static void run_check_psr_su_mpo(data_t *data)
 	/* init */
 	test_init(data);
 	frame_rate = data->mode->vrefresh;
+	memset(&old, 0, sizeof(pos_t) * 2);
+	memset(&new, 0, sizeof(pos_t));
+	old[0].w = old[1].w = new.w = 30;
+	old[0].h = old[1].h = new.h = data->pfb_h;
 
 	/* run the test i.i.f. eDP panel supports and kernel driver both support PSR-SU  */
 	igt_skip_on(!psr_su_supported(data));
@@ -347,25 +375,14 @@ static void run_check_psr_su_mpo(data_t *data)
 	 */
 	igt_create_color_fb(data->fd, data->w, data->h, DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_LINEAR,
 			    1.0, 1.0, 1.0, &data->ov_fb[0]);
-	for (int i = 0; i < N_MPO_TEST_RECT_FB; ++i) {
-		cairo_t *cr;
-		int strip_w = data->w / (2 * N_MPO_TEST_RECT_FB);
-
-		igt_create_fb(data->fd, data->pfb_w, data->pfb_h, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_LINEAR,
-			      &rect_fb[i]);
-		cr = igt_get_cairo_ctx(data->fd, &rect_fb[i]);
-		igt_assert_f(cr, "Failed to get cairo context\n");
-		/* background in black */
-		igt_paint_color(cr, 0, 0, data->pfb_w, data->pfb_h, .0, .0, .0);
-		/* foreground (megenta strip) */
-		igt_paint_color(cr, i * strip_w, 0, strip_w, data->pfb_h, 1.0, .0, 1.0);
-
-		igt_put_cairo_ctx(cr);
-	}
+	igt_create_color_fb(data->fd, data->pfb_w, data->pfb_h, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_LINEAR,
+			    .0, .0, .0, &data->pm_fb[0]);
+	igt_create_color_fb(data->fd, data->pfb_w, data->pfb_h, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_LINEAR,
+			    .0, .0, .0, &data->pm_fb[1]);
 
 	/* tie fbs to planes and set position/size/blending */
 	igt_plane_set_fb(data->overlay, &data->ov_fb[0]);
-	igt_plane_set_fb(data->primary, &rect_fb[0]);
+	igt_plane_set_fb(data->primary, &data->pm_fb[1]);
 	igt_plane_set_position(data->primary, 0, 0);
 	igt_plane_set_size(data->primary, data->pfb_w, data->pfb_h);
 
@@ -389,23 +406,28 @@ static void run_check_psr_su_mpo(data_t *data)
 	igt_info("\n start flipping ...\n");
 
 	for (int i = 0; i < run_sec * frame_rate; ++i) {
-		igt_info(" About to commit a primary plane (FB %d), loop %d \n", i % N_MPO_TEST_RECT_FB, i);
-		flip_fb = &rect_fb[i % N_MPO_TEST_RECT_FB];
+		flip_fb = &data->pm_fb[i & 1];
+		/* draw the color strip onto primary plane FB */
+		update_color_strip(flip_fb, &old[i & 1], &new, 1.0, .0, 1.0);
 
 		igt_plane_set_fb(data->primary, flip_fb);
 		igt_output_set_pipe(data->output, data->pipe_id);
 
-		ret = drmModePageFlip(data->fd, data->output->config.crtc->crtc_id,
-				      flip_fb->fb_id, DRM_MODE_PAGE_FLIP_EVENT, NULL);
+		ret = igt_display_try_commit_atomic(&data->display, DRM_MODE_PAGE_FLIP_EVENT, NULL);
 		igt_require(ret == 0);
 		kmstest_wait_for_pageflip(data->fd);
+
+		/* update strip position */
+		old[i & 1].x = new.x;
+		new.x += 3;
+		new.x = (new.x + new.w > data->pfb_w) ? 0 : new.x;
 	}
 
 	/* fini */
 	igt_remove_fb(data->fd, &ref_fb);
 	igt_remove_fb(data->fd, &data->ov_fb[0]);
-	for (int i = 0; i < N_MPO_TEST_RECT_FB; ++i)
-		igt_remove_fb(data->fd, &rect_fb[i]);
+	igt_remove_fb(data->fd, &data->pm_fb[0]);
+	igt_remove_fb(data->fd, &data->pm_fb[1]);
 	test_fini(data);
 }
 
-- 
2.25.1



More information about the igt-dev mailing list