summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Langdale <philipl@overt.org>2018-12-30 14:59:48 -0800
committersfan5 <sfan5@live.de>2019-07-08 01:57:02 +0200
commitb70ed35ba4ea8c08632e585b7027090ac00a0bb8 (patch)
tree3f3f749e3750a81d0eb5b5b02bda63d6bcf4e1bc
parent6842755feb04a7a9e0820b3e999586cb54e329e3 (diff)
downloadmpv-b70ed35ba4ea8c08632e585b7027090ac00a0bb8.tar.bz2
mpv-b70ed35ba4ea8c08632e585b7027090ac00a0bb8.tar.xz
vo_gpu: hwdec_vaapi: Add Vulkan interop
This change introduces a vulkan interop path for the vaapi hwdec. The basic principles are mostly the same as for EGL, with the exported dma_buf being imported by Vukan. The biggest difference is that we cannot reuse the texture as we do with OpenGL - there's no way to rebind a VkImage to a different piece of memory, as far as I can see. So, a new texture is created on each map call. I did not bother implementing a code path for the old libva API as I think it's safe to assume any system with a working vulkan driver will have access to a newer libva. Note that we are using separate layers for the vaapi surface, just as is done for EGL. This is because libplacebo doesn't support multiplane images. This change does not include format negotiation because no driver implements the vk_ext_image_drm_format_modifier extension that would be required to do that. In practice, the two formats we care about (nv12, p010) work correctly, so we are not blocked. A separate change had to be made in libplacebo to filter out non-fatal validation errors related to surface sizes due to the lack of format negotiation.
-rw-r--r--video/out/hwdec/hwdec_vaapi.c451
-rw-r--r--video/out/vulkan/context_wayland.c2
-rw-r--r--video/out/vulkan/context_xlib.c2
-rw-r--r--wscript5
-rw-r--r--wscript_build.py2
5 files changed, 304 insertions, 158 deletions
diff --git a/video/out/hwdec/hwdec_vaapi.c b/video/out/hwdec/hwdec_vaapi.c
index 2ff0d98df3..eed79799e9 100644
--- a/video/out/hwdec/hwdec_vaapi.c
+++ b/video/out/hwdec/hwdec_vaapi.c
@@ -20,9 +20,6 @@
#include <assert.h>
#include <unistd.h>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
#include <va/va_drmcommon.h>
#include <libavutil/common.h>
@@ -34,8 +31,17 @@
#include "video/out/gpu/hwdec.h"
#include "video/mp_image_pool.h"
#include "video/vaapi.h"
-#include "common.h"
-#include "ra_gl.h"
+
+#if HAVE_VULKAN
+#include "video/out/placebo/ra_pl.h"
+#include "video/out/vulkan/common.h"
+#endif
+
+#if HAVE_GL
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include "video/out/opengl/common.h"
+#include "video/out/opengl/ra_gl.h"
#include "libmpv/render_gl.h"
#ifndef GL_OES_EGL_image
@@ -53,6 +59,8 @@ typedef void *EGLImageKHR;
#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
#endif
+#endif // HAVE_GL
+
#if HAVE_VAAPI_X11
#include <va/va_x11.h>
@@ -124,9 +132,12 @@ struct priv_owner {
struct priv {
int num_planes;
+ struct mp_image layout;
struct ra_tex *tex[4];
+#if HAVE_GL
GLuint gl_textures[4];
EGLImageKHR images[4];
+#endif
VAImage current_image;
bool buffer_acquired;
#if VA_CHECK_VERSION(1, 1, 0)
@@ -135,11 +146,13 @@ struct priv {
bool surface_acquired;
#endif
+#if HAVE_GL
EGLImageKHR (EGLAPIENTRY *CreateImageKHR)(EGLDisplay, EGLContext,
EGLenum, EGLClientBuffer,
const EGLint *);
EGLBoolean (EGLAPIENTRY *DestroyImageKHR)(EGLDisplay, EGLImageKHR);
void (EGLAPIENTRY *EGLImageTargetTexture2DOES)(GLenum, GLeglImageOES);
+#endif
};
static void determine_working_formats(struct ra_hwdec *hw);
@@ -156,19 +169,38 @@ static int init(struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;
- if (!ra_is_gl(hw->ra) || !eglGetCurrentContext())
- return -1;
+#if HAVE_GL
+ if (ra_is_gl(hw->ra)) {
+ if (!eglGetCurrentContext())
+ return -1;
- const char *exts = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
- if (!exts)
- return -1;
+ const char *exts = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
+ if (!exts)
+ return -1;
- GL *gl = ra_gl_get(hw->ra);
- if (!strstr(exts, "EXT_image_dma_buf_import") ||
- !strstr(exts, "EGL_KHR_image_base") ||
- !strstr(gl->extensions, "GL_OES_EGL_image") ||
- !(gl->mpgl_caps & MPGL_CAP_TEX_RG))
- return -1;
+ GL *gl = ra_gl_get(hw->ra);
+ if (!strstr(exts, "EXT_image_dma_buf_import") ||
+ !strstr(exts, "EGL_KHR_image_base") ||
+ !strstr(gl->extensions, "GL_OES_EGL_image") ||
+ !(gl->mpgl_caps & MPGL_CAP_TEX_RG))
+ return -1;
+
+ MP_VERBOSE(hw, "using VAAPI EGL interop\n");
+ }
+#endif
+
+#if HAVE_VULKAN
+ if (ra_pl_get(hw->ra)) {
+ const struct pl_gpu *gpu = ra_pl_get(hw->ra);
+ if (!(gpu->import_caps.tex & PL_HANDLE_DMA_BUF)) {
+ MP_VERBOSE(hw, "VAAPI Vulkan interop requires support for "
+ "dma_buf import in Vulkan.\n");
+ return -1;
+ }
+
+ MP_VERBOSE(hw, "using VAAPI Vulkan interop\n");
+ }
+#endif
p->display = create_native_va_display(hw->ra, hw->log);
if (!p->display) {
@@ -190,8 +222,6 @@ static int init(struct ra_hwdec *hw)
return -1;
}
- MP_VERBOSE(hw, "using VAAPI EGL interop\n");
-
determine_working_formats(hw);
if (!p->formats || !p->formats[0]) {
return -1;
@@ -209,11 +239,26 @@ static void mapper_unmap(struct ra_hwdec_mapper *mapper)
VADisplay *display = p_owner->display;
struct priv *p = mapper->priv;
VAStatus status;
+#if HAVE_GL
+ bool is_gl = ra_is_gl(mapper->ra);
+#endif
+#if HAVE_VULKAN
+ const struct pl_gpu *gpu = ra_pl_get(mapper->ra);
+#endif
for (int n = 0; n < 4; n++) {
- if (p->images[n])
- p->DestroyImageKHR(eglGetCurrentDisplay(), p->images[n]);
- p->images[n] = 0;
+#if HAVE_GL
+ if (is_gl) {
+ if (p->images[n])
+ p->DestroyImageKHR(eglGetCurrentDisplay(), p->images[n]);
+ p->images[n] = 0;
+ }
+#endif
+#if HAVE_VULKAN
+ if (gpu) {
+ ra_tex_free(mapper->ra, &mapper->tex[n]);
+ }
+#endif
}
#if VA_CHECK_VERSION(1, 1, 0)
@@ -238,14 +283,18 @@ static void mapper_unmap(struct ra_hwdec_mapper *mapper)
static void mapper_uninit(struct ra_hwdec_mapper *mapper)
{
+#if HAVE_GL
struct priv *p = mapper->priv;
- GL *gl = ra_gl_get(mapper->ra);
- gl->DeleteTextures(4, p->gl_textures);
- for (int n = 0; n < 4; n++) {
- p->gl_textures[n] = 0;
- ra_tex_free(mapper->ra, &p->tex[n]);
+ if (ra_is_gl(mapper->ra)) {
+ GL *gl = ra_gl_get(mapper->ra);
+ gl->DeleteTextures(4, p->gl_textures);
+ for (int n = 0; n < 4; n++) {
+ p->gl_textures[n] = 0;
+ ra_tex_free(mapper->ra, &p->tex[n]);
+ }
}
+#endif
}
static bool check_fmt(struct ra_hwdec_mapper *mapper, int fmt)
@@ -262,61 +311,71 @@ static int mapper_init(struct ra_hwdec_mapper *mapper)
{
struct priv_owner *p_owner = mapper->owner->priv;
struct priv *p = mapper->priv;
- GL *gl = ra_gl_get(mapper->ra);
+#if HAVE_GL
+ bool is_gl = ra_is_gl(mapper->ra);
+#endif
p->current_image.buf = p->current_image.image_id = VA_INVALID_ID;
- // EGL_KHR_image_base
- p->CreateImageKHR = (void *)eglGetProcAddress("eglCreateImageKHR");
- p->DestroyImageKHR = (void *)eglGetProcAddress("eglDestroyImageKHR");
- // GL_OES_EGL_image
- p->EGLImageTargetTexture2DOES =
- (void *)eglGetProcAddress("glEGLImageTargetTexture2DOES");
-
- if (!p->CreateImageKHR || !p->DestroyImageKHR ||
- !p->EGLImageTargetTexture2DOES)
- return -1;
+#if HAVE_GL
+ if (is_gl) {
+ // EGL_KHR_image_base
+ p->CreateImageKHR = (void *)eglGetProcAddress("eglCreateImageKHR");
+ p->DestroyImageKHR = (void *)eglGetProcAddress("eglDestroyImageKHR");
+ // GL_OES_EGL_image
+ p->EGLImageTargetTexture2DOES =
+ (void *)eglGetProcAddress("glEGLImageTargetTexture2DOES");
+
+ if (!p->CreateImageKHR || !p->DestroyImageKHR ||
+ !p->EGLImageTargetTexture2DOES)
+ return -1;
+ }
+#endif
mapper->dst_params = mapper->src_params;
mapper->dst_params.imgfmt = mapper->src_params.hw_subfmt;
mapper->dst_params.hw_subfmt = 0;
struct ra_imgfmt_desc desc = {0};
- struct mp_image layout = {0};
if (!ra_get_imgfmt_desc(mapper->ra, mapper->dst_params.imgfmt, &desc))
return -1;
p->num_planes = desc.num_planes;
- mp_image_set_params(&layout, &mapper->dst_params);
-
- gl->GenTextures(4, p->gl_textures);
- for (int n = 0; n < desc.num_planes; n++) {
- gl->BindTexture(GL_TEXTURE_2D, p->gl_textures[n]);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- gl->BindTexture(GL_TEXTURE_2D, 0);
-
- struct ra_tex_params params = {
- .dimensions = 2,
- .w = mp_image_plane_w(&layout, n),
- .h = mp_image_plane_h(&layout, n),
- .d = 1,
- .format = desc.planes[n],
- .render_src = true,
- .src_linear = true,
- };
-
- if (params.format->ctype != RA_CTYPE_UNORM)
- return -1;
-
- p->tex[n] = ra_create_wrapped_tex(mapper->ra, &params,
- p->gl_textures[n]);
- if (!p->tex[n])
- return -1;
+ mp_image_set_params(&p->layout, &mapper->dst_params);
+
+#if HAVE_GL
+ if (is_gl) {
+ GL *gl = ra_gl_get(mapper->ra);
+ gl->GenTextures(4, p->gl_textures);
+ for (int n = 0; n < desc.num_planes; n++) {
+ gl->BindTexture(GL_TEXTURE_2D, p->gl_textures[n]);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ gl->BindTexture(GL_TEXTURE_2D, 0);
+
+ struct ra_tex_params params = {
+ .dimensions = 2,
+ .w = mp_image_plane_w(&p->layout, n),
+ .h = mp_image_plane_h(&p->layout, n),
+ .d = 1,
+ .format = desc.planes[n],
+ .render_src = true,
+ .src_linear = true,
+ };
+
+ if (params.format->ctype != RA_CTYPE_UNORM)
+ return -1;
+
+ p->tex[n] = ra_create_wrapped_tex(mapper->ra, &params,
+ p->gl_textures[n]);
+ if (!p->tex[n])
+ return -1;
+ }
}
+#endif
if (!p_owner->probing_formats && !check_fmt(mapper, mapper->dst_params.imgfmt))
{
@@ -340,9 +399,13 @@ static int mapper_map(struct ra_hwdec_mapper *mapper)
{
struct priv_owner *p_owner = mapper->owner->priv;
struct priv *p = mapper->priv;
- GL *gl = ra_gl_get(mapper->ra);
+#if HAVE_GL
+ bool is_gl = ra_is_gl(mapper->ra);
+#endif
+#if HAVE_VULKAN
+ const struct pl_gpu *gpu = ra_pl_get(mapper->ra);
+#endif
VAStatus status;
- VAImage *va_image = &p->current_image;
VADisplay *display = p_owner->display;
#if VA_CHECK_VERSION(1, 1, 0)
@@ -354,49 +417,110 @@ static int mapper_map(struct ra_hwdec_mapper *mapper)
VA_EXPORT_SURFACE_READ_ONLY |
VA_EXPORT_SURFACE_SEPARATE_LAYERS,
&p->desc);
- if (!CHECK_VA_STATUS(mapper, "vaAcquireSurfaceHandle()")) {
+ if (!CHECK_VA_STATUS(mapper, "vaExportSurfaceHandle()")) {
if (status == VA_STATUS_ERROR_UNIMPLEMENTED)
p->esh_not_implemented = true;
goto esh_failed;
}
p->surface_acquired = true;
- for (int n = 0; n < p->num_planes; n++) {
- int attribs[20] = {EGL_NONE};
- int num_attribs = 0;
-
- ADD_ATTRIB(EGL_LINUX_DRM_FOURCC_EXT, p->desc.layers[n].drm_format);
- ADD_ATTRIB(EGL_WIDTH, p->tex[n]->params.w);
- ADD_ATTRIB(EGL_HEIGHT, p->tex[n]->params.h);
-
-#define ADD_PLANE_ATTRIBS(plane) do { \
- ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _FD_EXT, \
- p->desc.objects[p->desc.layers[n].object_index[plane]].fd); \
- ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _OFFSET_EXT, \
- p->desc.layers[n].offset[plane]); \
- ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _PITCH_EXT, \
- p->desc.layers[n].pitch[plane]); \
- } while (0)
-
- ADD_PLANE_ATTRIBS(0);
- if (p->desc.layers[n].num_planes > 1)
- ADD_PLANE_ATTRIBS(1);
- if (p->desc.layers[n].num_planes > 2)
- ADD_PLANE_ATTRIBS(2);
- if (p->desc.layers[n].num_planes > 3)
- ADD_PLANE_ATTRIBS(3);
-
- p->images[n] = p->CreateImageKHR(eglGetCurrentDisplay(),
- EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
- if (!p->images[n])
+#if HAVE_GL
+ if (is_gl) {
+ GL *gl = ra_gl_get(mapper->ra);
+ for (int n = 0; n < p->num_planes; n++) {
+ int attribs[20] = {EGL_NONE};
+ int num_attribs = 0;
+
+ ADD_ATTRIB(EGL_LINUX_DRM_FOURCC_EXT, p->desc.layers[n].drm_format);
+ ADD_ATTRIB(EGL_WIDTH, p->tex[n]->params.w);
+ ADD_ATTRIB(EGL_HEIGHT, p->tex[n]->params.h);
+
+ #define ADD_PLANE_ATTRIBS(plane) do { \
+ ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _FD_EXT, \
+ p->desc.objects[p->desc.layers[n].object_index[plane]].fd); \
+ ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _OFFSET_EXT, \
+ p->desc.layers[n].offset[plane]); \
+ ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _PITCH_EXT, \
+ p->desc.layers[n].pitch[plane]); \
+ } while (0)
+
+ ADD_PLANE_ATTRIBS(0);
+ if (p->desc.layers[n].num_planes > 1)
+ ADD_PLANE_ATTRIBS(1);
+ if (p->desc.layers[n].num_planes > 2)
+ ADD_PLANE_ATTRIBS(2);
+ if (p->desc.layers[n].num_planes > 3)
+ ADD_PLANE_ATTRIBS(3);
+
+ p->images[n] = p->CreateImageKHR(eglGetCurrentDisplay(),
+ EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
+ if (!p->images[n])
+ goto esh_failed;
+
+ gl->BindTexture(GL_TEXTURE_2D, p->gl_textures[n]);
+ p->EGLImageTargetTexture2DOES(GL_TEXTURE_2D, p->images[n]);
+
+ mapper->tex[n] = p->tex[n];
+ }
+ gl->BindTexture(GL_TEXTURE_2D, 0);
+ }
+#endif
+#if HAVE_VULKAN
+ if (gpu) {
+ struct ra_imgfmt_desc desc = {0};
+ if (!ra_get_imgfmt_desc(mapper->ra, mapper->dst_params.imgfmt, &desc))
goto esh_failed;
- gl->BindTexture(GL_TEXTURE_2D, p->gl_textures[n]);
- p->EGLImageTargetTexture2DOES(GL_TEXTURE_2D, p->images[n]);
-
- mapper->tex[n] = p->tex[n];
+ for (int n = 0; n < p->desc.num_layers; n++) {
+ if (p->desc.layers[n].num_planes > 1) {
+ // Should never happen because we request separate layers
+ MP_ERR(mapper, "Multi-plane VA surfaces are not supported\n");
+ goto esh_failed;
+ }
+
+ const struct ra_format *format = desc.planes[n];
+ int id = p->desc.layers[n].object_index[0];
+ int fd = p->desc.objects[id].fd;
+ uint32_t size = p->desc.objects[id].size;
+ uint32_t offset = p->desc.layers[n].offset[0];
+
+ struct pl_tex_params tex_params = {
+ .w = mp_image_plane_w(&p->layout, n),
+ .h = mp_image_plane_h(&p->layout, n),
+ .d = 0,
+ .format = format->priv,
+ .sampleable = true,
+ .sample_mode = format->linear_filter ? PL_TEX_SAMPLE_LINEAR
+ : PL_TEX_SAMPLE_NEAREST,
+ .import_handle = PL_HANDLE_DMA_BUF,
+ .shared_mem = (struct pl_shared_mem) {
+ .handle = {
+ .fd = fd,
+ },
+ .size = size,
+ .offset = offset,
+ },
+ };
+
+ const struct pl_tex *pltex = pl_tex_create(gpu, &tex_params);
+ if (!pltex) {
+ goto esh_failed;
+ }
+
+ struct ra_tex *ratex = talloc_ptrtype(NULL, ratex);
+ int ret = mppl_wrap_tex(mapper->ra, pltex, ratex);
+ if (!ret) {
+ pl_tex_destroy(gpu, &pltex);
+ talloc_free(ratex);
+ goto esh_failed;
+ }
+ mapper->tex[n] = ratex;
+
+ MP_TRACE(mapper, "Object %d with fd %d imported as %p\n",
+ id, fd, ratex);
+ }
}
- gl->BindTexture(GL_TEXTURE_2D, 0);
+#endif
if (p->desc.fourcc == VA_FOURCC_YV12)
MPSWAP(struct ra_tex*, mapper->tex[1], mapper->tex[2]);
@@ -409,67 +533,80 @@ esh_failed:
close(p->desc.objects[n].fd);
p->surface_acquired = false;
}
-#endif
-
- status = vaDeriveImage(display, va_surface_id(mapper->src), va_image);
- if (!CHECK_VA_STATUS(mapper, "vaDeriveImage()"))
- goto err;
-
- VABufferInfo buffer_info = {.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME};
- status = vaAcquireBufferHandle(display, va_image->buf, &buffer_info);
- if (!CHECK_VA_STATUS(mapper, "vaAcquireBufferHandle()"))
- goto err;
- p->buffer_acquired = true;
-
- int drm_fmts[8] = {
- // 1 bytes per component, 1-4 components
- MKTAG('R', '8', ' ', ' '), // DRM_FORMAT_R8
- MKTAG('G', 'R', '8', '8'), // DRM_FORMAT_GR88
- 0, // untested (DRM_FORMAT_RGB888?)
- 0, // untested (DRM_FORMAT_RGBA8888?)
- // 2 bytes per component, 1-4 components
- MKTAG('R', '1', '6', ' '), // proposed DRM_FORMAT_R16
- MKTAG('G', 'R', '3', '2'), // proposed DRM_FORMAT_GR32
- 0, // N/A
- 0, // N/A
- };
-
- for (int n = 0; n < p->num_planes; n++) {
- int attribs[20] = {EGL_NONE};
- int num_attribs = 0;
-
- const struct ra_format *fmt = p->tex[n]->params.format;
- int n_comp = fmt->num_components;
- int comp_s = fmt->component_size[n] / 8;
- if (n_comp < 1 || n_comp > 3 || comp_s < 1 || comp_s > 2)
- goto err;
- int drm_fmt = drm_fmts[n_comp - 1 + (comp_s - 1) * 4];
- if (!drm_fmt)
+#endif // VA_CHECK_VERSION
+
+#if HAVE_GL
+ if (is_gl) {
+ GL *gl = ra_gl_get(mapper->ra);
+ VAImage *va_image = &p->current_image;
+ status = vaDeriveImage(display, va_surface_id(mapper->src), va_image);
+ if (!CHECK_VA_STATUS(mapper, "vaDeriveImage()"))
goto err;
- ADD_ATTRIB(EGL_LINUX_DRM_FOURCC_EXT, drm_fmt);
- ADD_ATTRIB(EGL_WIDTH, p->tex[n]->params.w);
- ADD_ATTRIB(EGL_HEIGHT, p->tex[n]->params.h);
- ADD_ATTRIB(EGL_DMA_BUF_PLANE0_FD_EXT, buffer_info.handle);
- ADD_ATTRIB(EGL_DMA_BUF_PLANE0_OFFSET_EXT, va_image->offsets[n]);
- ADD_ATTRIB(EGL_DMA_BUF_PLANE0_PITCH_EXT, va_image->pitches[n]);
-
- p->images[n] = p->CreateImageKHR(eglGetCurrentDisplay(),
- EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
- if (!p->images[n])
+ VABufferInfo buffer_info = {.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME};
+ status = vaAcquireBufferHandle(display, va_image->buf, &buffer_info);
+ if (!CHECK_VA_STATUS(mapper, "vaAcquireBufferHandle()"))
goto err;
+ p->buffer_acquired = true;
+
+ int drm_fmts[8] = {
+ // 1 bytes per component, 1-4 components
+ MKTAG('R', '8', ' ', ' '), // DRM_FORMAT_R8
+ MKTAG('G', 'R', '8', '8'), // DRM_FORMAT_GR88
+ 0, // untested (DRM_FORMAT_RGB888?)
+ 0, // untested (DRM_FORMAT_RGBA8888?)
+ // 2 bytes per component, 1-4 components
+ MKTAG('R', '1', '6', ' '), // proposed DRM_FORMAT_R16
+ MKTAG('G', 'R', '3', '2'), // proposed DRM_FORMAT_GR32
+ 0, // N/A
+ 0, // N/A
+ };
- gl->BindTexture(GL_TEXTURE_2D, p->gl_textures[n]);
- p->EGLImageTargetTexture2DOES(GL_TEXTURE_2D, p->images[n]);
-
- mapper->tex[n] = p->tex[n];
- }
- gl->BindTexture(GL_TEXTURE_2D, 0);
+ for (int n = 0; n < p->num_planes; n++) {
+ int attribs[20] = {EGL_NONE};
+ int num_attribs = 0;
+
+ const struct ra_format *fmt = p->tex[n]->params.format;
+ int n_comp = fmt->num_components;
+ int comp_s = fmt->component_size[n] / 8;
+ if (n_comp < 1 || n_comp > 3 || comp_s < 1 || comp_s > 2)
+ goto err;
+ int drm_fmt = drm_fmts[n_comp - 1 + (comp_s - 1) * 4];
+ if (!drm_fmt)
+ goto err;
+
+ ADD_ATTRIB(EGL_LINUX_DRM_FOURCC_EXT, drm_fmt);
+ ADD_ATTRIB(EGL_WIDTH, p->tex[n]->params.w);
+ ADD_ATTRIB(EGL_HEIGHT, p->tex[n]->params.h);
+ ADD_ATTRIB(EGL_DMA_BUF_PLANE0_FD_EXT, buffer_info.handle);
+ ADD_ATTRIB(EGL_DMA_BUF_PLANE0_OFFSET_EXT, va_image->offsets[n]);
+ ADD_ATTRIB(EGL_DMA_BUF_PLANE0_PITCH_EXT, va_image->pitches[n]);
+
+ p->images[n] = p->CreateImageKHR(eglGetCurrentDisplay(),
+ EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
+ if (!p->images[n])
+ goto err;
+
+ gl->BindTexture(GL_TEXTURE_2D, p->gl_textures[n]);
+ p->EGLImageTargetTexture2DOES(GL_TEXTURE_2D, p->images[n]);
+
+ mapper->tex[n] = p->tex[n];
+ }
+ gl->BindTexture(GL_TEXTURE_2D, 0);
- if (va_image->format.fourcc == VA_FOURCC_YV12)
- MPSWAP(struct ra_tex*, mapper->tex[1], mapper->tex[2]);
+ if (va_image->format.fourcc == VA_FOURCC_YV12)
+ MPSWAP(struct ra_tex*, mapper->tex[1], mapper->tex[2]);
- return 0;
+ return 0;
+ }
+#endif
+#if HAVE_VULKAN
+ // Seems unnecessary to support Vulkan interop with old libva API.
+ if (gpu) {
+ mapper_unmap(mapper);
+ goto err;
+ }
+#endif
err:
if (!p_owner->probing_formats)
diff --git a/video/out/vulkan/context_wayland.c b/video/out/vulkan/context_wayland.c
index f1091a534f..160e8f9da4 100644
--- a/video/out/vulkan/context_wayland.c
+++ b/video/out/vulkan/context_wayland.c
@@ -69,6 +69,8 @@ static bool wayland_vk_init(struct ra_ctx *ctx)
if (!ra_vk_ctx_init(ctx, vk, VK_PRESENT_MODE_MAILBOX_KHR))
goto error;
+ ra_add_native_resource(ctx->ra, "wl", ctx->vo->wl->display);
+
return true;
error:
diff --git a/video/out/vulkan/context_xlib.c b/video/out/vulkan/context_xlib.c
index 9baa7c4dc4..e2fc732e00 100644
--- a/video/out/vulkan/context_xlib.c
+++ b/video/out/vulkan/context_xlib.c
@@ -66,6 +66,8 @@ static bool xlib_init(struct ra_ctx *ctx)
if (!ra_vk_ctx_init(ctx, vk, VK_PRESENT_MODE_FIFO_KHR))
goto error;
+ ra_add_native_resource(ctx->ra, "x11", ctx->vo->x11->display);
+
return true;
error:
diff --git a/wscript b/wscript
index 733faa86c9..121f3613af 100644
--- a/wscript
+++ b/wscript
@@ -827,6 +827,11 @@ video_output_features = [
'deps': 'libplacebo',
'func': check_pkg_config('vulkan'),
}, {
+ 'name': 'vaapi-vulkan',
+ 'desc': 'VAAPI Vulkan',
+ 'deps': 'vaapi && vulkan',
+ 'func': check_true,
+ }, {
'name': 'egl-helpers',
'desc': 'EGL helper functions',
'deps': 'egl-x11 || mali-fbdev || rpi || gl-wayland || egl-drm || ' +
diff --git a/wscript_build.py b/wscript_build.py
index 9438b8c3ed..4c0a12283e 100644
--- a/wscript_build.py
+++ b/wscript_build.py
@@ -449,7 +449,7 @@ def build(ctx):
( "video/out/hwdec/hwdec_cuda.c", "cuda-hwaccel" ),
( "video/out/hwdec/hwdec_cuda_gl.c", "cuda-hwaccel && gl" ),
( "video/out/hwdec/hwdec_cuda_vk.c", "cuda-hwaccel && vulkan" ),
- ( "video/out/hwdec/hwdec_vaapi.c", "vaapi-egl" ),
+ ( "video/out/hwdec/hwdec_vaapi.c", "vaapi-egl || vaapi-vulkan" ),
( "video/out/placebo/ra_pl.c", "libplacebo" ),
( "video/out/placebo/utils.c", "libplacebo" ),
( "video/out/opengl/angle_dynamic.c", "egl-angle" ),