[RFC xserver v3 04/11] sync: Add support for DMA fences

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Mon Nov 6 21:42:53 UTC 2017


Functions are available to create a SyncFence from a DMA fence
fd and to retrieve the file descriptor from a SyncFence.

DMA fences can't be triggered/reset externally.

v2: Make SetTriggered and Reset return a status and remove fence type

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
 Xext/sync.c            |  39 ++++++++++---
 Xext/syncsrv.h         |   6 ++
 glamor/glamor_sync.c   |   7 ++-
 hw/xfree86/sdksyms.sh  |   1 +
 miext/sync/Makefile.am |   5 +-
 miext/sync/meson.build |   1 +
 miext/sync/misync.c    |  17 ++++--
 miext/sync/misync.h    |  22 +++++--
 miext/sync/misyncdma.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++
 miext/sync/misyncdma.h |  28 +++++++++
 miext/sync/misyncshm.c |  11 +++-
 11 files changed, 265 insertions(+), 24 deletions(-)
 create mode 100644 miext/sync/misyncdma.c
 create mode 100644 miext/sync/misyncdma.h

diff --git a/Xext/sync.c b/Xext/sync.c
index 37d41f224..034f9bf51 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -946,6 +946,34 @@ SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *pFence)
 #endif
 }
 
+int
+SyncCreateFenceFromDMAFenceFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd)
+{
+    SyncFence  *pFence;
+    int         status;
+
+    pFence = (SyncFence *) SyncCreate(client, id, SYNC_FENCE);
+    if (!pFence)
+        return BadAlloc;
+
+    status = miSyncInitFenceFromDMAFenceFD(pDraw->pScreen, pFence, fd);
+    if (status != Success) {
+        dixFreeObjectWithPrivates(pFence, PRIVATE_SYNC_FENCE);
+        return status;
+    }
+
+    if (!AddResource(id, RTFence, (void *) pFence))
+        return BadAlloc;
+
+    return Success;
+}
+
+int
+SyncDMAFenceFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *pFence)
+{
+    return miSyncDMAFenceFDFromFence(pDraw->pScreen, pFence);
+}
+
 static SyncCounter *
 SyncCreateCounter(ClientPtr client, XSyncCounter id, int64_t initialvalue)
 {
@@ -1931,9 +1959,7 @@ ProcSyncTriggerFence(ClientPtr client)
     if (rc != Success)
         return rc;
 
-    miSyncTriggerFence(pFence);
-
-    return Success;
+    return miSyncTriggerFence(pFence);
 }
 
 static int
@@ -1950,12 +1976,7 @@ ProcSyncResetFence(ClientPtr client)
     if (rc != Success)
         return rc;
 
-    if (pFence->funcs.CheckTriggered(pFence) != TRUE)
-        return BadMatch;
-
-    pFence->funcs.Reset(pFence);
-
-    return Success;
+    return pFence->funcs.Reset(pFence);
 }
 
 static int
diff --git a/Xext/syncsrv.h b/Xext/syncsrv.h
index 63f91a980..43fadbad5 100644
--- a/Xext/syncsrv.h
+++ b/Xext/syncsrv.h
@@ -142,6 +142,12 @@ SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL
 int
 SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *fence);
 
+int
+SyncCreateFenceFromDMAFenceFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd);
+
+int
+SyncDMAFenceFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *fence);
+
 void
 SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger);
 
diff --git a/glamor/glamor_sync.c b/glamor/glamor_sync.c
index 907e0c613..71835fcc4 100644
--- a/glamor/glamor_sync.c
+++ b/glamor/glamor_sync.c
@@ -44,21 +44,24 @@ glamor_get_sync_fence(SyncFence *fence)
     return (struct glamor_sync_fence *) dixLookupPrivate(&fence->devPrivates, &glamor_sync_fence_key);
 }
 
-static void
+static int
 glamor_sync_fence_set_triggered (SyncFence *fence)
 {
 	ScreenPtr screen = fence->pScreen;
 	glamor_screen_private *glamor = glamor_get_screen_private(screen);
 	struct glamor_sync_fence *glamor_fence = glamor_get_sync_fence(fence);
+	int ret;
 
 	/* Flush pending rendering operations */
         glamor_make_current(glamor);
         glFlush();
 
 	fence->funcs.SetTriggered = glamor_fence->set_triggered;
-	fence->funcs.SetTriggered(fence);
+	ret = fence->funcs.SetTriggered(fence);
 	glamor_fence->set_triggered = fence->funcs.SetTriggered;
 	fence->funcs.SetTriggered = glamor_sync_fence_set_triggered;
+
+	return ret;
 }
 
 static void
diff --git a/hw/xfree86/sdksyms.sh b/hw/xfree86/sdksyms.sh
index 9aa1eec4f..554d5590e 100755
--- a/hw/xfree86/sdksyms.sh
+++ b/hw/xfree86/sdksyms.sh
@@ -44,6 +44,7 @@ cat > sdksyms.c << EOF
 /* miext/sync/Makefile.am */
 #include "misync.h"
 #include "misyncstr.h"
+#include "misyncdma.h"
 #if HAVE_XSHMFENCE
 #include "misyncshm.h"
 #endif
diff --git a/miext/sync/Makefile.am b/miext/sync/Makefile.am
index 34961d5ff..cf62cd617 100644
--- a/miext/sync/Makefile.am
+++ b/miext/sync/Makefile.am
@@ -5,7 +5,7 @@ AM_CFLAGS = $(DIX_CFLAGS)
 AM_CPPFLAGS = 
 
 if XORG
-sdk_HEADERS = misync.h misyncstr.h misyncshm.h misyncfd.h
+sdk_HEADERS = misync.h misyncstr.h misyncshm.h misyncfd.h misyncdma.h
 endif
 
 XSHMFENCE_SRCS = misyncshm.c
@@ -14,7 +14,8 @@ libsync_la_SOURCES =	\
 	misync.c	\
 	misync.h	\
 	misyncfd.c	\
-	misyncstr.h
+	misyncstr.h \
+	misyncdma.c
 
 if XSHMFENCE
 libsync_la_SOURCES += $(XSHMFENCE_SRCS)
diff --git a/miext/sync/meson.build b/miext/sync/meson.build
index da86fcc84..d9847d0bf 100644
--- a/miext/sync/meson.build
+++ b/miext/sync/meson.build
@@ -1,6 +1,7 @@
 srcs_miext_sync = [
     'misync.c',
     'misyncfd.c',
+    'misyncdma.c',
 ]
 
 if build_dri3
diff --git a/miext/sync/misync.c b/miext/sync/misync.c
index d7880d39c..87c157cd6 100644
--- a/miext/sync/misync.c
+++ b/miext/sync/misync.c
@@ -42,16 +42,20 @@ miSyncScreenCreateFence(ScreenPtr pScreen, SyncFence * pFence,
 }
 
 /* Default implementations of the per-object functions */
-void
+int
 miSyncFenceSetTriggered(SyncFence * pFence)
 {
     pFence->triggered = TRUE;
+
+    return Success;
 }
 
-void
+int
 miSyncFenceReset(SyncFence * pFence)
 {
     pFence->triggered = FALSE;
+
+    return Success;
 }
 
 Bool
@@ -123,12 +127,15 @@ miSyncDestroyFence(SyncFence * pFence)
     dixFreeObjectWithPrivates(pFence, PRIVATE_SYNC_FENCE);
 }
 
-void
+int
 miSyncTriggerFence(SyncFence * pFence)
 {
     SyncTriggerList *ptl, *pNext;
+    int ret;
 
-    pFence->funcs.SetTriggered(pFence);
+    ret = pFence->funcs.SetTriggered(pFence);
+    if (ret != Success)
+        return ret;
 
     /* run through triggers to see if any fired */
     for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext) {
@@ -136,6 +143,8 @@ miSyncTriggerFence(SyncFence * pFence)
         if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, 0))
             (*ptl->pTrigger->TriggerFired) (ptl->pTrigger);
     }
+
+    return Success;
 }
 
 SyncScreenFuncsPtr
diff --git a/miext/sync/misync.h b/miext/sync/misync.h
index b3838f1e2..78a7d4998 100644
--- a/miext/sync/misync.h
+++ b/miext/sync/misync.h
@@ -44,8 +44,8 @@ extern _X_EXPORT void
 miSyncScreenCreateFence(ScreenPtr pScreen, SyncFence * pFence,
                         Bool initially_triggered);
 
-typedef void (*SyncFenceSetTriggeredFunc) (SyncFence * pFence);
-typedef void (*SyncFenceResetFunc) (SyncFence * pFence);
+typedef int  (*SyncFenceSetTriggeredFunc) (SyncFence * pFence);
+typedef int  (*SyncFenceResetFunc) (SyncFence * pFence);
 typedef Bool (*SyncFenceCheckTriggeredFunc) (SyncFence * pFence);
 typedef void (*SyncFenceAddTriggerFunc) (SyncTrigger * pTrigger);
 typedef void (*SyncFenceDeleteTriggerFunc) (SyncTrigger * pTrigger);
@@ -66,7 +66,7 @@ miSyncInitFence(ScreenPtr pScreen, SyncFence * pFence,
                 Bool initially_triggered);
 extern _X_EXPORT void
  miSyncDestroyFence(SyncFence * pFence);
-extern _X_EXPORT void
+extern _X_EXPORT int
  miSyncTriggerFence(SyncFence * pFence);
 
 extern _X_EXPORT SyncScreenFuncsPtr miSyncGetScreenFuncs(ScreenPtr pScreen);
@@ -76,10 +76,10 @@ extern _X_EXPORT Bool
 Bool
 miSyncFenceCheckTriggered(SyncFence * pFence);
 
-void
+int
 miSyncFenceSetTriggered(SyncFence * pFence);
 
-void
+int
 miSyncFenceReset(SyncFence * pFence);
 
 void
@@ -97,4 +97,16 @@ miSyncInitFenceFromFD(DrawablePtr pDraw, SyncFence *pFence, int fd, BOOL initial
 int
 miSyncFDFromFence(DrawablePtr pDraw, SyncFence *pFence);
 
+extern _X_EXPORT Bool
+miSyncIsDMAFence(SyncFence *pFence);
+
+extern _X_EXPORT int
+miSyncDMAFenceFDFromFence(ScreenPtr pScreen, SyncFence *pFence);
+
+extern _X_EXPORT int
+miSyncInitFenceFromDMAFenceFD(ScreenPtr pScreen, SyncFence *pFence, int fd);
+
+extern _X_EXPORT int
+miSyncTakeDMAFenceFDFromFence(ScreenPtr pScreen, SyncFence *pFence);
+
 #endif                          /* _MISYNC_H_ */
diff --git a/miext/sync/misyncdma.c b/miext/sync/misyncdma.c
new file mode 100644
index 000000000..9aaf04e6a
--- /dev/null
+++ b/miext/sync/misyncdma.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright © 2017 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "scrnintstr.h"
+#include "misync.h"
+#include "misyncstr.h"
+#include "misyncdma.h"
+#include "pixmapstr.h"
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <X11/xshmfence.h>
+
+static DevPrivateKeyRec syncDmaFencePrivateKey;
+
+typedef struct _SyncDmaFencePrivate {
+    int                        fd;
+} SyncDmaFencePrivateRec, *SyncDmaFencePrivatePtr;
+
+#define SYNC_FENCE_PRIV(pFence) \
+    (SyncDmaFencePrivatePtr) dixLookupPrivate(&pFence->devPrivates, &syncDmaFencePrivateKey)
+
+static int
+miSyncDmaFenceSetTriggered(SyncFence * pFence)
+{
+    return BadMatch;
+}
+
+static int
+miSyncDmaFenceReset(SyncFence * pFence)
+{
+    return BadMatch;
+}
+
+static Bool
+miSyncDmaFenceCheckTriggered(SyncFence * pFence)
+{
+    SyncDmaFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
+    struct pollfd fds;
+
+    if (pPriv->fd > 0) {
+        fds.fd = pPriv->fd;
+        fds.events = POLLOUT;
+        fds.revents = 0;
+        poll(&fds, 1, 0);
+        return fds.revents & POLLOUT;
+    } else {
+        return miSyncFenceCheckTriggered(pFence);
+    }
+}
+
+static void
+miSyncDmaFenceAddTrigger(SyncTrigger * pTrigger)
+{
+    miSyncFenceAddTrigger(pTrigger);
+}
+
+static void
+miSyncDmaFenceDeleteTrigger(SyncTrigger * pTrigger)
+{
+    miSyncFenceDeleteTrigger(pTrigger);
+}
+
+static void
+miSyncDmaFenceDestroy(SyncFence * pFence)
+{
+    SyncDmaFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
+
+    if (pPriv->fd >= 0)
+        close(pPriv->fd);
+    pPriv->fd = -1;
+}
+
+static const SyncFenceFuncsRec miSyncDmaFenceFuncs = {
+    &miSyncDmaFenceSetTriggered,
+    &miSyncDmaFenceReset,
+    &miSyncDmaFenceCheckTriggered,
+    &miSyncDmaFenceAddTrigger,
+    &miSyncDmaFenceDeleteTrigger,
+    &miSyncDmaFenceDestroy
+};
+
+Bool
+miSyncIsDMAFence(SyncFence *pFence)
+{
+    return (pFence->funcs.Destroy == &miSyncDmaFenceDestroy);
+}
+
+int
+miSyncInitFenceFromDMAFenceFD(ScreenPtr pScreen, SyncFence *pFence, int fd)
+{
+    SyncDmaFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
+
+    pFence->pScreen = pScreen;
+    pFence->funcs = miSyncDmaFenceFuncs;
+
+    pPriv->fd = fd < 0 ? -1 : dup(fd);
+    return Success;
+}
+
+int
+miSyncDMAFenceFDFromFence(ScreenPtr pScreen, SyncFence *pFence)
+{
+    SyncDmaFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
+
+    return pPriv->fd;
+}
+
+int
+miSyncTakeDMAFenceFDFromFence(ScreenPtr pScreen, SyncFence *pFence)
+{
+    SyncDmaFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
+    int fd = pPriv->fd;
+    pPriv->fd = -1;
+    return fd;
+}
+
+_X_EXPORT Bool miSyncDmaScreenInit(ScreenPtr pScreen)
+{
+    if (!dixPrivateKeyRegistered(&syncDmaFencePrivateKey)) {
+        if (!dixRegisterPrivateKey(&syncDmaFencePrivateKey, PRIVATE_SYNC_FENCE,
+                                   sizeof(SyncDmaFencePrivateRec)))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
diff --git a/miext/sync/misyncdma.h b/miext/sync/misyncdma.h
new file mode 100644
index 000000000..8a27069d7
--- /dev/null
+++ b/miext/sync/misyncdma.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2017 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _MISYNCDMA_H_
+#define _MISYNCDMA_H_
+
+extern _X_EXPORT Bool miSyncDmaScreenInit(ScreenPtr pScreen);
+
+#endif /* _MISYNCDMA_H_ */
diff --git a/miext/sync/misyncshm.c b/miext/sync/misyncshm.c
index f55a3f8a5..0f1f828bf 100644
--- a/miext/sync/misyncshm.c
+++ b/miext/sync/misyncshm.c
@@ -45,7 +45,7 @@ typedef struct _SyncShmFencePrivate {
 #define SYNC_FENCE_PRIV(pFence) \
     (SyncShmFencePrivatePtr) dixLookupPrivate(&pFence->devPrivates, &syncShmFencePrivateKey)
 
-static void
+static int
 miSyncShmFenceSetTriggered(SyncFence * pFence)
 {
     SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
@@ -53,16 +53,23 @@ miSyncShmFenceSetTriggered(SyncFence * pFence)
     if (pPriv->fence)
         xshmfence_trigger(pPriv->fence);
     miSyncFenceSetTriggered(pFence);
+
+    return Success;
 }
 
-static void
+static int
 miSyncShmFenceReset(SyncFence * pFence)
 {
     SyncShmFencePrivatePtr      pPriv = SYNC_FENCE_PRIV(pFence);
 
+    if (!miSyncFenceCheckTriggered(pFence))
+        return BadMatch;
+
     if (pPriv->fence)
         xshmfence_reset(pPriv->fence);
     miSyncFenceReset(pFence);
+
+    return Success;
 }
 
 static Bool
-- 
2.13.0



More information about the xorg-devel mailing list