diff --git a/doc/libvlc/d3d9_player.c b/doc/libvlc/d3d9_player.c index 43fb3c1d4c4c39a691250ca2161a41e52edd5362..0333702e0def7f1066574dace4cac12eda46e4fe 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 87aaa186482c207da6ca2da03f537f8929fa712f..c274ae2ee03a9d705fe5944e9ea14e19ab93066f 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 a73b9d46e582dedd023d69daca889f129d29aa85..a0aee23101b3171f9afd5a1dc97d7182084537ec 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; }