[vlc-devel] [PATCH 6/8] direct3d11: handle external callbacks to render into an external surface

Steve Lhomme robux4 at ycbcr.xyz
Mon Jan 21 17:38:49 CET 2019


Instead of a swapchain we create.
---
 modules/video_output/win32/direct3d11.c | 113 ++++++++++++++++--------
 1 file changed, 78 insertions(+), 35 deletions(-)

diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index 2dc41eabfc..a31d37e3bf 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -118,11 +118,8 @@ struct vout_display_sys_t
     picture_t                **d3dregions;
 
     /* outside rendering */
-    void *outside_opaque;
-    void (*swapCb)(void* opaque);
-    void (*endRenderCb)(void* opaque);
-    bool (*starRenderCb)(void* opaque);
-    bool (*resizeCb)(void* opaque, unsigned, unsigned);
+    void                      *outside_opaque;
+    vlc_video_surface_control ctrlCb;
 };
 
 #define RECTWidth(r)   (int)((r).right - (r).left)
@@ -223,10 +220,11 @@ static HRESULT UpdateBackBuffer(vout_display_t *vd)
     if (!GetRect(&sys->sys, &rect))
 #endif
         rect = sys->sys.rect_dest_clipped;
-    uint32_t i_width = RECTWidth(rect);
-    uint32_t i_height = RECTHeight(rect);
 
-    if (!sys->resizeCb(sys->outside_opaque, i_width, i_height))
+    vlc_video_surface_cfg_t cfg;
+    cfg.width  = RECTWidth(rect);
+    cfg.height = RECTHeight(rect);
+    if (!vlc_video_surface_update_output(sys->outside_opaque, sys->ctrlCb, &cfg))
         return E_FAIL;
 
     return S_OK;
@@ -267,9 +265,8 @@ static void Manage(vout_display_t *vd)
     }
 }
 
-static bool Resize(void *opaque, unsigned i_width, unsigned i_height)
+static bool Resize(vout_display_t *vd, unsigned i_width, unsigned i_height)
 {
-    vout_display_t *vd = opaque;
     vout_display_sys_t *sys = vd->sys;
     ID3D11Texture2D* pBackBuffer;
     HRESULT hr;
@@ -324,9 +321,8 @@ static bool Resize(void *opaque, unsigned i_width, unsigned i_height)
     return true;
 }
 
-static bool StartRendering(void *opaque)
+static bool StartRendering(vout_display_t *vd)
 {
-    vout_display_t *vd = opaque;
     vout_display_sys_t *sys = vd->sys;
 
     Manage(vd);
@@ -335,9 +331,8 @@ static bool StartRendering(void *opaque)
     return true;
 }
 
-static void Swap(void *opaque)
+static void Swap(vout_display_t *vd)
 {
-    vout_display_t *vd = opaque;
     vout_display_sys_t *sys = vd->sys;
 
     DXGI_PRESENT_PARAMETERS presentParams = { 0 };
@@ -350,6 +345,40 @@ static void Swap(void *opaque)
     }
 }
 
+static int LocalRender(void* opaque, vlc_video_surface_control_t control, const void *input, void **output)
+{
+    vout_display_t *vd = opaque;
+    switch (control)
+    {
+    case VLC_VIDEO_SURFACE_SETUP:
+        return -1; /* don't used an "external" D3D11 device */
+    case VLC_VIDEO_SURFACE_CLEANUP:
+        /* DO NOTHING */
+        break;
+    case VLC_VIDEO_SURFACE_UPDATE_OUTPUT:
+    {
+        const vlc_video_surface_cfg_t *cfg = input;
+        Resize(vd, cfg->width, cfg->height);
+        break;
+    }
+    case VLC_VIDEO_SURFACE_SWAP:
+        Swap(vd);
+        break;
+    case VLC_VIDEO_SURFACE_START_RENDER:
+        if (!StartRendering(vd))
+            return -1;
+        break;
+    case VLC_VIDEO_SURFACE_FINISHED_RENDERING:
+        /*  DO NOTHING */
+        break;
+    case VLC_VIDEO_SURFACE_MAKE_CURRENT:
+    case VLC_VIDEO_SURFACE_GET_PROCADDRESS:
+        /* ignore OpenGL specific controls */
+        break;
+    }
+    return 0;
+}
+
 static unsigned int GetPictureWidth(const vout_display_t *vd)
 {
     return vd->sys->picQuad.i_width;
@@ -384,12 +413,21 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
     if (ret != VLC_SUCCESS)
         return ret;
 
-    ID3D11DeviceContext *d3d11_ctx = NULL;
+    sys->outside_opaque = var_InheritAddress(vd, "vout-cb-opaque");
+    sys->ctrlCb         = var_InheritAddress(vd, "vout-cb-control");
+
+    if ( sys->ctrlCb == NULL )
+    {
+        sys->outside_opaque = vd;
+        sys->ctrlCb         = LocalRender;
+    }
+
+    bool windowless = sys->ctrlCb != LocalRender;
 #if VLC_WINSTORE_APP
-    if (d3d11_ctx == NULL)
-        d3d11_ctx = var_InheritInteger(vd, "winrt-d3dcontext");
+    if ( !windowless )
+        windowless = var_InheritInteger(vd, "winrt-d3dcontext") != 0; /* LEGACY */
 #endif
-    if (CommonInit(vd, d3d11_ctx != NULL, cfg))
+    if (CommonInit(vd, windowless, cfg))
         goto error;
 
 #if VLC_WINSTORE_APP
@@ -398,15 +436,6 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
     sys->sys.pf_GetPictureWidth  = GetPictureWidth;
     sys->sys.pf_GetPictureHeight = GetPictureHeight;
 
-    if (!sys->swapCb || !sys->starRenderCb || !sys->endRenderCb || !sys->resizeCb)
-    {
-        sys->outside_opaque = vd;
-        sys->swapCb       = Swap;
-        sys->starRenderCb = StartRendering;
-        sys->endRenderCb  = NULL;
-        sys->resizeCb     = Resize;
-    }
-
     if (Direct3D11Open(vd, fmtp)) {
         msg_Err(vd, "Direct3D11 could not be opened");
         assert(!vd->info.is_slow); /* vd->info was not modified */
@@ -890,7 +919,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
     {
         D3D11_UpdateQuadLuminanceScale(vd, &sys->d3d_dev, &sys->picQuad, GetFormatLuminance(VLC_OBJECT(vd), &picture->format) / (float)sys->display.luminance_peak);
 
-        if (sys->dxgiswapChain4)
+        if (sys->dxgiswapChain4) /* TODO pass the HDR metadata through a callback in windowless mode */
         {
             DXGI_HDR_METADATA_HDR10 hdr10 = {0};
             hdr10.GreenPrimary[0] = picture->format.mastering.primaries[0];
@@ -955,12 +984,11 @@ static void Prepare(vout_display_t *vd, picture_t *picture,
 
     VLC_UNUSED(date);
 
-    if (sys->starRenderCb(sys->outside_opaque))
+    if (vlc_video_surface_start_rendering( sys->outside_opaque, sys->ctrlCb ))
     {
         PreparePicture(vd, picture, subpicture);
 
-        if (sys->endRenderCb)
-            sys->endRenderCb(sys->outside_opaque);
+        vlc_video_surface_finished_rendering( sys->outside_opaque, sys->ctrlCb );
     }
 }
 
@@ -970,7 +998,7 @@ static void Display(vout_display_t *vd, picture_t *picture)
     VLC_UNUSED(picture);
 
     d3d11_device_lock( &sys->d3d_dev );
-    sys->swapCb(sys->outside_opaque);
+    vlc_video_surface_swap( sys->outside_opaque, sys->ctrlCb );
     d3d11_device_unlock( &sys->d3d_dev );
 
     CommonDisplay(vd);
@@ -1191,12 +1219,18 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmtp)
     IDXGIFactory2 *dxgifactory;
     HRESULT hr = E_FAIL;
     DXGI_SWAP_CHAIN_DESC1 scd;
-    DXGI_FORMAT windowlessFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
+    DXGI_FORMAT windowlessFormat = DXGI_FORMAT_R8G8B8A8_UNORM; /* TODO get it from a callback */
 
     ID3D11DeviceContext *d3d11_ctx = NULL;
+    if ( sys->ctrlCb != LocalRender )
+    {
+        d3d11_ctx = vlc_video_surface_setup( sys->outside_opaque, sys->ctrlCb );
+        if ( d3d11_ctx == NULL)
+            return VLC_EGENERIC;
+    }
 #if VLC_WINSTORE_APP
     if (d3d11_ctx == NULL)
-        d3d11_ctx = var_InheritInteger(vd, "winrt-d3dcontext");
+        d3d11_ctx = var_InheritInteger(vd, "winrt-d3dcontext"); /* LEGACY */
     if (d3d11_ctx == NULL)
         return VLC_EGENERIC;
 #endif /* VLC_WINSTORE_APP */
@@ -1234,6 +1268,7 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmtp)
 #endif /* VLC_WINSTORE_APP */
     if (sys->sys.b_windowless)
     {
+        /* TODO query the output format using callbacks */
         for (const d3d_format_t *output_format = GetRenderFormatList();
              output_format->name != NULL; ++output_format)
         {
@@ -1298,10 +1333,16 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmtp)
            msg_Err(vd, "Could not create the SwapChain. (hr=0x%lX)", hr);
            return VLC_EGENERIC;
         }
+    }
+#endif /* !VLC_WINSTORE_APP */
 
+    if (sys->dxgiswapChain)
+    {
+        /* we still handle a swapchain in the legacy winrt mode even though
+         * we don't have a window
+         */
         IDXGISwapChain_QueryInterface( sys->dxgiswapChain, &IID_IDXGISwapChain4, (void **)&sys->dxgiswapChain4);
     }
-#endif /* !VLC_WINSTORE_APP */
 
     D3D11SetColorSpace(vd);
 
@@ -1459,6 +1500,8 @@ static void Direct3D11Close(vout_display_t *vd)
 
     D3D11_ReleaseDevice( &sys->d3d_dev );
 
+    vlc_video_surface_cleanup( sys->outside_opaque, sys->ctrlCb );
+
     msg_Dbg(vd, "Direct3D11 device adapter closed");
 }
 
-- 
2.17.1



More information about the vlc-devel mailing list