[vlc-devel] [PATCH 01/12] d3d11: allow rendering video to DirectComposition surfaces
Pierre Lamot
pierre at videolabs.io
Mon May 11 18:04:51 CEST 2020
---
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;
#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)
{
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
+
+#include <vlc_common.h>
+
+#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
More information about the vlc-devel
mailing list