1 // Copyright (c) 2012-2019 Intel Corporation
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 
21 #define INITGUID
22 #include <d3d9.h>
23 #include <dxgi.h>
24 
25 #include "mfx_dxva2_device.h"
26 
27 
28 using namespace MFX;
29 
30 
DXDevice(void)31 DXDevice::DXDevice(void)
32 {
33     m_hModule = (HMODULE) 0;
34 
35     m_numAdapters = 0;
36 
37     m_vendorID = 0;
38     m_deviceID = 0;
39     m_driverVersion = 0;
40     m_luid = 0;
41 
42 } // DXDevice::DXDevice(void)
43 
~DXDevice(void)44 DXDevice::~DXDevice(void)
45 {
46     Close();
47 
48     // free DX library only when device is destroyed
49     UnloadDLLModule();
50 
51 } // DXDevice::~DXDevice(void)
52 
GetVendorID(void) const53 mfxU32 DXDevice::GetVendorID(void) const
54 {
55     return m_vendorID;
56 
57 } // mfxU32 DXDevice::GetVendorID(void) const
58 
GetDeviceID(void) const59 mfxU32 DXDevice::GetDeviceID(void) const
60 {
61     return m_deviceID;
62 
63 } // mfxU32 DXDevice::GetDeviceID(void) const
64 
GetDriverVersion(void) const65 mfxU64 DXDevice::GetDriverVersion(void) const
66 {
67     return m_driverVersion;
68 
69 }// mfxU64 DXDevice::GetDriverVersion(void) const
70 
GetLUID(void) const71 mfxU64 DXDevice::GetLUID(void) const
72 {
73     return m_luid;
74 
75 } // mfxU64 DXDevice::GetLUID(void) const
76 
GetAdapterCount(void) const77 mfxU32 DXDevice::GetAdapterCount(void) const
78 {
79     return m_numAdapters;
80 
81 } // mfxU32 DXDevice::GetAdapterCount(void) const
82 
Close(void)83 void DXDevice::Close(void)
84 {
85     m_numAdapters = 0;
86 
87     m_vendorID = 0;
88     m_deviceID = 0;
89     m_luid = 0;
90 
91 } // void DXDevice::Close(void)
92 
LoadDLLModule(const wchar_t * pModuleName)93 void DXDevice::LoadDLLModule(const wchar_t *pModuleName)
94 {
95     // unload the module if it is required
96     UnloadDLLModule();
97 
98 #if !defined(MEDIASDK_UWP_DISPATCHER)
99     DWORD prevErrorMode = 0;
100     // set the silent error mode
101 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN7)
102     SetThreadErrorMode(SEM_FAILCRITICALERRORS, &prevErrorMode);
103 #else
104     prevErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
105 #endif
106 #endif // !defined(MEDIASDK_UWP_DISPATCHER)
107 
108     // load specified library
109     m_hModule = LoadLibraryExW(pModuleName, NULL, 0);
110 
111 #if !defined(MEDIASDK_UWP_DISPATCHER)
112     // set the previous error mode
113 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN7)
114     SetThreadErrorMode(prevErrorMode, NULL);
115 #else
116     SetErrorMode(prevErrorMode);
117 #endif
118 #endif // !defined(MEDIASDK_UWP_DISPATCHER)
119 
120 } // void LoadDLLModule(const wchar_t *pModuleName)
121 
UnloadDLLModule(void)122 void DXDevice::UnloadDLLModule(void)
123 {
124     if (m_hModule)
125     {
126         FreeLibrary(m_hModule);
127         m_hModule = (HMODULE) 0;
128     }
129 
130 } // void DXDevice::UnloaDLLdModule(void)
131 
132 #ifdef MFX_D3D9_ENABLED
D3D9Device(void)133 D3D9Device::D3D9Device(void)
134 {
135     m_pD3D9 = (void *) 0;
136     m_pD3D9Ex = (void *) 0;
137 
138 } // D3D9Device::D3D9Device(void)
139 
~D3D9Device(void)140 D3D9Device::~D3D9Device(void)
141 {
142     Close();
143 
144 } // D3D9Device::~D3D9Device(void)
145 
Close(void)146 void D3D9Device::Close(void)
147 {
148     // release the interfaces
149     if (m_pD3D9Ex)
150     {
151         ((IDirect3D9Ex *) m_pD3D9Ex)->Release();
152     }
153 
154     // release the interfaces
155     if (m_pD3D9)
156     {
157         ((IDirect3D9 *) m_pD3D9)->Release();
158     }
159 
160     m_pD3D9 = (void *) 0;
161     m_pD3D9Ex = (void *) 0;
162 
163 } // void D3D9Device::Close(void)
164 
165 typedef
166     IDirect3D9 * (WINAPI *D3DCreateFunctionPtr_t) (UINT);
167 
168 typedef
169     HRESULT (WINAPI *D3DExCreateFunctionPtr_t) (UINT, IDirect3D9Ex **);
170 
Init(const mfxU32 adapterNum)171 bool D3D9Device::Init(const mfxU32 adapterNum)
172 {
173     // close the device before initialization
174     Close();
175 
176     // load the library
177     if (NULL == m_hModule)
178     {
179         LoadDLLModule(L"d3d9.dll");
180     }
181 
182     if (m_hModule)
183     {
184         D3DCreateFunctionPtr_t pFunc;
185 
186         // load address of procedure to create D3D device
187         pFunc = (D3DCreateFunctionPtr_t) GetProcAddress(m_hModule, "Direct3DCreate9");
188         if (pFunc)
189         {
190             D3DADAPTER_IDENTIFIER9 adapterIdent;
191             IDirect3D9 *pD3D9;
192             HRESULT hRes;
193 
194             // create D3D object
195             m_pD3D9 = pFunc(D3D_SDK_VERSION);
196 
197             if (NULL == m_pD3D9)
198             {
199                 DXVA2DEVICE_TRACE(("FAIL: Direct3DCreate9(%d) : GetLastError()=0x%x", D3D_SDK_VERSION, GetLastError()));
200                 return false;
201             }
202 
203             // cast the interface
204             pD3D9 = (IDirect3D9 *) m_pD3D9;
205 
206             m_numAdapters = pD3D9->GetAdapterCount();
207             if (adapterNum >= m_numAdapters)
208             {
209                 return false;
210             }
211 
212             // get the card's parameters
213             hRes = pD3D9->GetAdapterIdentifier(adapterNum, 0, &adapterIdent);
214             if (D3D_OK != hRes)
215             {
216                 DXVA2DEVICE_TRACE(("FAIL: GetAdapterIdentifier(%d) = 0x%x \n", adapterNum, hRes));
217                 return false;
218             }
219 
220             m_vendorID = adapterIdent.VendorId;
221             m_deviceID = adapterIdent.DeviceId;
222             m_driverVersion = (mfxU64)adapterIdent.DriverVersion.QuadPart;
223 
224             // load LUID
225             IDirect3D9Ex *pD3D9Ex;
226             D3DExCreateFunctionPtr_t pFuncEx;
227             LUID d3d9LUID;
228 
229             // find the appropriate function
230             pFuncEx = (D3DExCreateFunctionPtr_t) GetProcAddress(m_hModule, "Direct3DCreate9Ex");
231             if (NULL == pFuncEx)
232             {
233                 // the extended interface is not supported
234                 return true;
235             }
236 
237             // create extended interface
238             hRes = pFuncEx(D3D_SDK_VERSION, &pD3D9Ex);
239             if (FAILED(hRes))
240             {
241                 // can't create extended interface
242                 return true;
243             }
244             m_pD3D9Ex = pD3D9Ex;
245 
246             // obtain D3D9 device LUID
247             hRes = pD3D9Ex->GetAdapterLUID(adapterNum, &d3d9LUID);
248             if (FAILED(hRes))
249             {
250                 // can't get LUID
251                 return true;
252             }
253             // copy the LUID
254             *((LUID *) &m_luid) = d3d9LUID;
255         }
256         else
257         {
258             DXVA2DEVICE_TRACE_OPERATION({
259                 wchar_t path[1024];
260                 DWORD lastErr = GetLastError();
261                 GetModuleFileNameW(m_hModule, path, sizeof(path)/sizeof(path[0]));
262                 DXVA2DEVICE_TRACE(("FAIL: invoking GetProcAddress(Direct3DCreate9) in %S : GetLastError()==0x%x\n", path, lastErr)); });
263                 return false;
264         }
265     }
266     else
267     {
268         DXVA2DEVICE_TRACE(("FAIL: invoking LoadLibrary(\"d3d9.dll\") : GetLastError()==0x%x\n", GetLastError()));
269         return false;
270     }
271 
272     return true;
273 
274 } // bool D3D9Device::Init(const mfxU32 adapterNum)
275 #endif //MFX_D3D9_ENABLED
276 
277 typedef
278 HRESULT (WINAPI *DXGICreateFactoryFunc) (REFIID riid, void **ppFactory);
279 
DXGI1Device(void)280 DXGI1Device::DXGI1Device(void)
281 {
282     m_pDXGIFactory1 = (void *) 0;
283     m_pDXGIAdapter1 = (void *) 0;
284 
285 } // DXGI1Device::DXGI1Device(void)
286 
~DXGI1Device(void)287 DXGI1Device::~DXGI1Device(void)
288 {
289     Close();
290 
291 } // DXGI1Device::~DXGI1Device(void)
292 
Close(void)293 void DXGI1Device::Close(void)
294 {
295     // release the interfaces
296     if (m_pDXGIAdapter1)
297     {
298         ((IDXGIAdapter1 *) m_pDXGIAdapter1)->Release();
299     }
300 
301     if (m_pDXGIFactory1)
302     {
303         ((IDXGIFactory1 *) m_pDXGIFactory1)->Release();
304     }
305 
306     m_pDXGIFactory1 = (void *) 0;
307     m_pDXGIAdapter1 = (void *) 0;
308 
309 } // void DXGI1Device::Close(void)
310 
Init(const mfxU32 adapterNum)311 bool DXGI1Device::Init(const mfxU32 adapterNum)
312 {
313     // release the object before initialization
314     Close();
315 
316     IDXGIFactory1 *pFactory = NULL;
317     IDXGIAdapter1 *pAdapter = NULL;
318     DXGI_ADAPTER_DESC1 desc = { 0 };
319     mfxU32 curAdapter = 0;
320     mfxU32 maxAdapters = 0;
321     HRESULT hRes = E_FAIL;
322 
323     DXGICreateFactoryFunc pFunc = NULL;
324 
325     // load up the library if it is not loaded
326     if (NULL == m_hModule)
327     {
328         LoadDLLModule(L"dxgi.dll");
329     }
330 
331     if (m_hModule)
332     {
333         // load address of procedure to create DXGI 1.1 factory
334         pFunc = (DXGICreateFactoryFunc)GetProcAddress(m_hModule, "CreateDXGIFactory1");
335     }
336 
337     if (NULL == pFunc)
338     {
339         return false;
340     }
341 
342     // create the factory
343 #if _MSC_VER >= 1400
344     hRes = pFunc(__uuidof(IDXGIFactory1), (void**)(&pFactory));
345 #else
346     hRes = pFunc(IID_IDXGIFactory1, (void**)(&pFactory));
347 #endif
348 
349     if (FAILED(hRes))
350     {
351         return false;
352     }
353     m_pDXGIFactory1 = pFactory;
354 
355     // get the number of adapters
356     curAdapter = 0;
357     maxAdapters = 0;
358     do
359     {
360         // get the required adapted
361         hRes = pFactory->EnumAdapters1(curAdapter, &pAdapter);
362         if (FAILED(hRes))
363         {
364             break;
365         }
366 
367         // if it is the required adapter, save the interface
368         if (curAdapter == adapterNum)
369         {
370             m_pDXGIAdapter1 = pAdapter;
371         }
372         else
373         {
374             pAdapter->Release();
375         }
376 
377         // get the next adapter
378         curAdapter += 1;
379 
380     } while (SUCCEEDED(hRes));
381     maxAdapters = curAdapter;
382 
383     // there is no required adapter
384     if (adapterNum >= maxAdapters)
385     {
386         return false;
387     }
388     pAdapter = (IDXGIAdapter1 *) m_pDXGIAdapter1;
389 
390     // get the adapter's parameters
391     hRes = pAdapter->GetDesc1(&desc);
392     if (FAILED(hRes))
393     {
394         return false;
395     }
396 
397     // save the parameters
398     m_vendorID = desc.VendorId;
399     m_deviceID = desc.DeviceId;
400     *((LUID *) &m_luid) = desc.AdapterLuid;
401 
402     return true;
403 
404 } // bool DXGI1Device::Init(const mfxU32 adapterNum)
405 
DXVA2Device(void)406 DXVA2Device::DXVA2Device(void)
407 {
408     m_numAdapters = 0;
409 
410     m_vendorID = 0;
411     m_deviceID = 0;
412 
413     m_driverVersion = 0;
414 } // DXVA2Device::DXVA2Device(void)
415 
~DXVA2Device(void)416 DXVA2Device::~DXVA2Device(void)
417 {
418     Close();
419 
420 } // DXVA2Device::~DXVA2Device(void)
421 
Close(void)422 void DXVA2Device::Close(void)
423 {
424     m_numAdapters = 0;
425 
426     m_vendorID = 0;
427     m_deviceID = 0;
428 
429     m_driverVersion = 0;
430 } // void DXVA2Device::Close(void)
431 
432 #ifdef MFX_D3D9_ENABLED
InitD3D9(const mfxU32 adapterNum)433 bool DXVA2Device::InitD3D9(const mfxU32 adapterNum)
434 {
435     D3D9Device d3d9Device;
436     bool bRes;
437 
438     // release the object before initialization
439     Close();
440 
441     // create 'old fashion' device
442     bRes = d3d9Device.Init(adapterNum);
443     if (false == bRes)
444     {
445         return false;
446     }
447 
448 
449     m_numAdapters = d3d9Device.GetAdapterCount();
450 
451     // check if the application is under Remote Desktop
452     if ((0 == d3d9Device.GetVendorID()) || (0 == d3d9Device.GetDeviceID()))
453     {
454         // get the required parameters alternative way and ...
455         UseAlternativeWay(&d3d9Device);
456     }
457     else
458     {
459         // save the parameters and ...
460         m_vendorID = d3d9Device.GetVendorID();
461         m_deviceID = d3d9Device.GetDeviceID();
462         m_driverVersion = d3d9Device.GetDriverVersion();
463     }
464 
465     // ... say goodbye
466     return true;
467 } // bool InitD3D9(const mfxU32 adapterNum)
468 #else // MFX_D3D9_ENABLED
InitD3D9(const mfxU32 adapterNum)469 bool DXVA2Device::InitD3D9(const mfxU32 adapterNum)
470 {
471     (void)adapterNum;
472     return false;
473 }
474 #endif // MFX_D3D9_ENABLED
475 
InitDXGI1(const mfxU32 adapterNum)476 bool DXVA2Device::InitDXGI1(const mfxU32 adapterNum)
477 {
478     DXGI1Device dxgi1Device;
479     bool bRes;
480 
481     // release the object before initialization
482     Close();
483 
484     // create modern DXGI device
485     bRes = dxgi1Device.Init(adapterNum);
486     if (false == bRes)
487     {
488         return false;
489     }
490 
491     // save the parameters and ...
492     m_vendorID = dxgi1Device.GetVendorID();
493     m_deviceID = dxgi1Device.GetDeviceID();
494     m_numAdapters = dxgi1Device.GetAdapterCount();
495 
496     // ... say goodbye
497     return true;
498 
499 } // bool DXVA2Device::InitDXGI1(const mfxU32 adapterNum)
500 
501 #ifdef MFX_D3D9_ENABLED
UseAlternativeWay(const D3D9Device * pD3D9Device)502 void DXVA2Device::UseAlternativeWay(const D3D9Device *pD3D9Device)
503 {
504     mfxU64 d3d9LUID = pD3D9Device->GetLUID();
505 
506     // work only with valid LUIDs
507     if (0 == d3d9LUID)
508     {
509         return;
510     }
511 
512     DXGI1Device dxgi1Device;
513     mfxU32 curDevice = 0;
514     bool bRes = false;
515 
516     do
517     {
518         // initialize the next DXGI1 or DXGI device
519         bRes = dxgi1Device.Init(curDevice);
520         if (false == bRes)
521         {
522             // there is no more devices
523             break;
524         }
525 
526         // is it required device ?
527         if (d3d9LUID == dxgi1Device.GetLUID())
528         {
529             m_vendorID = dxgi1Device.GetVendorID();
530             m_deviceID = dxgi1Device.GetDeviceID();
531             m_driverVersion = dxgi1Device.GetDriverVersion();
532             return ;
533         }
534 
535         // get the next device
536         curDevice += 1;
537 
538     } while (bRes);
539 
540     dxgi1Device.Close();
541     // we need to match a DXGI(1) device to the D3D9 device
542 
543 } // void DXVA2Device::UseAlternativeWay(const D3D9Device *pD3D9Device)
544 #endif // MFX_D3D9_ENABLED
545 
GetVendorID(void) const546 mfxU32 DXVA2Device::GetVendorID(void) const
547 {
548     return m_vendorID;
549 
550 } // mfxU32 DXVA2Device::GetVendorID(void) const
551 
GetDeviceID(void) const552 mfxU32 DXVA2Device::GetDeviceID(void) const
553 {
554     return m_deviceID;
555 
556 } // mfxU32 DXVA2Device::GetDeviceID(void) const
557 
GetDriverVersion(void) const558 mfxU64 DXVA2Device::GetDriverVersion(void) const
559 {
560     return m_driverVersion;
561 }// mfxU64 DXVA2Device::GetDriverVersion(void) const
562 
GetAdapterCount(void) const563 mfxU32 DXVA2Device::GetAdapterCount(void) const
564 {
565     return m_numAdapters;
566 
567 } // mfxU32 DXVA2Device::GetAdapterCount(void) const
568 
569