Skip to content

Commit

Permalink
allocators: Add DMABuf synchronization
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ndufresne committed Mar 21, 2018
1 parent 4696eca commit 8ee306e
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 3 deletions.
3 changes: 3 additions & 0 deletions configure.ac
Expand Up @@ -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
Expand Down
59 changes: 56 additions & 3 deletions gst-libs/gst/allocators/gstdmabuf.c
Expand Up @@ -34,16 +34,67 @@
* 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);
#define GST_CAT_DEFAULT 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)
{
Expand All @@ -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;
}

/**
Expand Down
1 change: 1 addition & 0 deletions meson.build
Expand Up @@ -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))
Expand Down

0 comments on commit 8ee306e

Please sign in to comment.