hwdec/dmabuf_interop: use AVDRMFrameDescriptor to describe dmabufs

Annoyingly, libva and libdrm use different structs to describe dmabufs
and if we are going to support drmprime, we must pick one format and do
some shuffling in the other case.

I've decided to use AVDRMFrameDescriptor as our internal format as this
removes the libva dependency from dmabuf_interop. That means that the
future drmprime hwdec will be able to populate it directly and the
existing hwdec_vaapi needs to copy the struct members around, but
that's cheap and not a concern.
This commit is contained in:
Philip Langdale 2022-07-31 12:59:15 -07:00 committed by Philip Langdale
parent e9e5059589
commit 64f4249604
7 changed files with 80 additions and 31 deletions

View File

@ -1474,7 +1474,6 @@ vaapi_egl = {
if vaapi_egl['use']
dependencies += [vaapi_wayland['deps'], vaapi_drm['deps']]
features += vaapi_egl['name']
sources += files('video/out/hwdec/dmabuf_interop_gl.c')
endif
vaapi_libplacebo = {
@ -1483,13 +1482,32 @@ vaapi_libplacebo = {
}
if vaapi_libplacebo['use']
features += vaapi_libplacebo['name']
sources += files('video/out/hwdec/dmabuf_interop_pl.c')
endif
if vaapi_egl['use'] or vaapi_libplacebo['use']
sources += files('video/out/hwdec/hwdec_vaapi.c')
endif
dmabuf_interop_gl = {
'name': 'dmabuf-interop-gl',
'use': egl['use'] and drm['use']
}
if dmabuf_interop_gl['use']
features += dmabuf_interop_gl['name']
sources += files('video/out/hwdec/dmabuf_interop_gl.c')
endif
dmabuf_interop_pl = {
'name': 'dmabuf-interop-pl',
'use': vaapi_libplacebo['use']
}
if dmabuf_interop_pl['use']
features += dmabuf_interop_pl['name']
sources += files('video/out/hwdec/dmabuf_interop_pl.c')
endif
vdpau_opt = get_option('vdpau').require(
x11['use'],
error_message: 'x11 was not found!',
@ -1721,6 +1739,8 @@ conf_data.set10('HAVE_D3D_HWACCEL', d3d_hwaccel.allowed())
conf_data.set10('HAVE_D3D9_HWACCEL', d3d9_hwaccel.allowed())
conf_data.set10('HAVE_D3D11', d3d11.allowed())
conf_data.set10('HAVE_DIRECT3D', direct3d)
conf_data.set10('HAVE_DMABUF_INTEROP_GL', dmabuf_interop_gl['use'])
conf_data.set10('HAVE_DMABUF_INTEROP_PL', dmabuf_interop_pl['use'])
conf_data.set10('HAVE_DOS_PATHS', win32)
conf_data.set10('HAVE_DRM', drm['use'])
conf_data.set10('HAVE_DVBIN', dvbin.allowed())

View File

@ -17,7 +17,7 @@
#pragma once
#include <va/va_drmcommon.h>
#include <libavutil/hwcontext_drm.h>
#include "config.h"
#include "video/out/gpu/hwdec.h"
@ -40,7 +40,7 @@ struct priv {
struct mp_image layout;
struct ra_tex *tex[4];
VADRMPRIMESurfaceDescriptor desc;
AVDRMFrameDescriptor desc;
bool surface_acquired;
void *interop_mapper_priv;

View File

@ -144,11 +144,11 @@ static void vaapi_gl_mapper_uninit(const struct ra_hwdec_mapper *mapper)
} while(0)
#define ADD_PLANE_ATTRIBS(plane) do { \
uint64_t drm_format_modifier = p_mapper->desc.objects[p_mapper->desc.layers[n].object_index[plane]].drm_format_modifier; \
uint64_t drm_format_modifier = p_mapper->desc.objects[p_mapper->desc.layers[n].planes[plane].object_index].format_modifier; \
ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _FD_EXT, \
p_mapper->desc.objects[p_mapper->desc.layers[n].object_index[plane]].fd); \
p_mapper->desc.objects[p_mapper->desc.layers[n].planes[plane].object_index].fd); \
ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _OFFSET_EXT, \
p_mapper->desc.layers[n].offset[plane]); \
p_mapper->desc.layers[n].planes[plane].offset); \
ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _PITCH_EXT, \
p_mapper->desc.layers[n].planes[plane].pitch); \
if (dmabuf_interop->use_modifiers && drm_format_modifier != DRM_FORMAT_MOD_INVALID) { \
@ -167,7 +167,7 @@ static bool vaapi_gl_map(struct ra_hwdec_mapper *mapper,
GL *gl = ra_gl_get(mapper->ra);
for (int n = 0; n < p_mapper->num_planes; n++) {
if (p_mapper->desc.layers[n].num_planes > 1) {
if (p_mapper->desc.layers[n].nb_planes > 1) {
// Should never happen because we request separate layers
MP_ERR(mapper, "Multi-plane surfaces are not supported\n");
return false;
@ -176,16 +176,16 @@ static bool vaapi_gl_map(struct ra_hwdec_mapper *mapper,
int attribs[48] = {EGL_NONE};
int num_attribs = 0;
ADD_ATTRIB(EGL_LINUX_DRM_FOURCC_EXT, p_mapper->desc.layers[n].drm_format);
ADD_ATTRIB(EGL_LINUX_DRM_FOURCC_EXT, p_mapper->desc.layers[n].format);
ADD_ATTRIB(EGL_WIDTH, p_mapper->tex[n]->params.w);
ADD_ATTRIB(EGL_HEIGHT, p_mapper->tex[n]->params.h);
ADD_PLANE_ATTRIBS(0);
if (p_mapper->desc.layers[n].num_planes > 1)
if (p_mapper->desc.layers[n].nb_planes > 1)
ADD_PLANE_ATTRIBS(1);
if (p_mapper->desc.layers[n].num_planes > 2)
if (p_mapper->desc.layers[n].nb_planes > 2)
ADD_PLANE_ATTRIBS(2);
if (p_mapper->desc.layers[n].num_planes > 3)
if (p_mapper->desc.layers[n].nb_planes > 3)
ADD_PLANE_ATTRIBS(3);
p->images[n] = p->CreateImageKHR(eglGetCurrentDisplay(),

View File

@ -41,11 +41,11 @@ static bool vaapi_pl_map(struct ra_hwdec_mapper *mapper,
for (int n = 0; n < p->num_planes; n++) {
const struct ra_format *format = desc.planes[n];
int id = p->desc.layers[layer].object_index[layer_plane];
int id = p->desc.layers[layer].planes[layer_plane].object_index;
int fd = p->desc.objects[id].fd;
uint32_t size = p->desc.objects[id].size;
uint32_t offset = p->desc.layers[layer].offset[layer_plane];
uint32_t pitch = p->desc.layers[layer].pitch[layer_plane];
uint32_t offset = p->desc.layers[layer].planes[layer_plane].offset;
uint32_t pitch = p->desc.layers[layer].planes[layer_plane].pitch;
// AMD drivers do not return the size in the surface description, so we
// need to query it manually.
@ -77,7 +77,7 @@ static bool vaapi_pl_map(struct ra_hwdec_mapper *mapper,
},
.size = size,
.offset = offset,
.drm_format_mod = p->desc.objects[id].drm_format_modifier,
.drm_format_mod = p->desc.objects[id].format_modifier,
.stride_w = pitch,
},
};
@ -101,7 +101,7 @@ static bool vaapi_pl_map(struct ra_hwdec_mapper *mapper,
id, fd, ratex);
layer_plane++;
if (layer_plane == p->desc.layers[layer].num_planes) {
if (layer_plane == p->desc.layers[layer].nb_planes) {
layer_plane = 0;
layer++;
}

View File

@ -22,6 +22,7 @@
#include <libavutil/hwcontext.h>
#include <libavutil/hwcontext_vaapi.h>
#include <va/va_drmcommon.h>
#include "config.h"
@ -117,10 +118,10 @@ static void uninit(struct ra_hwdec *hw)
}
const static dmabuf_interop_init interop_inits[] = {
#if HAVE_VAAPI_EGL
#if HAVE_DMABUF_INTEROP_GL
dmabuf_interop_gl_init,
#endif
#if HAVE_VAAPI_LIBPLACEBO
#if HAVE_DMABUF_INTEROP_PL
dmabuf_interop_pl_init,
#endif
NULL
@ -181,7 +182,7 @@ static void mapper_unmap(struct ra_hwdec_mapper *mapper)
p_owner->dmabuf_interop.interop_unmap(mapper);
if (p->surface_acquired) {
for (int n = 0; n < p->desc.num_objects; n++)
for (int n = 0; n < p->desc.nb_objects; n++)
close(p->desc.objects[n].fd);
p->surface_acquired = false;
}
@ -242,12 +243,13 @@ static int mapper_map(struct ra_hwdec_mapper *mapper)
struct priv *p = mapper->priv;
VAStatus status;
VADisplay *display = p_owner->display;
VADRMPRIMESurfaceDescriptor desc;
status = vaExportSurfaceHandle(display, va_surface_id(mapper->src),
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
VA_EXPORT_SURFACE_READ_ONLY |
VA_EXPORT_SURFACE_SEPARATE_LAYERS,
&p->desc);
&desc);
if (!CHECK_VA_STATUS_LEVEL(mapper, "vaExportSurfaceHandle()",
p_owner->probing_formats ? MSGL_DEBUG : MSGL_ERR))
{
@ -258,21 +260,38 @@ static int mapper_map(struct ra_hwdec_mapper *mapper)
CHECK_VA_STATUS(mapper, "vaSyncSurface()");
p->surface_acquired = true;
// We use AVDRMFrameDescriptor to store the dmabuf so we need to copy the
// values over.
int num_returned_planes = 0;
p->desc.nb_layers = desc.num_layers;
p->desc.nb_objects = desc.num_objects;
for (int i = 0; i < desc.num_layers; i++) {
p->desc.layers[i].format = desc.layers[i].drm_format;
p->desc.layers[i].nb_planes = desc.layers[i].num_planes;
for (int j = 0; j < desc.layers[i].num_planes; j++)
{
p->desc.layers[i].planes[j].object_index = desc.layers[i].object_index[j];
p->desc.layers[i].planes[j].offset = desc.layers[i].offset[j];
p->desc.layers[i].planes[j].pitch = desc.layers[i].pitch[j];
}
num_returned_planes += desc.layers[i].num_planes;
}
for (int i = 0; i < desc.num_objects; i++) {
p->desc.objects[i].format_modifier = desc.objects[i].drm_format_modifier;
p->desc.objects[i].fd = desc.objects[i].fd;
p->desc.objects[i].size = desc.objects[i].size;
}
// We can handle composed formats if the total number of planes is still
// equal the number of planes we expect. Complex formats with auxilliary
// planes cannot be supported.
int num_returned_planes = 0;
for (int i = 0; i < p->desc.num_layers; i++) {
num_returned_planes += p->desc.layers[i].num_planes;
}
if (p->num_planes != num_returned_planes) {
mp_msg(mapper->log, p_owner->probing_formats ? MSGL_DEBUG : MSGL_ERR,
"Mapped surface with format '%s' has unexpected number of planes. "
"(%d layers and %d planes, but expected %d planes)\n",
mp_imgfmt_to_name(mapper->src->params.hw_subfmt),
p->desc.num_layers, num_returned_planes, p->num_planes);
desc.num_layers, num_returned_planes, p->num_planes);
goto err;
}
@ -280,7 +299,7 @@ static int mapper_map(struct ra_hwdec_mapper *mapper)
p_owner->probing_formats))
goto err;
if (p->desc.fourcc == VA_FOURCC_YV12)
if (desc.fourcc == VA_FOURCC_YV12)
MPSWAP(struct ra_tex*, mapper->tex[1], mapper->tex[2]);
return 0;

10
wscript
View File

@ -782,6 +782,16 @@ video_output_features = [
'name': '--sixel',
'desc': 'Sixel',
'func': check_pkg_config('libsixel', '>= 1.5'),
}, {
'name': 'dmabuf-interop-gl',
'desc': 'dmabuf GL Interop',
'deps': 'egl && drm',
'func': check_true,
}, {
'name': 'dmabuf-interop-pl',
'desc': 'dmabuf libplacebo interop',
'deps': 'vaapi-libplacebo',
'func': check_true,
}
]

View File

@ -471,8 +471,8 @@ def build(ctx):
( "video/out/hwdec/hwdec_cuda_gl.c", "cuda-interop && gl" ),
( "video/out/hwdec/hwdec_cuda_vk.c", "cuda-interop && vulkan" ),
( "video/out/hwdec/hwdec_vaapi.c", "vaapi-egl || vaapi-libplacebo" ),
( "video/out/hwdec/dmabuf_interop_gl.c", "vaapi-egl" ),
( "video/out/hwdec/dmabuf_interop_pl.c", "vaapi-libplacebo" ),
( "video/out/hwdec/dmabuf_interop_gl.c", "dmabuf-interop-gl" ),
( "video/out/hwdec/dmabuf_interop_pl.c", "dmabuf-interop-pl" ),
( "video/out/libmpv_sw.c" ),
( "video/out/placebo/ra_pl.c", "libplacebo" ),
( "video/out/placebo/utils.c", "libplacebo" ),