1 /*############################################################################
2 # Copyright (C) Intel Corporation
4 # SPDX-License-Identifier: MIT
5 ############################################################################*/
7 #include "windows/mfx_library_iterator.h"
9 #include "windows/mfx_dispatcher.h"
10 #include "windows/mfx_dispatcher_log.h"
12 #include "windows/mfx_dxva2_device.h"
13 #include "windows/mfx_load_dll.h"
22 enum { MFX_MAX_MERIT = 0x7fffffff };
25 // declare registry keys
28 const wchar_t rootDispPath[] = L"Software\\Intel\\MediaSDK\\Dispatch";
29 const wchar_t vendorIDKeyName[] = L"VendorID";
30 const wchar_t deviceIDKeyName[] = L"DeviceID";
31 const wchar_t meritKeyName[] = L"Merit";
32 const wchar_t pathKeyName[] = L"Path";
33 const wchar_t apiVersionName[] = L"APIVersion";
35 mfxStatus SelectImplementationType(const mfxU32 adapterNum,
36 mfxIMPL *pImplInterface,
40 if (NULL == pImplInterface) {
41 return MFX_ERR_NULL_PTR;
43 mfxIMPL impl_via = *pImplInterface;
45 DXVA2Device dxvaDevice;
46 if (MFX_IMPL_VIA_D3D9 == impl_via) {
47 // try to create the Direct3D 9 device and find right adapter
48 if (!dxvaDevice.InitD3D9(adapterNum)) {
49 DISPATCHER_LOG_INFO((("dxvaDevice.InitD3D9(%d) Failed "), adapterNum));
50 return MFX_ERR_UNSUPPORTED;
53 else if (MFX_IMPL_VIA_D3D11 == impl_via) {
54 // try to open DXGI 1.1 device to get hardware ID
55 if (!dxvaDevice.InitDXGI1(adapterNum)) {
56 DISPATCHER_LOG_INFO((("dxvaDevice.InitDXGI1(%d) Failed "), adapterNum));
57 return MFX_ERR_UNSUPPORTED;
60 else if (MFX_IMPL_VIA_ANY == impl_via) {
61 // try the Direct3D 9 device
62 if (dxvaDevice.InitD3D9(adapterNum)) {
63 *pImplInterface = MFX_IMPL_VIA_D3D9; // store value for GetImplementationType() call
65 // else try to open DXGI 1.1 device to get hardware ID
66 else if (dxvaDevice.InitDXGI1(adapterNum)) {
67 *pImplInterface = MFX_IMPL_VIA_D3D11; // store value for GetImplementationType() call
70 DISPATCHER_LOG_INFO((("Unsupported adapter %d "), adapterNum));
71 return MFX_ERR_UNSUPPORTED;
75 DISPATCHER_LOG_ERROR((("Unknown implementation type %d "), *pImplInterface));
76 return MFX_ERR_UNSUPPORTED;
79 // obtain card's parameters
80 if (pVendorID && pDeviceID) {
81 *pVendorID = dxvaDevice.GetVendorID();
82 *pDeviceID = dxvaDevice.GetDeviceID();
86 *pLUID = dxvaDevice.GetLUID();
92 mfxStatus SelectImplementationType(const mfxU32 adapterNum,
93 mfxIMPL *pImplInterface,
97 return SelectImplementationType(adapterNum, pImplInterface, pVendorID, pDeviceID, nullptr);
100 MFXLibraryIterator::MFXLibraryIterator(void)
101 #if !defined(MEDIASDK_UWP_DISPATCHER)
105 m_implType = MFX_LIB_PSEUDO;
106 m_implInterface = MFX_IMPL_UNSUPPORTED;
112 m_lastLibMerit = MFX_MAX_MERIT;
114 m_bIsSubKeyValid = 0;
118 m_driverStoreDir[0] = 0;
119 } // MFXLibraryIterator::MFXLibraryIterator(void)
121 MFXLibraryIterator::~MFXLibraryIterator(void) {
124 } // MFXLibraryIterator::~MFXLibraryIterator(void)
126 void MFXLibraryIterator::Release(void) {
127 m_implType = MFX_LIB_PSEUDO;
128 m_implInterface = MFX_IMPL_UNSUPPORTED;
134 m_lastLibMerit = MFX_MAX_MERIT;
137 } // void MFXLibraryIterator::Release(void)
139 DECLSPEC_NOINLINE HMODULE GetThisDllModuleHandle() {
143 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
144 reinterpret_cast<LPCWSTR>(&GetThisDllModuleHandle),
149 // wchar_t* sImplPath must be allocated with size not less then msdk_disp_path_len
150 bool GetImplPath(int storageID, wchar_t *sImplPath) {
151 HMODULE hModule = NULL;
153 sImplPath[0] = L'\0';
159 case MFX_PATH_MSDK_FOLDER:
160 hModule = GetThisDllModuleHandle();
161 HMODULE exeModule = GetModuleHandleW(NULL);
162 //It should works only if Dispatcher is linked with Dynamic Linked Library
163 if (!hModule || !exeModule || hModule == exeModule)
169 DWORD allocSize = msdk_disp_path_len;
171 nSize = GetModuleFileNameW(hModule, &sImplPath[0], allocSize);
173 if (nSize == 0 || nSize == allocSize) {
174 // nSize == 0 meanse that system can't get this info for hModule
175 // nSize == allocSize buffer is too small
179 // for any case because WinXP implementation of GetModuleFileName does not add \0 to the end of string
180 sImplPath[nSize] = L'\0';
182 wchar_t *dirSeparator = wcsrchr(sImplPath, L'\\');
183 if (dirSeparator != NULL && dirSeparator < (sImplPath + msdk_disp_path_len)) {
189 mfxStatus MFXLibraryIterator::Init(eMfxImplType implType,
190 mfxIMPL implInterface,
191 const mfxU32 adapterNum,
194 if ((MFX_LIB_SOFTWARE != implType) && (MFX_LIB_HARDWARE != implType)) {
195 return MFX_ERR_UNSUPPORTED;
198 // release the object before initialization
200 m_StorageID = storageID;
202 m_implType = implType;
203 m_implInterface = implInterface != 0 ? implInterface : MFX_IMPL_VIA_ANY;
205 // for HW impl check impl interface, check adapter, obtain deviceID and vendorID
206 if (m_implType != MFX_LIB_SOFTWARE) {
208 MFX::SelectImplementationType(adapterNum, &m_implInterface, &m_vendorID, &m_deviceID);
209 if (MFX_ERR_NONE != mfxRes) {
214 #if !defined(MEDIASDK_UWP_DISPATCHER)
215 if (storageID == MFX_CURRENT_USER_KEY || storageID == MFX_LOCAL_MACHINE_KEY ||
216 storageID == MFX_CURRENT_USER_KEY_ONEVPL || storageID == MFX_LOCAL_MACHINE_KEY_ONEVPL) {
217 return InitRegistry(storageID);
220 #if defined(MFX_TRACER_WA_FOR_DS)
221 if (storageID == MFX_TRACER) {
222 return InitRegistryTracer();
227 if (storageID == MFX_DRIVER_STORE) {
228 m_driverStoreDir[0] = 0;
229 if (!m_driverStoreLoader.GetDriverStorePath(m_driverStoreDir,
230 sizeof(m_driverStoreDir),
232 L"DriverStorePathForMediaSDK")) {
233 return MFX_ERR_UNSUPPORTED;
236 else if (storageID == MFX_DRIVER_STORE_ONEVPL || storageID == MFX_DRIVER_STORE_ONEVPL_MFXINIT) {
237 // get path to runtime directory only (without library name)
238 m_driverStoreDir[0] = 0;
239 if (!m_driverStoreLoader.GetDriverStorePath(m_driverStoreDir,
240 sizeof(m_driverStoreDir),
242 L"DriverStorePathForVPL")) {
243 return MFX_ERR_UNSUPPORTED;
246 else if (!GetImplPath(storageID, m_driverStoreDir)) {
247 return MFX_ERR_UNSUPPORTED;
250 // only need the path for oneVPL loader
251 if (storageID == MFX_DRIVER_STORE_ONEVPL || storageID == MFX_CURRENT_USER_KEY_ONEVPL ||
252 storageID == MFX_LOCAL_MACHINE_KEY_ONEVPL) {
256 return InitFolder(implType, m_driverStoreDir, storageID);
258 } // mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, const mfxU32 adapterNum, int storageID)
260 mfxStatus MFXLibraryIterator::InitRegistry(int storageID) {
261 #if !defined(MEDIASDK_UWP_DISPATCHER)
265 // open required registry key
267 case MFX_LOCAL_MACHINE_KEY:
268 case MFX_LOCAL_MACHINE_KEY_ONEVPL:
269 rootHKey = HKEY_LOCAL_MACHINE;
272 rootHKey = HKEY_CURRENT_USER;
276 bRes = m_baseRegKey.Open(rootHKey, rootDispPath, KEY_READ);
279 (("Can't open %s\\%S : RegOpenKeyExA()==0x%x\n"),
280 (MFX_LOCAL_MACHINE_KEY == storageID) ? ("HKEY_LOCAL_MACHINE") : ("HKEY_CURRENT_USER"),
283 return MFX_ERR_UNKNOWN;
287 (("Inspecting %s\\%S\n"),
288 (MFX_LOCAL_MACHINE_KEY == storageID) ? ("HKEY_LOCAL_MACHINE") : ("HKEY_CURRENT_USER"),
294 return MFX_ERR_UNSUPPORTED;
295 #endif // #if !defined(MEDIASDK_UWP_DISPATCHER)
297 } // mfxStatus MFXLibraryIterator::InitRegistry(int storageID)
299 #if defined(MFX_TRACER_WA_FOR_DS)
300 mfxStatus MFXLibraryIterator::InitRegistryTracer() {
301 #if !defined(MEDIASDK_UWP_DISPATCHER)
303 const wchar_t tracerRegKeyPath[] = L"Software\\Intel\\MediaSDK\\Dispatch\\tracer";
305 if (!m_baseRegKey.Open(HKEY_LOCAL_MACHINE, tracerRegKeyPath, KEY_READ) &&
306 !m_baseRegKey.Open(HKEY_CURRENT_USER, tracerRegKeyPath, KEY_READ)) {
307 DISPATCHER_LOG_WRN(("can't find tracer registry key\n"))
308 return MFX_ERR_UNKNOWN;
311 DISPATCHER_LOG_INFO(("found tracer registry key\n"))
315 return MFX_ERR_UNSUPPORTED;
316 #endif // #if !defined(MEDIASDK_UWP_DISPATCHER)
318 } // mfxStatus MFXLibraryIterator::InitRegistryTracer()
321 mfxStatus MFXLibraryIterator::InitFolder(eMfxImplType implType,
323 const int storageID) {
324 const int maxPathLen = sizeof(m_path) / sizeof(m_path[0]);
326 wcscpy_s(m_path, maxPathLen, path);
327 size_t pathLen = wcslen(m_path);
329 if (storageID == MFX_APP_FOLDER) {
330 // we looking for runtime in application folder, it should be named libmfxsw64 or libmfxsw32
331 mfx_get_default_dll_name(m_path + pathLen, msdk_disp_path_len - pathLen, MFX_LIB_SOFTWARE);
333 else if (storageID == MFX_DRIVER_STORE_ONEVPL_MFXINIT) {
334 mfx_get_default_onevpl_dll_name(m_path + pathLen, msdk_disp_path_len - pathLen);
337 mfx_get_default_dll_name(m_path + pathLen, msdk_disp_path_len - pathLen, implType);
341 } // mfxStatus MFXLibraryIterator::InitFolder(eMfxImplType implType, const wchar_t * path, const int storageID)
343 mfxStatus MFXLibraryIterator::SelectDLLVersion(wchar_t *pPath,
345 eMfxImplType *pImplType,
346 mfxVersion minVersion) {
347 UNREFERENCED_PARAMETER(minVersion);
349 if (m_StorageID == MFX_APP_FOLDER) {
350 if (m_lastLibIndex != 0)
351 return MFX_ERR_NOT_FOUND;
352 if (m_vendorID != INTEL_VENDOR_ID)
353 return MFX_ERR_UNKNOWN;
356 wcscpy_s(pPath, pathSize, m_path);
357 *pImplType = MFX_LIB_SOFTWARE;
361 if (m_StorageID == MFX_PATH_MSDK_FOLDER || m_StorageID == MFX_DRIVER_STORE ||
362 m_StorageID == MFX_DRIVER_STORE_ONEVPL_MFXINIT) {
363 if (m_lastLibIndex != 0)
364 return MFX_ERR_NOT_FOUND;
365 if (m_vendorID != INTEL_VENDOR_ID)
366 return MFX_ERR_UNKNOWN;
369 wcscpy_s(pPath, pathSize, m_path);
370 // do not change impl type
374 #if !defined(MEDIASDK_UWP_DISPATCHER)
376 #if defined(MFX_TRACER_WA_FOR_DS)
377 if (m_StorageID == MFX_TRACER) {
378 if (m_lastLibIndex != 0)
379 return MFX_ERR_NOT_FOUND;
380 if (m_vendorID != INTEL_VENDOR_ID)
381 return MFX_ERR_UNKNOWN;
385 if (m_baseRegKey.Query(pathKeyName, REG_SZ, (LPBYTE)pPath, (DWORD *)&pathSize)) {
386 DISPATCHER_LOG_INFO((("loaded %S : %S\n"), pathKeyName, pPath));
390 (("error querying %S : RegQueryValueExA()==0x%x\n"), pathKeyName, GetLastError()));
396 wchar_t libPath[MFX_MAX_DLL_PATH] = L"";
404 m_bIsSubKeyValid = false;
407 wchar_t subKeyName[MFX_MAX_REGISTRY_KEY_NAME] = { 0 };
408 DWORD subKeyNameSize = sizeof(subKeyName) / sizeof(subKeyName[0]);
410 // query next value name
411 enumRes = m_baseRegKey.EnumKey(index, subKeyName, &subKeyNameSize);
413 DISPATCHER_LOG_WRN((("no more subkeys : RegEnumKeyExA()==0x%x\n"), GetLastError()))
416 DISPATCHER_LOG_INFO((("found subkey: %S\n"), subKeyName))
421 bRes = subKey.Open(m_baseRegKey, subKeyName, KEY_READ);
423 DISPATCHER_LOG_WRN((("error opening key %S :RegOpenKeyExA()==0x%x\n"),
428 DISPATCHER_LOG_INFO((("opened key: %S\n"), subKeyName));
430 mfxU32 vendorID = 0, deviceID = 0, merit = 0;
433 // query vendor and device IDs
434 size = sizeof(vendorID);
435 bRes = subKey.Query(vendorIDKeyName, REG_DWORD, (LPBYTE)&vendorID, &size);
436 DISPATCHER_LOG_OPERATION({
438 DISPATCHER_LOG_INFO((("loaded %S : 0x%x\n"), vendorIDKeyName, vendorID));
441 DISPATCHER_LOG_WRN((("querying %S : RegQueryValueExA()==0x%x\n"),
448 size = sizeof(deviceID);
449 bRes = subKey.Query(deviceIDKeyName, REG_DWORD, (LPBYTE)&deviceID, &size);
450 DISPATCHER_LOG_OPERATION({
453 (("loaded %S : 0x%x\n"), deviceIDKeyName, deviceID));
456 DISPATCHER_LOG_WRN((("querying %S : RegQueryValueExA()==0x%x\n"),
464 size = sizeof(merit);
465 bRes = subKey.Query(meritKeyName, REG_DWORD, (LPBYTE)&merit, &size);
466 DISPATCHER_LOG_OPERATION({
468 DISPATCHER_LOG_INFO((("loaded %S : %d\n"), meritKeyName, merit));
471 DISPATCHER_LOG_WRN((("querying %S : RegQueryValueExA()==0x%x\n"),
478 // if the library fits required parameters,
479 // query the library's path
481 // compare device's and library's IDs
482 if (MFX_LIB_HARDWARE == m_implType) {
483 if (m_vendorID != vendorID) {
485 DISPATCHER_LOG_WRN((("%S conflict, actual = 0x%x : required = 0x%x\n"),
490 if (bRes && m_deviceID != deviceID) {
492 DISPATCHER_LOG_WRN((("%S conflict, actual = 0x%x : required = 0x%x\n"),
499 DISPATCHER_LOG_OPERATION({
501 if (!(((m_lastLibMerit > merit) ||
502 ((m_lastLibMerit == merit) && (m_lastLibIndex < index))) &&
503 (libMerit < merit))) {
505 ("merit conflict: lastMerit = 0x%x, requiredMerit = 0x%x, libraryMerit = 0x%x, lastindex = %d, index = %d\n"),
516 ((m_lastLibMerit > merit) ||
517 ((m_lastLibMerit == merit) && (m_lastLibIndex < index))) &&
518 (libMerit < merit)) {
519 wchar_t tmpPath[MFX_MAX_DLL_PATH];
520 DWORD tmpPathSize = sizeof(tmpPath);
522 bRes = subKey.Query(pathKeyName, REG_SZ, (LPBYTE)tmpPath, &tmpPathSize);
524 DISPATCHER_LOG_WRN((("error querying %S : RegQueryValueExA()==0x%x\n"),
529 DISPATCHER_LOG_INFO((("loaded %S : %S\n"), pathKeyName, tmpPath));
531 wcscpy_s(libPath, sizeof(libPath) / sizeof(libPath[0]), tmpPath);
532 wcscpy_s(m_SubKeyName,
533 sizeof(m_SubKeyName) / sizeof(m_SubKeyName[0]),
539 // set the library's type
540 if ((0 == vendorID) || (0 == deviceID)) {
541 *pImplType = MFX_LIB_SOFTWARE;
542 DISPATCHER_LOG_INFO((("Library type is MFX_LIB_SOFTWARE\n")));
545 *pImplType = MFX_LIB_HARDWARE;
546 DISPATCHER_LOG_INFO((("Library type is MFX_LIB_HARDWARE\n")));
559 // if the library's path was successfully read,
560 // the merit variable holds valid value
562 return MFX_ERR_NOT_FOUND;
565 wcscpy_s(pPath, pathSize, libPath);
567 m_lastLibIndex = libIndex;
568 m_lastLibMerit = libMerit;
569 m_bIsSubKeyValid = true;
575 } // mfxStatus MFXLibraryIterator::SelectDLLVersion(wchar_t *pPath, size_t pathSize, eMfxImplType *pImplType, mfxVersion minVersion)
577 mfxIMPL MFXLibraryIterator::GetImplementationType() {
578 return m_implInterface;
579 } // mfxIMPL MFXLibraryIterator::GetImplementationType()
581 bool MFXLibraryIterator::GetSubKeyName(wchar_t *subKeyName, size_t length) const {
582 wcscpy_s(subKeyName, length, m_SubKeyName);
583 return m_bIsSubKeyValid;
586 // lightweight implementation that takes deviceID as an argument, avoiding need to init the adapter
587 mfxStatus MFXLibraryIterator::GetDriverStoreDir(std::wstring &driverStoreDir,
591 wchar_t wcDir[MFX_MAX_DLL_PATH];
594 DriverStoreLoader dsLoader;
596 if (storageID == MFX_DRIVER_STORE_ONEVPL) {
597 // pass size of wcDir in bytes (see implementation of GetDriverStorePath)
598 if (!dsLoader.GetDriverStorePath(wcDir, sizeof(wcDir), deviceID, L"DriverStorePathForVPL"))
599 return MFX_ERR_UNSUPPORTED;
601 else if (storageID == MFX_DRIVER_STORE) {
602 if (!dsLoader.GetDriverStorePath(wcDir,
605 L"DriverStorePathForMediaSDK"))
606 return MFX_ERR_UNSUPPORTED;
609 if (wcslen(wcDir) == 0)
610 return MFX_ERR_UNSUPPORTED;
612 // return path to driverStorDir
613 driverStoreDir = wcDir;
618 mfxStatus MFXLibraryIterator::GetRegkeyDir(std::wstring ®Dir, size_t length, int storageID) {
619 mfxStatus sts = MFX_ERR_UNSUPPORTED;
620 MFX::MFXLibraryIterator libIterator;
621 wchar_t wRegDir[MFX_MAX_DLL_PATH];
624 sts = libIterator.Init(MFX_LIB_HARDWARE, MFX_IMPL_VIA_D3D11, 0, storageID);
626 return MFX_ERR_UNSUPPORTED;
628 eMfxImplType implType = MFX_LIB_HARDWARE;
629 mfxVersion ver = { 0, 1 };
631 libIterator.SelectDLLVersion(wRegDir, sizeof(wRegDir) / sizeof(wRegDir[0]), &implType, ver);
633 return MFX_ERR_UNSUPPORTED;
635 // remove DLL name - only need the path
636 std::wstring s = wRegDir;
637 size_t f = s.find_last_of('\\');
638 if (f == std::string::npos)
639 return MFX_ERR_UNSUPPORTED;
641 regDir = s.substr(0, f);