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

Reply via email to