[PATCH i-g-t v3 1/1] RFC tests/intel/kms_frontbuffer_tracking: Introduce plane-fbc-dr test

Santhosh Reddy Guddati santhosh.reddy.guddati at intel.com
Tue Nov 26 14:19:58 UTC 2024


Use the FP_DAMAGE_CLIPS property of the plane for non psr modes
and fill the damaged rectangles on the plane with framebuffer
coordinates and verify that fbc dirty ctl is enabled.

v2: Fix typo , add version check for feature support,
    extend support for all pipes (Rama Naidu).

v3: Add new subtest to scatter dirty rectangles at differnt places in a
    frame and commit all rectangles at once (Rama Naidu).
    Add a negative case with invalid coordinates (Vinod)

Signed-off-by: Santhosh Reddy Guddati <santhosh.reddy.guddati at intel.com>
---
 tests/intel/kms_frontbuffer_tracking.c | 233 +++++++++++++++++++++++++
 1 file changed, 233 insertions(+)

diff --git a/tests/intel/kms_frontbuffer_tracking.c b/tests/intel/kms_frontbuffer_tracking.c
index b7e3f7379..730e02b04 100644
--- a/tests/intel/kms_frontbuffer_tracking.c
+++ b/tests/intel/kms_frontbuffer_tracking.c
@@ -57,6 +57,14 @@
  * Description: Sanity test to enable FBC on a plane.
  * Functionality: fbc
  *
+ * SUBTEST: plane-fbc-dr
+ * Description: Sanity test to verify FBC DR by sending multiple damaged areas with non psr modes
+ * Functionality: fbc
+ *
+ * SUBTEST: plane-fbc-dr-scatter
+ * Description: Sanity test to verify FBC DR by sending multiple damaged areas scattered.
+ * Functionality: fbc
+ *
  * SUBTEST: pipe-fbc-rte
  * Description: Sanity test to enable FBC on each pipe.
  * Functionality: fbc
@@ -1168,6 +1176,7 @@
  */
 
 #define TIME SLOW_QUICK(1000, 10000)
+#define MAX_DIRTY_RECT 3
 
 IGT_TEST_DESCRIPTION("Test the Kernel's frontbuffer tracking mechanism and "
 		     "its related features: FBC, PSR and DRRS");
@@ -4282,6 +4291,204 @@ static int opt_handler(int option, int option_index, void *data)
 	return IGT_OPT_HANDLER_SUCCESS;
 }
 
+static void set_damage_clip(struct drm_mode_rect *damage, int x1, int y1, int x2, int y2)
+{
+	damage->x1 = x1;
+	damage->y1 = y1;
+	damage->x2 = x2;
+	damage->y2 = y2;
+}
+
+static void fbc_dirty_rectangle_basic(const struct test_mode *t)
+{
+	struct drm_mode_rect rect_data[MAX_DIRTY_RECT];
+	uint32_t color;
+	drmModeModeInfo *mode;
+	int width, height, x, y;
+
+	prepare_subtest_data(t, NULL);
+
+	igt_output_override_mode(prim_mode_params.output, &prim_mode_params.mode);
+	igt_output_set_pipe(prim_mode_params.output, prim_mode_params.pipe);
+
+	mode = igt_output_get_mode(prim_mode_params.output);
+
+	set_damage_clip(&rect_data[0], 0, 0, mode->hdisplay - 1, mode->vdisplay - 1);
+	set_damage_clip(&rect_data[1], mode->hdisplay / 2, mode->vdisplay / 2,
+			mode->hdisplay - 1, mode->vdisplay - 1);
+	set_damage_clip(&rect_data[2], mode->hdisplay - 10, mode->vdisplay - 10,
+			mode->hdisplay - 1, mode->vdisplay - 1);
+
+	igt_debug("Dirty Rectangle data = {%d, %d, %d, %d}, {%d, %d, %d, %d}, {%d, %d, %d, %d}\n",
+		   rect_data[0].x1, rect_data[0].y1, rect_data[0].x2, rect_data[0].y2,
+		   rect_data[1].x1, rect_data[1].y1, rect_data[1].x2, rect_data[1].y2,
+		   rect_data[2].x1, rect_data[2].y1, rect_data[2].x2, rect_data[2].y2);
+
+	for (int i = 0; i < MAX_DIRTY_RECT; i++) {
+		igt_plane_t *primary;
+		igt_fb_t fb[MAX_DIRTY_RECT];
+
+		primary = igt_output_get_plane_type(prim_mode_params.output,
+						    DRM_PLANE_TYPE_PRIMARY);
+		width = rect_data[i].x2 - rect_data[i].x1;
+		height = rect_data[i].y2 - rect_data[i].y1;
+		x = rect_data[i].x1;
+		y = rect_data[i].y1;
+
+		create_fb(t->format, width, height, t->tiling, t->plane, &fb[i]);
+		color = pick_color(&fb[i], COLOR_PRIM_BG);
+		igt_draw_rect_fb(drm.fd, drm.bops, 0, &fb[i], t->method,
+				 x, y, width, height, color);
+		igt_plane_set_fb(primary, &fb[i]);
+		igt_plane_set_position(primary, x, y);
+		igt_plane_set_size(primary, width, height);
+		igt_fb_set_size(&fb[i], primary, width, height);
+		igt_plane_replace_prop_blob(primary, IGT_PLANE_FB_DAMAGE_CLIPS,
+					    &rect_data[i], sizeof(rect_data[i]));
+
+		igt_display_commit_atomic(&drm.display, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+
+		fbc_update_last_action();
+		do_assertions(ASSERT_FBC_ENABLED | ASSERT_NO_ACTION_CHANGE);
+		igt_assert_f(fbc_enable_per_plane(primary->index + 1,
+			     prim_mode_params.pipe), "FBC disabled\n");
+
+		igt_remove_fb(drm.fd, &fb[i]);
+		igt_plane_set_fb(primary, NULL);
+		igt_display_commit2(&drm.display, COMMIT_ATOMIC);
+	}
+}
+
+static void fbc_dirty_rectangle_scatter(const struct test_mode *t)
+{
+	struct drm_mode_rect rect_data[MAX_DIRTY_RECT];
+	uint32_t color;
+	drmModeModeInfo *mode;
+	int width, height, x, y;
+	int hdisplay, vdisplay;
+	igt_plane_t *primary;
+	igt_fb_t fb[MAX_DIRTY_RECT];
+
+	prepare_subtest_data(t, NULL);
+	igt_output_override_mode(prim_mode_params.output, &prim_mode_params.mode);
+	igt_output_set_pipe(prim_mode_params.output, prim_mode_params.pipe);
+
+	mode = igt_output_get_mode(prim_mode_params.output);
+	hdisplay = mode->hdisplay;
+	vdisplay = mode->vdisplay;
+
+	// Set damage clips
+	set_damage_clip(&rect_data[0], 0, 0, hdisplay / 4, vdisplay / 4);
+	set_damage_clip(&rect_data[1], hdisplay / 2, vdisplay / 2,
+			hdisplay / 2 + 50, vdisplay / 2 + 50);
+	set_damage_clip(&rect_data[2], hdisplay - 100,
+			vdisplay - 100, hdisplay - 1, vdisplay - 1);
+
+	igt_debug("Dirty Rectangle data = {%d, %d, %d, %d}, {%d, %d, %d, %d}, {%d, %d, %d, %d}\n",
+		   rect_data[0].x1, rect_data[0].y1, rect_data[0].x2, rect_data[0].y2,
+		   rect_data[1].x1, rect_data[1].y1, rect_data[1].x2, rect_data[1].y2,
+		   rect_data[2].x1, rect_data[2].y1, rect_data[2].x2, rect_data[2].y2);
+
+	primary = igt_output_get_plane_type(prim_mode_params.output,
+					    DRM_PLANE_TYPE_PRIMARY);
+
+	for (int i = 0; i < MAX_DIRTY_RECT; i++) {
+		width = rect_data[i].x2 - rect_data[i].x1;
+		height = rect_data[i].y2 - rect_data[i].y1;
+		x = rect_data[i].x1;
+		y = rect_data[i].y1;
+
+		create_fb(t->format, width, height, t->tiling, t->plane, &fb[i]);
+		color = pick_color(&fb[i], COLOR_PRIM_BG);
+		igt_draw_rect_fb(drm.fd, drm.bops, 0, &fb[i], t->method,
+				 x, y, width, height, color);
+		igt_plane_set_fb(primary, &fb[i]);
+		igt_plane_set_position(primary, x, y);
+		igt_plane_set_size(primary, width, height);
+		igt_fb_set_size(&fb[i], primary, width, height);
+	}
+
+	igt_plane_replace_prop_blob(primary, IGT_PLANE_FB_DAMAGE_CLIPS,
+				    rect_data, sizeof(rect_data));
+
+	igt_display_commit_atomic(&drm.display, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+
+	fbc_update_last_action();
+	do_assertions(ASSERT_FBC_ENABLED | ASSERT_NO_ACTION_CHANGE);
+	igt_assert_f(fbc_enable_per_plane(primary->index + 1,
+					  prim_mode_params.pipe),
+					  "FBC disabled\n");
+
+	for (int i = 0; i < MAX_DIRTY_RECT; i++)
+		igt_remove_fb(drm.fd, &fb[i]);
+
+	igt_plane_set_fb(primary, NULL);
+	igt_display_commit2(&drm.display, COMMIT_ATOMIC);
+}
+
+static void fbc_dirty_rectangle_negative(const struct test_mode *t)
+{
+	struct drm_mode_rect rect_data[MAX_DIRTY_RECT];
+	uint32_t color, ret;
+	drmModeModeInfo *mode;
+	int width, height, x, y;
+	igt_plane_t *primary;
+	igt_fb_t fb[MAX_DIRTY_RECT];
+
+	prepare_subtest_data(t, NULL);
+
+	igt_output_override_mode(prim_mode_params.output, &prim_mode_params.mode);
+	igt_output_set_pipe(prim_mode_params.output, prim_mode_params.pipe);
+
+	mode = igt_output_get_mode(prim_mode_params.output);
+
+	// Set invalid damage clips
+	set_damage_clip(&rect_data[0], -10, -10,
+			mode->hdisplay / 4, mode->vdisplay / 4);
+	set_damage_clip(&rect_data[1], mode->hdisplay / 2, mode->vdisplay / 2,
+			mode->hdisplay / 2 + 50, mode->vdisplay / 2 + 50);
+	set_damage_clip(&rect_data[2], mode->hdisplay - 100, mode->vdisplay - 100,
+			mode->hdisplay + 10, mode->vdisplay + 10);
+
+	igt_debug("Dirty Rectangle data = {%d, %d, %d, %d}, {%d, %d, %d, %d}, {%d, %d, %d, %d}\n",
+		   rect_data[0].x1, rect_data[0].y1, rect_data[0].x2, rect_data[0].y2,
+		   rect_data[1].x1, rect_data[1].y1, rect_data[1].x2, rect_data[1].y2,
+		   rect_data[2].x1, rect_data[2].y1, rect_data[2].x2, rect_data[2].y2);
+
+	primary = igt_output_get_plane_type(prim_mode_params.output, DRM_PLANE_TYPE_PRIMARY);
+
+	for (int i = 0; i < MAX_DIRTY_RECT; i++) {
+		width = rect_data[i].x2 - rect_data[i].x1;
+		height = rect_data[i].y2 - rect_data[i].y1;
+		x = rect_data[i].x1;
+		y = rect_data[i].y1;
+
+		create_fb(t->format, width, height, t->tiling, t->plane, &fb[i]);
+		color = pick_color(&fb[i], COLOR_PRIM_BG);
+		igt_draw_rect_fb(drm.fd, drm.bops, 0, &fb[i], t->method,
+				 x, y, width, height, color);
+		igt_plane_set_fb(primary, &fb[i]);
+		igt_plane_set_position(primary, x, y);
+		igt_plane_set_size(primary, width, height);
+		igt_fb_set_size(&fb[i], primary, width, height);
+	}
+
+	igt_plane_replace_prop_blob(primary, IGT_PLANE_FB_DAMAGE_CLIPS,
+				    rect_data, sizeof(rect_data));
+
+	ret = igt_display_try_commit_atomic(&drm.display, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+	igt_assert_eq(ret, -EINVAL);
+
+	fbc_update_last_action();
+	do_assertions(ASSERT_FBC_DISABLED | ASSERT_NO_ACTION_CHANGE);
+
+	for (int i = 0; i < MAX_DIRTY_RECT; i++)
+		igt_remove_fb(drm.fd, &fb[i]);
+
+	igt_plane_set_fb(primary, NULL);
+	igt_display_commit2(&drm.display, COMMIT_ATOMIC);
+}
+
 const char *help_str =
 "  --no-status-check           Don't check for enable/disable status\n"
 "  --no-crc-check              Don't check for CRC values\n"
@@ -4507,6 +4714,32 @@ igt_main_args("", long_options, help_str, opt_handler, NULL)
 		plane_fbc_rte_subtest(&t);
 	}
 
+	igt_subtest_group {
+		igt_subtest_with_dynamic("plane-fbc-dr") {
+			t.feature = FEATURE_FBC;
+			igt_require_f(drm.display_ver > 20,
+				      "FBC with dirty region is not supported\n");
+			igt_dynamic_f("pipe-%s", kmstest_pipe_name(prim_mode_params.pipe))
+			fbc_dirty_rectangle_basic(&t);
+		}
+
+		igt_subtest_with_dynamic("plane-fbc-dr-scatter") {
+			t.feature = FEATURE_FBC;
+			igt_require_f(drm.display_ver > 20,
+				      "FBC with dirty region is not supported\n");
+			igt_dynamic_f("pipe-%s", kmstest_pipe_name(prim_mode_params.pipe))
+			fbc_dirty_rectangle_scatter(&t);
+		}
+
+		igt_subtest_with_dynamic("plane-fbc-dr-negative") {
+			t.feature = FEATURE_FBC;
+			igt_require_f(drm.display_ver > 20,
+					  "FBC with dirty region is not supported\n");
+			igt_dynamic_f("pipe-%s", kmstest_pipe_name(prim_mode_params.pipe))
+			fbc_dirty_rectangle_negative(&t);
+		}
+	}
+
 	igt_subtest_group {
 		igt_subtest_with_dynamic("pipe-fbc-rte") {
 
-- 
2.34.1



More information about the igt-dev mailing list