[Intel-gfx] [PATCH igt 10/28] lib/display: Add support for the cursor plane

Damien Lespiau damien.lespiau at intel.com
Fri Feb 7 15:48:54 CET 2014


Signed-off-by: Damien Lespiau <damien.lespiau at intel.com>
---
 lib/igt_kms.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 lib/igt_kms.h |  13 +++++-
 2 files changed, 150 insertions(+), 11 deletions(-)

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index 64fb39a..3b75478 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -889,16 +889,29 @@ void igt_display_init(igt_display_t *display, int drm_fd)
 	for (i = 0; i < display->n_pipes; i++) {
 		igt_pipe_t *pipe = &display->pipes[i];
 		igt_plane_t *plane;
+		int p;
 
 		pipe->display = display;
 		pipe->pipe = i;
-		pipe->n_planes = 1;
 
 		/* primary plane */
-		plane = &pipe->planes[0];
+		p = IGT_PLANE_PRIMARY;
+		plane = &pipe->planes[p];
 		plane->pipe = pipe;
-		plane->index = 0;
+		plane->index = p;
 		plane->is_primary = true;
+
+		/* cursor plane */
+		p++;
+		plane = &pipe->planes[p];
+		plane->pipe = pipe;
+		plane->index = p;
+		plane->is_cursor = true;
+
+		pipe->n_planes = ++p;
+
+		/* make sure we don't overflow the plane array */
+		igt_assert(pipe->n_planes <= IGT_MAX_PLANES);
 	}
 
 	/*
@@ -1009,6 +1022,22 @@ static igt_pipe_t *igt_output_get_driving_pipe(igt_output_t *output)
 	return &display->pipes[pipe];
 }
 
+static igt_plane_t *igt_pipe_get_plane(igt_pipe_t *pipe, enum igt_plane plane)
+{
+	int idx;
+
+	/* Cursor plane is always the upper plane */
+	if (plane == IGT_PLANE_CURSOR)
+		idx = pipe->n_planes - 1;
+	else {
+		igt_assert_f(plane >= 0 && plane < (pipe->n_planes - 1),
+			     "plane=%d\n", plane);
+		idx = plane;
+	}
+
+	return &pipe->planes[idx];
+}
+
 static uint32_t igt_plane_get_fd_id(igt_plane_t *plane)
 {
 	if (plane->fb)
@@ -1017,10 +1046,53 @@ static uint32_t igt_plane_get_fd_id(igt_plane_t *plane)
 		return 0;
 }
 
+static uint32_t igt_plane_get_fb_gem_handle(igt_plane_t *plane)
+{
+	if (plane->fb)
+		return plane->fb->gem_handle;
+	else
+		return 0;
+}
+
+static int igt_cursor_commit(igt_plane_t *plane, igt_output_t *output)
+{
+	igt_display_t *display = output->display;
+	uint32_t crtc_id = output->config.crtc->crtc_id;
+	int ret;
+
+	if (plane->position_changed) {
+		int x = plane->crtc_x;
+		int y = plane->crtc_y;
+
+		LOG(display,
+		    "%s: MoveCursor pipe %c, (%d, %d)\n",
+		    igt_output_name(output),
+		    pipe_name(output->config.pipe),
+		    x, y);
+
+		ret = drmModeMoveCursor(display->drm_fd, crtc_id, x, y);
+
+		igt_assert(ret == 0);
+
+		plane->position_changed = false;
+	}
+
+	return 0;
+}
+
+static int igt_plane_commit(igt_plane_t *plane, igt_output_t *output)
+{
+	if (plane->is_cursor)
+		igt_cursor_commit(plane, output);
+
+	return 0;
+}
+
 static int igt_output_commit(igt_output_t *output)
 {
 	igt_display_t *display = output->display;
 	igt_pipe_t *pipe;
+	int i;
 
 	pipe = igt_output_get_driving_pipe(output);
 	if (pipe->need_set_crtc) {
@@ -1073,6 +1145,48 @@ static int igt_output_commit(igt_output_t *output)
 		pipe->need_set_crtc = false;
 	}
 
+	if (pipe->need_set_cursor) {
+		igt_plane_t *cursor;
+		uint32_t gem_handle, crtc_id;
+		int ret;
+
+		cursor = igt_pipe_get_plane(pipe, IGT_PLANE_CURSOR);
+		crtc_id = output->config.crtc->crtc_id;
+		gem_handle = igt_plane_get_fb_gem_handle(cursor);
+
+		if (gem_handle) {
+			LOG(display,
+			    "%s: SetCursor pipe %c, fb %u %dx%d\n",
+			    igt_output_name(output),
+			    pipe_name(output->config.pipe),
+			    gem_handle,
+			    cursor->fb->width, cursor->fb->height);
+
+			ret = drmModeSetCursor(display->drm_fd, crtc_id,
+					       gem_handle,
+					       cursor->fb->width,
+					       cursor->fb->height);
+		} else {
+			LOG(display,
+			    "%s: SetCursor pipe %c, disabling\n",
+			    igt_output_name(output),
+			    pipe_name(output->config.pipe));
+
+			ret = drmModeSetCursor(display->drm_fd, crtc_id,
+					       0, 0, 0);
+		}
+
+		igt_assert(ret == 0);
+
+		pipe->need_set_cursor = false;
+	}
+
+	for (i = 0; i < pipe->n_planes; i++) {
+		igt_plane_t *plane = &pipe->planes[i];
+
+		igt_plane_commit(plane, output);
+	}
+
 	return 0;
 }
 
@@ -1118,12 +1232,6 @@ void igt_output_set_pipe(igt_output_t *output, enum pipe pipe)
 	output->pending_crtc_idx_mask = 1 << pipe;
 }
 
-static igt_plane_t *igt_pipe_get_plane(igt_pipe_t *pipe, int index)
-{
-	igt_assert(index >= 0 && index < pipe->n_planes);
-	return &pipe->planes[index];
-}
-
 igt_plane_t *igt_ouput_get_plane(igt_output_t *output, enum igt_plane plane)
 {
 	igt_pipe_t *pipe;
@@ -1144,4 +1252,26 @@ void igt_plane_set_fb(igt_plane_t *plane, struct kmstest_fb *fb)
 
 	if (plane->is_primary)
 		pipe->need_set_crtc = true;
+	else if (plane->is_cursor)
+		pipe->need_set_cursor = true;
+}
+
+void igt_plane_set_position(igt_plane_t *plane, int x, int y)
+{
+	igt_pipe_t *pipe = plane->pipe;
+	igt_display_t *display = pipe->display;
+
+	/*
+	 * XXX: Some platforms don't need the primary plane to cover the
+	 * whole pipe. Of course this test becomes wrong when we support that.
+	 */
+	igt_assert(!plane->is_primary || (x == 0 && y == 0));
+
+	LOG(display, "%c.%d: plane_set_position(%d,%d)\n",
+	    pipe_name(pipe->pipe), plane->index, x, y);
+
+	plane->crtc_x = x;
+	plane->crtc_y = y;
+
+	plane->position_changed = true;
 }
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index bb74fc4..e86cff4 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -109,18 +109,24 @@ uint32_t drm_format_to_bpp(uint32_t drm_format);
 
 typedef struct igt_display igt_display_t;
 typedef struct igt_pipe igt_pipe_t;
+typedef uint32_t igt_fixed_t;			/* 16.16 fixed point */
 
 typedef struct {
 	igt_pipe_t *pipe;
 	int index;
-	unsigned int is_primary : 1;
+	unsigned int is_primary       : 1;
+	unsigned int is_cursor        : 1;
+	unsigned int position_changed : 1;
 	struct kmstest_fb *fb;
+	/* position within pipe_src_w x pipe_src_h */
+	int crtc_x, crtc_y;
 } igt_plane_t;
 
 struct igt_pipe {
 	igt_display_t *display;
 	enum pipe pipe;
-	unsigned int need_set_crtc : 1;
+	unsigned int need_set_crtc   : 1;
+	unsigned int need_set_cursor : 1;
 #define IGT_MAX_PLANES	4
 	int n_planes;
 	igt_plane_t planes[IGT_MAX_PLANES];
@@ -158,10 +164,13 @@ void igt_output_set_pipe(igt_output_t *output, enum pipe pipe);
 igt_plane_t *igt_ouput_get_plane(igt_output_t *output, enum igt_plane plane);
 
 void igt_plane_set_fb(igt_plane_t *plane, struct kmstest_fb *fb);
+void igt_plane_set_position(igt_plane_t *plane, int x, int y);
 
 #define for_each_connected_output(display, output)		\
 	for (int i__ = 0;  i__ < (display)->n_outputs; i__++)	\
 		if ((output = &(display)->outputs[i__]), output->valid)
 
+#define IGT_FIXED(i,f)	((i) << 16 | (f))
+
 #endif /* __IGT_KMS_H__ */
 
-- 
1.8.3.1




More information about the Intel-gfx mailing list