On Thu, Feb 2, 2017 at 4:43 PM, Hendrik Leppkes <[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);
>
> I'm not sure its safe to mismatch the release function to the actual
> object in the C API, even if its an "inherited" type, so this would
> need to use the Ex release.

Yes it is safe. In C it calls the callback in a structure with all the
callbacks. The order of the callbacks matter. It is in the same place
for each inherited interface.

If you dislike mismatches you can always call IUnknown_Release() which
is really what it calls and where the method comes from.

> In consequence, this would also mean you would need a separate member
> in the priv context to be able to distinguish them later when doing
> the release again.
>
>> +            } else {
>> +                av_log(ctx, AV_LOG_VERBOSE, "Using D3D9Ex device.\n");
>> +                priv->d3d9 = d3d9ex;
>> +                priv->d3d9device = exdev;
>> +            }
>> +        }
>> +    }
>> +
>> +    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,
>> +                                    &d3dpp, &priv->d3d9device);
>> +        if (FAILED(hr)) {
>> +            av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n");
>> +            return AVERROR_UNKNOWN;
>> +        }
>>      }
>>
>>      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
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to