[vlc-devel] [PATCH 08/31] direct3d11: create a decoder device when the local swapchain is used
Steve Lhomme
robux4 at ycbcr.xyz
Fri Jul 5 16:19:47 CEST 2019
The display module always use the device from the vlc_video_context.
Do not use it if a DXVA2 decoder is requested
---
modules/video_output/win32/d3d11_swapchain.c | 103 +++++++++++++------
modules/video_output/win32/d3d11_swapchain.h | 7 +-
modules/video_output/win32/direct3d11.c | 65 +++++-------
3 files changed, 103 insertions(+), 72 deletions(-)
diff --git a/modules/video_output/win32/d3d11_swapchain.c b/modules/video_output/win32/d3d11_swapchain.c
index 67d9a381cc..7d1691daf7 100644
--- a/modules/video_output/win32/d3d11_swapchain.c
+++ b/modules/video_output/win32/d3d11_swapchain.c
@@ -33,6 +33,7 @@
#include <assert.h>
+#include <windows.h>
#if !defined(_WIN32_WINNT) || _WIN32_WINNT < _WIN32_WINNT_WIN7
# undef _WIN32_WINNT
# define _WIN32_WINNT _WIN32_WINNT_WIN7
@@ -49,6 +50,7 @@
#include "d3d11_swapchain.h"
#include "d3d11_shaders.h"
+#include "../../video_chroma/d3d9_fmt.h"
typedef enum video_color_axis {
COLOR_AXIS_RGB,
@@ -68,7 +70,6 @@ typedef struct {
struct d3d11_local_swapchain
{
vlc_object_t *obj;
- d3d11_handle_t *hd3d;
d3d11_device_t d3d_dev;
const d3d_format_t *pixelFormat;
@@ -432,30 +433,6 @@ static bool UpdateSwapchain( struct d3d11_local_swapchain *display, const libvlc
return true;
}
-bool LocalSwapchainSetupDevice( void **opaque, const libvlc_video_direct3d_device_cfg_t *cfg, libvlc_video_direct3d_device_setup_t *out )
-{
- struct d3d11_local_swapchain *display = *opaque;
- HRESULT hr;
-#if VLC_WINSTORE_APP
- ID3D11DeviceContext *legacy_ctx = var_InheritInteger( display->obj, "winrt-d3dcontext" ); /* LEGACY */
- if ( legacy_ctx == NULL )
- hr = E_FAIL;
- else
- hr = D3D11_CreateDeviceExternal( display->obj,
- legacy_ctx,
- cfg->hardware_decoding,
- &display->d3d_dev );
-#else /* !VLC_WINSTORE_APP */
- hr = D3D11_CreateDevice( display->obj, display->hd3d, NULL,
- cfg->hardware_decoding,
- &display->d3d_dev );
-#endif /* !VLC_WINSTORE_APP */
- if ( FAILED( hr ) )
- return false;
- out->device_context = display->d3d_dev.d3dcontext;
- return true;
-}
-
void LocalSwapchainCleanupDevice( void *opaque )
{
struct d3d11_local_swapchain *display = opaque;
@@ -563,16 +540,78 @@ bool LocalSwapchainSelectPlane( void *opaque, size_t plane )
return true;
}
-void *CreateLocalSwapchainHandle(vlc_object_t *o, d3d11_handle_t *hd3d, HWND hwnd)
+void *CreateLocalSwapchainHandle(vlc_object_t *o, HWND hwnd, ID3D11DeviceContext *d3d11_ctx)
{
struct d3d11_local_swapchain *display = vlc_obj_calloc(o, 1, sizeof(*display));
- if (likely(display != NULL))
- {
- display->obj = o;
- display->hd3d = hd3d;
+ if (unlikely(display == NULL))
+ return NULL;
+
+ display->obj = o;
#if !VLC_WINSTORE_APP
- display->swapchainHwnd = hwnd;
+ display->swapchainHwnd = hwnd;
#endif /* !VLC_WINSTORE_APP */
- }
+ D3D11_CreateDeviceExternal( o, d3d11_ctx, true /* is_d3d11_opaque(vd->source.i_chroma) */, &display->d3d_dev);
+
return display;
}
+
+struct local_render_device
+{
+ d3d11_handle_t hd3d;
+ d3d11_device_t d3d_dev;
+ d3d11_decoder_device_t dec_device;
+};
+
+int LocalSwapchainOpenDevice(vlc_decoder_device *device, bool forced, vout_window_t *wnd)
+{
+ VLC_UNUSED(wnd);
+#if !VLC_WINSTORE_APP
+ if (!forced)
+ {
+ /* Allow using D3D11 automatically starting from Windows 8.1 */
+ bool isWin81OrGreater = false;
+ HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32.dll"));
+ if (likely(hKernel32 != NULL))
+ isWin81OrGreater = GetProcAddress(hKernel32, "IsProcessCritical") != NULL;
+ if (!isWin81OrGreater)
+ return VLC_EGENERIC;
+ }
+#endif /* !VLC_WINSTORE_APP */
+
+ struct local_render_device *display = vlc_obj_calloc(VLC_OBJECT(device), 1, sizeof(*display));
+ if (unlikely(display == NULL))
+ return VLC_ENOMEM;
+
+ int ret = D3D11_Create(device, &display->hd3d, true);
+ if (ret != VLC_SUCCESS)
+ goto error;
+
+ HRESULT hr = D3D11_CreateDevice( device, &display->hd3d, NULL,
+ true /* is_d3d11_opaque(chroma) */,
+ &display->d3d_dev );
+ if ( FAILED( hr ) )
+ {
+ ret = VLC_EGENERIC;
+ goto error;
+ }
+
+ display->dec_device.device = display->d3d_dev.d3dcontext;
+
+ device->opaque = &display->dec_device;
+ device->type = VLC_DECODER_DEVICE_D3D11VA;
+ device->sys = display;
+
+ return VLC_SUCCESS;
+
+error:
+ D3D11_Destroy( &display->hd3d );
+ vlc_obj_free( VLC_OBJECT(device), display );
+ return ret;
+}
+
+void LocalSwapchainCloseDevice(vlc_decoder_device *device)
+{
+ struct local_render_device *display = device->sys;
+ D3D11_Destroy( &display->hd3d );
+ vlc_obj_free( VLC_OBJECT(device), display );
+}
diff --git a/modules/video_output/win32/d3d11_swapchain.h b/modules/video_output/win32/d3d11_swapchain.h
index f6a4d15201..75a512601d 100644
--- a/modules/video_output/win32/d3d11_swapchain.h
+++ b/modules/video_output/win32/d3d11_swapchain.h
@@ -25,11 +25,14 @@
#define VLC_D3D11_SWAPCHAIN_H
#include <vlc_common.h>
+#include <vlc_codec.h>
#include "../../video_chroma/d3d11_fmt.h"
-void *CreateLocalSwapchainHandle(vlc_object_t *, d3d11_handle_t *, HWND);
+void *CreateLocalSwapchainHandle(vlc_object_t *, HWND, ID3D11DeviceContext *);
+
+int LocalSwapchainOpenDevice(vlc_decoder_device *, bool, vout_window_t *);
+void LocalSwapchainCloseDevice(vlc_decoder_device *);
-bool LocalSwapchainSetupDevice( void **opaque, const libvlc_video_direct3d_device_cfg_t *cfg, libvlc_video_direct3d_device_setup_t *out );
void LocalSwapchainCleanupDevice( void *opaque );
void LocalSwapchainSwap( void *opaque );
bool LocalSwapchainUpdateOutput( void *opaque, const libvlc_video_direct3d_cfg_t *cfg, libvlc_video_output_cfg_t *out );
diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index c05e305e80..3434d37457 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -86,6 +86,10 @@ vlc_module_begin ()
set_capability("vout display", 300)
add_shortcut("direct3d11")
set_callbacks(Open, Close)
+
+ add_submodule()
+ set_capability( "decoder device", 10 )
+ set_callbacks( LocalSwapchainOpenDevice, LocalSwapchainCloseDevice )
vlc_module_end ()
struct vout_display_sys_t
@@ -122,8 +126,6 @@ struct vout_display_sys_t
/* outside rendering */
void *outside_opaque;
- libvlc_video_direct3d_device_setup_cb setupDeviceCb;
- libvlc_video_direct3d_device_cleanup_cb cleanupDeviceCb;
libvlc_video_direct3d_update_output_cb updateOutputCb;
libvlc_video_swap_cb swapCb;
libvlc_video_direct3d_start_end_rendering_cb startEndRenderingCb;
@@ -137,7 +139,7 @@ static void Display(vout_display_t *, picture_t *);
static void Direct3D11Destroy(vout_display_t *);
-static int Direct3D11Open (vout_display_t *, video_format_t *);
+static int Direct3D11Open (vout_display_t *, video_format_t *, ID3D11DeviceContext *);
static void Direct3D11Close(vout_display_t *);
static int SetupOutputFormat(vout_display_t *, video_format_t *);
@@ -322,34 +324,32 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
CommonInit(vd, &sys->area, cfg);
sys->outside_opaque = var_InheritAddress( vd, "vout-cb-opaque" );
- sys->setupDeviceCb = var_InheritAddress( vd, "vout-cb-setup" );
- sys->cleanupDeviceCb = var_InheritAddress( vd, "vout-cb-cleanup" );
sys->updateOutputCb = var_InheritAddress( vd, "vout-cb-update-output" );
sys->swapCb = var_InheritAddress( vd, "vout-cb-swap" );
sys->startEndRenderingCb = var_InheritAddress( vd, "vout-cb-make-current" );
sys->selectPlaneCb = var_InheritAddress( vd, "vout-cb-select-plane" );
- if ( sys->setupDeviceCb == NULL || sys->swapCb == NULL || sys->startEndRenderingCb == NULL || sys->updateOutputCb == NULL )
+ d3d11_decoder_device_t *d3d11_decoder = NULL;
+ if ( context && context->device->type == VLC_DECODER_DEVICE_D3D11VA )
+ d3d11_decoder = context->device->opaque;
+ if ( d3d11_decoder == NULL || d3d11_decoder->device == NULL )
{
-#if VLC_WINSTORE_APP
- /* LEGACY, the d3dcontext and swapchain were given by the host app */
- if (var_InheritInteger(vd, "winrt-d3dcontext") == 0)
- {
- msg_Err(vd, "missing direct3d context for winstore");
- goto error;
- }
-#else /* !VLC_WINSTORE_APP */
+ msg_Err(vd, "Missing D3D device");
+ goto error;
+ }
+
+ if ( sys->swapCb == NULL || sys->startEndRenderingCb == NULL || sys->updateOutputCb == NULL )
+ {
+#if !VLC_WINSTORE_APP
if (CommonWindowInit(VLC_OBJECT(vd), &sys->area, &sys->sys,
vd->source.projection_mode != PROJECTION_MODE_RECTANGULAR))
goto error;
#endif /* !VLC_WINSTORE_APP */
/* use our internal swapchain callbacks */
- sys->outside_opaque = CreateLocalSwapchainHandle(VLC_OBJECT(vd), &sys->hd3d, sys->sys.hvideownd);
+ sys->outside_opaque = CreateLocalSwapchainHandle(VLC_OBJECT(vd), sys->sys.hvideownd, d3d11_decoder->device);
if (unlikely(sys->outside_opaque == NULL))
goto error;
- sys->setupDeviceCb = LocalSwapchainSetupDevice;
- sys->cleanupDeviceCb = LocalSwapchainCleanupDevice;
sys->updateOutputCb = LocalSwapchainUpdateOutput;
sys->swapCb = LocalSwapchainSwap;
sys->startEndRenderingCb = LocalSwapchainStartEndRendering;
@@ -359,7 +359,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
if (vd->source.projection_mode != PROJECTION_MODE_RECTANGULAR && sys->sys.hvideownd)
sys->p_sensors = HookWindowsSensors(vd, sys->sys.hvideownd);
- if (Direct3D11Open(vd, fmtp)) {
+ if (Direct3D11Open(vd, fmtp, d3d11_decoder->device)) {
msg_Err(vd, "Direct3D11 could not be opened");
goto error;
}
@@ -848,29 +848,18 @@ static const d3d_format_t *GetBlendableFormat(vout_display_t *vd, vlc_fourcc_t i
return FindD3D11Format( vd, &vd->sys->d3d_dev, i_src_chroma, false, 0, 0, 0, false, supportFlags );
}
-static int Direct3D11Open(vout_display_t *vd, video_format_t *fmtp)
+static int Direct3D11Open(vout_display_t *vd, video_format_t *fmtp, ID3D11DeviceContext *d3d11_ctx)
{
vout_display_sys_t *sys = vd->sys;
HRESULT hr = E_FAIL;
- libvlc_video_direct3d_device_cfg_t cfg = {
- .hardware_decoding = is_d3d11_opaque( vd->source.i_chroma ),
- };
- libvlc_video_direct3d_device_setup_t out;
- if ( !sys->setupDeviceCb( &sys->outside_opaque, &cfg, &out ) ||
- out.device_context == NULL )
- {
- msg_Err(vd, "Missing external ID3D11DeviceContext");
- return VLC_EGENERIC;
- }
- ID3D11DeviceContext *d3d11_ctx = out.device_context;
hr = D3D11_CreateDeviceExternal(vd, d3d11_ctx,
is_d3d11_opaque(vd->source.i_chroma),
&sys->d3d_dev);
if (FAILED(hr)) {
msg_Err(vd, "Could not Create the D3D11 device. (hr=0x%lX)", hr);
- if ( sys->cleanupDeviceCb )
- sys->cleanupDeviceCb( sys->outside_opaque );
+ if ( sys->swapCb == LocalSwapchainSwap )
+ LocalSwapchainCleanupDevice( sys->outside_opaque );
return VLC_EGENERIC;
}
@@ -899,8 +888,8 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmtp)
}
if (err != VLC_SUCCESS)
{
- if ( sys->cleanupDeviceCb )
- sys->cleanupDeviceCb( sys->outside_opaque );
+ if ( sys->swapCb == LocalSwapchainSwap )
+ LocalSwapchainCleanupDevice( sys->outside_opaque );
return err;
}
}
@@ -934,8 +923,8 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmtp)
if (Direct3D11CreateGenericResources(vd)) {
msg_Err(vd, "Failed to allocate resources");
- if ( sys->cleanupDeviceCb )
- sys->cleanupDeviceCb( sys->outside_opaque );
+ if ( sys->swapCb == LocalSwapchainSwap )
+ LocalSwapchainCleanupDevice( sys->outside_opaque );
return VLC_EGENERIC;
}
@@ -1046,8 +1035,8 @@ static void Direct3D11Close(vout_display_t *vd)
D3D11_ReleaseDevice( &sys->d3d_dev );
- if ( sys->cleanupDeviceCb )
- sys->cleanupDeviceCb( sys->outside_opaque );
+ if ( sys->swapCb == LocalSwapchainSwap )
+ LocalSwapchainCleanupDevice( sys->outside_opaque );
msg_Dbg(vd, "Direct3D11 device adapter closed");
}
--
2.17.1
More information about the vlc-devel
mailing list