The existing writeback tests validate captured framebuffer contents, but do not keep pipe CRC capture active across writeback completion. This misses the VKMS bug where writeback cleanup disables the composer while CRC capture still needs it, leaving subsequent CRC reads waiting for samples that never arrive.
Add writeback-preserves-crc. Complete the initial modeset before starting capture and establish reference CRCs for separate red and blue input framebuffers. Keep capture open across four alternating writebacks, wait for each output fence, and compare three fresh CRC samples with the corresponding reference after each writeback. Use atomic updates without ALLOW_MODESET once capture starts, and release capture from the final fixture so a failed subtest also closes it. Check output fence status in the shared wait helper so a signalled error fence cannot be treated as a successful writeback. On ARM64 QEMU with one and two CPUs, the new subtest fails on unmodified mainline and passes with the local VKMS composer-user lifetime fix. Four existing applicable writeback subtests pass on both kernels; the two XRGB2101010 subtests skip because the format probe rejects them. Signed-off-by: Aditya Tipre <[email protected]> --- Changes in v2: - Use my full name in the author and Signed-off-by fields. - No code changes. tests/kms_writeback.c | 62 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/kms_writeback.c b/tests/kms_writeback.c index 7c30e8e..71317cf 100644 --- a/tests/kms_writeback.c +++ b/tests/kms_writeback.c @@ -64,6 +64,10 @@ * * SUBTEST: writeback-pixel-formats * Description: Check the writeback format + * + * SUBTEST: writeback-preserves-crc + * Description: CRC capture remains active across completed writebacks + * Driver requirement: i915, xe, vkms */ IGT_TEST_DESCRIPTION( @@ -317,6 +321,7 @@ static void get_and_wait_out_fence(igt_output_t *output) ret = sync_fence_wait(output->writeback_out_fence_fd, 1000); igt_assert_f(ret == 0, "sync_fence_wait failed: %s\n", strerror(-ret)); + igt_assert_eq(sync_fence_status(output->writeback_out_fence_fd), 1); close(output->writeback_out_fence_fd); output->writeback_out_fence_fd = -1; } @@ -537,6 +542,7 @@ int igt_main_args("b:c:f:dl", long_options, help_str, opt_handler, NULL) igt_output_t *output; igt_plane_t *plane; igt_fb_t input_fb, input_fb_10bit; + static igt_pipe_crc_t *pipe_crc; drmModeModeInfo mode; unsigned int fb_id; int ret; @@ -709,7 +715,63 @@ int igt_main_args("b:c:f:dl", long_options, help_str, opt_handler, NULL) igt_remove_fb(display.drm_fd, &output_fb); } + igt_describe("CRC capture remains active across completed writebacks"); + igt_subtest("writeback-preserves-crc") { + igt_fb_t blue_fb, output_fb; + igt_fb_t *colors[] = { &input_fb, &blue_fb }; + igt_crc_t reference[2], crc; + int i, j; + + igt_skip_on(data.dump_check || data.list_modes); + igt_require(data.supported_colors & XRGB8888); + igt_require_pipe_crc(display.drm_fd); + + igt_create_color_fb(display.drm_fd, mode.hdisplay, mode.vdisplay, + DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_LINEAR, + 0.0, 0.0, 1.0, &blue_fb); + igt_create_fb(display.drm_fd, mode.hdisplay, mode.vdisplay, + DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_LINEAR, + &output_fb); + fill_fb(&input_fb, 0x00ff0000); + igt_plane_set_fb(plane, &input_fb); + igt_output_set_writeback_fb(output, NULL); + igt_display_commit_atomic(&display, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); + + /* Finish the modeset before starting continuous CRC capture. */ + pipe_crc = igt_pipe_crc_new(display.drm_fd, output->config.crtc_index, + IGT_PIPE_CRC_SOURCE_AUTO); + igt_pipe_crc_start(pipe_crc); + + /* Establish both references before writeback can affect capture. */ + for (i = 0; i < ARRAY_SIZE(colors); i++) { + igt_plane_set_fb(plane, colors[i]); + igt_display_commit_atomic(&display, 0, NULL); + igt_pipe_crc_get_current(display.drm_fd, pipe_crc, &reference[i]); + } + + for (i = 0; i < 4; i++) { + int color = i % ARRAY_SIZE(colors); + + igt_plane_set_fb(plane, colors[color]); + igt_output_set_writeback_fb(output, &output_fb); + igt_display_commit_atomic(&display, 0, NULL); + get_and_wait_out_fence(output); + + /* Require fresh frames without stopping or restarting capture. */ + for (j = 0; j < 3; j++) { + igt_pipe_crc_get_current(display.drm_fd, pipe_crc, &crc); + igt_assert_crc_equal(&reference[color], &crc); + } + } + + igt_plane_set_fb(plane, &input_fb); + igt_display_commit_atomic(&display, 0, NULL); + igt_remove_fb(display.drm_fd, &blue_fb); + igt_remove_fb(display.drm_fd, &output_fb); + } + igt_fixture() { + igt_pipe_crc_free(pipe_crc); cleanup_writeback(&display, output); igt_remove_fb(display.drm_fd, &input_fb); base-commit: bb76404eac7032ba85c53eac15b76e4fadaff0de -- 2.50.1 (Apple Git-155)
