allocators: Add DMABuf synchronization
authorNicolas Dufresne <nicolas.dufresne@collabora.com>
Sat, 10 Mar 2018 02:24:52 +0000 (21:24 -0500)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>
Wed, 21 Mar 2018 19:58:06 +0000 (15:58 -0400)
When doing CPU Access, some architecture may require caches to be
synchronize before use. Otherwise, some visual artifact may be
visible, as the CPU modification may still resides in cache.

https://bugzilla.gnome.org/show_bug.cgi?id=794216

configure.ac
gst-libs/gst/allocators/gstdmabuf.c
meson.build

index 67ebb75..cca8233 100644 (file)
@@ -486,6 +486,9 @@ esac
 dnl Check for mmap (needed by allocators library)
 AC_CHECK_FUNC([mmap], [AC_DEFINE(HAVE_MMAP, 1, [Defined if mmap is supported])])
 
+dnl Check for DMABuf synchronization ioctl (needed for DMABuf CPU access)
+AC_CHECK_HEADERS([linux/dma-buf.h], [])
+
 dnl *** plug-ins to include ***
 
 dnl these are all the gst plug-ins, compilable without additional libs
index 170267b..e9c5dd3 100644 (file)
@@ -34,9 +34,9 @@
  * Since: 1.2
  */
 
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#include <unistd.h>
+#ifdef HAVE_LINUX_DMA_BUF_H
+#include <sys/ioctl.h>
+#include <linux/dma-buf.h>
 #endif
 
 GST_DEBUG_CATEGORY_STATIC (dmabuf_debug);
@@ -44,6 +44,57 @@ GST_DEBUG_CATEGORY_STATIC (dmabuf_debug);
 
 G_DEFINE_TYPE (GstDmaBufAllocator, gst_dmabuf_allocator, GST_TYPE_FD_ALLOCATOR);
 
+static gpointer
+gst_dmabuf_mem_map (GstMemory * gmem, GstMapInfo * info, gsize maxsize)
+{
+  GstAllocator *allocator = gmem->allocator;
+#ifdef HAVE_LINUX_DMA_BUF_H
+  struct dma_buf_sync sync = { DMA_BUF_SYNC_START };
+  gpointer ret;
+
+  if (info->flags & GST_MAP_READ)
+    sync.flags |= DMA_BUF_SYNC_READ;
+
+  if (info->flags & GST_MAP_WRITE)
+    sync.flags |= DMA_BUF_SYNC_WRITE;
+#endif
+
+  ret = allocator->mem_map (gmem, maxsize, info->flags);
+
+#ifdef HAVE_LINUX_DMA_BUF_H
+  if (ret) {
+    if (ioctl (gst_fd_memory_get_fd (gmem), DMA_BUF_IOCTL_SYNC, &sync) < 0)
+      GST_WARNING_OBJECT (allocator, "Failed to synchronize DMABuf: %s (%i)",
+          g_strerror (errno), errno);
+  }
+#endif
+
+  return ret;
+}
+
+static void
+gst_dmabuf_mem_unmap (GstMemory * gmem, GstMapInfo * info)
+{
+  GstAllocator *allocator = gmem->allocator;
+#ifdef HAVE_LINUX_DMA_BUF_H
+  struct dma_buf_sync sync = { DMA_BUF_SYNC_END };
+
+  if (info->flags & GST_MAP_READ)
+    sync.flags |= DMA_BUF_SYNC_READ;
+
+  if (info->flags & GST_MAP_WRITE)
+    sync.flags |= DMA_BUF_SYNC_WRITE;
+
+  if (ioctl (gst_fd_memory_get_fd (gmem), DMA_BUF_IOCTL_SYNC, &sync) < 0)
+    GST_WARNING_OBJECT (allocator, "Failed to synchronize DMABuf: %s (%i)",
+        g_strerror (errno), errno);
+#else
+  GST_WARNING_OBJECT (allocator, "Using DMABuf without synchronization.");
+#endif
+
+  allocator->mem_unmap (gmem);
+}
+
 static void
 gst_dmabuf_allocator_class_init (GstDmaBufAllocatorClass * klass)
 {
@@ -55,6 +106,8 @@ gst_dmabuf_allocator_init (GstDmaBufAllocator * allocator)
   GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
 
   alloc->mem_type = GST_ALLOCATOR_DMABUF;
+  alloc->mem_map_full = gst_dmabuf_mem_map;
+  alloc->mem_unmap_full = gst_dmabuf_mem_unmap;
 }
 
 /**
index 344f25f..5c26811 100644 (file)
@@ -79,6 +79,7 @@ check_headers = [
   ['HAVE_UNISTD_H', 'unistd.h'],
   ['HAVE_WINSOCK2_H', 'winsock2.h'],
   ['HAVE_XMMINTRIN_H', 'xmmintrin.h'],
+  ['HAVE_LINUX_DMA_BUF_H', 'linux/dma-buf.h'],
 ]
 foreach h : check_headers
   if cc.has_header(h.get(1))