diff options
-rw-r--r-- | tests/kms_flip_tiling.c | 230 |
1 files changed, 184 insertions, 46 deletions
diff --git a/tests/kms_flip_tiling.c b/tests/kms_flip_tiling.c index 83455058..c7fd4de2 100644 --- a/tests/kms_flip_tiling.c +++ b/tests/kms_flip_tiling.c @@ -35,8 +35,7 @@ #include "ioctl_wrappers.h" #include "intel_chipset.h" -IGT_TEST_DESCRIPTION("Test that a page flip from a tiled buffer to a linear" - " one works correctly."); +IGT_TEST_DESCRIPTION("Test page flips and tiling scenarios"); typedef struct { int drm_fd; @@ -44,16 +43,8 @@ typedef struct { int gen; } data_t; -/* - * Test that a page flip from a tiled buffer to a linear one works - * correctly. First, it sets the crtc with the linear buffer and generate - * a reference crc for the pipe. Then, the crtc is set with the tiled one - * and page flip to the linear one issued. A new crc is generated and - * compared to the rerence one. - */ - static void -fill_linear_fb(struct igt_fb *fb, data_t *data, drmModeModeInfo *mode) +fill_fb(struct igt_fb *fb, data_t *data, drmModeModeInfo *mode) { cairo_t *cr; @@ -62,67 +53,124 @@ fill_linear_fb(struct igt_fb *fb, data_t *data, drmModeModeInfo *mode) cairo_destroy(cr); } +static igt_pipe_crc_t *_pipe_crc; + +static igt_pipe_crc_t *pipe_crc_new(int pipe) +{ + if (_pipe_crc) { + igt_pipe_crc_free(_pipe_crc); + _pipe_crc = NULL; + } + + _pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO); + igt_assert(_pipe_crc); + + return _pipe_crc; +} + +static void pipe_crc_free(void) +{ + if (_pipe_crc) { + igt_pipe_crc_free(_pipe_crc); + _pipe_crc = NULL; + } +} + +static void wait_for_pageflip(int fd) +{ + drmEventContext evctx = { .version = DRM_EVENT_CONTEXT_VERSION }; + struct timeval timeout = { .tv_sec = 0, .tv_usec = 32000 }; + fd_set fds; + int ret; + + /* Wait for pageflip completion, then consume event on fd */ + FD_ZERO(&fds); + FD_SET(fd, &fds); + do { + ret = select(fd + 1, &fds, NULL, NULL, &timeout); + } while (ret < 0 && errno == EINTR); + igt_assert_eq(ret, 1); + igt_assert(drmHandleEvent(fd, &evctx) == 0); +} + static void -test_flip_changes_tiling(data_t *data, igt_output_t *output, uint64_t tiling) +test_flip_tiling(data_t *data, igt_output_t *output, uint64_t tiling[2]) { - struct igt_fb linear, tiled; drmModeModeInfo *mode; igt_plane_t *primary; + struct igt_fb fb[2]; igt_pipe_crc_t *pipe_crc; igt_crc_t reference_crc, crc; int fb_id, pipe, ret, width; pipe = output->config.pipe; - pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO); + pipe_crc = pipe_crc_new(pipe); igt_output_set_pipe(output, pipe); mode = igt_output_get_mode(output); primary = igt_output_get_plane(output, 0); - /* Allocate a linear buffer. Since a page flip to a buffer with - * different stride doesn't work, choose width so that the stride of - * both buffers is the same. */ - width = 512; - while (width < mode->hdisplay) - width *= 2; + width = mode->hdisplay; + + if (tiling[0] != tiling[1] && + (tiling[0] != LOCAL_DRM_FORMAT_MOD_NONE || + tiling[1] != LOCAL_DRM_FORMAT_MOD_NONE)) { + /* + * Since a page flip to a buffer with different stride + * doesn't work, choose width so that the stride of both + * buffers is the same. + */ + width = 512; + while (width < mode->hdisplay) + width *= 2; + } + fb_id = igt_create_fb(data->drm_fd, width, mode->vdisplay, - DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE, - &linear); + DRM_FORMAT_XRGB8888, tiling[0], + &fb[0]); + igt_assert(fb_id); + + /* Second fb has different background so CRC does not match. */ + fb_id = igt_create_color_fb(data->drm_fd, width, mode->vdisplay, + DRM_FORMAT_XRGB8888, tiling[1], + 0.5, 0.5, 0.5, &fb[1]); + igt_assert(fb_id); - /* fill it with a pattern that will look wrong if tiling is wrong */ - fill_linear_fb(&linear, data, mode); + fill_fb(&fb[0], data, mode); + fill_fb(&fb[1], data, mode); - /* set the crtc and generate a reference crc */ - igt_plane_set_fb(primary, &linear); + /* Set the crtc and generate a reference CRC. */ + igt_plane_set_fb(primary, &fb[1]); igt_display_commit(&data->display); igt_pipe_crc_collect_crc(pipe_crc, &reference_crc); - /* allocate a tiled buffer and set the crtc with it */ - igt_create_color_fb(data->drm_fd, width, mode->vdisplay, - DRM_FORMAT_XRGB8888, tiling, - 0.0, 0.0, 0.0, &tiled); - igt_plane_set_fb(primary, &tiled); + /* Commit the first fb. */ + igt_plane_set_fb(primary, &fb[0]); igt_display_commit(&data->display); - /* flip to the linear buffer */ + /* Flip to the second fb. */ ret = drmModePageFlip(data->drm_fd, output->config.crtc->crtc_id, - fb_id, 0, NULL); - igt_assert_eq(ret, 0); + fb[1].fb_id, DRM_MODE_PAGE_FLIP_EVENT, NULL); + /* + * Page flip should work but some transitions may be temporarily + * on some kernels. + */ + igt_require(ret == 0); - igt_wait_for_vblank(data->drm_fd, pipe); + wait_for_pageflip(data->drm_fd); - /* get a crc and compare with the reference */ + /* Get a crc and compare with the reference. */ igt_pipe_crc_collect_crc(pipe_crc, &crc); igt_assert_crc_equal(&reference_crc, &crc); - /* clean up */ + /* Clean up. */ igt_plane_set_fb(primary, NULL); - igt_pipe_crc_free(pipe_crc); + pipe_crc_free(); igt_output_set_pipe(output, PIPE_ANY); igt_display_commit(&data->display); - igt_remove_fb(data->drm_fd, &tiled); - igt_remove_fb(data->drm_fd, &linear); + igt_remove_fb(data->drm_fd, &fb[0]); + igt_remove_fb(data->drm_fd, &fb[1]); } static data_t data; @@ -142,28 +190,118 @@ igt_main igt_display_init(&data.display, data.drm_fd); } + /* + * Test that a page flip from a tiled buffer to a linear one works + * correctly. First, it sets the crtc with the linear buffer and + * generates a reference crc for the pipe. Then, the crtc is set with + * the tiled one and page flip to the linear one issued. A new crc is + * generated and compared to the reference one. + */ + igt_subtest_f("flip-changes-tiling") { + uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_X_TILED, + LOCAL_DRM_FORMAT_MOD_NONE }; + for_each_connected_output(&data.display, output) - test_flip_changes_tiling(&data, output, - LOCAL_I915_FORMAT_MOD_X_TILED); + test_flip_tiling(&data, output, tiling); } igt_subtest_f("flip-changes-tiling-Y") { + uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_Y_TILED, + LOCAL_DRM_FORMAT_MOD_NONE }; + igt_require_fb_modifiers(data.drm_fd); igt_require(data.gen >= 9); for_each_connected_output(&data.display, output) - test_flip_changes_tiling(&data, output, - LOCAL_I915_FORMAT_MOD_Y_TILED); + test_flip_tiling(&data, output, tiling); } igt_subtest_f("flip-changes-tiling-Yf") { + uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_Yf_TILED, + LOCAL_DRM_FORMAT_MOD_NONE }; + + igt_require_fb_modifiers(data.drm_fd); + igt_require(data.gen >= 9); + + for_each_connected_output(&data.display, output) + test_flip_tiling(&data, output, tiling); + } + + /* + * Test that a page flip from a tiled buffer to another tiled one works + * correctly. First, it sets the crtc with the tiled buffer and + * generates a reference crc for the pipe. Then a page flip to second + * tiled buffer is issued. A new crc is generated and compared to the + * reference one. + */ + + igt_subtest_f("flip-X-tiled") { + uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_X_TILED, + LOCAL_I915_FORMAT_MOD_X_TILED }; + + for_each_connected_output(&data.display, output) + test_flip_tiling(&data, output, tiling); + } + + igt_subtest_f("flip-Y-tiled") { + uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_Y_TILED, + LOCAL_I915_FORMAT_MOD_Y_TILED }; + + igt_require_fb_modifiers(data.drm_fd); + igt_require(data.gen >= 9); + + for_each_connected_output(&data.display, output) + test_flip_tiling(&data, output, tiling); + } + + igt_subtest_f("flip-Yf-tiled") { + uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_Yf_TILED, + LOCAL_I915_FORMAT_MOD_Yf_TILED }; + + igt_require_fb_modifiers(data.drm_fd); + igt_require(data.gen >= 9); + + for_each_connected_output(&data.display, output) + test_flip_tiling(&data, output, tiling); + } + + /* + * Test that a page flip from a linear buffer to a tiled one works + * correctly. First, it sets the crtc with the linear buffer and + * generates a reference crc for the pipe. Then a page flip to a tiled + * buffer is issued. A new crc is generated and compared to the + * reference one. + */ + + igt_subtest_f("flip-to-X-tiled") { + uint64_t tiling[2] = { LOCAL_DRM_FORMAT_MOD_NONE, + LOCAL_I915_FORMAT_MOD_X_TILED }; + + for_each_connected_output(&data.display, output) + test_flip_tiling(&data, output, tiling); + } + + igt_subtest_f("flip-to-Y-tiled") { + uint64_t tiling[2] = { LOCAL_DRM_FORMAT_MOD_NONE, + LOCAL_I915_FORMAT_MOD_Y_TILED }; + + igt_require_fb_modifiers(data.drm_fd); + igt_require(data.gen >= 9); + + for_each_connected_output(&data.display, output) + test_flip_tiling(&data, output, tiling); + } + + igt_subtest_f("flip-to-Yf-tiled") { + uint64_t tiling[2] = { LOCAL_DRM_FORMAT_MOD_NONE, + LOCAL_I915_FORMAT_MOD_Yf_TILED }; + igt_require_fb_modifiers(data.drm_fd); igt_require(data.gen >= 9); for_each_connected_output(&data.display, output) - test_flip_changes_tiling(&data, output, - LOCAL_I915_FORMAT_MOD_Yf_TILED); + test_flip_tiling(&data, output, tiling); } igt_fixture { |