mirror of
https://github.com/xenia-project/FFmpeg.git
synced 2024-11-24 03:59:43 +00:00
hwcontext_dxva2: support D3D9Ex
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. Signed-off-by: Anton Khirnov <anton@khirnov.net>
This commit is contained in:
parent
04f3bd3496
commit
c2f97f0508
@ -38,8 +38,22 @@
|
||||
#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)
|
||||
|
||||
static const D3DPRESENT_PARAMETERS dxva2_present_params = {
|
||||
.Windowed = TRUE,
|
||||
.BackBufferWidth = 640,
|
||||
.BackBufferHeight = 480,
|
||||
.BackBufferCount = 0,
|
||||
.SwapEffect = D3DSWAPEFFECT_DISCARD,
|
||||
.Flags = D3DPRESENTFLAG_VIDEO,
|
||||
};
|
||||
|
||||
typedef struct DXVA2Mapping {
|
||||
uint32_t palette_dummy[256];
|
||||
} DXVA2Mapping;
|
||||
@ -411,19 +425,83 @@ 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 = dxva2_present_params;
|
||||
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.BackBufferFormat = d3ddm.Format;
|
||||
|
||||
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 = dxva2_present_params;
|
||||
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.BackBufferFormat = modeex.Format;
|
||||
|
||||
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 +526,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 +533,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);
|
||||
|
Loading…
Reference in New Issue
Block a user