[Intel-gfx] [PATCH i-g-t 2/3] lib/kms: Add nuclear pageflip commit style

Matt Roper matthew.d.roper at intel.com
Mon Jan 19 20:05:12 PST 2015


This commit style only covers the "nuclear pageflip" subset of the
atomic API (i.e., single CRTC, plane updates only).  In the future when
our kernel driver has full atomic modeset support, we'll add another
commit style 'atomic' which will re-use the same plane commit calls
added here, but will generate and commit property sets in the display's
commit handler rather than the output's commit handler.

Since nuclear pageflip (and full atomic eventually) depend on very new
(currently unreleased) libdrm, use autoconf to check for support so that
we can still run with just legacy + universal styles when built with
older libdrm's.

Signed-off-by: Matt Roper <matthew.d.roper at intel.com>
---
 configure.ac  |   3 ++
 lib/igt_kms.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 lib/igt_kms.h |  19 ++++++-
 3 files changed, 181 insertions(+), 10 deletions(-)

diff --git a/configure.ac b/configure.ac
index 16d6a2e..1e3c2f1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -87,6 +87,9 @@ PKG_CHECK_MODULES(PCIACCESS, [pciaccess >= 0.10])
 PKG_CHECK_MODULES(OVERLAY_XVLIB, [xv x11 xext dri2proto >= 2.6], enable_overlay_xvlib=yes, enable_overlay_xvlib=no)
 PKG_CHECK_MODULES(OVERLAY_XLIB, [cairo-xlib dri2proto >= 2.6], enable_overlay_xlib=yes, enable_overlay_xlib=no)
 
+# Check for atomic modeset support in libdrm
+AC_CHECK_LIB(drm, drmModePropertySetCommit, AC_DEFINE(HAVE_ATOMIC, [], [Atomic modeset supported]))
+
 AM_CONDITIONAL(BUILD_OVERLAY_XVLIB, [test "x$enable_overlay_xvlib" = xyes])
 AM_CONDITIONAL(BUILD_OVERLAY_XLIB, [test "x$enable_overlay_xlib" = xyes])
 AM_CONDITIONAL(BUILD_OVERLAY, [test "x$enable_overlay_xlib" = xyes -o "x$enable_overlay_xvlib"])
diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index bb72c68..26e4913 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -50,13 +50,15 @@
 #include "igt_debugfs.h"
 
 /*
- * There hasn't been a release of libdrm containing these #define's yet, so
- * copy them here to allow compilation to succeed in the mean time.
+ * Universal plane bits didn't show up until libdrm 2.4.55 and atomic hasn't
+ * landed in a release yet, so copy the relevant #define's here to allow
+ * compilation to succeeed on older libdrm's.
  *
  * We can drop these #define's and just make i-g-t depend on the proper libdrm
  * version in the future.
  */
 #define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
+#define DRM_CLIENT_CAP_ATOMIC 3
 #define DRM_PLANE_TYPE_OVERLAY 0
 #define DRM_PLANE_TYPE_PRIMARY 1
 #define DRM_PLANE_TYPE_CURSOR  2
@@ -944,6 +946,42 @@ static int get_drm_plane_type(int drm_fd, uint32_t plane_id)
 	return DRM_PLANE_TYPE_OVERLAY;
 }
 
+/*
+ * Lookup all of the properties we use for a plane.
+ */
+static void lookup_plane_properties(int drm_fd,
+				    igt_plane_t *plane)
+{
+	uint64_t prop_value;
+
+	get_plane_property(drm_fd, plane->drm_plane->plane_id, "rotation",
+			   &plane->rotation_property, &prop_value, NULL);
+	plane->rotation = (igt_rotation_t)prop_value;
+
+	get_plane_property(drm_fd, plane->drm_plane->plane_id, "FB_ID",
+			   &plane->fb_property, NULL, NULL);
+	get_plane_property(drm_fd, plane->drm_plane->plane_id, "CRTC_ID",
+			   &plane->crtc_property, NULL, NULL);
+
+	get_plane_property(drm_fd, plane->drm_plane->plane_id, "CRTC_X",
+			   &plane->dstx_property, NULL, NULL);
+	get_plane_property(drm_fd, plane->drm_plane->plane_id, "CRTC_Y",
+			   &plane->dsty_property, NULL, NULL);
+	get_plane_property(drm_fd, plane->drm_plane->plane_id, "CRTC_W",
+			   &plane->dstw_property, NULL, NULL);
+	get_plane_property(drm_fd, plane->drm_plane->plane_id, "CRTC_H",
+			   &plane->dsth_property, NULL, NULL);
+
+	get_plane_property(drm_fd, plane->drm_plane->plane_id, "SRC_X",
+			   &plane->srcx_property, NULL, NULL);
+	get_plane_property(drm_fd, plane->drm_plane->plane_id, "SRC_Y",
+			   &plane->srcy_property, NULL, NULL);
+	get_plane_property(drm_fd, plane->drm_plane->plane_id, "SRC_W",
+			   &plane->srcw_property, NULL, NULL);
+	get_plane_property(drm_fd, plane->drm_plane->plane_id, "SRC_H",
+			   &plane->srch_property, NULL, NULL);
+}
+
 void igt_display_init(igt_display_t *display, int drm_fd)
 {
 	drmModeRes *resources;
@@ -966,6 +1004,7 @@ void igt_display_init(igt_display_t *display, int drm_fd)
 	display->n_pipes = resources->count_crtcs;
 
 	drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+	drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, 1);
 	plane_resources = drmModeGetPlaneResources(display->drm_fd);
 	igt_assert(plane_resources);
 
@@ -981,7 +1020,6 @@ void igt_display_init(igt_display_t *display, int drm_fd)
 		/* add the planes that can be used with that pipe */
 		for (j = 0; j < plane_resources->count_planes; j++) {
 			drmModePlane *drm_plane;
-			uint64_t prop_value;
 
 			drm_plane = drmModeGetPlane(display->drm_fd,
 						    plane_resources->planes[j]);
@@ -1023,12 +1061,21 @@ void igt_display_init(igt_display_t *display, int drm_fd)
 			plane->pipe = pipe;
 			plane->drm_plane = drm_plane;
 
-			get_plane_property(display->drm_fd, drm_plane->plane_id,
-					   "rotation",
-					   &plane->rotation_property,
-					   &prop_value,
-					   NULL);
-			plane->rotation = (igt_rotation_t)prop_value;
+			lookup_plane_properties(display->drm_fd, plane);
+#ifdef HAVE_ATOMIC
+			display->has_atomic_props =
+				(plane->fb_property &&
+				 plane->crtc_property &&
+				 plane->rotation_property &&
+				 plane->dstx_property &&
+				 plane->dsty_property &&
+				 plane->dstw_property &&
+				 plane->dsth_property &&
+				 plane->srcx_property &&
+				 plane->srcy_property &&
+				 plane->srcw_property &&
+				 plane->srch_property);
+#endif
 		}
 
 		if (display->has_universal_planes) {
@@ -1336,6 +1383,79 @@ static int igt_drm_plane_commit(igt_plane_t *plane,
 	return 0;
 }
 
+#ifdef HAVE_ATOMIC
+/*
+ * Apply plane changes for an atomic operation.  Note that we don't actually
+ * perform the commit here; we just push the proper values into the atomic
+ * property set and let either igt_output_commit (nuclear) or
+ * igt_display_commit (atomic) issue the actual commit.
+ */
+static int igt_drm_plane_commit_atomic(igt_plane_t *plane,
+				       igt_output_t *output,
+				       drmModePropertySetPtr set,
+				       bool fail_on_error)
+{
+	uint32_t fb_id, crtc_id, plane_id;
+
+	igt_assert(set);
+	igt_assert(plane->drm_plane);
+
+	/* it's an error to try an unsupported feature */
+	igt_assert(igt_plane_supports_rotation(plane) ||
+		   !plane->rotation_changed);
+
+	fb_id = igt_plane_get_fb_id(plane);
+	crtc_id = fb_id ? output->config.crtc->crtc_id : 0;
+	plane_id = plane->drm_plane->plane_id;
+
+	if (plane->fb_changed) {
+		drmModePropertySetAdd(set, plane_id, plane->fb_property,
+				      fb_id);
+		drmModePropertySetAdd(set, plane_id,
+				      plane->crtc_property, crtc_id);
+	}
+
+	if (plane->fb &&
+	    (plane->fb_changed || plane->position_changed || plane->panning_changed)) {
+		/* Source coordinates */
+		drmModePropertySetAdd(set, plane_id,
+				      plane->srcx_property,
+				      IGT_FIXED(plane->pan_x,0));
+		drmModePropertySetAdd(set, plane_id,
+				      plane->srcy_property,
+				      IGT_FIXED(plane->pan_y,0));
+		drmModePropertySetAdd(set, plane_id,
+				      plane->srcw_property,
+				      IGT_FIXED(plane->fb->width - plane->pan_x,0));
+		drmModePropertySetAdd(set, plane_id,
+				      plane->srch_property,
+				      IGT_FIXED(plane->fb->height - plane->pan_y,0));
+
+		/* Destination coordinates */
+		drmModePropertySetAdd(set, plane_id, plane->dstx_property,
+				      plane->crtc_x);
+		drmModePropertySetAdd(set, plane_id, plane->dsty_property,
+				      plane->crtc_y);
+		drmModePropertySetAdd(set, plane_id, plane->dstw_property,
+				      plane->crtc_w);
+		drmModePropertySetAdd(set, plane_id, plane->dsth_property,
+				      plane->crtc_h);
+	}
+
+	if (plane->rotation_changed)
+		drmModePropertySetAdd(set, plane_id, plane->rotation_property,
+				      plane->rotation);
+
+
+	plane->fb_changed = false;
+	plane->position_changed = false;
+	plane->panning_changed = false;
+	plane->rotation = false;
+
+	return 0;
+}
+#endif
+
 /*
  * Commit position and fb changes to a cursor via legacy ioctl's.  If commit
  * fails, we'll either fail immediately (for tests that expect the commit to
@@ -1486,6 +1606,11 @@ static int igt_plane_commit(igt_plane_t *plane,
 	} else if (plane->is_primary && s == COMMIT_LEGACY) {
 		return igt_primary_plane_commit_legacy(plane, output,
 						       fail_on_error);
+#ifdef HAVE_ATOMIC
+	} else if (s == COMMIT_NUCLEAR) {
+		return igt_drm_plane_commit_atomic(plane, output, output->set,
+						   fail_on_error);
+#endif
 	} else {
 		return igt_drm_plane_commit(plane, output, fail_on_error);
 	}
@@ -1513,6 +1638,13 @@ static int igt_output_commit(igt_output_t *output,
 
 	pipe = igt_output_get_driving_pipe(output);
 
+#ifdef HAVE_ATOMIC
+	if (s == COMMIT_NUCLEAR) {
+		output->set = drmModePropertySetAlloc();
+		igt_assert(output->set);
+	}
+#endif
+
 	for (i = 0; i < pipe->n_planes; i++) {
 		igt_plane_t *plane = &pipe->planes[i];
 
@@ -1523,6 +1655,17 @@ static int igt_output_commit(igt_output_t *output,
 		CHECK_RETURN(ret, fail_on_error);
 	}
 
+#ifdef HAVE_ATOMIC
+	/* Nuclear pageflip commit */
+	if (s == COMMIT_NUCLEAR) {
+		ret = drmModePropertySetCommit(display->drm_fd, 0, NULL,
+					       output->set);
+		drmModePropertySetFree(output->set);
+		output->set = NULL;
+		CHECK_RETURN(ret, fail_on_error);
+	}
+#endif
+
 	/*
 	 * If the crtc is enabled, wait until the next vblank before returning
 	 * if we made changes to any of the planes.
@@ -1551,6 +1694,14 @@ static int do_display_commit(igt_display_t *display,
 
 	LOG_INDENT(display, "commit");
 
+#ifndef HAVE_ATOMIC
+	/*
+	 * If our libdrm doesn't support atomic; skip any tests that explicitly
+	 * ask for nuclear pageflip or atomic modeset.
+	 */
+	igt_skip_on(s == COMMIT_NUCLEAR);
+#endif
+
 	igt_debug_wait_for_keypress("commit");
 	igt_display_refresh(display);
 
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index a1483a4..2fab30e 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -154,7 +154,8 @@ void kmstest_unset_all_crtcs(int drm_fd, drmModeResPtr resources);
 enum igt_commit_style {
 	COMMIT_LEGACY = 0,
 	COMMIT_UNIVERSAL,
-	/* We'll add atomic here eventually. */
+	COMMIT_NUCLEAR,   /* atomic plane operations on single crtc only */
+	/* We'll add full atomic here eventually. */
 };
 
 typedef struct igt_display igt_display_t;
@@ -189,6 +190,16 @@ typedef struct {
 	struct igt_fb *fb;
 
 	uint32_t rotation_property;
+	uint32_t fb_property;
+	uint32_t crtc_property;
+	uint32_t dstx_property;
+	uint32_t dsty_property;
+	uint32_t dstw_property;
+	uint32_t dsth_property;
+	uint32_t srcx_property;
+	uint32_t srcy_property;
+	uint32_t srcw_property;
+	uint32_t srch_property;
 
 	/* position within pipe_src_w x pipe_src_h */
 	int crtc_x, crtc_y;
@@ -216,6 +227,11 @@ typedef struct {
 	char *name;
 	bool valid;
 	unsigned long pending_crtc_idx_mask;
+
+#ifdef HAVE_ATOMIC
+	/* Property set for nuclear pageflip */
+	drmModePropertySetPtr set;
+#endif
 } igt_output_t;
 
 struct igt_display {
@@ -227,6 +243,7 @@ struct igt_display {
 	igt_output_t *outputs;
 	igt_pipe_t pipes[I915_MAX_PIPES];
 	bool has_universal_planes;
+	bool has_atomic_props;
 };
 
 void igt_display_init(igt_display_t *display, int drm_fd);
-- 
1.8.5.1



More information about the Intel-gfx mailing list