d3d: simplify DLL loading

For some reason, the d3d9/dxva2/d3d11 DLLs are still optional. But we
don't need to try so hard to keep exact references. In fact, there's no
reason to unload them at all.

So load them once in a central place. For simplicity, the d3d9/d3d11
backends both load all DLLs. (They will error out only if the required
DLLs could not be loaded.)

In theory, we could just call LoadLibrary multiple times (without
calling FreeLibrary), but I'm slightly worried that this could be
detected as a "bug", or that the reference count could even have a low
static limit that could be hit soon.
This commit is contained in:
wm4 2016-05-17 11:57:28 +02:00
parent 39b64fb176
commit a02d77ba0d
4 changed files with 34 additions and 49 deletions

View File

@ -15,6 +15,8 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <pthread.h>
#include <libavcodec/avcodec.h>
#include "lavc.h"
@ -96,6 +98,22 @@ static const struct d3dva_mode d3dva_modes[] = {
#undef MODE
#undef MODE2
HMODULE d3d11_dll, d3d9_dll, dxva2_dll;
static pthread_once_t d3d_load_once = PTHREAD_ONCE_INIT;
static void d3d_do_load(void)
{
d3d11_dll = LoadLibrary(L"d3d11.dll");
d3d9_dll = LoadLibrary(L"d3d9.dll");
dxva2_dll = LoadLibrary(L"dxva2.dll");
}
void d3d_load_dlls(void)
{
pthread_once(&d3d_load_once, d3d_do_load);
}
int d3d_probe_codec(const char *codec)
{
enum AVCodecID codecid = mp_codec_to_av_codec_id(codec);

View File

@ -36,6 +36,12 @@ struct d3d_decoder_fmt {
const struct d3d_decoded_format *format;
};
// Must call d3d_load_dlls() before accessing. Once this is done, the DLLs
// remain loaded forever.
extern HMODULE d3d11_dll, d3d9_dll, dxva2_dll;
void d3d_load_dlls(void);
int d3d_probe_codec(const char *codec);
struct d3d_decoder_fmt d3d_select_decoder_mode(

View File

@ -40,7 +40,6 @@ struct d3d11va_decoder {
struct priv {
struct mp_log *log;
HMODULE d3d11_dll;
ID3D11Device *device;
ID3D11DeviceContext *device_ctx;
ID3D11VideoDevice *video_dev;
@ -51,7 +50,6 @@ struct priv {
};
struct d3d11va_surface {
HMODULE d3d11_dll;
ID3D11Texture2D *texture;
int subindex;
ID3D11VideoDecoderOutputView *surface;
@ -66,9 +64,6 @@ static void d3d11va_release_img(void *arg)
if (surface->texture)
ID3D11Texture2D_Release(surface->texture);
if (surface->d3d11_dll)
FreeLibrary(surface->d3d11_dll);
talloc_free(surface);
}
@ -79,10 +74,6 @@ static struct mp_image *d3d11va_new_ref(ID3D11VideoDecoderOutputView *view,
return NULL;
struct d3d11va_surface *surface = talloc_zero(NULL, struct d3d11va_surface);
surface->d3d11_dll = LoadLibrary(L"d3d11.dll");
if (!surface->d3d11_dll)
goto fail;
surface->surface = view;
ID3D11VideoDecoderOutputView_AddRef(surface->surface);
ID3D11VideoDecoderOutputView_GetResource(
@ -105,9 +96,6 @@ static struct mp_image *d3d11va_new_ref(ID3D11VideoDecoderOutputView *view,
mpi->planes[3] = (void *)surface->surface;
return mpi;
fail:
d3d11va_release_img(surface);
return NULL;
}
static struct mp_image *d3d11va_allocate_image(struct lavc_ctx *s, int w, int h)
@ -434,9 +422,6 @@ static void destroy_device(struct lavc_ctx *s)
if (p->device_ctx)
ID3D11DeviceContext_Release(p->device_ctx);
if (p->d3d11_dll)
FreeLibrary(p->d3d11_dll);
}
static bool create_device(struct lavc_ctx *s, BOOL thread_safe)
@ -444,14 +429,14 @@ static bool create_device(struct lavc_ctx *s, BOOL thread_safe)
HRESULT hr;
struct priv *p = s->hwdec_priv;
p->d3d11_dll = LoadLibrary(L"d3d11.dll");
if (!p->d3d11_dll) {
d3d_load_dlls();
if (!d3d11_dll) {
MP_ERR(p, "Failed to load D3D11 library\n");
return false;
}
PFN_D3D11_CREATE_DEVICE CreateDevice =
(void *)GetProcAddress(p->d3d11_dll, "D3D11CreateDevice");
(void *)GetProcAddress(d3d11_dll, "D3D11CreateDevice");
if (!CreateDevice) {
MP_ERR(p, "Failed to get D3D11CreateDevice symbol from DLL: %s\n",
mp_LastError_to_str());

View File

@ -39,8 +39,6 @@
struct priv {
struct mp_log *log;
HMODULE d3d9_dll;
HMODULE dxva2_dll;
IDirect3D9 *d3d9;
IDirect3DDevice9 *device;
HANDLE device_handle;
@ -53,9 +51,6 @@ struct priv {
};
struct dxva2_surface {
HMODULE d3dlib;
HMODULE dxva2lib;
IDirectXVideoDecoder *decoder;
IDirect3DSurface9 *surface;
};
@ -69,12 +64,6 @@ static void dxva2_release_img(void *arg)
if (surface->decoder)
IDirectXVideoDecoder_Release(surface->decoder);
if (surface->dxva2lib)
FreeLibrary(surface->dxva2lib);
if (surface->d3dlib)
FreeLibrary(surface->d3dlib);
talloc_free(surface);
}
@ -86,13 +75,6 @@ static struct mp_image *dxva2_new_ref(IDirectXVideoDecoder *decoder,
return NULL;
struct dxva2_surface *surface = talloc_zero(NULL, struct dxva2_surface);
// Add additional references to the libraries which might otherwise be freed
// before the surface, which is observed to lead to bad behaviour
surface->d3dlib = LoadLibrary(L"d3d9.dll");
surface->dxva2lib = LoadLibrary(L"dxva2.dll");
if (!surface->d3dlib || !surface->dxva2lib)
goto fail;
surface->surface = d3d9_surface;
IDirect3DSurface9_AddRef(surface->surface);
surface->decoder = decoder;
@ -368,25 +350,20 @@ static void destroy_device(struct lavc_ctx *s)
if (p->d3d9)
IDirect3D9_Release(p->d3d9);
if (p->d3d9_dll)
FreeLibrary(p->d3d9_dll);
if (p->dxva2_dll)
FreeLibrary(p->dxva2_dll);
}
static bool create_device(struct lavc_ctx *s)
{
struct priv *p = s->hwdec_priv;
p->d3d9_dll = LoadLibrary(L"d3d9.dll");
if (!p->d3d9_dll) {
d3d_load_dlls();
if (!d3d9_dll) {
MP_ERR(p, "Failed to load D3D9 library\n");
return false;
}
IDirect3D9* (WINAPI *Direct3DCreate9)(UINT) =
(void *)GetProcAddress(p->d3d9_dll, "Direct3DCreate9");
(void *)GetProcAddress(d3d9_dll, "Direct3DCreate9");
if (!Direct3DCreate9) {
MP_ERR(p, "Failed to locate Direct3DCreate9\n");
return false;
@ -477,15 +454,14 @@ static int dxva2_init(struct lavc_ctx *s)
goto fail;
}
p->dxva2_dll = LoadLibrary(L"dxva2.dll");
if (!p->dxva2_dll) {
d3d_load_dlls();
if (!dxva2_dll) {
MP_ERR(p, "Failed to load DXVA2 library\n");
goto fail;
}
HRESULT (WINAPI *CreateDeviceManager9)(UINT *, IDirect3DDeviceManager9 **) =
(void *)GetProcAddress(p->dxva2_dll,
"DXVA2CreateDirect3DDeviceManager9");
(void *)GetProcAddress(dxva2_dll, "DXVA2CreateDirect3DDeviceManager9");
if (!CreateDeviceManager9) {
MP_ERR(p, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n");
goto fail;