[vlc-devel] [PATCH 3/7] direct3d11: create a decoder device when the local swapchain is used

Steve Lhomme robux4 at ycbcr.xyz
Wed Jun 26 15:49:00 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      |  67 +++++-------
 3 files changed, 104 insertions(+), 73 deletions(-)

diff --git a/modules/video_output/win32/d3d11_swapchain.c b/modules/video_output/win32/d3d11_swapchain.c
index 67d9a381cc..4b8e89b5be 100644
--- a/modules/video_output/win32/d3d11_swapchain.c
+++ b/modules/video_output/win32/d3d11_swapchain.c
@@ -49,6 +49,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 +69,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 +432,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 +539,79 @@ 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;
+};
+
+int LocalSwapchainOpenDevice(vlc_decoder_device *device, vout_window_t *wnd, vlc_fourcc_t chroma)
+{
+    VLC_UNUSED(wnd);
+#if !VLC_WINSTORE_APP
+    /* Allow using D3D11 automatically starting from Windows 8.1 */
+    if (!device->obj.force)
+    {
+        if (is_d3d9_opaque(chroma)) /* fallback to D3D9 for DXVA2 */
+            return VLC_EGENERIC;
+
+        /* 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,
+                                     is_d3d11_opaque(chroma),
+                                     &display->d3d_dev );
+    if ( FAILED( hr ) )
+    {
+        ret = VLC_EGENERIC;
+        goto error;
+    }
+
+    device->opaque = display->d3d_dev.d3dcontext;
+    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..c20cae0f5a 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 *, vout_window_t *, vlc_fourcc_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 411860d813..eb078f9d02 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -27,6 +27,7 @@
 
 #include <vlc_common.h>
 #include <vlc_plugin.h>
+#include <vlc_codec.h>
 #include <vlc_vout_display.h>
 
 #include <vlc/libvlc.h>
@@ -87,6 +88,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
@@ -123,8 +128,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;
@@ -138,7 +141,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 *);
@@ -323,34 +326,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 )
+    ID3D11DeviceContext *d3d11_ctx = NULL;
+    if ( context && context->device->type == VLC_DECODER_DEVICE_D3D11VA )
+        d3d11_ctx = context->device->opaque;
+    if ( d3d11_ctx == 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_ctx);
         if (unlikely(sys->outside_opaque == NULL))
             goto error;
-        sys->setupDeviceCb       = LocalSwapchainSetupDevice;
-        sys->cleanupDeviceCb     = LocalSwapchainCleanupDevice;
         sys->updateOutputCb      = LocalSwapchainUpdateOutput;
         sys->swapCb              = LocalSwapchainSwap;
         sys->startEndRenderingCb = LocalSwapchainStartEndRendering;
@@ -360,7 +361,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_ctx)) {
         msg_Err(vd, "Direct3D11 could not be opened");
         goto error;
     }
@@ -849,30 +850,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;
-    ID3D11DeviceContext *d3d11_ctx = NULL;
-    if ( sys->setupDeviceCb( &sys->outside_opaque, &cfg, &out ) )
-        d3d11_ctx = out.device_context;
-    if ( d3d11_ctx == NULL )
-    {
-        msg_Err(vd, "Missing external ID3D11DeviceContext");
-        return VLC_EGENERIC;
-    }
     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;
     }
 
@@ -901,8 +890,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;
         }
     }
@@ -936,8 +925,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;
     }
 
@@ -1048,8 +1037,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