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

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


Instead of the device backbuffer.
---
 modules/video_output/win32/direct3d9.c | 90 +++++++++++++++++---------
 1 file changed, 58 insertions(+), 32 deletions(-)

diff --git a/modules/video_output/win32/direct3d9.c b/modules/video_output/win32/direct3d9.c
index 6e3bcb799e..0f3d85c47b 100644
--- a/modules/video_output/win32/direct3d9.c
+++ b/modules/video_output/win32/direct3d9.c
@@ -161,11 +161,8 @@ struct vout_display_sys_t
     atomic_bool             new_desktop_mode;
 
     /* 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;
 };
 
 /* */
@@ -582,9 +579,10 @@ static int Direct3D9CreateScene(vout_display_t *vd, const video_format_t *fmt)
     IDirect3DDevice9        *d3ddev = p_d3d9_dev->dev;
     HRESULT hr;
 
-    if (sys->resizeCb && !sys->resizeCb( sys->outside_opaque,
-                                         fmt->i_visible_width,
-                                         fmt->i_visible_height ))
+    vlc_video_surface_cfg_t cfg;
+    cfg.width  = fmt->i_visible_width;
+    cfg.height = fmt->i_visible_height;
+    if (!vlc_video_surface_update_output( sys->outside_opaque, sys->ctrlCb, &cfg ))
     {
         msg_Err(vd, "Failed to set the external render size");
         return VLC_EGENERIC;
@@ -1162,9 +1160,8 @@ static int Direct3D9RenderRegion(vout_display_t *vd,
     return 0;
 }
 
-static bool StartRendering(void *opaque)
+static bool StartRendering(vout_display_t *vd)
 {
-    vout_display_t *vd = opaque;
     vout_display_sys_t *sys = vd->sys;
     IDirect3DDevice9 *d3ddev = sys->d3d_dev.dev;
     HRESULT hr;
@@ -1189,9 +1186,8 @@ static bool StartRendering(void *opaque)
     return true;
 }
 
-static void EndRendering(void *opaque)
+static void EndRendering(vout_display_t *vd)
 {
-    vout_display_t *vd = opaque;
     vout_display_sys_t *sys = vd->sys;
     IDirect3DDevice9 *d3ddev = sys->d3d_dev.dev;
     HRESULT hr;
@@ -1216,7 +1212,7 @@ static void Direct3D9RenderScene(vout_display_t *vd,
     vout_display_sys_t *sys = vd->sys;
     IDirect3DDevice9 *d3ddev = sys->d3d_dev.dev;
 
-    if (!sys->starRenderCb(sys->outside_opaque))
+    if (!vlc_video_surface_start_rendering( sys->outside_opaque, sys->ctrlCb ))
         return;
 
     Direct3D9RenderRegion(vd, picture, true);
@@ -1232,7 +1228,7 @@ static void Direct3D9RenderScene(vout_display_t *vd,
         IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHABLENDENABLE, FALSE);
     }
 
-    sys->endRenderCb(sys->outside_opaque);
+    vlc_video_surface_finished_rendering( sys->outside_opaque, sys->ctrlCb );
 }
 
 static void Prepare(vout_display_t *vd, picture_t *picture,
@@ -1314,9 +1310,8 @@ static void Prepare(vout_display_t *vd, picture_t *picture,
     }
 }
 
-static void Swap(void *opaque)
+static void Swap(vout_display_t *vd)
 {
-    vout_display_t *vd = opaque;
     vout_display_sys_t *sys = vd->sys;
     const d3d9_device_t *p_d3d9_dev = &sys->d3d_dev;
 
@@ -1343,7 +1338,7 @@ static void Display(vout_display_t *vd, picture_t *picture)
     if (sys->lost_not_ready)
         return;
 
-    sys->swapCb(sys->outside_opaque);
+    vlc_video_surface_swap( sys->outside_opaque, sys->ctrlCb );
 
     /* XXX See Prepare() */
     if ( !is_d3d9_opaque(picture->format.i_chroma) )
@@ -1364,6 +1359,8 @@ static void Direct3D9Destroy(vout_display_sys_t *sys)
         FreeLibrary(sys->hxdll);
         sys->hxdll = NULL;
     }
+
+    vlc_video_surface_cleanup( sys->outside_opaque, sys->ctrlCb );
 }
 
 /**
@@ -1612,6 +1609,35 @@ static int FindShadersCallback(const char *name, char ***values, char ***descs)
 
 }
 
+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" D3D9 device */
+    case VLC_VIDEO_SURFACE_CLEANUP:
+    case VLC_VIDEO_SURFACE_UPDATE_OUTPUT:
+        /* DO NOTHING */
+        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:
+        EndRendering(vd);
+        break;
+    case VLC_VIDEO_SURFACE_MAKE_CURRENT:
+    case VLC_VIDEO_SURFACE_GET_PROCADDRESS:
+        /* ignore OpenGL specific controls */
+        break;
+    }
+    return 0;
+}
+
 /**
  * It creates a Direct3D vout display.
  */
@@ -1642,10 +1668,20 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
     if (!sys)
         return VLC_ENOMEM;
 
-    IDirect3DDevice9 *d3d9_device = var_InheritAddress(vd, "vout-engine-ctx");
-    if (d3d9_device != NULL)
+    sys->outside_opaque = var_InheritAddress(vd, "vout-cb-opaque");
+    sys->ctrlCb         = var_InheritAddress(vd, "vout-cb-control");
+
+    if ( sys->ctrlCb == NULL )
+    {
+        /* use our own callbacks, since there isn't any external ones */
+        sys->outside_opaque = vd;
+        sys->ctrlCb         = LocalRender;
+    }
+
+    IDirect3DDevice9 *external_device = vlc_video_surface_setup( sys->outside_opaque, sys->ctrlCb );
+    if (external_device != NULL)
     {
-        if (D3D9_CreateExternal(vd, &sys->hd3d, d3d9_device)) {
+        if (D3D9_CreateExternal(vd, &sys->hd3d, external_device)) {
             msg_Err(vd, "External Direct3D9 could not be used");
             free(sys);
             return VLC_EGENERIC;
@@ -1657,16 +1693,6 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
         return VLC_EGENERIC;
     }
 
-    if (!sys->swapCb || !sys->starRenderCb || !sys->endRenderCb)
-    {
-        /* use our own callbacks, since there isn't any external ones */
-        sys->outside_opaque = vd;
-        sys->swapCb         = Swap;
-        sys->starRenderCb   = StartRendering;
-        sys->endRenderCb    = EndRendering;
-        sys->resizeCb       = NULL;
-    }
-
     sys->hxdll = Direct3D9LoadShaderLibrary();
     if (!sys->hxdll)
         msg_Warn(vd, "cannot load Direct3D9 Shader Library; HLSL pixel shading will be disabled.");
@@ -1678,12 +1704,12 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
     sys->desktop_save.is_fullscreen = cfg->is_fullscreen;
     sys->desktop_save.is_on_top     = false;
 
-    if (CommonInit(vd, d3d9_device != NULL, cfg))
+    if (CommonInit(vd, external_device != NULL, cfg))
         goto error;
 
     /* */
     video_format_t fmt;
-    if (Direct3D9Open(vd, &fmt, d3d9_device)) {
+    if (Direct3D9Open(vd, &fmt, external_device)) {
         msg_Err(vd, "Direct3D9 could not be opened");
         goto error;
     }
-- 
2.17.1



More information about the vlc-devel mailing list