summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDamien Lespiau <damien.lespiau@intel.com>2014-02-05 16:36:51 +0000
committerDamien Lespiau <damien.lespiau@intel.com>2014-02-11 13:50:16 +0000
commit5ec399b4a6b11dc6c2b1a1bd25b745d4dd9279a6 (patch)
tree6d7f2e3a6481d27ad3454e5d04e34970da63598f /lib
parentc4823ce9a4d51eeb422be822e8a6d971a7141c24 (diff)
lib/display: Add support for the cursor plane
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/igt_kms.c148
-rw-r--r--lib/igt_kms.h13
2 files changed, 150 insertions, 11 deletions
diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index c9e110c1..e2225e62 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -890,16 +890,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);
}
/*
@@ -1010,6 +1023,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)
@@ -1018,10 +1047,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) {
@@ -1074,6 +1146,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;
}
@@ -1119,12 +1233,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;
@@ -1145,4 +1253,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 bb74fc40..e86cff4e 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__ */