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