diff options
-rw-r--r-- | DOCS/client-api-changes.rst | 2 | ||||
-rw-r--r-- | libmpv/opengl_cb.h | 18 | ||||
-rw-r--r-- | video/decode/dxva2.c | 1 | ||||
-rw-r--r-- | video/out/gl_common.c | 9 | ||||
-rw-r--r-- | video/out/gl_common.h | 2 | ||||
-rw-r--r-- | video/out/gl_hwdec.c | 4 | ||||
-rw-r--r-- | video/out/gl_hwdec_dxva2.c | 64 | ||||
-rw-r--r-- | wscript_build.py | 1 |
8 files changed, 101 insertions, 0 deletions
diff --git a/DOCS/client-api-changes.rst b/DOCS/client-api-changes.rst index 54fe585b1b..8af045d633 100644 --- a/DOCS/client-api-changes.rst +++ b/DOCS/client-api-changes.rst @@ -32,6 +32,8 @@ API changes :: + ... - add "GL_MP_D3D_interfaces" pseudo extension to make it possible to + use DXVA2 in OpenGL fullscreen mode in some situations 1.19 - mpv_request_log_messages() now accepts "terminal-default" as parameter 1.18 - add MPV_END_FILE_REASON_REDIRECT, and change behavior of MPV_EVENT_END_FILE accordingly diff --git a/libmpv/opengl_cb.h b/libmpv/opengl_cb.h index fd1409a253..1902268201 100644 --- a/libmpv/opengl_cb.h +++ b/libmpv/opengl_cb.h @@ -107,6 +107,24 @@ extern "C" { * When the mpv core is destroyed (e.g. via mpv_terminate_destroy()), the OpenGL * context must have been uninitialized. If this doesn't happen, undefined * behavior will result. + * + * Special D3D interop considerations + * ---------------------------------- + * + * If OpenGL switches to fullscreen, most players give it access GPU access, + * which means DXVA2 hardware decoding in mpv won't work. This can be worked + * around by giving mpv access to Direct3D device, which it will then use to + * create a decoder. The device can be either the real device used for display, + * or a "blank" device created before switching to fullscreen. + * + * You can do this by adding "GL_MP_D3D_interfaces" to the additional extension + * string when calling mpv_opengl_cb_init_gl(). The get_proc_address callback + * should resolve a function named "glMPGetD3DInterface", which has the + * signature: "void* __stdcall glMPGetD3DInterface(const char* name)". If + * name is "IDirect3DDevice9", it should return a IDirect3DDevice9 pointer + * (or NULL if not available). libmpv will release this interface when it is + * done with it (usually when mpv_opengl_cb_uninit_gl() is called). New + * interface names can be added in the future. */ /** diff --git a/video/decode/dxva2.c b/video/decode/dxva2.c index 62b27671ef..0e99d550ba 100644 --- a/video/decode/dxva2.c +++ b/video/decode/dxva2.c @@ -675,6 +675,7 @@ static int dxva2_init_decoder(struct lavc_ctx *s, int fmt, int w, int h) static int probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, const char *decoder) { + hwdec_request_api(info, "dxva2"); // we can do without too for (int i = 0; dxva2_modes[i].guid; i++) { const dxva2_mode *mode = &dxva2_modes[i]; if (mp_codec_to_av_codec_id(decoder) == mode->codec) diff --git a/video/out/gl_common.c b/video/out/gl_common.c index 5560fe07e0..c127f16fa3 100644 --- a/video/out/gl_common.c +++ b/video/out/gl_common.c @@ -306,6 +306,15 @@ static const struct gl_functions gl_functions[] = { {0} }, }, + // These don't exist - they are for the sake of mpv internals, and libmpv + // interaction (see libmpv/opengl_cb.h). + { + .extension = "GL_MP_D3D_interfaces", + .functions = (const struct gl_function[]) { + DEF_FN(MPGetD3DInterface), + {0} + }, + }, }; #undef FN_OFFS diff --git a/video/out/gl_common.h b/video/out/gl_common.h index 0df44c75ec..39cde380a4 100644 --- a/video/out/gl_common.h +++ b/video/out/gl_common.h @@ -275,6 +275,8 @@ struct GL { void (GLAPIENTRY *DebugMessageCallback)(MP_GLDEBUGPROC callback, const void *userParam); + + void *(GLAPIENTRY *MPGetD3DInterface)(const char *name); }; #endif /* MPLAYER_GL_COMMON_H */ diff --git a/video/out/gl_hwdec.c b/video/out/gl_hwdec.c index 1d09177cf7..ba15950129 100644 --- a/video/out/gl_hwdec.c +++ b/video/out/gl_hwdec.c @@ -32,6 +32,7 @@ extern const struct gl_hwdec_driver gl_hwdec_vaglx; extern const struct gl_hwdec_driver gl_hwdec_vda; extern const struct gl_hwdec_driver gl_hwdec_vdpau; +extern const struct gl_hwdec_driver gl_hwdec_dxva2; static const struct gl_hwdec_driver *const mpgl_hwdec_drivers[] = { #if HAVE_VAAPI_GLX @@ -43,6 +44,9 @@ static const struct gl_hwdec_driver *const mpgl_hwdec_drivers[] = { #if HAVE_VDA_GL &gl_hwdec_vda, #endif +#if HAVE_DXVA2_HWACCEL + &gl_hwdec_dxva2, +#endif NULL }; diff --git a/video/out/gl_hwdec_dxva2.c b/video/out/gl_hwdec_dxva2.c new file mode 100644 index 0000000000..52a73de1b2 --- /dev/null +++ b/video/out/gl_hwdec_dxva2.c @@ -0,0 +1,64 @@ +#include "common/common.h" + +#include "gl_hwdec.h" +#include "gl_utils.h" +#include "video/d3d.h" +#include "video/hwdec.h" + +// This does not provide real (zero-copy) interop - it merely exists for +// making sure the same D3D device is used for decoding and display, which +// may help with OpenGL fullscreen mode. + +struct priv { + struct mp_d3d_ctx ctx; +}; + +static void destroy(struct gl_hwdec *hw) +{ + struct priv *p = hw->priv; + if (p->ctx.d3d9_device) + IDirect3DDevice9_Release(p->ctx.d3d9_device); +} + +static int create(struct gl_hwdec *hw) +{ + GL *gl = hw->gl; + if (hw->hwctx || !gl->MPGetD3DInterface) + return -1; + + struct priv *p = talloc_zero(hw, struct priv); + hw->priv = p; + + p->ctx.d3d9_device = gl->MPGetD3DInterface("IDirect3DDevice9"); + if (!p->ctx.d3d9_device) + return -1; + + p->ctx.hwctx.type = HWDEC_DXVA2_COPY; + p->ctx.hwctx.d3d_ctx = &p->ctx; + + MP_VERBOSE(hw, "Using libmpv supplied device %p.\n", p->ctx.d3d9_device); + + hw->hwctx = &p->ctx.hwctx; + hw->converted_imgfmt = 0; + return 0; +} + +static int reinit(struct gl_hwdec *hw, struct mp_image_params *params) +{ + return -1; +} + +static int map_image(struct gl_hwdec *hw, struct mp_image *hw_image, + GLuint *out_textures) +{ + return -1; +} + +const struct gl_hwdec_driver gl_hwdec_dxva2 = { + .api_name = "dxva2", + .imgfmt = -1, + .create = create, + .reinit = reinit, + .map_image = map_image, + .destroy = destroy, +}; diff --git a/wscript_build.py b/wscript_build.py index 6c8462340c..18b2792e90 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -334,6 +334,7 @@ def build(ctx): ( "video/out/gl_common.c", "gl" ), ( "video/out/gl_rpi.c", "rpi-gles" ), ( "video/out/gl_hwdec.c", "gl" ), + ( "video/out/gl_hwdec_dxva2.c", "gl-win32" ), ( "video/out/gl_hwdec_vaglx.c", "vaapi-glx" ), ( "video/out/gl_hwdec_vda.c", "vda-gl" ), ( "video/out/gl_hwdec_vdpau.c", "vdpau-gl-x11" ), |