Exercise the drm_syncobj / vGEM coupling. Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> --- lib/igt_vgem.c | 68 +++++++++++----- lib/igt_vgem.h | 15 +++- tests/Makefile.sources | 1 + tests/vgem_syncobj.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 276 insertions(+), 20 deletions(-) create mode 100644 tests/vgem_syncobj.c diff --git a/lib/igt_vgem.c b/lib/igt_vgem.c index 21cccb37..d2f65adb 100644 --- a/lib/igt_vgem.c +++ b/lib/igt_vgem.c @@ -64,6 +64,15 @@ void vgem_create(int fd, struct vgem_bo *bo) igt_assert_eq(__vgem_create(fd, bo), 0); } +struct vgem_bo vgem_create_dummy(int fd) +{ + struct vgem_bo bo = { .width = 1, .height = 1, .bpp = 4 }; + + vgem_create(fd, &bo); + + return bo; +} + void *__vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot) { struct drm_mode_map_dumb arg; @@ -134,26 +143,11 @@ static int __vgem_fence_attach(int fd, struct local_vgem_fence_attach *arg) bool vgem_fence_has_flag(int fd, unsigned flags) { - struct local_vgem_fence_attach arg; - struct vgem_bo bo; - bool ret = false; + struct local_vgem_fence_attach arg = { + .flags = flags, + }; - memset(&bo, 0, sizeof(bo)); - bo.width = 1; - bo.height = 1; - bo.bpp = 32; - vgem_create(fd, &bo); - - memset(&arg, 0, sizeof(arg)); - arg.handle = bo.handle; - arg.flags = flags; - if (__vgem_fence_attach(fd, &arg) == 0) { - vgem_fence_signal(fd, arg.out_fence); - ret = true; - } - gem_close(fd, bo.handle); - - return ret; + return __vgem_fence_attach(fd, &arg) != -EINVAL; } uint32_t vgem_fence_attach(int fd, struct vgem_bo *bo, unsigned flags) @@ -167,6 +161,42 @@ uint32_t vgem_fence_attach(int fd, struct vgem_bo *bo, unsigned flags) return arg.out_fence; } +int __vgem_fence_attach_to_syncobj(int fd, + struct vgem_bo *bo, + uint32_t syncobj, + unsigned flags, + uint32_t *fence) +{ + struct local_vgem_fence_attach arg = { + .handle = bo->handle, + .flags = VGEM_FENCE_SYNCOBJ | flags, + .pad = syncobj, + }; + int err; + + err = __vgem_fence_attach(fd, &arg); + if (err) + return err; + + *fence = arg.out_fence; + return 0; +} + +uint32_t vgem_fence_attach_to_syncobj(int fd, + struct vgem_bo *bo, + uint32_t syncobj, + unsigned flags) +{ + struct local_vgem_fence_attach arg = { + .handle = bo->handle, + .flags = VGEM_FENCE_SYNCOBJ | flags, + .pad = syncobj, + }; + igt_assert_eq(__vgem_fence_attach(fd, &arg), 0); + + return arg.out_fence; +} + static int ioctl_vgem_fence_signal(int fd, struct local_vgem_fence_signal *arg) { int err = 0; diff --git a/lib/igt_vgem.h b/lib/igt_vgem.h index 002ad7f0..f50c70b4 100644 --- a/lib/igt_vgem.h +++ b/lib/igt_vgem.h @@ -35,15 +35,28 @@ struct vgem_bo { int __vgem_create(int fd, struct vgem_bo *bo); void vgem_create(int fd, struct vgem_bo *bo); +struct vgem_bo vgem_create_dummy(int fd); void *__vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot); void *vgem_mmap(int fd, struct vgem_bo *bo, unsigned prot); bool vgem_has_fences(int fd); bool vgem_fence_has_flag(int fd, unsigned flags); + uint32_t vgem_fence_attach(int fd, struct vgem_bo *bo, unsigned flags); #define VGEM_FENCE_WRITE 0x1 -#define WIP_VGEM_FENCE_NOTIMEOUT 0x2 +#define VGEM_FENCE_SYNCOBJ 0x2 +#define WIP_VGEM_FENCE_NOTIMEOUT (1<<31) +int __vgem_fence_attach_to_syncobj(int fd, + struct vgem_bo *bo, + uint32_t syncobj, + unsigned flags, + uint32_t *fence); +uint32_t vgem_fence_attach_to_syncobj(int fd, + struct vgem_bo *bo, + uint32_t syncobj, + unsigned flags); + int __vgem_fence_signal(int fd, uint32_t fence); void vgem_fence_signal(int fd, uint32_t fence); diff --git a/tests/Makefile.sources b/tests/Makefile.sources index 7a99cafc..3352aad4 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -235,6 +235,7 @@ TESTS_progs = \ tools_test \ vgem_basic \ vgem_slow \ + vgem_syncobj \ $(NULL) TESTS_progs_X = \ diff --git a/tests/vgem_syncobj.c b/tests/vgem_syncobj.c new file mode 100644 index 00000000..6ef2d8ba --- /dev/null +++ b/tests/vgem_syncobj.c @@ -0,0 +1,212 @@ +/* + * Copyright © 2017 Intel Corporation + * + * 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 (including the next + * paragraph) 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. + */ + +#include <sys/ioctl.h> +#include <sys/poll.h> + +#include "igt.h" +#include "igt_vgem.h" + +IGT_TEST_DESCRIPTION("Check the vGEM / syncobj interoperability"); + +static uint32_t __syncobj_create(int fd) +{ + struct local_syncobj_create { + uint32_t handle, flags; + } arg; +#define LOCAL_IOCTL_SYNCOBJ_CREATE DRM_IOWR(0xBF, struct local_syncobj_create) + + memset(&arg, 0, sizeof(arg)); + ioctl(fd, LOCAL_IOCTL_SYNCOBJ_CREATE, &arg); + + return arg.handle; +} + +static uint32_t syncobj_create(int fd) +{ + uint32_t ret; + + igt_assert_neq((ret = __syncobj_create(fd)), 0); + + return ret; +} + +static int __syncobj_destroy(int fd, uint32_t handle) +{ + struct local_syncobj_destroy { + uint32_t handle, flags; + } arg; +#define LOCAL_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct local_syncobj_destroy) + int err = 0; + + memset(&arg, 0, sizeof(arg)); + arg.handle = handle; + if (ioctl(fd, LOCAL_IOCTL_SYNCOBJ_DESTROY, &arg)) + err = -errno; + + errno = 0; + return err; +} + +static void syncobj_destroy(int fd, uint32_t handle) +{ + igt_assert_eq(__syncobj_destroy(fd, handle), 0); +} + +static int __syncobj_to_sync_file(int fd, uint32_t handle) +{ + struct local_syncobj_handle { + uint32_t handle; + uint32_t flags; + int32_t fd; + uint32_t pad; + } arg; +#define LOCAL_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct local_syncobj_handle) + + memset(&arg, 0, sizeof(arg)); + arg.handle = handle; + arg.flags = 1 << 0; /* EXPORT_SYNC_FILE */ + if (ioctl(fd, LOCAL_IOCTL_SYNCOBJ_HANDLE_TO_FD, &arg)) + arg.fd = -errno; + + errno = 0; + return arg.fd; +} + +static int syncobj_to_sync_file(int fd, uint32_t handle) +{ + int ret; + + igt_assert_lte(0, (ret = __syncobj_to_sync_file(fd, handle))); + + return ret; +} + +static bool syncobj_busy(int fd, uint32_t handle) +{ + bool result; + int sf; + + sf = syncobj_to_sync_file(fd, handle); + result = poll(&(struct pollfd){sf, POLLIN}, 1, 0) == 0; + close(sf); + + return result; +} + +static void test_create(int vgem) +{ + syncobj_destroy(vgem, syncobj_create(vgem)); +} + +static void test_invalid_attach(int vgem) +{ + struct vgem_bo bo; + uint32_t dummy; + + bo = vgem_create_dummy(vgem); + + igt_assert_eq(__vgem_fence_attach_to_syncobj(vgem, &bo, 0, 0, &dummy), + -ENOENT); + igt_assert_eq(__vgem_fence_attach_to_syncobj(vgem, &bo, bo.handle, 0, + &dummy), + -ENOENT); + + gem_close(vgem, bo.handle); +} + +static void test_attach(int vgem) +{ + struct vgem_bo bo; + uint32_t sync; + + sync = syncobj_create(vgem); + bo = vgem_create_dummy(vgem); + + vgem_fence_attach_to_syncobj(vgem, &bo, sync, 0); + igt_assert(syncobj_busy(vgem, sync)); + + gem_close(vgem, bo.handle); + syncobj_destroy(vgem, sync); +} + +static void test_signal(int vgem) +{ + struct vgem_bo bo; + uint32_t sync, fence; + + sync = syncobj_create(vgem); + bo = vgem_create_dummy(vgem); + + fence = vgem_fence_attach_to_syncobj(vgem, &bo, sync, 0); + igt_assert(syncobj_busy(vgem, sync)); + + vgem_fence_signal(vgem, fence); + igt_assert(!syncobj_busy(vgem, sync)); + + syncobj_destroy(vgem, sync); + gem_close(vgem, bo.handle); +} + +static bool has_syncobj(int fd) +{ + struct drm_get_cap cap = { .capability = 0x13 }; + + if (ioctl(fd, DRM_IOCTL_GET_CAP, &cap)) + return false; + + return cap.value; +} + +igt_main +{ + int fd = -1; + + igt_fixture { + fd = drm_open_driver(DRIVER_VGEM); + igt_require(vgem_has_fences(fd)); + igt_require(has_syncobj(fd)); + } + + igt_subtest_f("create") + test_create(fd); + + igt_subtest_group { + igt_fixture { + igt_require(vgem_fence_has_flag(fd, VGEM_FENCE_SYNCOBJ)); + } + + igt_subtest_f("invalid-attach") + test_invalid_attach(fd); + + igt_subtest_f("attach") + test_attach(fd); + + igt_subtest_f("signal") + test_signal(fd); + } + + igt_fixture { + close(fd); + } +} -- 2.13.3 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx