[Intel-gfx] [PATCH igt] igt: Add vgem_syncobj

Chris Wilson chris at chris-wilson.co.uk
Wed Aug 9 20:08:35 UTC 2017


Exercise the drm_syncobj / vGEM coupling.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 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



More information about the Intel-gfx mailing list