On Tue, 13 Jun 2017 21:56:42 +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.
> ---
> Requiring both d3d11.dll and dxgi.dll now, simplifying it slightly.
> 
> Moved the configure check as suggested by Diego, and renamed the
> createD3D function as suggested by wm4.
> 
> Still untested at runtime, I've only compile tested it (both codepaths,
> with MSVC, but not with mingw).
> ---
>  configure                     |  4 +++
>  libavutil/hwcontext_d3d11va.c | 80 
> +++++++++++++++++++++++++------------------
>  2 files changed, 51 insertions(+), 33 deletions(-)
> 
> diff --git a/configure b/configure
> index 019902c..223106f 100755
> --- a/configure
> +++ b/configure
> @@ -4885,6 +4885,10 @@ if enabled libxcb; then
>          check_pkg_config libxcb_xfixes xcb-xfixes xcb/xfixes.h 
> xcb_xfixes_get_cursor_image
>  fi
>  
> +# d3d11va requires linking directly to dxgi and d3d11 if not building for
> +# the desktop api partition
> +enabled LoadLibrary || d3d11va_extralibs="-ldxgi -ld3d11"
> +
>  enabled vaapi && require vaapi va/va.h vaInitialize -lva
>  
>  enabled vaapi &&
> diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c
> index 3940502..5432dd8 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,34 @@
>  
>  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 mD3D11CreateDevice;
> +
> +static av_cold void load_functions(void)
> +{
> +#if HAVE_LOADLIBRARY
> +    // 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 || !dxgilib)
> +        return;
> +
> +    mD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE) GetProcAddress(d3dlib, 
> "D3D11CreateDevice");
> +    mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) GetProcAddress(dxgilib, 
> "CreateDXGIFactory");
> +#else
> +    // In UWP (which lacks LoadLibrary), CreateDXGIFactory isn't available,
> +    // only CreateDXGIFactory1
> +    mD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE) D3D11CreateDevice;
> +    mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) CreateDXGIFactory1;
> +#endif
> +}
> +
>  typedef struct D3D11VAFramesContext {
>      int nb_surfaces_used;
>  
> @@ -407,50 +439,32 @@ 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 AVERROR_UNKNOWN;
> +    if (!mD3D11CreateDevice || !mCreateDXGIFactory) {
> +        av_log(ctx, AV_LOG_ERROR, "Failed to load D3D11 library or its 
> functions\n");
>          return AVERROR_UNKNOWN;
>      }
>  
> -    createD3D = (PFN_D3D11_CREATE_DEVICE) GetProcAddress(d3dlib, 
> "D3D11CreateDevice");
> -    if (!createD3D) {
> -        av_log(ctx, AV_LOG_ERROR, "Failed to locate D3D11CreateDevice\n");
> -        return AVERROR_UNKNOWN;
> +    if (device) {
> +        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);
> +        }
>      }
>  
> -    hr = createD3D(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : 
> D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0,
> +    hr = mD3D11CreateDevice(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : 
> D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0,
>                     D3D11_SDK_VERSION, &device_hwctx->device, NULL, NULL);
>      if (pAdapter)
>          IDXGIAdapter_Release(pAdapter);

LGTM (I didn't test it yet either.)
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to