[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