[vlc-commits] direct3d9: the setup callback returns a IDirect3D9 not a IDirect3DDevice9

Steve Lhomme git at videolan.org
Wed Jun 26 15:48:35 CEST 2019


vlc | branch: master | Steve Lhomme <robux4 at ycbcr.xyz> | Wed Jun 26 13:29:08 2019 +0200| [cfaa0bdfe684e95eb8653219d0b3e04a1d5433ee] | committer: Steve Lhomme

direct3d9: the setup callback returns a IDirect3D9 not a IDirect3DDevice9

It's simpler on the host side and we don't need to be tied to the HWND it would
use internally.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=cfaa0bdfe684e95eb8653219d0b3e04a1d5433ee
---

 doc/libvlc/d3d9_player.c               | 35 ++++++++++--------
 include/vlc/libvlc_media_player.h      | 10 ++++--
 modules/video_output/win32/direct3d9.c | 65 ++++++++++++++++------------------
 3 files changed, 59 insertions(+), 51 deletions(-)

diff --git a/doc/libvlc/d3d9_player.c b/doc/libvlc/d3d9_player.c
index 43fb3c1d4c..0333702e0d 100644
--- a/doc/libvlc/d3d9_player.c
+++ b/doc/libvlc/d3d9_player.c
@@ -118,6 +118,7 @@ static void Swap(struct render_context *ctx)
  * This is called outside of the UI thread (not the VLC rendering thread).
  */
 static bool Resize(struct render_context *ctx, unsigned width, unsigned height,
+                   IDirect3DDevice9 *vlc_device,
                    libvlc_video_output_cfg_t *out)
 {
     HRESULT hr;
@@ -132,16 +133,23 @@ static bool Resize(struct render_context *ctx, unsigned width, unsigned height,
         ctx->renderTexture = NULL;
         ctx->sharedHandled = NULL;
     }
+    if (ctx->sharedRenderTexture)
+    {
+        IDirect3DTexture9_Release(ctx->sharedRenderTexture);
+        ctx->sharedRenderTexture = NULL;
+    }
     if (ctx->sharedRenderSurface)
     {
         IDirect3DSurface9_Release(ctx->sharedRenderSurface);
         ctx->sharedRenderSurface = NULL;
     }
-    if (ctx->sharedRenderTexture)
+    /* the device to use may have changed */
+    if (ctx->libvlc_d3d)
     {
-        IDirect3DTexture9_Release(ctx->sharedRenderTexture);
-        ctx->sharedRenderTexture = NULL;
+        IDirect3DDevice9_Release(ctx->libvlc_d3d);
     }
+    ctx->libvlc_d3d = vlc_device;
+    IDirect3DDevice9_AddRef(ctx->libvlc_d3d);
 
     /* texture we can use on our device */
     hr = IDirect3DDevice9_CreateTexture(ctx->d3ddev, width, height, 1, D3DUSAGE_RENDERTARGET,
@@ -191,15 +199,6 @@ static void init_direct3d(struct render_context *ctx, HWND hWnd)
                             &d3dpp,
                             &ctx->d3ddev);
 
-    d3dpp.hDeviceWindow = 0;
-
-    IDirect3D9Ex_CreateDevice(ctx->d3d, D3DADAPTER_DEFAULT,
-                            D3DDEVTYPE_HAL,
-                            NULL,
-                            D3DCREATE_MULTITHREADED| D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
-                            &d3dpp,
-                            &ctx->libvlc_d3d);
-
     IDirect3DDevice9_GetRenderTarget(ctx->d3ddev, 0, &ctx->backBuffer);
 
     struct CUSTOMVERTEX rectangleVertices[] =
@@ -234,7 +233,8 @@ static void release_direct3d(struct render_context *ctx)
         IDirect3DTexture9_Release(ctx->sharedRenderTexture);
     if (ctx->rectangleFVFVertexBuf)
         IDirect3DVertexBuffer9_Release(ctx->rectangleFVFVertexBuf);
-    IDirect3DDevice9_Release(ctx->libvlc_d3d);
+    if (ctx->libvlc_d3d)
+        IDirect3DDevice9_Release(ctx->libvlc_d3d);
     IDirect3DDevice9_Release(ctx->d3ddev);
     IDirect3D9_Release(ctx->d3d);
 }
@@ -242,7 +242,7 @@ static void release_direct3d(struct render_context *ctx)
 static bool Setup_cb( void **opaque, const libvlc_video_direct3d_device_cfg_t *cfg, libvlc_video_direct3d_device_setup_t *out )
 {
     struct render_context *ctx = *opaque;
-    out->device_context = ctx->libvlc_d3d;
+    out->device_context = ctx->d3d;
     return true;
 }
 
@@ -250,6 +250,11 @@ static void Cleanup_cb( void *opaque )
 {
     /* here we can release all things Direct3D9 for good  (if playing only one file) */
     struct render_context *ctx = opaque;
+    if (ctx->libvlc_d3d)
+    {
+        IDirect3DDevice9_Release(ctx->libvlc_d3d);
+        ctx->libvlc_d3d = NULL;
+    }
 }
 
 static void Resize_cb( void *opaque,
@@ -272,7 +277,7 @@ static void Resize_cb( void *opaque,
 static bool UpdateOutput_cb( void *opaque, const libvlc_video_direct3d_cfg_t *cfg, libvlc_video_output_cfg_t *out )
 {
     struct render_context *ctx = opaque;
-    return Resize(ctx, cfg->width, cfg->height, out);
+    return Resize(ctx, cfg->width, cfg->height, (IDirect3DDevice9*)cfg->device, out);
 }
 
 static void Swap_cb( void* opaque )
diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index 87aaa18648..c274ae2ee0 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -615,7 +615,7 @@ typedef struct
 
 typedef struct
 {
-    void *device_context; /** ID3D11DeviceContext* for D3D11, IDirect3DDevice9 * for D3D9 */
+    void *device_context; /** ID3D11DeviceContext* for D3D11, IDirect3D9 * for D3D9 */
 } libvlc_video_direct3d_device_setup_t;
 
 /** Setup the rendering environment.
@@ -628,7 +628,7 @@ typedef struct
  * \return true on success
  * \version LibVLC 4.0.0 or later
  *
- * For \ref libvlc_video_direct3d_engine_d3d9 the output must be a IDirect3DDevice9*.
+ * For \ref libvlc_video_direct3d_engine_d3d9 the output must be a IDirect3D9*.
  * A reference to this object is held until the \ref LIBVLC_VIDEO_DEVICE_CLEANUP is called.
  * the device must be created with D3DPRESENT_PARAMETERS.hDeviceWindow set to 0.
  *
@@ -673,6 +673,7 @@ typedef struct
     libvlc_video_color_space_t colorspace;              /** video color space */
     libvlc_video_color_primaries_t primaries;       /** video color primaries */
     libvlc_video_transfer_func_t transfer;        /** video transfer function */
+    void *device;   /** device used for rendering, IDirect3DDevice9* for D3D9 */
 } libvlc_video_direct3d_cfg_t;
 
 typedef struct
@@ -692,6 +693,11 @@ typedef struct
  * \param output configuration describing with how the rendering is setup [OUT]
  * \version LibVLC 4.0.0 or later
  *
+ * \note the configuration device for Direct3D9 is the IDirect3DDevice9 that VLC
+ *       uses to render. The host must set a Render target and call Present()
+ *       when it needs the drawing from VLC to be done. This object is not valid
+ *       anymore after Cleanup is called.
+ *
  * Tone mapping, range and color conversion will be done depending on the values
  * set in the output structure.
  */
diff --git a/modules/video_output/win32/direct3d9.c b/modules/video_output/win32/direct3d9.c
index a73b9d46e5..a0aee23101 100644
--- a/modules/video_output/win32/direct3d9.c
+++ b/modules/video_output/win32/direct3d9.c
@@ -600,6 +600,8 @@ static int UpdateOutput(vout_display_t *vd, const video_format_t *fmt)
     cfg.colorspace = fmt->space;
     cfg.transfer   = fmt->transfer;
 
+    cfg.device = sys->d3d_dev.dev;
+
     libvlc_video_output_cfg_t out;
     if (!sys->updateOutputCb( sys->outside_opaque, &cfg, &out ))
     {
@@ -1501,23 +1503,9 @@ static const d3d9_format_t *Direct3DFindFormat(vout_display_t *vd, const video_f
 /**
  * It creates a Direct3D9 device and the associated resources.
  */
-static int Direct3D9Open(vout_display_t *vd, video_format_t *fmt,
-                         IDirect3DDevice9 *external_dev)
+static int Direct3D9Open(vout_display_t *vd, video_format_t *fmt)
 {
     vout_display_sys_t *sys = vd->sys;
-    HRESULT hr;
-
-    if (external_dev)
-        hr = D3D9_CreateDeviceExternal(external_dev, &sys->hd3d, sys->sys.hvideownd,
-                                       &sys->d3d_dev);
-    else
-        hr = D3D9_CreateDevice(vd, &sys->hd3d, sys->sys.hvideownd,
-                               &sys->d3d_dev);
-
-    if (FAILED(hr)) {
-        msg_Err( vd, "D3D9 Creation failed! (hr=0x%lX)", hr);
-        return VLC_EGENERIC;
-    }
 
     const d3d9_device_t *p_d3d9_dev = &sys->d3d_dev;
     /* */
@@ -1628,7 +1616,23 @@ 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 )
 {
-    return false; /* don't use an "external" D3D9 device */
+    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;
+    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 )
@@ -1704,7 +1708,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
 
         sys->outside_opaque = vd;
         sys->setupDeviceCb       = LocalSwapchainSetupDevice;
-        sys->cleanupDeviceCb     = NULL;
+        sys->cleanupDeviceCb     = LocalSwapchainCleanupDevice;
         sys->updateOutputCb      = LocalSwapchainUpdateOutput;
         sys->swapCb              = LocalSwapchainSwap;
         sys->startEndRenderingCb = LocalSwapchainStartEndRendering;
@@ -1714,29 +1718,22 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
         .hardware_decoding = is_d3d9_opaque( vd->source.i_chroma ),
     };
     libvlc_video_direct3d_device_setup_t device_setup;
-    IDirect3DDevice9 *d3d9_device = NULL;
+    IDirect3D9 *d3d9_device = NULL;
     if ( sys->setupDeviceCb( &sys->outside_opaque, &surface_cfg, &device_setup ) )
         d3d9_device = device_setup.device_context;
-    if ( d3d9_device == NULL && sys->setupDeviceCb != LocalSwapchainSetupDevice )
+    if ( d3d9_device == NULL )
     {
-        msg_Err(vd, "Missing external IDirect3DDevice9");
+        msg_Err(vd, "Missing external IDirect3D9");
         return VLC_EGENERIC;
     }
-    if (d3d9_device != NULL)
-    {
-        if (D3D9_CreateExternal(vd, &sys->hd3d, d3d9_device)) {
-            msg_Err(vd, "External Direct3D9 could not be used");
-            if ( sys->cleanupDeviceCb )
-                sys->cleanupDeviceCb( sys->outside_opaque );
-            free(sys);
-            return VLC_EGENERIC;
-        }
-    }
-    else if (D3D9_Create(vd, &sys->hd3d)) {
-        msg_Err( vd, "Direct3D9 could not be initialized" );
+    D3D9_CloneExternal( &sys->hd3d, d3d9_device );
+    HRESULT hr = D3D9_CreateDevice(vd, &sys->hd3d, sys->sys.hvideownd, &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 );
+        free(sys);
         return VLC_EGENERIC;
     }
 
@@ -1763,7 +1760,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
 
     /* */
     video_format_t fmt;
-    if (Direct3D9Open(vd, &fmt, d3d9_device)) {
+    if (Direct3D9Open(vd, &fmt)) {
         msg_Err(vd, "Direct3D9 could not be opened");
         goto error;
     }



More information about the vlc-commits mailing list