allocators: Add DMABuf synchronization

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
This commit is contained in:
Nicolas Dufresne 2018-03-09 21:24:52 -05:00
parent 4696ecab15
commit 8ee306eb3f
3 changed files with 60 additions and 3 deletions

View 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

View 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;
}
/**

View 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))