diff options
Diffstat (limited to 'tests/kms_vblank.c')
-rw-r--r-- | tests/kms_vblank.c | 161 |
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); + } } |