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

Message ID 1431099688-10165-1-git-send-email-tvrtko.ursulin@linux.intel.com
State New
Headers show

Commit Message

Tvrtko Ursulin May 8, 2015, 3:41 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.

v4:
   * Refactored for less code.
   * Check crc after page flip to ensure it happened. (Chris Wilson)
   * Skip rather than fail when flip fails. (Chris Wilson)

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

Patch
diff mbox

diff --git a/tests/kms_flip_tiling.c b/tests/kms_flip_tiling.c
index 8345505..c7fd4de 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,67 +53,124 @@  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);
+}
+
 static void
-test_flip_changes_tiling(data_t *data, igt_output_t *output, uint64_t tiling)
+test_flip_tiling(data_t *data, igt_output_t *output, uint64_t tiling[2])
 {
-	struct igt_fb linear, tiled;
 	drmModeModeInfo *mode;
 	igt_plane_t *primary;
+	struct igt_fb fb[2];
 	igt_pipe_crc_t *pipe_crc;
 	igt_crc_t reference_crc, crc;
 	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);
 	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;
+	width = mode->hdisplay;
+
+	if (tiling[0] != tiling[1] &&
+	    (tiling[0] != LOCAL_DRM_FORMAT_MOD_NONE ||
+	     tiling[1] != LOCAL_DRM_FORMAT_MOD_NONE)) {
+		/*
+		 * 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;
+	}
+
 	fb_id = igt_create_fb(data->drm_fd, width, mode->vdisplay,
-			      DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
-			      &linear);
+			      DRM_FORMAT_XRGB8888, tiling[0],
+			      &fb[0]);
+	igt_assert(fb_id);
+
+	/* Second fb has different background so CRC does not match. */
+	fb_id = igt_create_color_fb(data->drm_fd, width, mode->vdisplay,
+				    DRM_FORMAT_XRGB8888, tiling[1],
+				    0.5, 0.5, 0.5, &fb[1]);
+	igt_assert(fb_id);
 
-	/* fill it with a pattern that will look wrong if tiling is wrong */
-	fill_linear_fb(&linear, data, mode);
+	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, &linear);
+	/* Set the crtc and generate a reference CRC. */
+	igt_plane_set_fb(primary, &fb[1]);
 	igt_display_commit(&data->display);
 	igt_pipe_crc_collect_crc(pipe_crc, &reference_crc);
 
-	/* allocate a tiled buffer and set the crtc with it */
-	igt_create_color_fb(data->drm_fd, width, mode->vdisplay,
-			    DRM_FORMAT_XRGB8888, tiling,
-			    0.0, 0.0, 0.0, &tiled);
-	igt_plane_set_fb(primary, &tiled);
+	/* Commit the first fb. */
+	igt_plane_set_fb(primary, &fb[0]);
 	igt_display_commit(&data->display);
 
-	/* flip to the linear buffer */
+	/* Flip to the second fb. */
 	ret = drmModePageFlip(data->drm_fd, output->config.crtc->crtc_id,
-			      fb_id, 0, NULL);
-	igt_assert_eq(ret, 0);
+			      fb[1].fb_id, DRM_MODE_PAGE_FLIP_EVENT, NULL);
+	/*
+	 * Page flip should work but some transitions may be temporarily
+	 * on some kernels.
+	 */
+	igt_require(ret == 0);
 
-	igt_wait_for_vblank(data->drm_fd, pipe);
+	wait_for_pageflip(data->drm_fd);
 
-	/* get a crc and compare with the reference */
+	/* 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 */
+	/* 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);
 
-	igt_remove_fb(data->drm_fd, &tiled);
-	igt_remove_fb(data->drm_fd, &linear);
+	igt_remove_fb(data->drm_fd, &fb[0]);
+	igt_remove_fb(data->drm_fd, &fb[1]);
 }
 
 static data_t data;
@@ -142,28 +190,118 @@  igt_main
 		igt_display_init(&data.display, data.drm_fd);
 	}
 
+	/*
+	 * 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.
+	 */
+
 	igt_subtest_f("flip-changes-tiling") {
+		uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_X_TILED,
+				       LOCAL_DRM_FORMAT_MOD_NONE };
+
 		for_each_connected_output(&data.display, output)
-			test_flip_changes_tiling(&data, output,
-						LOCAL_I915_FORMAT_MOD_X_TILED);
+			test_flip_tiling(&data, output, tiling);
 	}
 
 	igt_subtest_f("flip-changes-tiling-Y") {
+		uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_Y_TILED,
+				       LOCAL_DRM_FORMAT_MOD_NONE };
+
 		igt_require_fb_modifiers(data.drm_fd);
 		igt_require(data.gen >= 9);
 
 		for_each_connected_output(&data.display, output)
-			test_flip_changes_tiling(&data, output,
-						LOCAL_I915_FORMAT_MOD_Y_TILED);
+			test_flip_tiling(&data, output, tiling);
 	}
 
 	igt_subtest_f("flip-changes-tiling-Yf") {
+		uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_Yf_TILED,
+				       LOCAL_DRM_FORMAT_MOD_NONE };
+
+		igt_require_fb_modifiers(data.drm_fd);
+		igt_require(data.gen >= 9);
+
+		for_each_connected_output(&data.display, output)
+			test_flip_tiling(&data, output, tiling);
+	}
+
+	/*
+	 * 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.
+	 */
+
+	igt_subtest_f("flip-X-tiled") {
+		uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_X_TILED,
+				       LOCAL_I915_FORMAT_MOD_X_TILED };
+
+		for_each_connected_output(&data.display, output)
+			test_flip_tiling(&data, output, tiling);
+	}
+
+	igt_subtest_f("flip-Y-tiled") {
+		uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_Y_TILED,
+				       LOCAL_I915_FORMAT_MOD_Y_TILED };
+
+		igt_require_fb_modifiers(data.drm_fd);
+		igt_require(data.gen >= 9);
+
+		for_each_connected_output(&data.display, output)
+			test_flip_tiling(&data, output, tiling);
+	}
+
+	igt_subtest_f("flip-Yf-tiled") {
+		uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_Yf_TILED,
+				       LOCAL_I915_FORMAT_MOD_Yf_TILED };
+
+		igt_require_fb_modifiers(data.drm_fd);
+		igt_require(data.gen >= 9);
+
+		for_each_connected_output(&data.display, output)
+			test_flip_tiling(&data, output, tiling);
+	}
+
+	/*
+	 * 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.
+	 */
+
+	igt_subtest_f("flip-to-X-tiled") {
+		uint64_t tiling[2] = { LOCAL_DRM_FORMAT_MOD_NONE,
+				       LOCAL_I915_FORMAT_MOD_X_TILED };
+
+		for_each_connected_output(&data.display, output)
+			test_flip_tiling(&data, output, tiling);
+	}
+
+	igt_subtest_f("flip-to-Y-tiled") {
+		uint64_t tiling[2] = { LOCAL_DRM_FORMAT_MOD_NONE,
+				       LOCAL_I915_FORMAT_MOD_Y_TILED };
+
+		igt_require_fb_modifiers(data.drm_fd);
+		igt_require(data.gen >= 9);
+
+		for_each_connected_output(&data.display, output)
+			test_flip_tiling(&data, output, tiling);
+	}
+
+	igt_subtest_f("flip-to-Yf-tiled") {
+		uint64_t tiling[2] = { LOCAL_DRM_FORMAT_MOD_NONE,
+				       LOCAL_I915_FORMAT_MOD_Yf_TILED };
+
 		igt_require_fb_modifiers(data.drm_fd);
 		igt_require(data.gen >= 9);
 
 		for_each_connected_output(&data.display, output)
-			test_flip_changes_tiling(&data, output,
-						LOCAL_I915_FORMAT_MOD_Yf_TILED);
+			test_flip_tiling(&data, output, tiling);
 	}
 
 	igt_fixture {