On Thu, Feb 2, 2017 at 11:27 AM, wm4 <[email protected]> wrote:
> D3D9Ex uses different driver paths. This helps with "headless"
> configurations when no user logs in. Plain D3D9 device creation will
> fail if no user is logged in, while it works with D3D9Ex.
> ---
> libavutil/hwcontext_dxva2.c | 61
> ++++++++++++++++++++++++++++++++++-----------
> 1 file changed, 47 insertions(+), 14 deletions(-)
>
> diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c
> index ccf03c8e9f..b9c26a84f4 100644
> --- a/libavutil/hwcontext_dxva2.c
> +++ b/libavutil/hwcontext_dxva2.c
> @@ -38,6 +38,7 @@
> #include "pixfmt.h"
>
> typedef IDirect3D9* WINAPI pDirect3DCreate9(UINT);
> +typedef HRESULT WINAPI pDirect3DCreate9Ex(UINT, IDirect3D9Ex **);
> typedef HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9
> **);
>
> typedef struct DXVA2Mapping {
> @@ -418,6 +419,7 @@ static int dxva2_device_create(AVHWDeviceContext *ctx,
> const char *device,
> DXVA2DevicePriv *priv;
>
> pDirect3DCreate9 *createD3D = NULL;
> + pDirect3DCreate9Ex *createD3DEx = NULL;
> pCreateDeviceManager9 *createDeviceManager = NULL;
> D3DPRESENT_PARAMETERS d3dpp = {0};
> D3DDISPLAYMODE d3ddm;
> @@ -453,6 +455,7 @@ static int dxva2_device_create(AVHWDeviceContext *ctx,
> const char *device,
> av_log(ctx, AV_LOG_ERROR, "Failed to locate Direct3DCreate9\n");
> return AVERROR_UNKNOWN;
> }
> + createD3DEx = (pDirect3DCreate9Ex *)GetProcAddress(priv->d3dlib,
> "Direct3DCreate9Ex");
> createDeviceManager = (pCreateDeviceManager9
> *)GetProcAddress(priv->dxva2lib,
>
> "DXVA2CreateDirect3DDeviceManager9");
> if (!createDeviceManager) {
> @@ -460,27 +463,57 @@ static int dxva2_device_create(AVHWDeviceContext *ctx,
> const char *device,
> return AVERROR_UNKNOWN;
> }
>
> - priv->d3d9 = createD3D(D3D_SDK_VERSION);
> - if (!priv->d3d9) {
> - av_log(ctx, AV_LOG_ERROR, "Failed to create IDirect3D object\n");
> - return AVERROR_UNKNOWN;
> - }
> -
> - IDirect3D9_GetAdapterDisplayMode(priv->d3d9, adapter, &d3ddm);
> d3dpp.Windowed = TRUE;
> d3dpp.BackBufferWidth = 640;
> d3dpp.BackBufferHeight = 480;
> d3dpp.BackBufferCount = 0;
> - d3dpp.BackBufferFormat = d3ddm.Format;
> d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
> d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
>
> - hr = IDirect3D9_CreateDevice(priv->d3d9, adapter, D3DDEVTYPE_HAL,
> GetShellWindow(),
> - D3DCREATE_SOFTWARE_VERTEXPROCESSING |
> D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
> - &d3dpp, &priv->d3d9device);
> - if (FAILED(hr)) {
> - av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n");
> - return AVERROR_UNKNOWN;
> + if (createD3DEx) {
> + IDirect3D9Ex *d3d9ex = NULL;
> +
> + hr = createD3DEx(D3D_SDK_VERSION, &d3d9ex);
> + if (!FAILED(hr)) {
> + D3DDISPLAYMODEEX modeex = {0};
> + IDirect3DDevice9Ex *exdev = NULL;
> +
> + IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, adapter, &modeex,
> NULL);
> + d3dpp.BackBufferFormat = modeex.Format;
> +
> + hr = IDirect3D9Ex_CreateDeviceEx(d3d9ex, adapter,
> D3DDEVTYPE_HAL, GetShellWindow(),
> +
> D3DCREATE_SOFTWARE_VERTEXPROCESSING |
> + D3DCREATE_MULTITHREADED |
> + D3DCREATE_FPU_PRESERVE,
> + &d3dpp, NULL, &exdev);
> + if (FAILED(hr)) {
> + // Retry with "classic" d3d9 below
> + IDirect3D9_Release(d3d9ex);
> + } else {
> + av_log(ctx, AV_LOG_VERBOSE, "Using D3D9Ex device.\n");
> + priv->d3d9 = d3d9ex;
> + priv->d3d9device = exdev;
In this code path you don't release d3d9ex. Once exdev is created you
don't need to keep a reference. So it can be done right after the
IDirect3D9Ex_CreateDeviceEx() call.
> + }
> + }
> + }
> +
> + if (!priv->d3d9device) {
> + priv->d3d9 = createD3D(D3D_SDK_VERSION);
> + if (!priv->d3d9) {
> + av_log(ctx, AV_LOG_ERROR, "Failed to create IDirect3D object\n");
> + return AVERROR_UNKNOWN;
> + }
> +
> + IDirect3D9_GetAdapterDisplayMode(priv->d3d9, adapter, &d3ddm);
> + d3dpp.BackBufferFormat = d3ddm.Format;
> +
> + hr = IDirect3D9_CreateDevice(priv->d3d9, adapter, D3DDEVTYPE_HAL,
> GetShellWindow(),
> + D3DCREATE_SOFTWARE_VERTEXPROCESSING |
> D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
Maybe the flags value can be factorize to avoid mismatches in the future.
> + &d3dpp, &priv->d3d9device);
> + if (FAILED(hr)) {
> + av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n");
> + return AVERROR_UNKNOWN;
d3d9 should probably be released.
> + }
> }
>
> hr = createDeviceManager(&resetToken, &hwctx->devmgr);
> --
> 2.11.0
>
> _______________________________________________
> libav-devel mailing list
> [email protected]
> https://lists.libav.org/mailman/listinfo/libav-devel
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel