[vlc-devel] [PATCH 04/31] direct3d9: create a decoder device when the local swapchain is used

Steve Lhomme robux4 at ycbcr.xyz
Fri Jul 5 16:19:43 CEST 2019


The display module always use the device from the vlc_video_context.

Use it in the OpenGL converter if possible.
---
 modules/video_output/win32/direct3d9.c | 137 +++++++++++++++----------
 1 file changed, 85 insertions(+), 52 deletions(-)

diff --git a/modules/video_output/win32/direct3d9.c b/modules/video_output/win32/direct3d9.c
index 4fe32fbb6d..e625c22d48 100644
--- a/modules/video_output/win32/direct3d9.c
+++ b/modules/video_output/win32/direct3d9.c
@@ -41,6 +41,7 @@
 
 #include <vlc_common.h>
 #include <vlc_plugin.h>
+#include <vlc_codec.h>
 #include <vlc_vout_display.h>
 
 #include <vlc/libvlc.h>
@@ -72,6 +73,9 @@ static int  Open(vout_display_t *, const vout_display_cfg_t *,
                  video_format_t *, vlc_video_context *);
 static void Close(vout_display_t *);
 
+static int OpenD3D9DecoderDevice(vlc_decoder_device *, vout_window_t *);
+static void CloseD3D9DecoderDevice(vlc_decoder_device *);
+
 static int  GLConvOpen(vlc_object_t *);
 static void GLConvClose(vlc_object_t *);
 
@@ -117,6 +121,10 @@ vlc_module_begin ()
     add_shortcut("direct3d9", "direct3d")
     set_callbacks(Open, Close)
 
+    add_submodule()
+    set_capability( "decoder device", 10 )
+    set_callbacks( OpenD3D9DecoderDevice, CloseD3D9DecoderDevice )
+
 #ifdef HAVE_GL
     add_submodule()
     set_description("DX OpenGL surface converter for D3D9")
@@ -174,8 +182,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;
@@ -1388,9 +1394,6 @@ static void Direct3D9Destroy(vout_display_sys_t *sys)
         FreeLibrary(sys->hxdll);
         sys->hxdll = NULL;
     }
-
-    if ( sys->cleanupDeviceCb )
-        sys->cleanupDeviceCb( sys->outside_opaque );
 }
 
 /**
@@ -1599,28 +1602,6 @@ static int FindShadersCallback(const char *name, char ***values, char ***descs)
 
 }
 
-static bool LocalSwapchainSetupDevice( void **opaque, const libvlc_video_direct3d_device_cfg_t *cfg, libvlc_video_direct3d_device_setup_t *out )
-{
-    vout_display_t *vd = *opaque;
-    vout_display_sys_t *sys = vd->sys;
-    if (D3D9_Create(vd, &sys->hd3d) != VLC_SUCCESS)
-    {
-        msg_Err( vd, "Direct3D9 could not be initialized" );
-        return false;
-    }
-
-    out->device_context = sys->hd3d.obj;
-    out->adapter = -1;
-    return true;
-}
-
-static void LocalSwapchainCleanupDevice( void *opaque )
-{
-    vout_display_t *vd = opaque;
-    vout_display_sys_t *sys = vd->sys;
-    D3D9_Destroy(&sys->hd3d);
-}
-
 static bool LocalSwapchainUpdateOutput( void *opaque, const libvlc_video_direct3d_cfg_t *cfg, libvlc_video_output_cfg_t *out )
 {
     vout_display_t *vd = opaque;
@@ -1667,44 +1648,35 @@ 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" );
 
-    if ( sys->setupDeviceCb == NULL || sys->swapCb == NULL || sys->startEndRenderingCb == NULL || sys->updateOutputCb == NULL )
+    if ( sys->swapCb == NULL || sys->startEndRenderingCb == NULL || sys->updateOutputCb == NULL )
     {
         /* use our own callbacks, since there isn't any external ones */
         if (CommonWindowInit(VLC_OBJECT(vd), &sys->area, &sys->sys, false))
             goto error;
 
         sys->outside_opaque = vd;
-        sys->setupDeviceCb       = LocalSwapchainSetupDevice;
-        sys->cleanupDeviceCb     = LocalSwapchainCleanupDevice;
         sys->updateOutputCb      = LocalSwapchainUpdateOutput;
         sys->swapCb              = LocalSwapchainSwap;
         sys->startEndRenderingCb = NULL;
     }
 
-    libvlc_video_direct3d_device_cfg_t surface_cfg = {
-        .hardware_decoding = is_d3d9_opaque( vd->source.i_chroma ),
-    };
-    libvlc_video_direct3d_device_setup_t device_setup;
-    if ( !sys->setupDeviceCb( &sys->outside_opaque, &surface_cfg, &device_setup ) ||
-         device_setup.device_context == NULL )
+    d3d9_decoder_device_t *d3d9_decoder = NULL;
+    if ( context && context->device->type == VLC_DECODER_DEVICE_DXVA2 )
+        d3d9_decoder = context->device->opaque;
+    if ( d3d9_decoder == NULL || d3d9_decoder->device == NULL )
     {
-        msg_Err(vd, "Missing external IDirect3D9");
-        return VLC_EGENERIC;
+        msg_Err(vd, "Missing D3D device");
+        goto error;
     }
-    IDirect3D9 *d3d9_device = device_setup.device_context;
-    D3D9_CloneExternal( &sys->hd3d, d3d9_device );
-    HRESULT hr = D3D9_CreateDevice(vd, &sys->hd3d, device_setup.adapter, &sys->d3d_dev);
+    D3D9_CloneExternal( &sys->hd3d, d3d9_decoder->device );
+    HRESULT hr = D3D9_CreateDevice(vd, &sys->hd3d, d3d9_decoder->adapter, &sys->d3d_dev);
     if (FAILED(hr)) {
         msg_Err( vd, "D3D9 Creation failed! (hr=0x%lX)", hr);
         D3D9_Destroy(&sys->hd3d);
-        if ( sys->cleanupDeviceCb )
-            sys->cleanupDeviceCb( sys->outside_opaque );
         free(sys);
         return VLC_EGENERIC;
     }
@@ -1719,7 +1691,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
         goto error;
     }
 
-    if (sys->setupDeviceCb != LocalSwapchainSetupDevice)
+    if (sys->swapCb == LocalSwapchainSwap)
         CommonPlacePicture(VLC_OBJECT(vd), &sys->area, &sys->sys);
 
     sys->hxdll = Direct3D9LoadShaderLibrary();
@@ -1952,20 +1924,30 @@ GLConvOpen(vlc_object_t *obj)
     tc->priv = priv;
     priv->vt = vt;
 
-    if (D3D9_Create(obj, &priv->hd3d) != VLC_SUCCESS)
-        goto error;
-
+    HRESULT hr;
+    int adapter = -1;
+    if (tc->dec_device->type == VLC_DECODER_DEVICE_DXVA2)
+    {
+        d3d9_decoder_device_t *d3d9_decoder = tc->dec_device->opaque;
+        D3D9_CloneExternal(&priv->hd3d, d3d9_decoder->device);
+        adapter = d3d9_decoder->adapter;
+    }
+    else
+    {
+        if (D3D9_Create(obj, &priv->hd3d) != VLC_SUCCESS)
+            goto error;
+    }
     if (!priv->hd3d.use_ex)
     {
         msg_Warn(obj, "DX/GL interrop only working on d3d9x");
         goto error;
     }
 
-    if (FAILED(D3D9_CreateDevice(obj, &priv->hd3d, -1,
-                                 &priv->d3d_dev)))
+    hr = D3D9_CreateDevice(obj, &priv->hd3d, adapter,
+                            &priv->d3d_dev);
+    if (FAILED(hr))
         goto error;
 
-    HRESULT hr;
     HANDLE shared_handle = NULL;
     hr = IDirect3DDevice9Ex_CreateRenderTarget(priv->d3d_dev.devex,
                                                tc->fmt.i_visible_width,
@@ -2005,3 +1987,54 @@ error:
     return VLC_EGENERIC;
 }
 #endif
+
+/* decoder device */
+struct local_render_device
+{
+    d3d9_handle_t         hd3d;
+    d3d9_decoder_device_t device;
+};
+
+static int OpenD3D9DecoderDevice(vlc_decoder_device *device, vout_window_t *wnd)
+{
+    VLC_UNUSED(wnd);
+    struct local_render_device *display = vlc_obj_calloc(VLC_OBJECT(device), 1, sizeof(*display));
+    if (unlikely(display == NULL))
+        return VLC_ENOMEM;
+
+    if (D3D9_Create(device, &display->hd3d) != VLC_SUCCESS)
+    {
+        msg_Err( device, "Direct3D9 could not be initialized" );
+        goto error;
+    }
+
+    d3d9_device_t tmp_d3ddev;
+    /* find the best adapter to use, not based on the HWND used */
+    HRESULT hr = D3D9_CreateDevice( device, &display->hd3d, -1, &tmp_d3ddev );
+    if ( FAILED(hr) )
+    {
+        goto error;
+    }
+
+    display->device.device = display->hd3d.obj;
+    display->device.adapter = tmp_d3ddev.adapterId;
+
+    D3D9_ReleaseDevice(&tmp_d3ddev);
+
+    device->opaque = &display->device;
+    device->type = VLC_DECODER_DEVICE_DXVA2;
+    device->sys = display;
+
+    return VLC_SUCCESS;
+
+error:
+    D3D9_Destroy(&display->hd3d);
+    return VLC_EGENERIC;
+}
+
+static void CloseD3D9DecoderDevice(vlc_decoder_device *device)
+{
+    struct local_render_device *display = device->sys;
+    D3D9_Destroy(&display->hd3d);
+}
+
-- 
2.17.1



More information about the vlc-devel mailing list