winsys/svga/drm: Connect winsys-side fence_* functions
authorSinclair Yeh <syeh@vmware.com>
Tue, 16 May 2017 00:10:38 +0000 (17:10 -0700)
committerBrian Paul <brianp@vmware.com>
Mon, 17 Jul 2017 16:09:25 +0000 (10:09 -0600)
Connect fence_get_fd, fence_create_fd, and fence_server_sync.

Implement the required functions in vmw_fence module.

Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Charmaine Lee <charmainel@vmware.com>
src/gallium/winsys/svga/drm/vmw_fence.c
src/gallium/winsys/svga/drm/vmw_fence.h
src/gallium/winsys/svga/drm/vmw_screen_ioctl.c
src/gallium/winsys/svga/drm/vmw_screen_svga.c

index 5b1ba69930bfa8b0b8e2cebb742261e955a5858d..061f588c86443f454b2a92a6553afa742b2be904 100644 (file)
@@ -22,6 +22,8 @@
  * SOFTWARE.
  *
  **********************************************************/
+#include <libsync.h>
+
 #include "util/u_memory.h"
 #include "util/u_atomic.h"
 #include "util/list.h"
@@ -32,7 +34,7 @@
 #include "vmw_screen.h"
 #include "vmw_fence.h"
 
-struct vmw_fence_ops 
+struct vmw_fence_ops
 {
    /*
     * Immutable members.
@@ -58,6 +60,8 @@ struct vmw_fence
    uint32_t mask;
    int32_t signalled;
    uint32_t seqno;
+   int32_t fence_fd;
+   boolean imported; /* TRUE if imported from another process */
 };
 
 /**
@@ -175,15 +179,16 @@ vmw_fence(struct pipe_fence_handle *fence)
  * @fence_ops: The fence_ops manager to register with.
  * @handle: Handle identifying the kernel fence object.
  * @mask: Mask of flags that this fence object may signal.
+ * @fd: File descriptor to associate with the fence
  *
  * Returns NULL on failure.
  */
 struct pipe_fence_handle *
 vmw_fence_create(struct pb_fence_ops *fence_ops, uint32_t handle,
-                 uint32_t seqno, uint32_t mask)
+                 uint32_t seqno, uint32_t mask, int32_t fd)
 {
    struct vmw_fence *fence = CALLOC_STRUCT(vmw_fence);
-   struct vmw_fence_ops *ops = vmw_fence_ops(fence_ops);
+   struct vmw_fence_ops *ops = NULL;
 
    if (!fence)
       return NULL;
@@ -192,7 +197,20 @@ vmw_fence_create(struct pb_fence_ops *fence_ops, uint32_t handle,
    fence->handle = handle;
    fence->mask = mask;
    fence->seqno = seqno;
+   fence->fence_fd = fd;
    p_atomic_set(&fence->signalled, 0);
+
+   /*
+    * If the fence was not created by our device, then we won't
+    * manage it with our ops
+    */
+   if (!fence_ops) {
+      fence->imported = true;
+      return (struct pipe_fence_handle *) fence;
+   }
+
+   ops = vmw_fence_ops(fence_ops);
+
    mtx_lock(&ops->mutex);
 
    if (vmw_fence_seq_is_signaled(seqno, ops->last_signaled, seqno)) {
@@ -209,6 +227,21 @@ vmw_fence_create(struct pb_fence_ops *fence_ops, uint32_t handle,
 }
 
 
+/**
+ * vmw_fence_destroy - Frees a vmw fence object.
+ *
+ * Also closes the file handle associated with the object, if any
+ */
+static
+void vmw_fence_destroy(struct vmw_fence *vfence)
+{
+   if (vfence->fence_fd != -1)
+      close(vfence->fence_fd);
+
+   FREE(vfence);
+}
+
+
 /**
  * vmw_fence_reference - Reference / unreference a vmw fence object.
  *
@@ -227,13 +260,15 @@ vmw_fence_reference(struct vmw_winsys_screen *vws,
       if (p_atomic_dec_zero(&vfence->refcount)) {
          struct vmw_fence_ops *ops = vmw_fence_ops(vws->fence_ops);
 
-        vmw_ioctl_fence_unref(vws, vfence->handle);
+         if (!vfence->imported) {
+            vmw_ioctl_fence_unref(vws, vfence->handle);
 
-         mtx_lock(&ops->mutex);
-         LIST_DELINIT(&vfence->ops_list);
-         mtx_unlock(&ops->mutex);
+            mtx_lock(&ops->mutex);
+            LIST_DELINIT(&vfence->ops_list);
+            mtx_unlock(&ops->mutex);
+         }
 
-        FREE(vfence);
+         vmw_fence_destroy(vfence);
       }
    }
 
@@ -321,6 +356,16 @@ vmw_fence_finish(struct vmw_winsys_screen *vws,
       return 0;
 
    vfence = vmw_fence(fence);
+
+   if (vfence->imported) {
+      ret = sync_wait(vfence->fence_fd, timeout / 1000000);
+
+      if (!ret)
+         p_atomic_set(&vfence->signalled, 1);
+
+      return !!ret;
+   }
+
    old = p_atomic_read(&vfence->signalled);
    vflags &= ~vfence->mask;
 
@@ -341,6 +386,23 @@ vmw_fence_finish(struct vmw_winsys_screen *vws,
    return ret;
 }
 
+/**
+ * vmw_fence_get_fd
+ *
+ * Returns the file descriptor associated with the fence
+ */
+int
+vmw_fence_get_fd(struct pipe_fence_handle *fence)
+{
+   struct vmw_fence *vfence;
+
+   if (!fence)
+      return -1;
+
+   vfence = vmw_fence(fence);
+   return vfence->fence_fd;
+}
+
 
 /**
  * vmw_fence_ops_fence_reference - wrapper for the pb_fence_ops api.
index 31e1350c31675f3f89ef43c30c7b57cac8d8a44a..aab558f6b3dce61df793b2b039e8a403cb06bbb6 100644 (file)
@@ -38,13 +38,17 @@ struct vmw_winsys_screen;
 
 struct pipe_fence_handle *
 vmw_fence_create(struct pb_fence_ops *fence_ops,
-                uint32_t handle, uint32_t seqno, uint32_t mask);
+                uint32_t handle, uint32_t seqno, uint32_t mask, int32_t fd);
 
 int
 vmw_fence_finish(struct vmw_winsys_screen *vws,
                 struct pipe_fence_handle *fence,
                 uint64_t timeout,
                 unsigned flag);
+
+int
+vmw_fence_get_fd(struct pipe_fence_handle *fence);
+
 int
 vmw_fence_signalled(struct vmw_winsys_screen *vws,
                    struct pipe_fence_handle *fence,
index 1740d1ab062ab0d9446a396c18d03f9898479213..aad5ff98105b26f8bf931ad465b63710f7a0f596 100644 (file)
@@ -475,7 +475,7 @@ vmw_ioctl_command(struct vmw_winsys_screen *vws, int32_t cid,
                            TRUE);
 
         *pfence = vmw_fence_create(vws->fence_ops, rep.handle,
-                                   rep.seqno, rep.mask);
+                                   rep.seqno, rep.mask, -1);
         if (*pfence == NULL) {
            /*
             * Fence creation failed. Need to sync.
index 46335378e0abe4456e35f9a462ca42a512e43998..7c80642b377188de0837ba4cdebec4f5d409302d 100644 (file)
@@ -32,6 +32,7 @@
  * @author Jose Fonseca
  */
 
+#include <libsync.h>
 
 #include "svga_cmd.h"
 #include "svga3d_caps.h"
@@ -132,6 +133,35 @@ vmw_svga_winsys_fence_finish(struct svga_winsys_screen *sws,
 }
 
 
+static int
+vmw_svga_winsys_fence_get_fd(struct svga_winsys_screen *sws,
+                             struct pipe_fence_handle *fence,
+                             boolean duplicate)
+{
+   if (duplicate)
+      return dup(vmw_fence_get_fd(fence));
+   else
+      return vmw_fence_get_fd(fence);
+}
+
+
+static void
+vmw_svga_winsys_fence_create_fd(struct svga_winsys_screen *sws,
+                                struct pipe_fence_handle **fence,
+                                int32_t fd)
+{
+   *fence = vmw_fence_create(NULL, 0, 0, 0, dup(fd));
+}
+
+static int
+vmw_svga_winsys_fence_server_sync(struct svga_winsys_screen *sws,
+                                  int32_t *context_fd,
+                                  struct pipe_fence_handle *fence)
+{
+   return sync_accumulate("vmwgfx", context_fd,
+                          sws->fence_get_fd(sws, fence, FALSE));
+}
+
 
 static struct svga_winsys_surface *
 vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws,
@@ -435,6 +465,9 @@ vmw_winsys_screen_init_svga(struct vmw_winsys_screen *vws)
    vws->base.shader_create = vmw_svga_winsys_shader_create;
    vws->base.shader_destroy = vmw_svga_winsys_shader_destroy;
    vws->base.fence_finish = vmw_svga_winsys_fence_finish;
+   vws->base.fence_get_fd = vmw_svga_winsys_fence_get_fd;
+   vws->base.fence_create_fd = vmw_svga_winsys_fence_create_fd;
+   vws->base.fence_server_sync = vmw_svga_winsys_fence_server_sync;
 
    vws->base.query_create = vmw_svga_winsys_query_create;
    vws->base.query_init = vmw_svga_winsys_query_init;