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.
> +
> +static av_cold void load_functions(void)
> +{
> +#if HAVE_LOADLIBRARY
The UWP define wasn't sufficient?
> + // 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");
> +#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?
> + if (!createD3D) {
> + 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;
> + if (!mCreateDXGIFactory)
> + return AVERROR_UNKNOWN;
> + 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,
Otherwise LGTM.
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel