On Fri, Feb 3, 2017 at 11:22 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 | 120 
> +++++++++++++++++++++++++++++++++-----------
>  1 file changed, 90 insertions(+), 30 deletions(-)
>
> diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c
> index ccf03c8e9f..eac98c3df0 100644
> --- a/libavutil/hwcontext_dxva2.c
> +++ b/libavutil/hwcontext_dxva2.c
> @@ -38,8 +38,13 @@
>  #include "pixfmt.h"
>
>  typedef IDirect3D9* WINAPI pDirect3DCreate9(UINT);
> +typedef HRESULT WINAPI pDirect3DCreate9Ex(UINT, IDirect3D9Ex **);
>  typedef HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9 
> **);
>
> +#define FF_D3DCREATE_FLAGS (D3DCREATE_SOFTWARE_VERTEXPROCESSING | \
> +                            D3DCREATE_MULTITHREADED | \
> +                            D3DCREATE_FPU_PRESERVE)
> +
>  typedef struct DXVA2Mapping {
>      uint32_t palette_dummy[256];
>  } DXVA2Mapping;
> @@ -411,19 +416,95 @@ static void dxva2_device_free(AVHWDeviceContext *ctx)
>      av_freep(&ctx->user_opaque);
>  }
>
> +static int dxva2_device_create9(AVHWDeviceContext *ctx, UINT adapter)
> +{
> +    DXVA2DevicePriv *priv = ctx->user_opaque;
> +    D3DPRESENT_PARAMETERS d3dpp = {0};
> +    D3DDISPLAYMODE d3ddm;
> +    HRESULT hr;
> +    pDirect3DCreate9 *createD3D = (pDirect3DCreate9 
> *)GetProcAddress(priv->d3dlib, "Direct3DCreate9");
> +    if (!createD3D) {
> +        av_log(ctx, AV_LOG_ERROR, "Failed to locate Direct3DCreate9\n");
> +        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(),
> +                                FF_D3DCREATE_FLAGS,
> +                                &d3dpp, &priv->d3d9device);
> +    if (FAILED(hr)) {
> +        av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n");
> +        return AVERROR_UNKNOWN;
> +    }
> +
> +    return 0;
> +}
> +
> +static int dxva2_device_create9ex(AVHWDeviceContext *ctx, UINT adapter)
> +{
> +    DXVA2DevicePriv *priv = ctx->user_opaque;
> +    D3DPRESENT_PARAMETERS d3dpp = {0};
> +    D3DDISPLAYMODEEX modeex = {0};
> +    IDirect3D9Ex *d3d9ex = NULL;
> +    IDirect3DDevice9Ex *exdev = NULL;
> +    HRESULT hr;
> +    pDirect3DCreate9Ex *createD3DEx = (pDirect3DCreate9Ex 
> *)GetProcAddress(priv->d3dlib, "Direct3DCreate9Ex");
> +    if (!createD3DEx)
> +        return AVERROR(ENOSYS);
> +
> +    hr = createD3DEx(D3D_SDK_VERSION, &d3d9ex);
> +    if (FAILED(hr))
> +        return AVERROR_UNKNOWN;
> +
> +    IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, adapter, &modeex, NULL);
> +
> +    d3dpp.Windowed         = TRUE;
> +    d3dpp.BackBufferWidth  = 640;
> +    d3dpp.BackBufferHeight = 480;
> +    d3dpp.BackBufferCount  = 0;
> +    d3dpp.BackBufferFormat = modeex.Format;
> +    d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
> +    d3dpp.Flags            = D3DPRESENTFLAG_VIDEO;

The whole D3DPRESENT_PARAMETERS init is the same so the code should be
common as well.

> +
> +    hr = IDirect3D9Ex_CreateDeviceEx(d3d9ex, adapter, D3DDEVTYPE_HAL, 
> GetShellWindow(),
> +                                     FF_D3DCREATE_FLAGS,
> +                                     &d3dpp, NULL, &exdev);
> +    if (FAILED(hr)) {
> +        IDirect3D9Ex_Release(d3d9ex);
> +        return AVERROR_UNKNOWN;
> +    }
> +
> +    av_log(ctx, AV_LOG_VERBOSE, "Using D3D9Ex device.\n");
> +    priv->d3d9 = (IDirect3D9 *)d3d9ex;
> +    priv->d3d9device = (IDirect3DDevice9 *)exdev;
> +    return 0;
> +}
> +
>  static int dxva2_device_create(AVHWDeviceContext *ctx, const char *device,
>                                 AVDictionary *opts, int flags)
>  {
>      AVDXVA2DeviceContext *hwctx = ctx->hwctx;
>      DXVA2DevicePriv *priv;
> -
> -    pDirect3DCreate9 *createD3D = NULL;
>      pCreateDeviceManager9 *createDeviceManager = NULL;
> -    D3DPRESENT_PARAMETERS d3dpp = {0};
> -    D3DDISPLAYMODE        d3ddm;
>      unsigned resetToken = 0;
>      UINT adapter = D3DADAPTER_DEFAULT;
>      HRESULT hr;
> +    int err;
>
>      if (device)
>          adapter = atoi(device);
> @@ -448,11 +529,6 @@ static int dxva2_device_create(AVHWDeviceContext *ctx, 
> const char *device,
>          return AVERROR_UNKNOWN;
>      }
>
> -    createD3D = (pDirect3DCreate9 *)GetProcAddress(priv->d3dlib, 
> "Direct3DCreate9");
> -    if (!createD3D) {
> -        av_log(ctx, AV_LOG_ERROR, "Failed to locate Direct3DCreate9\n");
> -        return AVERROR_UNKNOWN;
> -    }
>      createDeviceManager = (pCreateDeviceManager9 
> *)GetProcAddress(priv->dxva2lib,
>                                                                    
> "DXVA2CreateDirect3DDeviceManager9");
>      if (!createDeviceManager) {
> @@ -460,27 +536,11 @@ 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 (dxva2_device_create9ex(ctx, adapter) < 0) {
> +        // Retry with "classic" d3d9
> +        err = dxva2_device_create9(ctx, adapter);
> +        if (err < 0)
> +            return err;
>      }
>
>      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

Reply via email to