[vlc-commits] direct3d11: move the external device handling in the common code
Steve Lhomme
git at videolan.org
Wed Feb 12 17:09:12 CET 2020
vlc | branch: master | Steve Lhomme <robux4 at ycbcr.xyz> | Wed Feb 12 13:55:26 2020 +0100| [bff7cadc34a5e08292b97ba69fc14e160845e1cd] | committer: Steve Lhomme
direct3d11: move the external device handling in the common code
The D3D11 display module may be used without a decoder device (software decoding)
and we still need to use the device from the host app.
The allocated d3d11_decoder_device_t structure is freed with the object that
created it. But D3D11_ReleaseDevice() still need to be called.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=bff7cadc34a5e08292b97ba69fc14e160845e1cd
---
modules/hw/d3d11/d3d11_device.c | 92 +++----------------------
modules/video_chroma/d3d11_fmt.c | 116 ++++++++++++++++++++++++++++----
modules/video_chroma/d3d11_fmt.h | 8 +--
modules/video_output/win32/direct3d11.c | 25 +++----
4 files changed, 126 insertions(+), 115 deletions(-)
diff --git a/modules/hw/d3d11/d3d11_device.c b/modules/hw/d3d11/d3d11_device.c
index 5014716603..216b4f0750 100644
--- a/modules/hw/d3d11/d3d11_device.c
+++ b/modules/hw/d3d11/d3d11_device.c
@@ -31,39 +31,12 @@
#include <vlc_common.h>
#include <vlc_codec.h>
-#include <vlc/libvlc.h>
-#include <vlc/libvlc_picture.h>
-#include <vlc/libvlc_media.h>
-#include <vlc/libvlc_renderer_discoverer.h>
-#include <vlc/libvlc_media_player.h>
-
-#define COBJMACROS
-#include <d3d11.h>
#include "d3d11_filters.h"
-typedef struct {
- d3d11_handle_t hd3d;
-
- struct {
- void *opaque;
- libvlc_video_output_cleanup_cb cleanupDeviceCb;
- } external;
-
- d3d11_decoder_device_t dec_device;
-} d3d11_decoder_device;
-
static void D3D11CloseDecoderDevice(vlc_decoder_device *device)
{
- d3d11_decoder_device *sys = device->sys;
-
- D3D11_ReleaseDevice(&sys->dec_device.d3d_dev);
-
- D3D11_Destroy(&sys->hd3d);
-
- if ( sys->external.cleanupDeviceCb )
- sys->external.cleanupDeviceCb( sys->external.opaque );
-
- vlc_obj_free( VLC_OBJECT(device), sys );
+ d3d11_decoder_device_t *dec_device = device->opaque;
+ D3D11_ReleaseDevice( dec_device );
}
static const struct vlc_decoder_device_operations d3d11_dev_ops = {
@@ -73,66 +46,19 @@ static const struct vlc_decoder_device_operations d3d11_dev_ops = {
static int D3D11OpenDecoderDevice(vlc_decoder_device *device, bool forced, vout_window_t *wnd)
{
VLC_UNUSED(wnd);
- d3d11_decoder_device *sys = vlc_obj_malloc(VLC_OBJECT(device), sizeof(*sys));
- if (unlikely(sys==NULL))
- return VLC_ENOMEM;
-
- int ret = D3D11_Create(device, &sys->hd3d);
- if (ret != VLC_SUCCESS)
- return ret;
-
- sys->external.cleanupDeviceCb = NULL;
- HRESULT hr;
-#if VLC_WINSTORE_APP
- /* LEGACY, the d3dcontext and swapchain were given by the host app */
- ID3D11DeviceContext *d3dcontext = (ID3D11DeviceContext*)(uintptr_t) var_InheritInteger(device, "winrt-d3dcontext");
- if ( likely(d3dcontext != NULL) )
- {
- hr = D3D11_CreateDeviceExternal(device, d3dcontext, true, &sys->dec_device.d3d_dev);
- }
- else
-#endif
- {
- libvlc_video_output_setup_cb setupDeviceCb = var_InheritAddress( device, "vout-cb-setup" );
- if ( setupDeviceCb )
- {
- /* decoder device coming from the external app */
- sys->external.opaque = var_InheritAddress( device, "vout-cb-opaque" );
- sys->external.cleanupDeviceCb = var_InheritAddress( device, "vout-cb-cleanup" );
- libvlc_video_setup_device_cfg_t cfg = {
- .hardware_decoding = true, /* always favor hardware decoding */
- };
- libvlc_video_setup_device_info_t out = { .d3d11.device_context = NULL };
- if (!setupDeviceCb( &sys->external.opaque, &cfg, &out ))
- {
- if (sys->external.cleanupDeviceCb)
- sys->external.cleanupDeviceCb( sys->external.opaque );
- goto error;
- }
- hr = D3D11_CreateDeviceExternal(device, out.d3d11.device_context, true, &sys->dec_device.d3d_dev);
- }
- else
- {
- /* internal decoder device */
- hr = D3D11_CreateDevice( device, &sys->hd3d, NULL,
- true /* is_d3d11_opaque(chroma) */,
- forced, &sys->dec_device.d3d_dev );
- }
- }
- if ( FAILED( hr ) )
- goto error;
+ d3d11_decoder_device_t *dec_device;
+ dec_device = D3D11_CreateDevice( device, NULL, true /* is_d3d11_opaque(chroma) */,
+ forced );
+ if ( dec_device == NULL )
+ return VLC_EGENERIC;
device->ops = &d3d11_dev_ops;
- device->opaque = &sys->dec_device;
+ device->opaque = dec_device;
device->type = VLC_DECODER_DEVICE_D3D11VA;
- device->sys = sys;
+ device->sys = NULL;
return VLC_SUCCESS;
-error:
- D3D11_Destroy(&sys->hd3d);
- vlc_obj_free( VLC_OBJECT(device), sys );
- return VLC_EGENERIC;
}
int D3D11OpenDecoderDeviceW8(vlc_decoder_device *device, vout_window_t *wnd)
diff --git a/modules/video_chroma/d3d11_fmt.c b/modules/video_chroma/d3d11_fmt.c
index 8c5da25aef..97ba9e6ca7 100644
--- a/modules/video_chroma/d3d11_fmt.c
+++ b/modules/video_chroma/d3d11_fmt.c
@@ -28,6 +28,12 @@
#include <vlc_picture.h>
#include <vlc_charset.h>
+#include <vlc/libvlc.h>
+#include <vlc/libvlc_picture.h>
+#include <vlc/libvlc_media.h>
+#include <vlc/libvlc_renderer_discoverer.h>
+#include <vlc/libvlc_media_player.h>
+
#define COBJMACROS
#include <d3d11.h>
#include <assert.h>
@@ -217,8 +223,20 @@ static void D3D11_GetDriverVersion(vlc_object_t *obj, d3d11_device_t *d3d_dev)
}
#endif /* VLC_WINSTORE_APP */
-void D3D11_ReleaseDevice(d3d11_device_t *d3d_dev)
+typedef struct {
+ struct {
+ void *opaque;
+ libvlc_video_output_cleanup_cb cleanupDeviceCb;
+ } external;
+
+ d3d11_handle_t hd3d;
+ d3d11_decoder_device_t dec_device;
+} d3d11_decoder_device;
+
+void D3D11_ReleaseDevice(d3d11_decoder_device_t *dev_sys)
{
+ d3d11_decoder_device *sys = container_of(dev_sys, d3d11_decoder_device, dec_device);
+ d3d11_device_t *d3d_dev = &dev_sys->d3d_dev;
if (d3d_dev->d3dcontext)
{
ID3D11DeviceContext_Flush(d3d_dev->d3dcontext);
@@ -237,6 +255,11 @@ void D3D11_ReleaseDevice(d3d11_device_t *d3d_dev)
d3d_dev->context_mutex = INVALID_HANDLE_VALUE;
}
#endif
+
+ if ( sys->external.cleanupDeviceCb )
+ sys->external.cleanupDeviceCb( sys->external.opaque );
+
+ D3D11_Destroy( &sys->hd3d );
}
#undef D3D11_CreateDeviceExternal
@@ -288,21 +311,11 @@ HRESULT D3D11_CreateDeviceExternal(vlc_object_t *obj, ID3D11DeviceContext *d3d11
return S_OK;
}
-HRESULT (D3D11_CreateDevice)(vlc_object_t *obj, d3d11_handle_t *hd3d,
- IDXGIAdapter *adapter,
- bool hw_decoding, bool forced, d3d11_device_t *out)
+static HRESULT CreateDevice(vlc_object_t *obj, d3d11_handle_t *hd3d,
+ IDXGIAdapter *adapter,
+ bool hw_decoding, d3d11_device_t *out)
{
#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 E_FAIL;
- }
# define D3D11CreateDevice(args...) pf_CreateDevice(args)
/* */
PFN_D3D11_CREATE_DEVICE pf_CreateDevice;
@@ -398,6 +411,81 @@ HRESULT (D3D11_CreateDevice)(vlc_object_t *obj, d3d11_handle_t *hd3d,
return hr;
}
+d3d11_decoder_device_t *(D3D11_CreateDevice)(vlc_object_t *obj,
+ IDXGIAdapter *adapter,
+ bool hw_decoding, bool forced)
+{
+ d3d11_decoder_device *sys = vlc_obj_malloc(obj, sizeof(*sys));
+ if (unlikely(sys==NULL))
+ return NULL;
+
+ int ret = D3D11_Create(obj, &sys->hd3d);
+ if (ret != VLC_SUCCESS)
+ {
+ vlc_obj_free( obj, sys );
+ return NULL;
+ }
+
+ sys->external.cleanupDeviceCb = NULL;
+ HRESULT hr = E_FAIL;
+#if VLC_WINSTORE_APP
+ /* LEGACY, the d3dcontext and swapchain were given by the host app */
+ ID3D11DeviceContext *d3dcontext = (ID3D11DeviceContext*)(uintptr_t) var_InheritInteger(obj, "winrt-d3dcontext");
+ if ( likely(d3dcontext != NULL) )
+ {
+ hr = D3D11_CreateDeviceExternal(obj, d3dcontext, true, &sys->dec_device.d3d_dev);
+ }
+ else
+#endif
+ {
+ libvlc_video_output_setup_cb setupDeviceCb = var_InheritAddress( obj, "vout-cb-setup" );
+ if ( setupDeviceCb )
+ {
+ /* decoder device coming from the external app */
+ sys->external.opaque = var_InheritAddress( obj, "vout-cb-opaque" );
+ sys->external.cleanupDeviceCb = var_InheritAddress( obj, "vout-cb-cleanup" );
+ libvlc_video_setup_device_cfg_t cfg = {
+ .hardware_decoding = true, /* always favor hardware decoding */
+ };
+ libvlc_video_setup_device_info_t out = { .d3d11.device_context = NULL };
+ if (!setupDeviceCb( &sys->external.opaque, &cfg, &out ))
+ {
+ if (sys->external.cleanupDeviceCb)
+ sys->external.cleanupDeviceCb( sys->external.opaque );
+ goto error;
+ }
+ hr = D3D11_CreateDeviceExternal(obj, out.d3d11.device_context, true, &sys->dec_device.d3d_dev);
+ }
+ else
+ {
+ /* internal decoder device */
+#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)
+ goto error;
+ }
+#endif /* !VLC_WINSTORE_APP */
+
+ hr = CreateDevice( obj, &sys->hd3d, adapter, hw_decoding, &sys->dec_device.d3d_dev );
+ }
+ }
+
+error:
+ if (FAILED(hr))
+ {
+ D3D11_Destroy(&sys->hd3d);
+ vlc_obj_free( obj, sys );
+ return NULL;
+ }
+ return &sys->dec_device;
+}
+
IDXGIAdapter *D3D11DeviceAdapter(ID3D11Device *d3ddev)
{
IDXGIDevice *pDXGIDevice = NULL;
diff --git a/modules/video_chroma/d3d11_fmt.h b/modules/video_chroma/d3d11_fmt.h
index b9ad54c549..9a14550f8a 100644
--- a/modules/video_chroma/d3d11_fmt.h
+++ b/modules/video_chroma/d3d11_fmt.h
@@ -147,15 +147,15 @@ int D3D11_AllocateResourceView(vlc_object_t *obj, ID3D11Device *d3ddevice,
ID3D11ShaderResourceView *output[D3D11_MAX_SHADER_VIEW]);
#define D3D11_AllocateResourceView(a,b,c,d,e,f) D3D11_AllocateResourceView(VLC_OBJECT(a),b,c,d,e,f)
-HRESULT D3D11_CreateDevice(vlc_object_t *obj, d3d11_handle_t *, IDXGIAdapter *,
- bool hw_decoding, bool forced, d3d11_device_t *out);
-#define D3D11_CreateDevice(a,b,c,d,e,f) D3D11_CreateDevice( VLC_OBJECT(a), b, c, d, e, f )
+d3d11_decoder_device_t *D3D11_CreateDevice(vlc_object_t *obj, IDXGIAdapter *,
+ bool hw_decoding, bool forced);
+#define D3D11_CreateDevice(a,b,c,d) D3D11_CreateDevice( VLC_OBJECT(a), b, c, d )
HRESULT D3D11_CreateDeviceExternal(vlc_object_t *obj, ID3D11DeviceContext *,
bool hw_decoding, d3d11_device_t *out);
#define D3D11_CreateDeviceExternal(a,b,c,d) \
D3D11_CreateDeviceExternal( VLC_OBJECT(a), b, c, d )
-void D3D11_ReleaseDevice(d3d11_device_t *);
+void D3D11_ReleaseDevice(d3d11_decoder_device_t *);
int D3D11_Create(vlc_object_t *, d3d11_handle_t *);
#define D3D11_Create(a,b) D3D11_Create( VLC_OBJECT(a), b )
diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index 21c98231b4..18e353813c 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -97,7 +97,7 @@ struct vout_display_sys_t
d3d11_handle_t hd3d;
d3d11_device_t *d3d_dev;
- d3d11_device_t local_d3d_dev; // when opened without a video context
+ d3d11_decoder_device_t *local_d3d_dev; // when opened without a video context
d3d11_shaders_t shaders;
d3d_quad_t picQuad;
@@ -312,21 +312,18 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
sys->sendMetadataCb = var_InheritAddress( vd, "vout-cb-metadata" );
sys->selectPlaneCb = var_InheritAddress( vd, "vout-cb-select-plane" );
- d3d11_decoder_device_t *dev_sys = GetD3D11OpaqueContext(context);
- if ( dev_sys != NULL )
- {
- sys->d3d_dev = &dev_sys->d3d_dev;
- }
- else
+ d3d11_decoder_device_t *dev_sys = GetD3D11OpaqueContext( context );
+ if ( dev_sys == NULL )
{
// No d3d11 device, we create one
- HRESULT hr = D3D11_CreateDevice(vd, &sys->hd3d, NULL, false, vd->obj.force, &sys->local_d3d_dev);
- if (FAILED(hr)) {
- msg_Err(vd, "Could not Create the D3D11 device. (hr=0x%lX)", hr);
+ sys->local_d3d_dev = D3D11_CreateDevice(vd, NULL, false, vd->obj.force);
+ if (sys->local_d3d_dev == NULL) {
+ msg_Err(vd, "Could not Create the D3D11 device.");
goto error;
}
- sys->d3d_dev = &sys->local_d3d_dev;
+ dev_sys = sys->local_d3d_dev;
}
+ sys->d3d_dev = &dev_sys->d3d_dev;
if ( sys->swapCb == NULL || sys->startEndRenderingCb == NULL || sys->updateOutputCb == NULL )
{
@@ -970,12 +967,12 @@ static void Direct3D11Close(vout_display_t *vd)
Direct3D11DestroyResources(vd);
- if (sys->d3d_dev == &sys->local_d3d_dev)
- D3D11_ReleaseDevice( &sys->local_d3d_dev );
-
if ( sys->swapCb == LocalSwapchainSwap )
LocalSwapchainCleanupDevice( sys->outside_opaque );
+ if (sys->d3d_dev == &sys->local_d3d_dev->d3d_dev)
+ D3D11_ReleaseDevice( sys->local_d3d_dev );
+
msg_Dbg(vd, "Direct3D11 display adapter closed");
}
More information about the vlc-commits
mailing list