mirror of
https://github.com/mpv-player/mpv
synced 2024-12-24 15:52:25 +00:00
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.
This commit is contained in:
parent
2ecf240b1c
commit
05cb8d28af
@ -18,6 +18,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
@ -127,6 +128,11 @@ struct priv {
|
|||||||
EGLImageKHR images[4];
|
EGLImageKHR images[4];
|
||||||
VAImage current_image;
|
VAImage current_image;
|
||||||
bool buffer_acquired;
|
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,
|
EGLImageKHR (EGLAPIENTRY *CreateImageKHR)(EGLDisplay, EGLContext,
|
||||||
EGLenum, EGLClientBuffer,
|
EGLenum, EGLClientBuffer,
|
||||||
@ -209,6 +215,14 @@ static void mapper_unmap(struct ra_hwdec_mapper *mapper)
|
|||||||
p->images[n] = 0;
|
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) {
|
if (p->buffer_acquired) {
|
||||||
status = vaReleaseBufferHandle(display, p->current_image.buf);
|
status = vaReleaseBufferHandle(display, p->current_image.buf);
|
||||||
CHECK_VA_STATUS(mapper, "vaReleaseBufferHandle()");
|
CHECK_VA_STATUS(mapper, "vaReleaseBufferHandle()");
|
||||||
@ -330,6 +344,72 @@ static int mapper_map(struct ra_hwdec_mapper *mapper)
|
|||||||
VAImage *va_image = &p->current_image;
|
VAImage *va_image = &p->current_image;
|
||||||
VADisplay *display = p_owner->display;
|
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);
|
status = vaDeriveImage(display, va_surface_id(mapper->src), va_image);
|
||||||
if (!CHECK_VA_STATUS(mapper, "vaDeriveImage()"))
|
if (!CHECK_VA_STATUS(mapper, "vaDeriveImage()"))
|
||||||
goto err;
|
goto err;
|
||||||
|
Loading…
Reference in New Issue
Block a user