[v3,i-g-t] kms_flip_tiling: New tiling tests, including Y/Yf
diff mbox

Message ID 1430231781-7945-1-git-send-email-tvrtko.ursulin@linux.intel.com
State New, archived
Headers show

Commit Message

Tvrtko Ursulin April 28, 2015, 2:36 p.m. UTC
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

New subtests to excercise flips from tiled to tiled and from
linear to tiled frame buffers.

These will catch display programming issues like not preserving the
tiling mode in page flips or not re-programming the watermarks.

v2: Cleanup crc object after failing subtests.

v3:
   * Wait for page flip completion instead of vblank. (Chris Wilson)
   * Added linear->tiled flip tests to catch watermark programming issues.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 tests/kms_flip_tiling.c | 256 +++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 240 insertions(+), 16 deletions(-)

Patch
diff mbox

diff --git a/tests/kms_flip_tiling.c b/tests/kms_flip_tiling.c
index 8345505..a0d3703 100644
--- a/tests/kms_flip_tiling.c
+++ b/tests/kms_flip_tiling.c
@@ -35,8 +35,7 @@ 
 #include "ioctl_wrappers.h"
 #include "intel_chipset.h"
 
-IGT_TEST_DESCRIPTION("Test that a page flip from a tiled buffer to a linear"
-		     " one works correctly.");
+IGT_TEST_DESCRIPTION("Test page flips and tiling scenarios");
 
 typedef struct {
 	int drm_fd;
@@ -44,16 +43,8 @@  typedef struct {
 	int gen;
 } data_t;
 
-/*
- * Test that a page flip from a tiled buffer to a linear one works
- * correctly. First, it sets the crtc with the linear buffer and generate
- * a reference crc for the pipe. Then, the crtc is set with the tiled one
- * and page flip to the linear one issued. A new crc is generated and
- * compared to the rerence one.
- */
-
 static void
-fill_linear_fb(struct igt_fb *fb, data_t *data, drmModeModeInfo *mode)
+fill_fb(struct igt_fb *fb, data_t *data, drmModeModeInfo *mode)
 {
 	cairo_t *cr;
 
@@ -62,6 +53,53 @@  fill_linear_fb(struct igt_fb *fb, data_t *data, drmModeModeInfo *mode)
 	cairo_destroy(cr);
 }
 
+static igt_pipe_crc_t *_pipe_crc;
+
+static igt_pipe_crc_t *pipe_crc_new(int pipe)
+{
+	if (_pipe_crc) {
+		igt_pipe_crc_free(_pipe_crc);
+		_pipe_crc = NULL;
+	}
+
+	_pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
+	igt_assert(_pipe_crc);
+
+	return _pipe_crc;
+}
+
+static void pipe_crc_free(void)
+{
+	if (_pipe_crc) {
+		igt_pipe_crc_free(_pipe_crc);
+		_pipe_crc = NULL;
+	}
+}
+
+static void wait_for_pageflip(int fd)
+{
+	drmEventContext evctx = { .version = DRM_EVENT_CONTEXT_VERSION };
+	struct timeval timeout = { .tv_sec = 0, .tv_usec = 32000 };
+	fd_set fds;
+	int ret;
+
+	/* Wait for pageflip completion, then consume event on fd */
+	FD_ZERO(&fds);
+	FD_SET(fd, &fds);
+	do {
+		ret = select(fd + 1, &fds, NULL, NULL, &timeout);
+	} while (ret < 0 && errno == EINTR);
+	igt_assert_eq(ret, 1);
+	igt_assert(drmHandleEvent(fd, &evctx) == 0);
+}
+
+/*
+ * Test that a page flip from a tiled buffer to a linear one works
+ * correctly. First, it sets the crtc with the linear buffer and generates
+ * a reference crc for the pipe. Then, the crtc is set with the tiled one
+ * and page flip to the linear one issued. A new crc is generated and
+ * compared to the reference one.
+ */
 static void
 test_flip_changes_tiling(data_t *data, igt_output_t *output, uint64_t tiling)
 {
@@ -73,7 +111,7 @@  test_flip_changes_tiling(data_t *data, igt_output_t *output, uint64_t tiling)
 	int fb_id, pipe, ret, width;
 
 	pipe = output->config.pipe;
-	pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
+	pipe_crc = pipe_crc_new(pipe);
 	igt_output_set_pipe(output, pipe);
 
 	mode = igt_output_get_mode(output);
@@ -90,7 +128,7 @@  test_flip_changes_tiling(data_t *data, igt_output_t *output, uint64_t tiling)
 			      &linear);
 
 	/* fill it with a pattern that will look wrong if tiling is wrong */
-	fill_linear_fb(&linear, data, mode);
+	fill_fb(&linear, data, mode);
 
 	/* set the crtc and generate a reference crc */
 	igt_plane_set_fb(primary, &linear);
@@ -106,10 +144,148 @@  test_flip_changes_tiling(data_t *data, igt_output_t *output, uint64_t tiling)
 
 	/* flip to the linear buffer */
 	ret = drmModePageFlip(data->drm_fd, output->config.crtc->crtc_id,
-			      fb_id, 0, NULL);
+			      fb_id, DRM_MODE_PAGE_FLIP_EVENT, NULL);
+	igt_assert_eq(ret, 0);
+
+	wait_for_pageflip(data->drm_fd);
+
+	/* get a crc and compare with the reference */
+	igt_pipe_crc_collect_crc(pipe_crc, &crc);
+	igt_assert_crc_equal(&reference_crc, &crc);
+
+	/* clean up */
+	igt_plane_set_fb(primary, NULL);
+	pipe_crc_free();
+	igt_output_set_pipe(output, PIPE_ANY);
+	igt_display_commit(&data->display);
+
+	igt_remove_fb(data->drm_fd, &tiled);
+	igt_remove_fb(data->drm_fd, &linear);
+}
+
+/*
+ * Test that a page flip from a tiled buffer to another tiled one works
+ * correctly. First, it sets the crtc with the tiled buffer and generates
+ * a reference crc for the pipe. Then a page flip to second tiled buffer is
+ * issued. A new crc is generated and compared to the reference one.
+ */
+static void
+test_tiled_flip(data_t *data, igt_output_t *output, uint64_t tiling)
+{
+	drmModeModeInfo *mode;
+	igt_plane_t *primary;
+	igt_pipe_crc_t *pipe_crc;
+	igt_crc_t reference_crc, crc;
+	struct igt_fb fb[2];
+	int fb_id[2], pipe, ret, width, height;
+
+	pipe = output->config.pipe;
+	pipe_crc = pipe_crc_new(pipe);
+	igt_output_set_pipe(output, pipe);
+
+	mode = igt_output_get_mode(output);
+	primary = igt_output_get_plane(output, 0);
+
+	width = mode->hdisplay;
+	height = mode->vdisplay;
+
+	/* create two identical fbs */
+	fb_id[0] = igt_create_fb(data->drm_fd, width, height,
+				 DRM_FORMAT_XRGB8888, tiling, &fb[0]);
+	igt_assert(fb_id[0]);
+
+	fb_id[1] = igt_create_fb(data->drm_fd, width, height,
+				 DRM_FORMAT_XRGB8888, tiling, &fb[1]);
+	igt_assert(fb_id[1]);
+
+	fill_fb(&fb[0], data, mode);
+	fill_fb(&fb[1], data, mode);
+
+	/* set the crtc and generate a reference crc */
+	igt_plane_set_fb(primary, &fb[0]);
+	igt_display_commit(&data->display);
+	igt_pipe_crc_collect_crc(pipe_crc, &reference_crc);
+
+	/* flip to the other fb */
+	ret = drmModePageFlip(data->drm_fd, output->config.crtc->crtc_id,
+			      fb_id[1], DRM_MODE_PAGE_FLIP_EVENT, NULL);
+	igt_assert_eq(ret, 0);
+
+	wait_for_pageflip(data->drm_fd);
+
+	/* get a crc and compare with the reference */
+	igt_pipe_crc_collect_crc(pipe_crc, &crc);
+	igt_assert_crc_equal(&reference_crc, &crc);
+
+	/* clean up */
+	igt_plane_set_fb(primary, NULL);
+	pipe_crc_free();
+	igt_output_set_pipe(output, PIPE_ANY);
+	igt_display_commit(&data->display);
+
+	igt_remove_fb(data->drm_fd, &fb[0]);
+	igt_remove_fb(data->drm_fd, &fb[1]);
+}
+
+/*
+ * Test that a page flip from a linear buffer to a tiled one works
+ * correctly. First, it sets the crtc with the linear buffer and generates
+ * a reference crc for the pipe. Then a page flip to a tiled buffer is
+ * issued. A new crc is generated and compared to the reference one.
+ */
+static void
+test_linear_tiled_flip(data_t *data, igt_output_t *output, uint64_t tiling)
+{
+	struct igt_fb linear, tiled;
+	drmModeModeInfo *mode;
+	igt_plane_t *primary;
+	igt_pipe_crc_t *pipe_crc;
+	igt_crc_t reference_crc, crc;
+	int linear_id, tiled_id;
+	int pipe, ret, width;
+
+	pipe = output->config.pipe;
+	pipe_crc = pipe_crc_new(pipe);
+	igt_output_set_pipe(output, pipe);
+
+	mode = igt_output_get_mode(output);
+	primary = igt_output_get_plane(output, 0);
+
+	/* Allocate a linear buffer. Since a page flip to a buffer with
+	 * different stride doesn't work, choose width so that the stride of
+	 * both buffers is the same. */
+	width = 512;
+	while (width < mode->hdisplay)
+		width *= 2;
+	linear_id = igt_create_fb(data->drm_fd, width, mode->vdisplay,
+			          DRM_FORMAT_XRGB8888,
+				  LOCAL_DRM_FORMAT_MOD_NONE,
+				  &linear);
+	igt_assert(linear_id);
+
+	/* fill it with a pattern that will look wrong if tiling is wrong */
+	fill_fb(&linear, data, mode);
+
+	/* set the crtc and generate a reference crc */
+	igt_plane_set_fb(primary, &linear);
+	igt_display_commit(&data->display);
+	igt_pipe_crc_collect_crc(pipe_crc, &reference_crc);
+
+	/* allocate a tiled buffer */
+	tiled_id = igt_create_fb(data->drm_fd, width, mode->vdisplay,
+				 DRM_FORMAT_XRGB8888, tiling,
+				 &tiled);
+	igt_assert(tiled_id);
+
+	/* fill it with a pattern that will look wrong if tiling is wrong */
+	fill_fb(&tiled, data, mode);
+
+	/* flip to the tiled buffer */
+	ret = drmModePageFlip(data->drm_fd, output->config.crtc->crtc_id,
+			      tiled_id, DRM_MODE_PAGE_FLIP_EVENT, NULL);
 	igt_assert_eq(ret, 0);
 
-	igt_wait_for_vblank(data->drm_fd, pipe);
+	wait_for_pageflip(data->drm_fd);
 
 	/* get a crc and compare with the reference */
 	igt_pipe_crc_collect_crc(pipe_crc, &crc);
@@ -117,7 +293,7 @@  test_flip_changes_tiling(data_t *data, igt_output_t *output, uint64_t tiling)
 
 	/* clean up */
 	igt_plane_set_fb(primary, NULL);
-	igt_pipe_crc_free(pipe_crc);
+	pipe_crc_free();
 	igt_output_set_pipe(output, PIPE_ANY);
 	igt_display_commit(&data->display);
 
@@ -166,6 +342,54 @@  igt_main
 						LOCAL_I915_FORMAT_MOD_Yf_TILED);
 	}
 
+	igt_subtest_f("flip-X-tiled") {
+		for_each_connected_output(&data.display, output)
+			test_tiled_flip(&data, output,
+					LOCAL_I915_FORMAT_MOD_X_TILED);
+	}
+
+	igt_subtest_f("flip-Y-tiled") {
+		igt_require_fb_modifiers(data.drm_fd);
+		igt_require(data.gen >= 9);
+
+		for_each_connected_output(&data.display, output)
+			test_tiled_flip(&data, output,
+					LOCAL_I915_FORMAT_MOD_Y_TILED);
+	}
+
+	igt_subtest_f("flip-Yf-tiled") {
+		igt_require_fb_modifiers(data.drm_fd);
+		igt_require(data.gen >= 9);
+
+		for_each_connected_output(&data.display, output)
+			test_tiled_flip(&data, output,
+					LOCAL_I915_FORMAT_MOD_Yf_TILED);
+	}
+
+	igt_subtest_f("flip-to-X-tiled") {
+		for_each_connected_output(&data.display, output)
+			test_linear_tiled_flip(&data, output,
+					       LOCAL_I915_FORMAT_MOD_X_TILED);
+	}
+
+	igt_subtest_f("flip-to-Y-tiled") {
+		igt_require_fb_modifiers(data.drm_fd);
+		igt_require(data.gen >= 9);
+
+		for_each_connected_output(&data.display, output)
+			test_linear_tiled_flip(&data, output,
+					       LOCAL_I915_FORMAT_MOD_Y_TILED);
+	}
+
+	igt_subtest_f("flip-to-Yf-tiled") {
+		igt_require_fb_modifiers(data.drm_fd);
+		igt_require(data.gen >= 9);
+
+		for_each_connected_output(&data.display, output)
+			test_linear_tiled_flip(&data, output,
+					       LOCAL_I915_FORMAT_MOD_Yf_TILED);
+	}
+
 	igt_fixture {
 		igt_display_fini(&data.display);
 	}