summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-08-09 20:30:31 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2020-09-03 13:52:05 +0100
commit76c3de3d10379f5af762cdc797cb4f8de5306c20 (patch)
treecea0b13ddeb00d12a1d53890eefd1768fa9923ae
parent785c9e5571444cd4842e79fc19dd1f1e2b282688 (diff)
igt: Add vgem_syncobj
Exercise the drm_syncobj / vGEM coupling. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--lib/igt_vgem.c68
-rw-r--r--lib/igt_vgem.h15
-rw-r--r--tests/Makefile.sources1
-rw-r--r--tests/vgem_syncobj.c212
4 files changed, 276 insertions, 20 deletions
diff --git a/lib/igt_vgem.c b/lib/igt_vgem.c
index 7f933b23..f323a6c8 100644
--- a/lib/igt_vgem.c
+++ b/lib/igt_vgem.c
@@ -66,6 +66,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;
@@ -136,26 +145,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)
@@ -169,6 +163,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 92045f0e..09b8b7aa 100644
--- a/lib/igt_vgem.h
+++ b/lib/igt_vgem.h
@@ -36,15 +36,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 967b2e0c..ee1ecd14 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -108,6 +108,7 @@ TESTS_progs = \
tools_test \
vgem_basic \
vgem_slow \
+ vgem_syncobj \
$(NULL)
TESTS_progs += api_intel_bb
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);
+ }
+}