From b620ab260d8969cf1d8ba44e7fc7bb77ef48925b Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 3 Feb 2021 11:02:24 -0800 Subject: [PATCH] tests: add test_virgl_fence Basic tests for fence create/poll/export. Note that export tests require VRENDTEST_USE_EGL_GLES to be set. Signed-off-by: Chia-I Wu Reviewed-by: Gert Wollny --- tests/meson.build | 1 + tests/test_virgl_fence.c | 311 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 312 insertions(+) create mode 100644 tests/test_virgl_fence.c diff --git a/tests/meson.build b/tests/meson.build index 66b1157..01649eb 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -42,6 +42,7 @@ libvrtest = static_library( tests = [ ['test_virgl_init', 'test_virgl_init.c'], + ['test_virgl_fence', 'test_virgl_fence.c'], ['test_virgl_resource', 'test_virgl_resource.c'], ['test_virgl_transfer', 'test_virgl_transfer.c'], ['test_virgl_cmd', 'test_virgl_cmd.c'], diff --git a/tests/test_virgl_fence.c b/tests/test_virgl_fence.c new file mode 100644 index 0000000..9e498ce --- /dev/null +++ b/tests/test_virgl_fence.c @@ -0,0 +1,311 @@ +/************************************************************************** + * + * Copyright 2020 Google LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * basic library initialisation, teardown, reset + * and context creation tests. + */ + +#include +#include +#include +#include +#include +#include + +#include "testvirgl.h" + +START_TEST(virgl_fence_create) +{ + int ret; + ret = testvirgl_init_single_ctx(); + ck_assert_int_eq(ret, 0); + + testvirgl_reset_fence(); + ret = virgl_renderer_create_fence(1, 0); + ck_assert_int_eq(ret, 0); + + testvirgl_fini_single_ctx(); +} +END_TEST + +START_TEST(virgl_fence_poll) +{ + const int target_seqno = 50; + int ret; + ret = testvirgl_init_single_ctx(); + ck_assert_int_eq(ret, 0); + + testvirgl_reset_fence(); + ret = virgl_renderer_create_fence(target_seqno, 0); + ck_assert_int_eq(ret, 0); + + do { + int seqno; + + virgl_renderer_poll(); + seqno = testvirgl_get_last_fence(); + if (seqno == target_seqno) + break; + + ck_assert_int_eq(seqno, 0); + usleep(1000); + } while(1); + + testvirgl_fini_single_ctx(); +} +END_TEST + +START_TEST(virgl_fence_poll_many) +{ + const int fence_count = 100; + const int base_seqno = 50; + const int target_seqno = base_seqno + fence_count - 1; + int last_seqno; + int ret; + int i; + + ret = testvirgl_init_single_ctx(); + ck_assert_int_eq(ret, 0); + + testvirgl_reset_fence(); + last_seqno = 0; + + for (i = 0; i < fence_count; i++) { + ret = virgl_renderer_create_fence(base_seqno + i, 0); + ck_assert_int_eq(ret, 0); + } + + do { + int seqno; + + virgl_renderer_poll(); + seqno = testvirgl_get_last_fence(); + if (seqno == target_seqno) + break; + + ck_assert(seqno == 0 || (seqno >= base_seqno && seqno < target_seqno)); + + /* monotonic increasing */ + ck_assert_int_ge(seqno, last_seqno); + last_seqno = seqno; + + usleep(1000); + } while(1); + + testvirgl_fini_single_ctx(); +} +END_TEST + +static int +wait_sync_fd(int fd, int timeout) +{ + struct pollfd pollfd = { + .fd = fd, + .events = POLLIN, + }; + int ret; + do { + ret = poll(&pollfd, 1, timeout); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + if (ret < 0) + return -errno; + else if (ret > 0 && !(pollfd.revents & POLLIN)) + return -EINVAL; + + return ret ? 0 : -ETIME; +} + +START_TEST(virgl_fence_export) +{ + const int target_seqno = 50; + int fd; + int ret; + + ret = testvirgl_init_single_ctx(); + ck_assert_int_eq(ret, 0); + + testvirgl_reset_fence(); + ret = virgl_renderer_create_fence(target_seqno, 0); + ck_assert_int_eq(ret, 0); + + ret = virgl_renderer_export_fence(target_seqno, &fd); + ck_assert_int_eq(ret, 0); + + ret = wait_sync_fd(fd, -1); + ck_assert_int_eq(ret, 0); + + virgl_renderer_poll(); + ck_assert_int_eq(testvirgl_get_last_fence(), target_seqno); + + close(fd); + + testvirgl_fini_single_ctx(); +} +END_TEST + +START_TEST(virgl_fence_export_signaled) +{ + const int target_seqno = 50; + const int test_range = 10; + int fd; + int ret; + int i; + + ret = testvirgl_init_single_ctx(); + ck_assert_int_eq(ret, 0); + + /* when there is no active fence, a signaled fd is always returned */ + for (i = 0; i < test_range; i++) { + ret = virgl_renderer_export_fence(target_seqno + 1 + i, &fd); + ck_assert_int_eq(ret, 0); + + ret = wait_sync_fd(fd, 0); + ck_assert_int_eq(ret, 0); + + close(fd); + } + + ret = virgl_renderer_create_fence(target_seqno, 0); + ck_assert_int_eq(ret, 0); + + /* when there is any active fence, a signaled fd is returned when the + * requested seqno is smaller than the first active fence + */ + for (i = 0; i < test_range; i++) { + ret = virgl_renderer_export_fence(target_seqno - 1 - i, &fd); + ck_assert_int_eq(ret, 0); + + ret = wait_sync_fd(fd, 0); + ck_assert_int_eq(ret, 0); + + close(fd); + } + + testvirgl_fini_single_ctx(); +} +END_TEST + +START_TEST(virgl_fence_export_invalid) +{ + const int target_seqno = 50; + const int target_seqno2 = 55; + int seqno; + int fd; + int ret; + + ret = testvirgl_init_single_ctx(); + ck_assert_int_eq(ret, 0); + + ret = virgl_renderer_create_fence(target_seqno, 0); + ck_assert_int_eq(ret, 0); + ret = virgl_renderer_create_fence(target_seqno2, 0); + ck_assert_int_eq(ret, 0); + + for (seqno = target_seqno; seqno <= target_seqno2 + 1; seqno++) { + ret = virgl_renderer_export_fence(seqno, &fd); + if (seqno == target_seqno || seqno == target_seqno2) { + ck_assert_int_eq(ret, 0); + close(fd); + } else { + ck_assert_int_eq(ret, -EINVAL); + } + } + + testvirgl_fini_single_ctx(); +} +END_TEST + +static Suite *virgl_init_suite(bool include_fence_export) +{ + Suite *s; + TCase *tc_core; + + s = suite_create("virgl_fence"); + tc_core = tcase_create("fence"); + + tcase_add_test(tc_core, virgl_fence_create); + tcase_add_test(tc_core, virgl_fence_poll); + tcase_add_test(tc_core, virgl_fence_poll_many); + + if (include_fence_export) { + tcase_add_test(tc_core, virgl_fence_export); + tcase_add_test(tc_core, virgl_fence_export_signaled); + tcase_add_test(tc_core, virgl_fence_export_invalid); + } + + suite_add_tcase(s, tc_core); + + return s; +} + +static bool detect_fence_export_support(void) +{ + int dummy_cookie; + struct virgl_renderer_callbacks dummy_cbs; + int fd; + int ret; + + memset(&dummy_cbs, 0, sizeof(dummy_cbs)); + dummy_cbs.version = 1; + + ret = virgl_renderer_init(&dummy_cookie, context_flags, &dummy_cbs); + if (ret) + return false; + + ret = virgl_renderer_export_fence(0, &fd); + if (ret) { + virgl_renderer_cleanup(&dummy_cookie); + return false; + } + + close(fd); + virgl_renderer_cleanup(&dummy_cookie); + return true; +} + +int main(void) +{ + Suite *s; + SRunner *sr; + int number_failed; + bool include_fence_export = false; + + if (getenv("VRENDTEST_USE_EGL_SURFACELESS")) + context_flags |= VIRGL_RENDERER_USE_SURFACELESS; + if (getenv("VRENDTEST_USE_EGL_GLES")) { + context_flags |= VIRGL_RENDERER_USE_GLES; + include_fence_export = detect_fence_export_support(); + } + + s = virgl_init_suite(include_fence_export); + sr = srunner_create(s); + + srunner_run_all(sr, CK_NORMAL); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + + return number_failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +}