[RFC] d3d11va: Link directly to dxgi.dll and d3d11.dll functions on UWP

Message ID 1496999279-10398-1-git-send-email-martin@martin.st
State Superseded
Headers show

Commit Message

Martin Storsjö June 9, 2017, 9:07 a.m.
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
instead.
---
 configure                     | 11 +++++++++++
 libavutil/hwcontext_d3d11va.c | 17 +++++++++++++++++
 2 files changed, 28 insertions(+)

Comments

wm4 June 9, 2017, 9:23 a.m. | #1
On Fri,  9 Jun 2017 12:07:59 +0300
Martin Storsjö <martin@martin.st> 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
> instead.
> ---

I guess I agree with this, since the only reason to dynamically load
the DLLs is for compatibility with older (non-UWP) systems.

The ifdeffery is still a bit heavy though. Would it be reasonable to do
the following:

1. Put all loading into an init_once function,
2. Load the DLL functions into global (static) variables,
3. Never unload the DLLs (this doesn't help anyway, other than exposing
   various driver bugs)

Then the d3d11va_device_create() code would still look relatively clean.

Anyway, feel no objections to this patch, my suggestion can be applied
later if there's agreement.

Patch

diff --git a/configure b/configure
index 019902c..f06aaaf 100755
--- a/configure
+++ b/configure
@@ -5159,6 +5159,17 @@  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
+check_cpp <<EOF || d3d11va_extralibs="-ldxgi -ld3d11"
+#ifdef WINAPI_FAMILY
+#include <winapifamily.h>
+#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#error not desktop
+#endif
+#endif
+EOF
+
 check_deps $CONFIG_LIST       \
            $CONFIG_EXTRA      \
            $HAVE_LIST         \
diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c
index 3940502..052ffbc 100644
--- a/libavutil/hwcontext_d3d11va.c
+++ b/libavutil/hwcontext_d3d11va.c
@@ -37,6 +37,13 @@ 
 #include "pixdesc.h"
 #include "pixfmt.h"
 
+#ifdef WINAPI_FAMILY
+#include <winapifamily.h>
+#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#define UWP
+#endif
+#endif
+
 typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
 
 typedef struct D3D11VAFramesContext {
@@ -417,11 +424,15 @@  static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
 
     if (device) {
         PFN_CREATE_DXGI_FACTORY mCreateDXGIFactory;
+#ifndef UWP
         HMODULE dxgilib = LoadLibrary("dxgi.dll");
         if (!dxgilib)
             return AVERROR_UNKNOWN;
 
         mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) GetProcAddress(dxgilib, "CreateDXGIFactory");
+#else
+        mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) CreateDXGIFactory1;
+#endif
         if (mCreateDXGIFactory) {
             IDXGIFactory2 *pDXGIFactory;
             hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory);
@@ -432,12 +443,15 @@  static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
                 IDXGIFactory2_Release(pDXGIFactory);
             }
         }
+#ifndef UWP
         FreeLibrary(dxgilib);
+#endif
     }
 
     // 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.
+#ifndef UWP
     d3dlib = LoadLibrary("d3d11.dll");
     if (!d3dlib) {
         av_log(ctx, AV_LOG_ERROR, "Failed to load D3D11 library\n");
@@ -445,6 +459,9 @@  static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
     }
 
     createD3D = (PFN_D3D11_CREATE_DEVICE) GetProcAddress(d3dlib, "D3D11CreateDevice");
+#else
+    createD3D = (PFN_D3D11_CREATE_DEVICE) D3D11CreateDevice;
+#endif
     if (!createD3D) {
         av_log(ctx, AV_LOG_ERROR, "Failed to locate D3D11CreateDevice\n");
         return AVERROR_UNKNOWN;