On Fri, 3 Feb 2017 10:02:44 +0000
Stève Lhomme <[email protected]> wrote:

> 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.

The reference goes to priv->d3d9.

> > +            }
> > +        }
> > +    }
> > +
> > +    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.

I'll make a define.

> > +                                    &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.

This is taken care by dxva2_device_free, which should be called by the
common hwcontext code if device creation returns with an error.
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to