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