summaryrefslogtreecommitdiff
path: root/tests/kms_vblank.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/kms_vblank.c')
-rw-r--r--tests/kms_vblank.c161
1 files changed, 136 insertions, 25 deletions
diff --git a/tests/kms_vblank.c b/tests/kms_vblank.c
index 40ab6fdb..9bc49296 100644
--- a/tests/kms_vblank.c
+++ b/tests/kms_vblank.c
@@ -44,6 +44,14 @@
IGT_TEST_DESCRIPTION("Test speed of WaitVblank.");
+typedef struct {
+ igt_display_t display;
+ struct igt_fb primary_fb;
+ igt_output_t *output;
+ enum pipe pipe;
+ uint8_t mode_busy:1;
+} data_t;
+
static double elapsed(const struct timespec *start,
const struct timespec *end,
int loop)
@@ -51,38 +59,119 @@ static double elapsed(const struct timespec *start,
return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000)/loop;
}
-static bool crtc0_active(int fd)
+static bool prepare_crtc(data_t *data, int fd, igt_output_t *output)
{
- union drm_wait_vblank vbl;
+ drmModeModeInfo *mode;
+ igt_display_t *display = &data->display;
+ igt_plane_t *primary;
+
+ /* select the pipe we want to use */
+ igt_output_set_pipe(output, data->pipe);
+ igt_display_commit(display);
+
+ if (!output->valid) {
+ igt_output_set_pipe(output, PIPE_ANY);
+ igt_display_commit(display);
+ return false;
+ }
- memset(&vbl, 0, sizeof(vbl));
- vbl.request.type = DRM_VBLANK_RELATIVE;
- return drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl) == 0;
+ /* create and set the primary plane fb */
+ mode = igt_output_get_mode(output);
+ igt_create_color_fb(fd, mode->hdisplay, mode->vdisplay,
+ DRM_FORMAT_XRGB8888,
+ LOCAL_DRM_FORMAT_MOD_NONE,
+ 0.0, 0.0, 0.0,
+ &data->primary_fb);
+
+ primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+ igt_plane_set_fb(primary, &data->primary_fb);
+
+ igt_display_commit(display);
+
+ igt_wait_for_vblank(fd, data->pipe);
+
+ return true;
+}
+
+static void cleanup_crtc(data_t *data, int fd, igt_output_t *output)
+{
+ igt_display_t *display = &data->display;
+ igt_plane_t *primary;
+
+ igt_remove_fb(fd, &data->primary_fb);
+
+ primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+ igt_plane_set_fb(primary, NULL);
+
+ igt_output_set_pipe(output, PIPE_ANY);
+ igt_display_commit(display);
+}
+
+static void run_test(data_t *data, int fd, void (*testfunc)(data_t *, int))
+{
+ igt_display_t *display = &data->display;
+ igt_output_t *output;
+ enum pipe p;
+ unsigned int valid_tests = 0;
+
+ for_each_connected_output(display, output) {
+ for_each_pipe(display, p) {
+ data->pipe = p;
+
+ if (!prepare_crtc(data, fd, output))
+ continue;
+
+ valid_tests++;
+
+ igt_info("Beginning %s on pipe %s, connector %s\n",
+ igt_subtest_name(),
+ kmstest_pipe_name(data->pipe),
+ igt_output_name(output));
+
+ testfunc(data, fd);
+
+ igt_info("\n%s on pipe %s, connector %s: PASSED\n\n",
+ igt_subtest_name(),
+ kmstest_pipe_name(data->pipe),
+ igt_output_name(output));
+
+ /* cleanup what prepare_crtc() has done */
+ cleanup_crtc(data, fd, output);
+ }
+ }
+
+ igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
}
-static void accuracy(int fd)
+static void accuracy(data_t *data, int fd)
{
union drm_wait_vblank vbl;
unsigned long target;
+ uint32_t pipe_id_flag;
int n;
memset(&vbl, 0, sizeof(vbl));
+ pipe_id_flag = kmstest_get_vbl_flag(data->pipe);
vbl.request.type = DRM_VBLANK_RELATIVE;
+ vbl.request.type |= pipe_id_flag;
vbl.request.sequence = 1;
do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
target = vbl.reply.sequence + 60;
for (n = 0; n < 60; n++) {
vbl.request.type = DRM_VBLANK_RELATIVE;
+ vbl.request.type |= pipe_id_flag;
vbl.request.sequence = 1;
do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+ vbl.request.type |= pipe_id_flag;
vbl.request.sequence = target;
do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
}
vbl.request.type = DRM_VBLANK_RELATIVE;
+ vbl.request.type |= pipe_id_flag;
vbl.request.sequence = 0;
do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
igt_assert_eq(vbl.reply.sequence, target);
@@ -94,22 +183,26 @@ static void accuracy(int fd)
}
}
-static void vblank_query(int fd, bool busy)
+static void vblank_query(data_t *data, int fd)
{
union drm_wait_vblank vbl;
struct timespec start, end;
unsigned long sq, count = 0;
struct drm_event_vblank buf;
+ uint32_t pipe_id_flag;
memset(&vbl, 0, sizeof(vbl));
+ pipe_id_flag = kmstest_get_vbl_flag(data->pipe);
- if (busy) {
+ if (data->mode_busy) {
vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
+ vbl.request.type |= pipe_id_flag;
vbl.request.sequence = 72;
do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
}
vbl.request.type = DRM_VBLANK_RELATIVE;
+ vbl.request.type |= pipe_id_flag;
vbl.request.sequence = 0;
do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
@@ -118,6 +211,7 @@ static void vblank_query(int fd, bool busy)
clock_gettime(CLOCK_MONOTONIC, &start);
do {
vbl.request.type = DRM_VBLANK_RELATIVE;
+ vbl.request.type |= pipe_id_flag;
vbl.request.sequence = 0;
do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
count++;
@@ -125,28 +219,32 @@ static void vblank_query(int fd, bool busy)
clock_gettime(CLOCK_MONOTONIC, &end);
igt_info("Time to query current counter (%s): %7.3fµs\n",
- busy ? "busy" : "idle", elapsed(&start, &end, count));
+ data->mode_busy ? "busy" : "idle", elapsed(&start, &end, count));
- if (busy)
+ if (data->mode_busy)
igt_assert_eq(read(fd, &buf, sizeof(buf)), sizeof(buf));
}
-static void vblank_wait(int fd, bool busy)
+static void vblank_wait(data_t *data, int fd)
{
union drm_wait_vblank vbl;
struct timespec start, end;
unsigned long sq, count = 0;
struct drm_event_vblank buf;
+ uint32_t pipe_id_flag;
memset(&vbl, 0, sizeof(vbl));
+ pipe_id_flag = kmstest_get_vbl_flag(data->pipe);
- if (busy) {
+ if (data->mode_busy) {
vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
+ vbl.request.type |= pipe_id_flag;
vbl.request.sequence = 72;
do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
}
vbl.request.type = DRM_VBLANK_RELATIVE;
+ vbl.request.type |= pipe_id_flag;
vbl.request.sequence = 0;
do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
@@ -155,6 +253,7 @@ static void vblank_wait(int fd, bool busy)
clock_gettime(CLOCK_MONOTONIC, &start);
do {
vbl.request.type = DRM_VBLANK_RELATIVE;
+ vbl.request.type |= pipe_id_flag;
vbl.request.sequence = 1;
do_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
count++;
@@ -163,36 +262,48 @@ static void vblank_wait(int fd, bool busy)
igt_info("Time to wait for %ld/%d vblanks (%s): %7.3fµs\n",
count, (int)(vbl.reply.sequence - sq),
- busy ? "busy" : "idle",
+ data->mode_busy ? "busy" : "idle",
elapsed(&start, &end, count));
- if (busy)
+ if (data->mode_busy)
igt_assert_eq(read(fd, &buf, sizeof(buf)), sizeof(buf));
}
igt_main
{
int fd;
+ data_t data;
igt_skip_on_simulation();
igt_fixture {
fd = drm_open_driver(DRIVER_ANY);
- igt_require(crtc0_active(fd));
+ kmstest_set_vt_graphics_mode();
+ igt_display_init(&data.display, fd);
}
- igt_subtest("accuracy")
- accuracy(fd);
+ igt_subtest("accuracy") {
+ data.mode_busy = 0;
+ run_test(&data, fd, accuracy);
+ }
- igt_subtest("query-idle")
- vblank_query(fd, false);
+ igt_subtest("query-idle") {
+ data.mode_busy = 0;
+ run_test(&data, fd, vblank_query);
+ }
- igt_subtest("query-busy")
- vblank_query(fd, true);
+ igt_subtest("query-busy") {
+ data.mode_busy = 1;
+ run_test(&data, fd, vblank_query);
+ }
- igt_subtest("wait-idle")
- vblank_wait(fd, false);
+ igt_subtest("wait-idle") {
+ data.mode_busy = 0;
+ run_test(&data, fd, vblank_wait);
+ }
- igt_subtest("wait-busy")
- vblank_wait(fd, true);
+ igt_subtest("wait-busy") {
+ data.mode_busy = 1;
+ run_test(&data, fd, vblank_wait);
+ }
}