public inbox for igt-dev@lists.freedesktop.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH i-g-t] tests/kms_chamelium: add a latency test
@ 2019-09-06 11:46 Simon Ser
  2019-09-06 11:56 ` Ser, Simon
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Simon Ser @ 2019-09-06 11:46 UTC (permalink / raw)
  To: igt-dev

This new test creates a red and a green framebuffer, then alternatively shows
one and the other for a while. We check that we correctly capture the
alternating pattern with Chamelium.

We do our best to capture the pattern, which is tricky because of
synchronization issues. We first show the red FB, start the capture, then
play the alternating pattern, and stop the capture. We capture more frames than
there are in the pattern to make sure the delay after starting the capture
doesn't make us completely miss the pattern.

Signed-off-by: Simon Ser <simon.ser@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Martin Peres <martin.peres@linux.intel.com>
---
 tests/kms_chamelium.c | 163 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 163 insertions(+)

diff --git a/tests/kms_chamelium.c b/tests/kms_chamelium.c
index 6b6292497cd7..ba9f8acb600c 100644
--- a/tests/kms_chamelium.c
+++ b/tests/kms_chamelium.c
@@ -2522,6 +2522,161 @@ test_hpd_storm_disable(data_t *data, struct chamelium_port *port, int width)
 	igt_hpd_storm_reset(data->drm_fd);
 }
 
+static void latency_page_flip_handler(int fd, unsigned seq, unsigned tv_sec,
+				      unsigned tv_usec, void *data)
+{
+	int64_t *seq_ptr = data;
+
+	igt_debug("Got page-flip event (seq=%u)\n", seq);
+	*seq_ptr = seq;
+}
+
+#define TEST_LATENCY_PLAYBACK_FRAMES 20
+#define TEST_LATENCY_CAPTURE_FRAMES (TEST_LATENCY_PLAYBACK_FRAMES + 10)
+
+static const char test_display_latency_desc[] =
+	"Alternate between two different buffers at each page-flip, "
+	"check there is no latency or tearing";
+static void
+test_display_latency(data_t *data, struct chamelium_port *port)
+{
+	igt_output_t *output;
+	igt_plane_t *primary;
+	struct igt_fb fbs[2];
+	unsigned int fb_ids[2];
+	struct chamelium_fb_crc_async_data *fb_crcs[2];
+	drmModeModeInfo mode;
+	drmModeConnector *connector;
+	struct pollfd pfd = {0};
+	drmEventContext drm_event = {0};
+	int i, j, ret, captured_frames_count, start, end;
+	int64_t prev_seq, seq;
+	igt_crc_t *crcs, *expected_crcs[2];
+
+	reset_state(data, port);
+
+	output = prepare_output(data, port, TEST_EDID_BASE);
+	connector = chamelium_port_get_connector(data->chamelium, port, false);
+	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
+	igt_assert(primary);
+
+	igt_assert(connector->count_modes > 0);
+	mode = connector->modes[0];
+
+	drmModeFreeConnector(connector);
+
+	fb_ids[0] = igt_create_color_pattern_fb(data->drm_fd,
+						mode.hdisplay, mode.vdisplay,
+						DRM_FORMAT_XRGB8888,
+						LOCAL_DRM_FORMAT_MOD_NONE,
+						1, 0, 0, &fbs[0]);
+	igt_assert(fb_ids[0] > 0);
+	fb_ids[1] = igt_create_color_pattern_fb(data->drm_fd,
+						mode.hdisplay, mode.vdisplay,
+						DRM_FORMAT_XRGB8888,
+						LOCAL_DRM_FORMAT_MOD_NONE,
+						0, 1, 0, &fbs[1]);
+	igt_assert(fb_ids[1] > 0);
+
+	fb_crcs[0] = chamelium_calculate_fb_crc_async_start(data->drm_fd,
+							    &fbs[0]);
+	fb_crcs[1] = chamelium_calculate_fb_crc_async_start(data->drm_fd,
+							    &fbs[1]);
+
+	igt_plane_set_fb(primary, &fbs[0]);
+	igt_plane_set_size(primary, mode.hdisplay, mode.vdisplay);
+	igt_output_override_mode(output, &mode);
+	igt_display_commit2(&data->display, COMMIT_ATOMIC);
+
+	chamelium_start_capture(data->chamelium, port, 0, 0, 0, 0);
+
+	pfd.fd = data->drm_fd;
+	pfd.events = POLLIN;
+
+	drm_event.version = 2;
+	drm_event.page_flip_handler = latency_page_flip_handler;
+
+	/* Make sure we stop the alternating pattern with fb[1] */
+	assert(TEST_LATENCY_PLAYBACK_FRAMES % 2 == 0);
+
+	prev_seq = -1;
+	for (i = 0; i < TEST_LATENCY_PLAYBACK_FRAMES; i++) {
+		igt_plane_set_fb(primary, &fbs[i % 2]);
+
+		igt_display_commit_atomic(&data->display,
+					  DRM_MODE_ATOMIC_NONBLOCK |
+					  DRM_MODE_PAGE_FLIP_EVENT,
+					  &seq);
+
+		ret = poll(&pfd, 1, 1000);
+		igt_assert_f(ret == 1, "poll returned %d, expected 1\n", ret);
+		seq = -1;
+		drmHandleEvent(data->drm_fd, &drm_event);
+		igt_assert(seq >= 0);
+
+		if (prev_seq >= 0) {
+			igt_assert((unsigned) (prev_seq + 1) == (unsigned) seq);
+		}
+		prev_seq = seq;
+	}
+
+	/* Capture more frames than necessary, because we don't want to miss
+	 * our alternating pattern. */
+	chamelium_stop_capture(data->chamelium, TEST_LATENCY_CAPTURE_FRAMES);
+	crcs = chamelium_read_captured_crcs(data->chamelium,
+					    &captured_frames_count);
+	igt_assert(captured_frames_count == TEST_LATENCY_CAPTURE_FRAMES);
+
+	igt_debug("Captured %d frames\n", captured_frames_count);
+
+	expected_crcs[0] = chamelium_calculate_fb_crc_async_finish(fb_crcs[0]);
+	expected_crcs[1] = chamelium_calculate_fb_crc_async_finish(fb_crcs[1]);
+
+	/* Assuming reference CRCs A and B, the captured CRCs should look like:
+	 * A A A A A B A B A B A B A B A B A B … A B A B B B B B B B
+	 *           ^                                 ^
+	 *           playback starts                   playback ends
+	 */
+	igt_debug("Reference CRC #0: %s\n", igt_crc_to_string(expected_crcs[0]));
+	igt_debug("Reference CRC #1: %s\n", igt_crc_to_string(expected_crcs[1]));
+	for (i = 0; i < captured_frames_count; i++) {
+		igt_debug("Captured CRC #%d: %s\n", i,
+			  igt_crc_to_string(&crcs[i]));
+	}
+
+	igt_debug("Searching start and end of alternating pattern...\n");
+	for (start = 0; start < captured_frames_count; start++) {
+		if (!igt_check_crc_equal(expected_crcs[0], &crcs[start]))
+			break;
+	}
+	for (end = captured_frames_count - 1; end >= 0; end--) {
+		if (!igt_check_crc_equal(expected_crcs[1], &crcs[end]))
+			break;
+	}
+	igt_debug("Alternating pattern starts at frame #%d and ends at "
+		  "frame #%d\n", start, end);
+	/* Make sure we captured a big enough chunk of the pattern */
+	igt_assert_f(end - start > TEST_LATENCY_PLAYBACK_FRAMES / 2,
+		     "Captured only %d frames of the alternating pattern, "
+		     "that's not enough (expected more than %d)\n",
+		     end - start, TEST_LATENCY_PLAYBACK_FRAMES / 2);
+
+	j = 1; /* crcs[start] should match expected_crcs[1] */
+	for (i = start; i <= end; i++) {
+		igt_assert_f(igt_check_crc_equal(expected_crcs[j % 2], &crcs[i]),
+			     "Captured CRC #%d mismatches reference CRC #%d\n",
+			     i, j % 2);
+		j++;
+	}
+
+	free(expected_crcs[0]);
+	free(expected_crcs[1]);
+	free(crcs);
+
+	igt_remove_fb(data->drm_fd, &fbs[0]);
+	igt_remove_fb(data->drm_fd, &fbs[1]);
+}
+
 static const struct edid *get_edid(enum test_edid edid)
 {
 	switch (edid) {
@@ -2659,6 +2814,10 @@ igt_main
 		connector_subtest("dp-audio-edid", DisplayPort)
 			test_display_audio_edid(&data, port,
 						TEST_EDID_DP_AUDIO);
+
+		igt_describe(test_display_latency_desc);
+		connector_subtest("dp-latency", DisplayPort)
+			test_display_latency(&data, port);
 	}
 
 	igt_subtest_group {
@@ -2820,6 +2979,10 @@ igt_main
 
 		connector_subtest("hdmi-aspect-ratio", HDMIA)
 			test_display_aspect_ratio(&data, port);
+
+		igt_describe(test_display_latency_desc);
+		connector_subtest("hdmi-latency", HDMIA)
+			test_display_latency(&data, port);
 	}
 
 	igt_subtest_group {
-- 
2.23.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-09-06 14:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-09-06 11:46 [igt-dev] [PATCH i-g-t] tests/kms_chamelium: add a latency test Simon Ser
2019-09-06 11:56 ` Ser, Simon
2019-09-06 12:28 ` [igt-dev] ✓ Fi.CI.BAT: success for " Patchwork
2019-09-06 14:09 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox