Exercise the drm_syncobj / vGEM coupling.

Signed-off-by: Chris Wilson <ch...@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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to