[Intel-gfx] [PATCH i-g-t] tests: atomic: add test to verify page flip event emissions

Lionel Landwerlin lionel.g.landwerlin at intel.com
Thu Apr 21 17:43:54 UTC 2016


It seems we don't have a test verifying events with atomic commits
yet. Here is a first step.

Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
---
 tests/kms_atomic.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 133 insertions(+), 16 deletions(-)

diff --git a/tests/kms_atomic.c b/tests/kms_atomic.c
index f27ee46..707fe12 100644
--- a/tests/kms_atomic.c
+++ b/tests/kms_atomic.c
@@ -234,7 +234,7 @@ static uint32_t blob_duplicate(int fd, uint32_t id_orig)
 	igt_assert_eq(errno, err); \
 }
 
-#define crtc_commit_atomic(crtc, plane, req, relax) { \
+#define crtc_commit_atomic(crtc, plane, req, flags, relax) {	\
 	drmModeAtomicSetCursor(req, 0); \
 	crtc_populate_req(crtc, req); \
 	plane_populate_req(plane, req); \
@@ -252,10 +252,10 @@ static uint32_t blob_duplicate(int fd, uint32_t id_orig)
 	plane_check_current_state(plane_old, relax); \
 }
 
-#define plane_commit_atomic(plane, req, relax) { \
+#define plane_commit_atomic(plane, req, flags, relax) {	\
 	drmModeAtomicSetCursor(req, 0); \
 	plane_populate_req(plane, req); \
-	do_atomic_commit((plane)->state->desc->fd, req, 0); \
+	do_atomic_commit((plane)->state->desc->fd, req, flags); \
 	plane_check_current_state(plane, relax); \
 }
 
@@ -886,10 +886,10 @@ static void plane_overlay(struct kms_atomic_crtc_state *crtc,
 
 	/* Enable the overlay plane using the atomic API, and double-check
 	 * state is what we think it should be. */
-	plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE);
+	plane_commit_atomic(&plane, req, 0, ATOMIC_RELAX_NONE);
 
 	/* Disable the plane and check the state matches the old. */
-	plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE);
+	plane_commit_atomic(plane_old, req, 0, ATOMIC_RELAX_NONE);
 
 	/* Re-enable the plane through the legacy plane API, and verify through
 	 * atomic. */
@@ -928,10 +928,10 @@ static void plane_primary(struct kms_atomic_crtc_state *crtc,
 
 	/* Flip the primary plane using the atomic API, and double-check
 	 * state is what we think it should be. */
-	crtc_commit_atomic(crtc, &plane, req, ATOMIC_RELAX_NONE);
+	crtc_commit_atomic(crtc, &plane, req, 0, ATOMIC_RELAX_NONE);
 
 	/* Restore the primary plane and check the state matches the old. */
-	crtc_commit_atomic(crtc, plane_old, req, ATOMIC_RELAX_NONE);
+	crtc_commit_atomic(crtc, plane_old, req, 0, ATOMIC_RELAX_NONE);
 
 	/* Re-enable the plane through the legacy CRTC/primary-plane API, and
 	 * verify through atomic. */
@@ -942,7 +942,7 @@ static void plane_primary(struct kms_atomic_crtc_state *crtc,
 	crtc_commit_legacy(crtc, plane_old, CRTC_RELAX_MODE);
 
 	/* Finally, restore to the original state. */
-	crtc_commit_atomic(crtc, plane_old, req, ATOMIC_RELAX_NONE);
+	crtc_commit_atomic(crtc, plane_old, req, 0, ATOMIC_RELAX_NONE);
 
 	drmModeAtomicFree(req);
 }
@@ -983,10 +983,10 @@ static void plane_cursor(struct kms_atomic_crtc_state *crtc,
 
 	/* Flip the cursor plane using the atomic API, and double-check
 	 * state is what we think it should be. */
-	plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE);
+	plane_commit_atomic(&plane, req, 0, ATOMIC_RELAX_NONE);
 
 	/* Restore the cursor plane and check the state matches the old. */
-	plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE);
+	plane_commit_atomic(plane_old, req, 0, ATOMIC_RELAX_NONE);
 
 	/* Re-enable the plane through the legacy cursor API, and verify
 	 * through atomic. */
@@ -1010,7 +1010,7 @@ static void plane_cursor(struct kms_atomic_crtc_state *crtc,
 	plane_check_current_state(plane_old, ATOMIC_RELAX_NONE);
 
 	/* Finally, restore to the original state. */
-	plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE);
+	plane_commit_atomic(plane_old, req, 0, ATOMIC_RELAX_NONE);
 
 	drmModeAtomicFree(req);
 }
@@ -1043,7 +1043,7 @@ static void plane_invalid_params(struct kms_atomic_crtc_state *crtc,
 	                        ATOMIC_RELAX_NONE, EINVAL);
 
 	plane.fb_id = plane_old->fb_id;
-	plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE);
+	plane_commit_atomic(&plane, req, 0, ATOMIC_RELAX_NONE);
 
 	/* Pass a series of invalid object IDs for the CRTC ID. */
 	plane.crtc_id = plane.obj;
@@ -1063,7 +1063,7 @@ static void plane_invalid_params(struct kms_atomic_crtc_state *crtc,
 	                        ATOMIC_RELAX_NONE, EINVAL);
 
 	plane.crtc_id = plane_old->crtc_id;
-	plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE);
+	plane_commit_atomic(&plane, req, 0, ATOMIC_RELAX_NONE);
 
 	/* Create a framebuffer too small for the plane configuration. */
 	igt_require(format != 0);
@@ -1085,7 +1085,7 @@ static void plane_invalid_params(struct kms_atomic_crtc_state *crtc,
 	                        ATOMIC_RELAX_NONE, ENOSPC);
 
 	/* Restore the primary plane and check the state matches the old. */
-	plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE);
+	plane_commit_atomic(plane_old, req, 0, ATOMIC_RELAX_NONE);
 
 	drmModeAtomicFree(req);
 }
@@ -1117,7 +1117,7 @@ static void crtc_invalid_params(struct kms_atomic_crtc_state *crtc_old,
 	                       ATOMIC_RELAX_NONE, EINVAL);
 
 	crtc.mode.id = crtc_old->mode.id;
-	crtc_commit_atomic(&crtc, plane, req, ATOMIC_RELAX_NONE);
+	crtc_commit_atomic(&crtc, plane, req, 0, ATOMIC_RELAX_NONE);
 
 	/* Create a blob which is the wrong size to be a valid mode. */
 	do_or_die(drmModeCreatePropertyBlob(crtc.state->desc->fd,
@@ -1136,7 +1136,7 @@ static void crtc_invalid_params(struct kms_atomic_crtc_state *crtc_old,
 	                       ATOMIC_RELAX_NONE, EINVAL);
 
 	/* Restore the CRTC and check the state matches the old. */
-	crtc_commit_atomic(crtc_old, plane, req, ATOMIC_RELAX_NONE);
+	crtc_commit_atomic(crtc_old, plane, req, 0, ATOMIC_RELAX_NONE);
 
 	drmModeAtomicFree(req);
 }
@@ -1280,6 +1280,112 @@ static void atomic_invalid_params(struct kms_atomic_crtc_state *crtc,
 	do_ioctl_err(desc->fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EFAULT);
 }
 
+static void get_events(struct kms_atomic_crtc_state *crtc,
+		       int *page_flips,
+		       int *vblank_count,
+		       int msec)
+{
+	struct kms_atomic_desc *desc = crtc->state->desc;
+	struct timeval timeout = { .tv_sec = 0, .tv_usec = msec * 1000 };
+	fd_set fds;
+	char buffer[1024];
+	int idx, len, ret;
+
+	FD_ZERO(&fds);
+	FD_SET(desc->fd, &fds);
+
+	ret = select(1, &fds, NULL, NULL, &timeout);
+	if (ret < 1)
+		return;
+
+	len = read(desc->fd, buffer, sizeof(buffer));
+	if (len == 0)
+		return;
+
+	idx = 0;
+	while (idx < len) {
+		struct drm_event event;
+
+		igt_assert_lte(sizeof(event), len - idx);
+
+		memcpy(&event, &buffer[idx], sizeof(event));
+		switch (event.type) {
+		case DRM_EVENT_FLIP_COMPLETE:
+			(*page_flips)++;
+			break;
+		case DRM_EVENT_VBLANK:
+			(*vblank_count)++;
+			break;
+		default:
+			break;
+		}
+
+		idx += event.length;
+	}
+}
+
+static void plane_pageflip_events(struct kms_atomic_crtc_state *crtc,
+				  struct kms_atomic_plane_state *plane_old)
+{
+	struct drm_mode_modeinfo *mode = crtc->mode.data;
+	struct kms_atomic_plane_state plane = *plane_old;
+	uint32_t format = plane_get_igt_format(&plane);
+	drmModeAtomicReq *req = drmModeAtomicAlloc();
+	struct igt_fb fb[2];
+	int i, pageflip_count = 0, vblank_count = 0;
+	int flags = DRM_MODE_PAGE_FLIP_EVENT;
+
+	igt_require(format != 0);
+
+	for (i = 0; i < ARRAY_SIZE(fb); i++)
+		igt_create_pattern_fb(plane.state->desc->fd,
+				      plane.crtc_w, plane.crtc_h,
+				      format, I915_TILING_NONE, &fb[i]);
+
+	plane.src_x = 0;
+	plane.src_y = 0;
+	plane.src_w = mode->hdisplay << 16;
+	plane.src_h = mode->vdisplay << 16;
+	plane.crtc_x = 0;
+	plane.crtc_y = 0;
+	plane.crtc_w = mode->hdisplay;
+	plane.crtc_h = mode->vdisplay;
+	plane.crtc_id = crtc->obj;
+	plane.fb_id = fb[0].fb_id;
+
+	/* Flip the primary plane using the atomic API, and double-check
+	 * state is what we think it should be. */
+	crtc_commit_atomic(crtc, &plane, req, flags, ATOMIC_RELAX_NONE);
+
+	get_events(crtc, &pageflip_count, &vblank_count, 20);
+	igt_assert_eq(1, pageflip_count);
+
+	drmModeAtomicFree(req);
+	req = drmModeAtomicAlloc();
+
+	/* Change the framebuffer on the plane, we should get one
+	 * pageflip event. */
+	plane.fb_id = fb[1].fb_id;
+	plane_commit_atomic(&plane, req, flags, ATOMIC_RELAX_NONE);
+	get_events(crtc, &pageflip_count, &vblank_count, 20);
+	igt_assert_eq(2, pageflip_count);
+
+	/* No change, page flip event count should remain the same. */
+	plane.fb_id = fb[1].fb_id;
+	plane_commit_atomic(&plane, req, flags, ATOMIC_RELAX_NONE);
+	get_events(crtc, &pageflip_count, &vblank_count, 20);
+	igt_assert_eq(2, pageflip_count);
+
+	/* Change back the plane's framebuffer to its original one, we
+	 * should get a page flip event. */
+	plane.fb_id = fb[0].fb_id;
+	plane_commit_atomic(&plane, req, flags, ATOMIC_RELAX_NONE);
+	get_events(crtc, &pageflip_count, &vblank_count, 20);
+	igt_assert_eq(3, pageflip_count);
+
+	drmModeAtomicFree(req);
+}
+
 igt_main
 {
 	struct kms_atomic_desc desc;
@@ -1373,6 +1479,17 @@ igt_main
 		atomic_state_free(scratch);
 	}
 
+	igt_subtest("atomic_pageflip_events") {
+		struct kms_atomic_state *scratch = atomic_state_dup(current);
+		struct kms_atomic_crtc_state *crtc = find_crtc(scratch, true);
+		struct kms_atomic_plane_state *plane =
+			find_plane(scratch, PLANE_TYPE_PRIMARY, crtc);
+
+		igt_require(plane);
+		plane_pageflip_events(crtc, plane);
+		atomic_state_free(scratch);
+	}
+
 	atomic_state_free(current);
 
 	igt_fixture
-- 
2.8.0.rc3.226.g39d4020



More information about the Intel-gfx mailing list