hwcontext_drm: issue DMA_BUF_IOCTL_SYNC when mapping FDs

This improves performance and helps a little when given FDs without
any synchronization fences.
This commit is contained in:
Lynne 2020-11-20 18:23:42 +01:00
parent dd34861018
commit 993d8d9429
No known key found for this signature in database
GPG Key ID: A2FEA5F03F034464
1 changed files with 30 additions and 4 deletions

View File

@ -19,6 +19,8 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <unistd.h> #include <unistd.h>
#include <linux/dma-buf.h>
#include <sys/ioctl.h>
#include <drm.h> #include <drm.h>
#include <xf86drm.h> #include <xf86drm.h>
@ -85,6 +87,8 @@ static int drm_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
typedef struct DRMMapping { typedef struct DRMMapping {
// Address and length of each mmap()ed region. // Address and length of each mmap()ed region.
int nb_regions; int nb_regions;
int sync_flags;
int object[AV_DRM_MAX_PLANES];
void *address[AV_DRM_MAX_PLANES]; void *address[AV_DRM_MAX_PLANES];
size_t length[AV_DRM_MAX_PLANES]; size_t length[AV_DRM_MAX_PLANES];
} DRMMapping; } DRMMapping;
@ -93,10 +97,16 @@ static void drm_unmap_frame(AVHWFramesContext *hwfc,
HWMapDescriptor *hwmap) HWMapDescriptor *hwmap)
{ {
DRMMapping *map = hwmap->priv; DRMMapping *map = hwmap->priv;
int i; struct dma_buf_sync sync = { .flags = DMA_BUF_SYNC_END | map->sync_flags };
int i, ret;
for (i = 0; i < map->nb_regions; i++) for (i = 0; i < map->nb_regions; i++) {
ret = ioctl(map->object[i], DMA_BUF_IOCTL_SYNC, &sync);
if (ret)
av_log(hwfc, AV_LOG_ERROR, "Failed to issue ioctl sync to DRM object "
"%d: %d.\n", map->object[i], errno);
munmap(map->address[i], map->length[i]); munmap(map->address[i], map->length[i]);
}
av_free(map); av_free(map);
} }
@ -105,6 +115,7 @@ static int drm_map_frame(AVHWFramesContext *hwfc,
AVFrame *dst, const AVFrame *src, int flags) AVFrame *dst, const AVFrame *src, int flags)
{ {
const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor*)src->data[0]; const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor*)src->data[0];
struct dma_buf_sync sync_start = { 0 };
DRMMapping *map; DRMMapping *map;
int err, i, p, plane; int err, i, p, plane;
int mmap_prot; int mmap_prot;
@ -115,10 +126,16 @@ static int drm_map_frame(AVHWFramesContext *hwfc,
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
mmap_prot = 0; mmap_prot = 0;
if (flags & AV_HWFRAME_MAP_READ) if (flags & AV_HWFRAME_MAP_READ) {
mmap_prot |= PROT_READ; mmap_prot |= PROT_READ;
if (flags & AV_HWFRAME_MAP_WRITE) map->sync_flags |= DMA_BUF_SYNC_READ;
}
if (flags & AV_HWFRAME_MAP_WRITE) {
mmap_prot |= PROT_WRITE; mmap_prot |= PROT_WRITE;
map->sync_flags |= DMA_BUF_SYNC_WRITE;
}
sync_start.flags = DMA_BUF_SYNC_START | map->sync_flags;
av_assert0(desc->nb_objects <= AV_DRM_MAX_PLANES); av_assert0(desc->nb_objects <= AV_DRM_MAX_PLANES);
for (i = 0; i < desc->nb_objects; i++) { for (i = 0; i < desc->nb_objects; i++) {
@ -133,6 +150,15 @@ static int drm_map_frame(AVHWFramesContext *hwfc,
map->address[i] = addr; map->address[i] = addr;
map->length[i] = desc->objects[i].size; map->length[i] = desc->objects[i].size;
map->object[i] = desc->objects[i].fd;
err = ioctl(desc->objects[i].fd, DMA_BUF_IOCTL_SYNC, &sync_start);
if (err) {
err = AVERROR(errno);
av_log(hwfc, AV_LOG_ERROR, "Failed to issue ioctl sync to DRM object "
"%d: %d.\n", desc->objects[i].fd, errno);
goto fail;
}
} }
map->nb_regions = i; map->nb_regions = i;