[vlc-devel] [PATCH 01/12] d3d11: allow rendering video to DirectComposition surfaces
Steve Lhomme
robux4 at ycbcr.xyz
Tue May 12 07:59:46 CEST 2020
Hi,
On 2020-05-11 18:04, Pierre Lamot wrote:
> ---
> include/vlc_vout_window.h | 5 ++
> modules/video_output/Makefile.am | 3 +-
> modules/video_output/win32/d3d11_swapchain.c | 51 +++++++++++++++++---
> modules/video_output/win32/d3d11_swapchain.h | 3 +-
> modules/video_output/win32/dcomp_wrapper.cpp | 31 ++++++++++++
> modules/video_output/win32/dcomp_wrapper.h | 42 ++++++++++++++++
> modules/video_output/win32/direct3d11.c | 13 +++--
> 7 files changed, 135 insertions(+), 13 deletions(-)
> create mode 100644 modules/video_output/win32/dcomp_wrapper.cpp
> create mode 100644 modules/video_output/win32/dcomp_wrapper.h
>
> diff --git a/include/vlc_vout_window.h b/include/vlc_vout_window.h
> index ad16955ace..2699d2f744 100644
> --- a/include/vlc_vout_window.h
> +++ b/include/vlc_vout_window.h
> @@ -61,6 +61,7 @@ enum vout_window_type {
> VOUT_WINDOW_TYPE_XID /**< X11 window */,
> VOUT_WINDOW_TYPE_HWND /**< Win32 or OS/2 window */,
> VOUT_WINDOW_TYPE_NSOBJECT /**< macOS/iOS view */,
> + VOUT_WINDOW_TYPE_DCOMP /**< Win32 DirectComposition */,
> VOUT_WINDOW_TYPE_ANDROID_NATIVE /**< Android native window */,
> VOUT_WINDOW_TYPE_WAYLAND /**< Wayland surface */,
> };
> @@ -360,6 +361,10 @@ typedef struct vout_window_t {
> void *nsobject; /**< macOS/iOS view object */
> void *anativewindow; /**< Android native window */
> struct wl_surface *wl; /**< Wayland surface (client pointer) */
> + struct {
> + void *device;
> + void *visual;
> + } dcomp; /**< Win32 direct composition surface */
> } handle;
>
> /** Display server (mandatory)
> diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
> index c82e9a0ed7..3bdb6929fb 100644
> --- a/modules/video_output/Makefile.am
> +++ b/modules/video_output/Makefile.am
> @@ -155,7 +155,8 @@ libdirect3d11_plugin_la_SOURCES = video_output/win32/direct3d11.c \
> video_output/win32/d3d11_quad.c video_output/win32/d3d11_quad.h \
> video_output/win32/d3d11_shaders.c video_output/win32/d3d11_shaders.h \
> video_output/win32/d3d11_swapchain.c video_output/win32/d3d11_swapchain.h \
> - video_output/win32/common.c video_output/win32/common.h
> + video_output/win32/common.c video_output/win32/common.h \
> + video_output/win32/dcomp_wrapper.cpp video_output/win32/dcomp_wrapper.h
> libdirect3d11_plugin_la_LIBADD = libchroma_copy.la libd3d11_common.la $(LIBCOM) -luuid
> if !HAVE_WINSTORE
> libdirect3d11_plugin_la_SOURCES += video_output/win32/events.c \
> diff --git a/modules/video_output/win32/d3d11_swapchain.c b/modules/video_output/win32/d3d11_swapchain.c
> index 7114bf57ef..3bfa989982 100644
> --- a/modules/video_output/win32/d3d11_swapchain.c
> +++ b/modules/video_output/win32/d3d11_swapchain.c
> @@ -51,6 +51,7 @@
>
> #include "d3d11_swapchain.h"
> #include "d3d11_shaders.h"
> +#include "dcomp_wrapper.h"
>
> typedef enum video_color_axis {
> COLOR_AXIS_RGB,
> @@ -76,7 +77,10 @@ struct d3d11_local_swapchain
> const dxgi_color_space *colorspace;
>
> #if !VLC_WINSTORE_APP
> + bool useDcomp;
> HWND swapchainHwnd;
> + void* dcompDevice;
> + void* dcompVisual;
The HWND APIs are not allowed in UWP that's why the swapchainHwnd is in
the ifdef. But DirectComposition is allowed so these variables should
not be in the ifdef.
You could also use a union to differentiate swapchainHwnd from
dcompDevice+dcompVisual.
> #endif /* !VLC_WINSTORE_APP */
> IDXGISwapChain1 *dxgiswapChain; /* DXGI 1.2 swap chain */
> IDXGISwapChain4 *dxgiswapChain4; /* DXGI 1.5 for HDR metadata */
> @@ -278,7 +282,7 @@ static void FillSwapChainDesc(struct d3d11_local_swapchain *display, UINT width,
>
> static void CreateSwapchain(struct d3d11_local_swapchain *display, UINT width, UINT height)
> {
> - if (display->swapchainHwnd == NULL)
> + if (!display->useDcomp && display->swapchainHwnd == NULL)
It may be easier to create another version of the function for
DirectComposition. It will go outside of the #ifdef too.
> {
> msg_Err(display->obj, "missing a HWND to create the swapchain");
> return;
> @@ -301,18 +305,31 @@ static void CreateSwapchain(struct d3d11_local_swapchain *display, UINT width, U
> return;
> }
>
> - hr = IDXGIFactory2_CreateSwapChainForHwnd(dxgifactory, (IUnknown *)display->d3d_dev->d3ddevice,
> - display->swapchainHwnd, &scd,
> - NULL, NULL, &display->dxgiswapChain);
> + if (display->useDcomp)
> + hr = IDXGIFactory2_CreateSwapChainForComposition(dxgifactory, (IUnknown *)display->d3d_dev->d3ddevice,
> + &scd, NULL, &display->dxgiswapChain);
> + else
> + hr = IDXGIFactory2_CreateSwapChainForHwnd(dxgifactory, (IUnknown *)display->d3d_dev->d3ddevice,
> + display->swapchainHwnd, &scd,
> + NULL, NULL, &display->dxgiswapChain);
> +
> if (hr == DXGI_ERROR_INVALID_CALL && scd.Format == DXGI_FORMAT_R10G10B10A2_UNORM)
> {
> msg_Warn(display->obj, "10 bits swapchain failed, try 8 bits");
> scd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
> - hr = IDXGIFactory2_CreateSwapChainForHwnd(dxgifactory, (IUnknown *)display->d3d_dev->d3ddevice,
> - display->swapchainHwnd, &scd,
> - NULL, NULL, &display->dxgiswapChain);
> + if (display->useDcomp)
> + hr = IDXGIFactory2_CreateSwapChainForComposition(dxgifactory, (IUnknown *)display->d3d_dev->d3ddevice,
> + &scd, NULL, &display->dxgiswapChain);
> + else
> + hr = IDXGIFactory2_CreateSwapChainForHwnd(dxgifactory, (IUnknown *)display->d3d_dev->d3ddevice,
> + display->swapchainHwnd, &scd,
> + NULL, NULL, &display->dxgiswapChain);
> }
> IDXGIFactory2_Release(dxgifactory);
> + if (display->useDcomp && SUCCEEDED(hr)) {
> + IDCompositionVisual_SetContent(display->dcompVisual, (IUnknown *)display->dxgiswapChain);
> + IDCompositionDevice_Commit(display->dcompDevice);
> + }
> if (FAILED(hr)) {
> msg_Err(display->obj, "Could not create the SwapChain. (hr=0x%lX)", hr);
> }
> @@ -555,7 +572,7 @@ bool LocalSwapchainSelectPlane( void *opaque, size_t plane )
> return true;
> }
>
> -void *CreateLocalSwapchainHandle(vlc_object_t *o, HWND hwnd, d3d11_device_t *d3d_dev)
> +void *CreateLocalSwapchainHandleHwnd(vlc_object_t *o, HWND hwnd, d3d11_device_t *d3d_dev)
> {
> struct d3d11_local_swapchain *display = vlc_obj_calloc(o, 1, sizeof(*display));
> if (unlikely(display == NULL))
> @@ -563,6 +580,7 @@ void *CreateLocalSwapchainHandle(vlc_object_t *o, HWND hwnd, d3d11_device_t *d3d
>
> display->obj = o;
> #if !VLC_WINSTORE_APP
> + display->useDcomp = false;
> display->swapchainHwnd = hwnd;
> #else // VLC_WINSTORE_APP
> VLC_UNUSED(hwnd);
> @@ -571,3 +589,20 @@ void *CreateLocalSwapchainHandle(vlc_object_t *o, HWND hwnd, d3d11_device_t *d3d
>
> return display;
> }
> +
> +void *CreateLocalSwapchainHandleDComp(vlc_object_t *o, void* dcompDevice, void* dcompVisual, d3d11_device_t *d3d_dev)
> +{
> + struct d3d11_local_swapchain *display = vlc_obj_calloc(o, 1, sizeof(*display));
> + if (unlikely(display == NULL))
> + return NULL;
> +
> + display->obj = o;
> +#if !VLC_WINSTORE_APP
> + display->useDcomp = true;
> + display->dcompDevice = dcompDevice;
> + display->dcompVisual = dcompVisual;
> +#endif /* !VLC_WINSTORE_APP */
> + display->d3d_dev = d3d_dev;
> +
> + return display;
> +}
> diff --git a/modules/video_output/win32/d3d11_swapchain.h b/modules/video_output/win32/d3d11_swapchain.h
> index a5bfeac3c3..b4f2374746 100644
> --- a/modules/video_output/win32/d3d11_swapchain.h
> +++ b/modules/video_output/win32/d3d11_swapchain.h
> @@ -28,7 +28,8 @@
> #include <vlc_codec.h>
> #include "../../video_chroma/d3d11_fmt.h"
>
> -void *CreateLocalSwapchainHandle(vlc_object_t *, HWND, d3d11_device_t *d3d_dev);
> +void *CreateLocalSwapchainHandleHwnd(vlc_object_t *, HWND, d3d11_device_t *d3d_dev);
> +void *CreateLocalSwapchainHandleDComp(vlc_object_t *, void* dcompDevice, void* dcompVisual, d3d11_device_t *d3d_dev);
>
> void LocalSwapchainCleanupDevice( void *opaque );
> void LocalSwapchainSwap( void *opaque );
> diff --git a/modules/video_output/win32/dcomp_wrapper.cpp b/modules/video_output/win32/dcomp_wrapper.cpp
> new file mode 100644
> index 0000000000..f9798ff9bf
> --- /dev/null
> +++ b/modules/video_output/win32/dcomp_wrapper.cpp
> @@ -0,0 +1,31 @@
> +/*****************************************************************************
> + * Copyright (c) 2020 VideoLAN
> + *
> + * 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.
> + *****************************************************************************/
> +#include "dcomp_wrapper.h"
> +#include <dcomp.h>
> +
> +HRESULT IDCompositionVisual_SetContent(void* opaque, IUnknown *content)
> +{
> + IDCompositionVisual* visual = (IDCompositionVisual*)opaque;
> + return visual->SetContent(content);
> +}
> +
> +HRESULT IDCompositionDevice_Commit(void* opaque)
> +{
> + IDCompositionDevice* device = (IDCompositionDevice*)opaque;
> + return device->Commit();
> +}
> diff --git a/modules/video_output/win32/dcomp_wrapper.h b/modules/video_output/win32/dcomp_wrapper.h
> new file mode 100644
> index 0000000000..e589b038bf
> --- /dev/null
> +++ b/modules/video_output/win32/dcomp_wrapper.h
> @@ -0,0 +1,42 @@
> +/*****************************************************************************
> + * Copyright (c) 2020 VideoLAN
> + *
> + * 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.
> + *****************************************************************************/
> +#ifndef VLC_DCOMP_WRAPPER_H_
> +#define VLC_DCOMP_WRAPPER_H_
> +
> +
> +#ifdef HAVE_CONFIG_H
> +# include "config.h"
> +#endif
Usually the config.h is not included in headers but C/C++ files.
> +
> +#include <vlc_common.h>
You don't use anything from this header.
> +
> +#include <windows.h>
> +#include <unknwn.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +HRESULT IDCompositionVisual_SetContent(void* visual, IUnknown *content);
> +HRESULT IDCompositionDevice_Commit(void* device);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
> index 66b06c50b9..ca213cc708 100644
> --- a/modules/video_output/win32/direct3d11.c
> +++ b/modules/video_output/win32/direct3d11.c
> @@ -321,13 +321,20 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
> if ( sys->swapCb == NULL || sys->startEndRenderingCb == NULL || sys->updateOutputCb == NULL )
> {
> #if !VLC_WINSTORE_APP
> - if (CommonWindowInit(VLC_OBJECT(vd), &sys->area, &sys->sys,
> + if (cfg->window->type == VOUT_WINDOW_TYPE_HWND)
> + {
> + if (CommonWindowInit(VLC_OBJECT(vd), &sys->area, &sys->sys,
> vd->source.projection_mode != PROJECTION_MODE_RECTANGULAR))
> - goto error;
> + goto error;
> + }
> +
> #endif /* !VLC_WINSTORE_APP */
>
> /* use our internal swapchain callbacks */
> - sys->outside_opaque = CreateLocalSwapchainHandle(VLC_OBJECT(vd), sys->sys.hvideownd, sys->d3d_dev);
> + if (cfg->window->type == VOUT_WINDOW_TYPE_DCOMP)
> + sys->outside_opaque = CreateLocalSwapchainHandleDComp(VLC_OBJECT(vd), cfg->window->handle.dcomp.device, cfg->window->handle.dcomp.visual, sys->d3d_dev);
> + else
> + sys->outside_opaque = CreateLocalSwapchainHandleHwnd(VLC_OBJECT(vd), sys->sys.hvideownd, sys->d3d_dev);
> if (unlikely(sys->outside_opaque == NULL))
> goto error;
> sys->updateOutputCb = LocalSwapchainUpdateOutput;
> --
> 2.25.1
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
>
More information about the vlc-devel
mailing list