vlc | branch: master | Steve Lhomme <[email protected]> | Mon Mar 16 12:02:22 2020 +0100| [886587dc8591ee3bada2bdef660cd0461d7249e7] | committer: Steve Lhomme
direct3d9: move the DXVA2 OpenGL Interop module in its own file It shares nothing with the D3D9 module and will never be loaded at the same time. No functional changes. > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=886587dc8591ee3bada2bdef660cd0461d7249e7 --- modules/video_output/Makefile.am | 9 + modules/video_output/opengl/interop_dxva2.c | 275 ++++++++++++++++++++++++++++ modules/video_output/win32/direct3d9.c | 225 ----------------------- 3 files changed, 284 insertions(+), 225 deletions(-) diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am index 566e7b5fd8..cb53932315 100644 --- a/modules/video_output/Makefile.am +++ b/modules/video_output/Makefile.am @@ -172,9 +172,18 @@ libdirect3d9_plugin_la_SOURCES = video_output/win32/direct3d9.c \ video_output/win32/win32touch.c video_output/win32/win32touch.h libdirect3d9_plugin_la_LIBADD = libchroma_copy.la libd3d9_common.la -lgdi32 $(LIBCOM) -luuid libdirect3d9_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)' + +libglinterop_dxva2_plugin_la_SOURCES = video_output/opengl/interop_dxva2.c \ + video_output/opengl/interop.h +libglinterop_dxva2_plugin_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAGS) +libglinterop_dxva2_plugin_la_LIBADD = libd3d9_common.la + if HAVE_WIN32_DESKTOP vout_LTLIBRARIES += $(LTLIBdirect3d9) EXTRA_LTLIBRARIES += libdirect3d9_plugin.la +if HAVE_GL +vout_LTLIBRARIES += libglinterop_dxva2_plugin.la +endif endif libdirect3d11_plugin_la_SOURCES = video_output/win32/direct3d11.c \ diff --git a/modules/video_output/opengl/interop_dxva2.c b/modules/video_output/opengl/interop_dxva2.c new file mode 100644 index 0000000000..a25ba942e6 --- /dev/null +++ b/modules/video_output/opengl/interop_dxva2.c @@ -0,0 +1,275 @@ +/***************************************************************************** + * direct3d9.c: Windows Direct3D9 video output module + ***************************************************************************** + * Copyright (C) 2006-2014 VLC authors and VideoLAN + * + * Authors: Martell Malone <[email protected]>, + * Damien Fouilleul <[email protected]>, + * Sasha Koruga <[email protected]>, + * Felix Abecassis <[email protected]> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble: + * + * This plugin will use YUV surface if supported, using YUV will result in + * the best video quality (hardware filtering when rescaling the picture) + * and the fastest display as it requires less processing. + * + * If YUV overlay is not supported this plugin will use RGB offscreen video + * surfaces that will be blitted onto the primary surface (display) to + * effectively display the pictures. + * + *****************************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <vlc_common.h> +#include <vlc_plugin.h> +#include <vlc_vout_display.h> + +#include <windows.h> +#include <d3d9.h> +#include "../../video_chroma/d3d9_fmt.h" +#include <dxvahd.h> + +#include "../opengl/interop.h" +#include "../opengl/renderer.h" +#include <GL/glew.h> +#include <GL/wglew.h> + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ +static int GLConvOpen(vlc_object_t *); +static void GLConvClose(vlc_object_t *); + +vlc_module_begin () + set_shortname("dxva2") + set_category(CAT_VIDEO) + set_subcategory(SUBCAT_VIDEO_VOUT) + set_description("DXVA2 surface converter") + set_capability("glinterop", 1) + set_callbacks(GLConvOpen, GLConvClose) +vlc_module_end () + +struct wgl_vt { + PFNWGLDXSETRESOURCESHAREHANDLENVPROC DXSetResourceShareHandleNV; + PFNWGLDXOPENDEVICENVPROC DXOpenDeviceNV; + PFNWGLDXCLOSEDEVICENVPROC DXCloseDeviceNV; + PFNWGLDXREGISTEROBJECTNVPROC DXRegisterObjectNV; + PFNWGLDXUNREGISTEROBJECTNVPROC DXUnregisterObjectNV; + PFNWGLDXLOCKOBJECTSNVPROC DXLockObjectsNV; + PFNWGLDXUNLOCKOBJECTSNVPROC DXUnlockObjectsNV; +}; +struct glpriv +{ + struct wgl_vt vt; + HANDLE gl_handle_d3d; + HANDLE gl_render; + IDirect3DSurface9 *dx_render; +}; + +static int +GLConvUpdate(const struct vlc_gl_interop *interop, GLuint *textures, + const GLsizei *tex_width, const GLsizei *tex_height, + picture_t *pic, const size_t *plane_offset) +{ + VLC_UNUSED(textures); VLC_UNUSED(tex_width); VLC_UNUSED(tex_height); VLC_UNUSED(plane_offset); + struct glpriv *priv = interop->priv; + HRESULT hr; + + picture_sys_d3d9_t *picsys = ActiveD3D9PictureSys(pic); + if (unlikely(!picsys || !priv->gl_render)) + return VLC_EGENERIC; + + if (!priv->vt.DXUnlockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render)) + { + msg_Warn(interop->gl, "DXUnlockObjectsNV failed"); + return VLC_EGENERIC; + } + + d3d9_decoder_device_t *d3d9_decoder = GetD3D9OpaqueContext(interop->vctx); + + const RECT rect = { + .left = 0, + .top = 0, + .right = pic->format.i_visible_width, + .bottom = pic->format.i_visible_height + }; + hr = IDirect3DDevice9Ex_StretchRect(d3d9_decoder->d3ddev.devex, picsys->surface, + &rect, priv->dx_render, NULL, D3DTEXF_NONE); + if (FAILED(hr)) + { + msg_Warn(interop->gl, "IDirect3DDevice9Ex_StretchRect failed. (0x%lX)", hr); + return VLC_EGENERIC; + } + + if (!priv->vt.DXLockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render)) + { + msg_Warn(interop->gl, "DXLockObjectsNV failed"); + priv->vt.DXUnregisterObjectNV(priv->gl_handle_d3d, priv->gl_render); + priv->gl_render = NULL; + return VLC_EGENERIC; + } + + return VLC_SUCCESS; +} + +static int +GLConvAllocateTextures(const struct vlc_gl_interop *interop, GLuint *textures, + const GLsizei *tex_width, const GLsizei *tex_height) +{ + VLC_UNUSED(tex_width); VLC_UNUSED(tex_height); + struct glpriv *priv = interop->priv; + + priv->gl_render = + priv->vt.DXRegisterObjectNV(priv->gl_handle_d3d, priv->dx_render, + textures[0], GL_TEXTURE_2D, WGL_ACCESS_WRITE_DISCARD_NV); + if (!priv->gl_render) + { + msg_Warn(interop->gl, "DXRegisterObjectNV failed: %lu", GetLastError()); + return VLC_EGENERIC; + } + + if (!priv->vt.DXLockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render)) + { + msg_Warn(interop->gl, "DXLockObjectsNV failed"); + priv->vt.DXUnregisterObjectNV(priv->gl_handle_d3d, priv->gl_render); + priv->gl_render = NULL; + return VLC_EGENERIC; + } + + return VLC_SUCCESS; +} + +static void +GLConvClose(vlc_object_t *obj) +{ + struct vlc_gl_interop *interop = (void *)obj; + struct glpriv *priv = interop->priv; + + if (priv->gl_handle_d3d) + { + if (priv->gl_render) + { + priv->vt.DXUnlockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render); + priv->vt.DXUnregisterObjectNV(priv->gl_handle_d3d, priv->gl_render); + } + + priv->vt.DXCloseDeviceNV(priv->gl_handle_d3d); + } + + if (priv->dx_render) + IDirect3DSurface9_Release(priv->dx_render); + + free(priv); +} + +static int +GLConvOpen(vlc_object_t *obj) +{ + struct vlc_gl_interop *interop = (void *) obj; + + if (interop->fmt.i_chroma != VLC_CODEC_D3D9_OPAQUE + && interop->fmt.i_chroma != VLC_CODEC_D3D9_OPAQUE_10B) + return VLC_EGENERIC; + + d3d9_video_context_t *vctx_sys = GetD3D9ContextPrivate( interop->vctx ); + d3d9_decoder_device_t *d3d9_decoder = GetD3D9OpaqueContext(interop->vctx); + if ( vctx_sys == NULL || d3d9_decoder == NULL ) + return VLC_EGENERIC; + + if (interop->gl->ext != VLC_GL_EXT_WGL || !interop->gl->wgl.getExtensionsString) + return VLC_EGENERIC; + + const char *wglExt = interop->gl->wgl.getExtensionsString(interop->gl); + + if (wglExt == NULL || !vlc_gl_StrHasToken(wglExt, "WGL_NV_DX_interop")) + return VLC_EGENERIC; + + struct wgl_vt vt; +#define LOAD_EXT(name, type) do { \ + vt.name = (type) vlc_gl_GetProcAddress(interop->gl, "wgl" #name); \ + if (!vt.name) { \ + msg_Warn(obj, "'wgl " #name "' could not be loaded"); \ + return VLC_EGENERIC; \ + } \ +} while(0) + + LOAD_EXT(DXSetResourceShareHandleNV, PFNWGLDXSETRESOURCESHAREHANDLENVPROC); + LOAD_EXT(DXOpenDeviceNV, PFNWGLDXOPENDEVICENVPROC); + LOAD_EXT(DXCloseDeviceNV, PFNWGLDXCLOSEDEVICENVPROC); + LOAD_EXT(DXRegisterObjectNV, PFNWGLDXREGISTEROBJECTNVPROC); + LOAD_EXT(DXUnregisterObjectNV, PFNWGLDXUNREGISTEROBJECTNVPROC); + LOAD_EXT(DXLockObjectsNV, PFNWGLDXLOCKOBJECTSNVPROC); + LOAD_EXT(DXUnlockObjectsNV, PFNWGLDXUNLOCKOBJECTSNVPROC); + + struct glpriv *priv = calloc(1, sizeof(struct glpriv)); + if (!priv) + return VLC_ENOMEM; + interop->priv = priv; + priv->vt = vt; + + if (!d3d9_decoder->hd3d.use_ex) + { + msg_Warn(obj, "DX/GL interrop only working on d3d9x"); + goto error; + } + + HRESULT hr; + HANDLE shared_handle = NULL; + hr = IDirect3DDevice9Ex_CreateRenderTarget(d3d9_decoder->d3ddev.devex, + interop->fmt.i_visible_width, + interop->fmt.i_visible_height, + D3DFMT_X8R8G8B8, + D3DMULTISAMPLE_NONE, 0, FALSE, + &priv->dx_render, &shared_handle); + if (FAILED(hr)) + { + msg_Warn(obj, "IDirect3DDevice9Ex_CreateRenderTarget failed"); + goto error; + } + + if (shared_handle) + priv->vt.DXSetResourceShareHandleNV(priv->dx_render, shared_handle); + + priv->gl_handle_d3d = priv->vt.DXOpenDeviceNV(d3d9_decoder->d3ddev.dev); + if (!priv->gl_handle_d3d) + { + msg_Warn(obj, "DXOpenDeviceNV failed: %lu", GetLastError()); + goto error; + } + + static const struct vlc_gl_interop_ops ops = { + .allocate_textures = GLConvAllocateTextures, + .update_textures = GLConvUpdate, + }; + interop->ops = &ops; + + int ret = opengl_interop_init(interop, GL_TEXTURE_2D, VLC_CODEC_RGB32, + COLOR_SPACE_UNDEF); + if (ret != VLC_SUCCESS) + goto error; + + return VLC_SUCCESS; + +error: + GLConvClose(obj); + return VLC_EGENERIC; +} diff --git a/modules/video_output/win32/direct3d9.c b/modules/video_output/win32/direct3d9.c index 06f1ab22bb..b72033b170 100644 --- a/modules/video_output/win32/direct3d9.c +++ b/modules/video_output/win32/direct3d9.c @@ -61,9 +61,6 @@ #include "common.h" #include "builtin_shaders.h" #include "../../video_chroma/copy.h" -#ifdef HAVE_GL -#include "../opengl/interop.h" -#endif #include <assert.h> @@ -74,9 +71,6 @@ static int Open(vout_display_t *, const vout_display_cfg_t *, video_format_t *, vlc_video_context *); static void Close(vout_display_t *); -static int GLConvOpen(vlc_object_t *); -static void GLConvClose(vlc_object_t *); - #define DESKTOP_LONGTEXT N_(\ "The desktop mode allows you to display the video on the desktop.") @@ -114,13 +108,6 @@ vlc_module_begin () add_shortcut("direct3d9", "direct3d") set_callback_display(Open, 280) - -#ifdef HAVE_GL - add_submodule() - set_description("DX OpenGL surface converter for D3D9") - set_capability("glinterop", 1) - set_callbacks(GLConvOpen, GLConvClose) -#endif vlc_module_end () /***************************************************************************** @@ -1920,215 +1907,3 @@ static void Close(vout_display_t *vd) free(vd->sys); } - -#if defined(HAVE_GL) && defined(HAVE_GL_WGLEW_H) -#include "../opengl/renderer.h" -#include <GL/glew.h> -#include <GL/wglew.h> - -struct wgl_vt { - PFNWGLDXSETRESOURCESHAREHANDLENVPROC DXSetResourceShareHandleNV; - PFNWGLDXOPENDEVICENVPROC DXOpenDeviceNV; - PFNWGLDXCLOSEDEVICENVPROC DXCloseDeviceNV; - PFNWGLDXREGISTEROBJECTNVPROC DXRegisterObjectNV; - PFNWGLDXUNREGISTEROBJECTNVPROC DXUnregisterObjectNV; - PFNWGLDXLOCKOBJECTSNVPROC DXLockObjectsNV; - PFNWGLDXUNLOCKOBJECTSNVPROC DXUnlockObjectsNV; -}; -struct glpriv -{ - struct wgl_vt vt; - HANDLE gl_handle_d3d; - HANDLE gl_render; - IDirect3DSurface9 *dx_render; -}; - -static int -GLConvUpdate(const struct vlc_gl_interop *interop, GLuint *textures, - const GLsizei *tex_width, const GLsizei *tex_height, - picture_t *pic, const size_t *plane_offset) -{ - VLC_UNUSED(textures); VLC_UNUSED(tex_width); VLC_UNUSED(tex_height); VLC_UNUSED(plane_offset); - struct glpriv *priv = interop->priv; - HRESULT hr; - - picture_sys_d3d9_t *picsys = ActiveD3D9PictureSys(pic); - if (unlikely(!picsys || !priv->gl_render)) - return VLC_EGENERIC; - - if (!priv->vt.DXUnlockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render)) - { - msg_Warn(interop->gl, "DXUnlockObjectsNV failed"); - return VLC_EGENERIC; - } - - d3d9_decoder_device_t *d3d9_decoder = GetD3D9OpaqueContext(interop->vctx); - - const RECT rect = { - .left = 0, - .top = 0, - .right = pic->format.i_visible_width, - .bottom = pic->format.i_visible_height - }; - hr = IDirect3DDevice9Ex_StretchRect(d3d9_decoder->d3ddev.devex, picsys->surface, - &rect, priv->dx_render, NULL, D3DTEXF_NONE); - if (FAILED(hr)) - { - msg_Warn(interop->gl, "IDirect3DDevice9Ex_StretchRect failed. (0x%lX)", hr); - return VLC_EGENERIC; - } - - if (!priv->vt.DXLockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render)) - { - msg_Warn(interop->gl, "DXLockObjectsNV failed"); - priv->vt.DXUnregisterObjectNV(priv->gl_handle_d3d, priv->gl_render); - priv->gl_render = NULL; - return VLC_EGENERIC; - } - - return VLC_SUCCESS; -} - -static int -GLConvAllocateTextures(const struct vlc_gl_interop *interop, GLuint *textures, - const GLsizei *tex_width, const GLsizei *tex_height) -{ - VLC_UNUSED(tex_width); VLC_UNUSED(tex_height); - struct glpriv *priv = interop->priv; - - priv->gl_render = - priv->vt.DXRegisterObjectNV(priv->gl_handle_d3d, priv->dx_render, - textures[0], GL_TEXTURE_2D, WGL_ACCESS_WRITE_DISCARD_NV); - if (!priv->gl_render) - { - msg_Warn(interop->gl, "DXRegisterObjectNV failed: %lu", GetLastError()); - return VLC_EGENERIC; - } - - if (!priv->vt.DXLockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render)) - { - msg_Warn(interop->gl, "DXLockObjectsNV failed"); - priv->vt.DXUnregisterObjectNV(priv->gl_handle_d3d, priv->gl_render); - priv->gl_render = NULL; - return VLC_EGENERIC; - } - - return VLC_SUCCESS; -} - -static void -GLConvClose(vlc_object_t *obj) -{ - struct vlc_gl_interop *interop = (void *)obj; - struct glpriv *priv = interop->priv; - - if (priv->gl_handle_d3d) - { - if (priv->gl_render) - { - priv->vt.DXUnlockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render); - priv->vt.DXUnregisterObjectNV(priv->gl_handle_d3d, priv->gl_render); - } - - priv->vt.DXCloseDeviceNV(priv->gl_handle_d3d); - } - - if (priv->dx_render) - IDirect3DSurface9_Release(priv->dx_render); - - free(priv); -} - -static int -GLConvOpen(vlc_object_t *obj) -{ - struct vlc_gl_interop *interop = (void *) obj; - - if (interop->fmt.i_chroma != VLC_CODEC_D3D9_OPAQUE - && interop->fmt.i_chroma != VLC_CODEC_D3D9_OPAQUE_10B) - return VLC_EGENERIC; - - d3d9_video_context_t *vctx_sys = GetD3D9ContextPrivate( interop->vctx ); - d3d9_decoder_device_t *d3d9_decoder = GetD3D9OpaqueContext(interop->vctx); - if ( vctx_sys == NULL || d3d9_decoder == NULL ) - return VLC_EGENERIC; - - if (interop->gl->ext != VLC_GL_EXT_WGL || !interop->gl->wgl.getExtensionsString) - return VLC_EGENERIC; - - const char *wglExt = interop->gl->wgl.getExtensionsString(interop->gl); - - if (wglExt == NULL || !vlc_gl_StrHasToken(wglExt, "WGL_NV_DX_interop")) - return VLC_EGENERIC; - - struct wgl_vt vt; -#define LOAD_EXT(name, type) do { \ - vt.name = (type) vlc_gl_GetProcAddress(interop->gl, "wgl" #name); \ - if (!vt.name) { \ - msg_Warn(obj, "'wgl " #name "' could not be loaded"); \ - return VLC_EGENERIC; \ - } \ -} while(0) - - LOAD_EXT(DXSetResourceShareHandleNV, PFNWGLDXSETRESOURCESHAREHANDLENVPROC); - LOAD_EXT(DXOpenDeviceNV, PFNWGLDXOPENDEVICENVPROC); - LOAD_EXT(DXCloseDeviceNV, PFNWGLDXCLOSEDEVICENVPROC); - LOAD_EXT(DXRegisterObjectNV, PFNWGLDXREGISTEROBJECTNVPROC); - LOAD_EXT(DXUnregisterObjectNV, PFNWGLDXUNREGISTEROBJECTNVPROC); - LOAD_EXT(DXLockObjectsNV, PFNWGLDXLOCKOBJECTSNVPROC); - LOAD_EXT(DXUnlockObjectsNV, PFNWGLDXUNLOCKOBJECTSNVPROC); - - struct glpriv *priv = calloc(1, sizeof(struct glpriv)); - if (!priv) - return VLC_ENOMEM; - interop->priv = priv; - priv->vt = vt; - - if (!d3d9_decoder->hd3d.use_ex) - { - msg_Warn(obj, "DX/GL interrop only working on d3d9x"); - goto error; - } - - HRESULT hr; - HANDLE shared_handle = NULL; - hr = IDirect3DDevice9Ex_CreateRenderTarget(d3d9_decoder->d3ddev.devex, - interop->fmt.i_visible_width, - interop->fmt.i_visible_height, - D3DFMT_X8R8G8B8, - D3DMULTISAMPLE_NONE, 0, FALSE, - &priv->dx_render, &shared_handle); - if (FAILED(hr)) - { - msg_Warn(obj, "IDirect3DDevice9Ex_CreateRenderTarget failed"); - goto error; - } - - if (shared_handle) - priv->vt.DXSetResourceShareHandleNV(priv->dx_render, shared_handle); - - priv->gl_handle_d3d = priv->vt.DXOpenDeviceNV(d3d9_decoder->d3ddev.dev); - if (!priv->gl_handle_d3d) - { - msg_Warn(obj, "DXOpenDeviceNV failed: %lu", GetLastError()); - goto error; - } - - static const struct vlc_gl_interop_ops ops = { - .allocate_textures = GLConvAllocateTextures, - .update_textures = GLConvUpdate, - }; - interop->ops = &ops; - - int ret = opengl_interop_init(interop, GL_TEXTURE_2D, VLC_CODEC_RGB32, - COLOR_SPACE_UNDEF); - if (ret != VLC_SUCCESS) - goto error; - - return VLC_SUCCESS; - -error: - GLConvClose(obj); - return VLC_EGENERIC; -} -#endif _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
