summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorMark Thompson <sw@jkqxz.net>2017-10-07 17:49:56 +0100
committerwm4 <wm4@nowhere>2017-10-09 21:35:49 +0200
commit05cb8d28afd8881667c3dea297b182a2ecdd91c8 (patch)
treeaa6adbdf905f833805890e934be5db3530df09a7 /video
parent2ecf240b1cd20875991a5b18efafbe799864ff7f (diff)
downloadmpv-05cb8d28afd8881667c3dea297b182a2ecdd91c8.tar.bz2
mpv-05cb8d28afd8881667c3dea297b182a2ecdd91c8.tar.xz
vo_opengl: hwdec_vaegl: Use vaExportSurfaceHandle() if present
This new interface in libva2 offers a cleaner way to export surfaces which can then be imported to EGL. In particular, this works with the Mesa driver, so we can have proper playback without a pointless download and upload on AMD cards. This change does nothing with libva1, and will fall back to the libva1 interface (vaDeriveImage() + vaAcquireBufferHandle()) if vaExportSurfaceHandle() is not present.
Diffstat (limited to 'video')
-rw-r--r--video/out/opengl/hwdec_vaegl.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/video/out/opengl/hwdec_vaegl.c b/video/out/opengl/hwdec_vaegl.c
index 6078222bd5..5d690d6131 100644
--- a/video/out/opengl/hwdec_vaegl.c
+++ b/video/out/opengl/hwdec_vaegl.c
@@ -18,6 +18,7 @@
#include <stddef.h>
#include <string.h>
#include <assert.h>
+#include <unistd.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -127,6 +128,11 @@ struct priv {
EGLImageKHR images[4];
VAImage current_image;
bool buffer_acquired;
+#if VA_CHECK_VERSION(1, 0, 0)
+ bool esh_not_implemented;
+ VADRMPRIMESurfaceDescriptor desc;
+ bool surface_acquired;
+#endif
EGLImageKHR (EGLAPIENTRY *CreateImageKHR)(EGLDisplay, EGLContext,
EGLenum, EGLClientBuffer,
@@ -209,6 +215,14 @@ static void mapper_unmap(struct ra_hwdec_mapper *mapper)
p->images[n] = 0;
}
+#if VA_CHECK_VERSION(1, 0, 0)
+ if (p->surface_acquired) {
+ for (int n = 0; n < p->desc.num_objects; n++)
+ close(p->desc.objects[n].fd);
+ p->surface_acquired = false;
+ }
+#endif
+
if (p->buffer_acquired) {
status = vaReleaseBufferHandle(display, p->current_image.buf);
CHECK_VA_STATUS(mapper, "vaReleaseBufferHandle()");
@@ -330,6 +344,72 @@ static int mapper_map(struct ra_hwdec_mapper *mapper)
VAImage *va_image = &p->current_image;
VADisplay *display = p_owner->display;
+#if VA_CHECK_VERSION(1, 0, 0)
+ if (p->esh_not_implemented)
+ goto esh_failed;
+
+ 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);
+ if (!CHECK_VA_STATUS(mapper, "vaAcquireSurfaceHandle()")) {
+ 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])
+ 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);
+
+ if (p->desc.fourcc == VA_FOURCC_YV12)
+ MPSWAP(struct ra_tex*, mapper->tex[1], mapper->tex[2]);
+
+ return 0;
+
+esh_failed:
+ if (p->surface_acquired) {
+ for (int n = 0; n < p->desc.num_objects; n++)
+ 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;