On Tue, 13 Jun 2017, wm4 wrote:

On Tue, 13 Jun 2017 15:31:12 +0300
Martin Storsjö <[email protected]> wrote:

When targeting the UWP API subset, the LoadLibrary function is not
available (and the fallback, LoadPackagedLibrary, can't be used to
load system DLLs). In these cases, link directly to the functions
in the DLLs instead of trying to load them dynamically at runtime.
---
I kept the behaviour where we don't error out if dxgi.dll is missing,
if the device parameter is null, although I'm not sure if the
distinction is relevant.

I changed checks for UWP into checks for the LoadLibrary function,
which in general feels more straightforward.

Do note that this uses the CreateDXGIFactory1 function if LoadLibrary
isn't available, since the unsuffixed version of the function isn't
available in UWP.

I don't have any actual environment to test this in, so I'd appreciate
if someone can do that.
---
 configure                     |  4 +++
 libavutil/hwcontext_d3d11va.c | 79 +++++++++++++++++++++++++------------------
 2 files changed, 51 insertions(+), 32 deletions(-)

diff --git a/configure b/configure
index 019902c..e7556e0 100755
--- a/configure
+++ b/configure
@@ -5159,6 +5159,10 @@ esac

 enabled asm || { arch=c; disable $ARCH_LIST $ARCH_EXT_LIST; }

+# d3d11va requires linking directly to dxgi and d3d11 if not building for
+# the desktop api partition
+enabled LoadLibrary || d3d11va_extralibs="-ldxgi -ld3d11"
+
 check_deps $CONFIG_LIST       \
            $CONFIG_EXTRA      \
            $HAVE_LIST         \
diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c
index 3940502..4de674d 100644
--- a/libavutil/hwcontext_d3d11va.c
+++ b/libavutil/hwcontext_d3d11va.c
@@ -18,6 +18,10 @@

 #include <windows.h>

+// Include thread.h before redefining _WIN32_WINNT, to get
+// the right implementation for AVOnce
+#include "thread.h"
+
 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600
 #undef _WIN32_WINNT
 #define _WIN32_WINNT 0x0600
@@ -39,6 +43,33 @@

 typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void 
**ppFactory);

+static AVOnce functions_loaded = AV_ONCE_INIT;
+
+static PFN_CREATE_DXGI_FACTORY mCreateDXGIFactory;
+static PFN_D3D11_CREATE_DEVICE createD3D;

I think following a consistent naming convention would be good. I like
"m" + real API name.

So mD3D11CreateDevice?

+
+static av_cold void load_functions(void)
+{
+#if HAVE_LOADLIBRARY

The UWP define wasn't sufficient?

It was sufficient, but IMO this condition is simpler (especially for configure). But with CreateDXGIFactory vs CreateDXGIFactory1, having it specific for UWP might be better of course.

+    // We let these "leak" - this is fine, as unloading has no great benefit, 
and
+    // Windows will mark a DLL as loaded forever if its internal refcount 
overflows
+    // from too many LoadLibrary calls.
+    HANDLE d3dlib, dxgilib;
+
+    d3dlib  = LoadLibrary("d3d11.dll");
+    dxgilib = LoadLibrary("dxgi.dll");
+    if (!d3dlib)
+        return;
+
+    createD3D = (PFN_D3D11_CREATE_DEVICE) GetProcAddress(d3dlib, 
"D3D11CreateDevice");
+    if (dxgilib)
+        mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) GetProcAddress(dxgilib, 
"CreateDXGIFactory");

Was this intentional that we should try to continue even if dxgi.dll doesn't exist, in case the device parameter is null? Or was that just coincidental behaviour in the previous form of the code?

+#else
+    createD3D = (PFN_D3D11_CREATE_DEVICE) D3D11CreateDevice;
+    mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) CreateDXGIFactory1;
+#endif
+}
+
 typedef struct D3D11VAFramesContext {
     int nb_surfaces_used;

@@ -407,47 +438,31 @@ static int d3d11va_device_create(AVHWDeviceContext *ctx, 
const char *device,
                                  AVDictionary *opts, int flags)
 {
     AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
-    HANDLE d3dlib;

     HRESULT hr;
-    PFN_D3D11_CREATE_DEVICE createD3D;
     IDXGIAdapter           *pAdapter = NULL;
     ID3D10Multithread      *pMultithread;
     UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
+    int ret;

-    if (device) {
-        PFN_CREATE_DXGI_FACTORY mCreateDXGIFactory;
-        HMODULE dxgilib = LoadLibrary("dxgi.dll");
-        if (!dxgilib)
-            return AVERROR_UNKNOWN;
-
-        mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) GetProcAddress(dxgilib, 
"CreateDXGIFactory");
-        if (mCreateDXGIFactory) {
-            IDXGIFactory2 *pDXGIFactory;
-            hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void 
**)&pDXGIFactory);
-            if (SUCCEEDED(hr)) {
-                int adapter = atoi(device);
-                if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, 
&pAdapter)))
-                    pAdapter = NULL;
-                IDXGIFactory2_Release(pDXGIFactory);
-            }
-        }
-        FreeLibrary(dxgilib);
-    }
-
-    // We let this "leak" - this is fine, as unloading has no great benefit, 
and
-    // Windows will mark a DLL as loaded forever if its internal refcount 
overflows
-    // from too many LoadLibrary calls.
-    d3dlib = LoadLibrary("d3d11.dll");
-    if (!d3dlib) {
-        av_log(ctx, AV_LOG_ERROR, "Failed to load D3D11 library\n");
+    if ((ret = ff_thread_once(&functions_loaded, load_functions)) != 0)
+        return ret;

Does this really return an AVERROR code?

Good catch - no it doesn't, changed to return AVERROR_UNKNOWN.

// Martin
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to