Message ID | 1497380202-30673-1-git-send-email-martin@martin.st |
---|---|
State | Committed |
Commit | fd1ffa1f10e940165035ccb79d4a6523da196062 |
Headers | show |
On Tue, 13 Jun 2017 21:56:42 +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. > --- > 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.)
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);