1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //    http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #include "wrappers.h"
17 #include "harness/errorHelpers.h"
18 
19 LPCTSTR CDeviceWrapper::WINDOW_TITLE = _T( "cl_khr_dx9_media_sharing" );
20 const int CDeviceWrapper::WINDOW_WIDTH = 256;
21 const int CDeviceWrapper::WINDOW_HEIGHT = 256;
22 CDeviceWrapper::TAccelerationType CDeviceWrapper::accelerationType =
23     CDeviceWrapper::ACCELERATION_HW;
24 
25 #if defined(_WIN32)
26 const D3DFORMAT CDXVAWrapper::RENDER_TARGET_FORMAT = D3DFMT_X8R8G8B8;
27 const D3DFORMAT CDXVAWrapper::VIDEO_FORMAT = D3DFMT_X8R8G8B8;
28 const unsigned int CDXVAWrapper::VIDEO_FPS = 60;
29 #endif
30 
31 #if defined(_WIN32)
WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)32 static LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
33 {
34     switch (msg)
35     {
36         case WM_DESTROY: PostQuitMessage(0); return 0;
37         case WM_PAINT: ValidateRect(hWnd, 0); return 0;
38         default: break;
39     }
40 
41     return DefWindowProc(hWnd, msg, wParam, lParam);
42 }
43 #endif
44 
CDeviceWrapper()45 CDeviceWrapper::CDeviceWrapper()
46 #if defined(_WIN32)
47     : _hInstance(NULL), _hWnd(NULL)
48 #endif
49 {}
50 
WindowInit()51 void CDeviceWrapper::WindowInit()
52 {
53 #if defined(_WIN32)
54     _hInstance = GetModuleHandle(NULL);
55     static WNDCLASSEX wc = {
56         sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L,   0L,
57         _hInstance,         NULL,       NULL,    NULL, NULL,
58         WINDOW_TITLE,       NULL
59     };
60 
61     RegisterClassEx(&wc);
62 
63     _hWnd = CreateWindow(WINDOW_TITLE, WINDOW_TITLE, WS_OVERLAPPEDWINDOW, 0, 0,
64                          WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, wc.hInstance,
65                          NULL);
66 
67     if (!_hWnd)
68     {
69         log_error("Failed to create window");
70         return;
71     }
72 
73     ShowWindow(_hWnd, SW_SHOWDEFAULT);
74     UpdateWindow(_hWnd);
75 #endif
76 }
77 
WindowDestroy()78 void CDeviceWrapper::WindowDestroy()
79 {
80 #if defined(_WIN32)
81     if (_hWnd) DestroyWindow(_hWnd);
82     _hWnd = NULL;
83 #endif
84 }
85 
86 #if defined(_WIN32)
WindowHandle() const87 HWND CDeviceWrapper::WindowHandle() const { return _hWnd; }
88 #endif
89 
WindowWidth() const90 int CDeviceWrapper::WindowWidth() const { return WINDOW_WIDTH; }
91 
WindowHeight() const92 int CDeviceWrapper::WindowHeight() const { return WINDOW_HEIGHT; }
93 
AccelerationType()94 CDeviceWrapper::TAccelerationType CDeviceWrapper::AccelerationType()
95 {
96     return accelerationType;
97 }
98 
AccelerationType(TAccelerationType accelerationTypeNew)99 void CDeviceWrapper::AccelerationType(TAccelerationType accelerationTypeNew)
100 {
101     accelerationType = accelerationTypeNew;
102 }
103 
~CDeviceWrapper()104 CDeviceWrapper::~CDeviceWrapper() { WindowDestroy(); }
105 
106 #if defined(_WIN32)
CD3D9Wrapper()107 CD3D9Wrapper::CD3D9Wrapper()
108     : _d3d9(NULL), _d3dDevice(NULL), _status(DEVICE_PASS), _adapterIdx(0),
109       _adapterFound(false)
110 {
111     WindowInit();
112 
113     _d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
114     if (!_d3d9)
115     {
116         log_error("Direct3DCreate9 failed\n");
117         _status = DEVICE_FAIL;
118     }
119 }
120 
~CD3D9Wrapper()121 CD3D9Wrapper::~CD3D9Wrapper()
122 {
123     Destroy();
124 
125     if (_d3d9) _d3d9->Release();
126     _d3d9 = 0;
127 }
128 
Destroy()129 void CD3D9Wrapper::Destroy()
130 {
131     if (_d3dDevice) _d3dDevice->Release();
132     _d3dDevice = 0;
133 }
134 
Init()135 cl_int CD3D9Wrapper::Init()
136 {
137     if (!WindowHandle())
138     {
139         log_error("D3D9: Window is not created\n");
140         _status = DEVICE_FAIL;
141         return DEVICE_FAIL;
142     }
143 
144     if (!_d3d9 || DEVICE_PASS != _status || !_adapterFound) return false;
145 
146     _d3d9->GetAdapterDisplayMode(_adapterIdx - 1, &_d3ddm);
147 
148     D3DPRESENT_PARAMETERS d3dParams;
149     ZeroMemory(&d3dParams, sizeof(d3dParams));
150 
151     d3dParams.Windowed = TRUE;
152     d3dParams.BackBufferCount = 1;
153     d3dParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
154     d3dParams.hDeviceWindow = WindowHandle();
155     d3dParams.BackBufferWidth = WindowWidth();
156     d3dParams.BackBufferHeight = WindowHeight();
157     d3dParams.BackBufferFormat = _d3ddm.Format;
158 
159     DWORD processingType = (AccelerationType() == ACCELERATION_HW)
160         ? D3DCREATE_HARDWARE_VERTEXPROCESSING
161         : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
162 
163     if (FAILED(_d3d9->CreateDevice(_adapterIdx - 1, D3DDEVTYPE_HAL,
164                                    WindowHandle(), processingType, &d3dParams,
165                                    &_d3dDevice)))
166     {
167         log_error("CreateDevice failed\n");
168         _status = DEVICE_FAIL;
169         return DEVICE_FAIL;
170     }
171 
172     _d3dDevice->BeginScene();
173     _d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0);
174     _d3dDevice->EndScene();
175 
176     return true;
177 }
178 
D3D() const179 void *CD3D9Wrapper::D3D() const { return _d3d9; }
180 
Device() const181 void *CD3D9Wrapper::Device() const { return _d3dDevice; }
182 
Format()183 D3DFORMAT CD3D9Wrapper::Format() { return _d3ddm.Format; }
184 
Adapter()185 D3DADAPTER_IDENTIFIER9 CD3D9Wrapper::Adapter() { return _adapter; }
186 
Status() const187 TDeviceStatus CD3D9Wrapper::Status() const { return _status; }
188 
AdapterNext()189 bool CD3D9Wrapper::AdapterNext()
190 {
191     if (DEVICE_PASS != _status) return false;
192 
193     _adapterFound = false;
194     for (; _adapterIdx < _d3d9->GetAdapterCount();)
195     {
196         ++_adapterIdx;
197         D3DCAPS9 caps;
198         if (FAILED(
199                 _d3d9->GetDeviceCaps(_adapterIdx - 1, D3DDEVTYPE_HAL, &caps)))
200             continue;
201 
202         if (FAILED(_d3d9->GetAdapterIdentifier(_adapterIdx - 1, 0, &_adapter)))
203         {
204             log_error("D3D9: GetAdapterIdentifier failed\n");
205             _status = DEVICE_FAIL;
206             return false;
207         }
208 
209         _adapterFound = true;
210 
211         Destroy();
212         if (!Init())
213         {
214             _status = DEVICE_FAIL;
215             _adapterFound = false;
216         }
217         break;
218     }
219 
220     return _adapterFound;
221 }
222 
AdapterIdx() const223 unsigned int CD3D9Wrapper::AdapterIdx() const { return _adapterIdx - 1; }
224 
225 
CD3D9ExWrapper()226 CD3D9ExWrapper::CD3D9ExWrapper()
227     : _d3d9Ex(NULL), _d3dDeviceEx(NULL), _status(DEVICE_PASS), _adapterIdx(0),
228       _adapterFound(false)
229 {
230     WindowInit();
231 
232     HRESULT result = Direct3DCreate9Ex(D3D_SDK_VERSION, &_d3d9Ex);
233     if (FAILED(result) || !_d3d9Ex)
234     {
235         log_error("Direct3DCreate9Ex failed\n");
236         _status = DEVICE_FAIL;
237     }
238 }
239 
~CD3D9ExWrapper()240 CD3D9ExWrapper::~CD3D9ExWrapper()
241 {
242     Destroy();
243 
244     if (_d3d9Ex) _d3d9Ex->Release();
245     _d3d9Ex = 0;
246 }
247 
D3D() const248 void *CD3D9ExWrapper::D3D() const { return _d3d9Ex; }
249 
Device() const250 void *CD3D9ExWrapper::Device() const { return _d3dDeviceEx; }
251 
Format()252 D3DFORMAT CD3D9ExWrapper::Format() { return _d3ddmEx.Format; }
253 
Adapter()254 D3DADAPTER_IDENTIFIER9 CD3D9ExWrapper::Adapter() { return _adapter; }
255 
Init()256 cl_int CD3D9ExWrapper::Init()
257 {
258     if (!WindowHandle())
259     {
260         log_error("D3D9EX: Window is not created\n");
261         _status = DEVICE_FAIL;
262         return DEVICE_FAIL;
263     }
264 
265     if (!_d3d9Ex || DEVICE_FAIL == _status || !_adapterFound)
266         return DEVICE_FAIL;
267 
268     RECT rect;
269     GetClientRect(WindowHandle(), &rect);
270 
271     D3DPRESENT_PARAMETERS d3dParams;
272     ZeroMemory(&d3dParams, sizeof(d3dParams));
273 
274     d3dParams.Windowed = TRUE;
275     d3dParams.SwapEffect = D3DSWAPEFFECT_FLIP;
276     d3dParams.BackBufferFormat = D3DFMT_X8R8G8B8;
277     d3dParams.BackBufferWidth = WindowWidth();
278     d3dParams.BackBufferHeight = WindowHeight();
279 
280     d3dParams.BackBufferCount = 1;
281     d3dParams.hDeviceWindow = WindowHandle();
282 
283     DWORD processingType = (AccelerationType() == ACCELERATION_HW)
284         ? D3DCREATE_HARDWARE_VERTEXPROCESSING
285         : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
286 
287     if (FAILED(_d3d9Ex->CreateDeviceEx(_adapterIdx - 1, D3DDEVTYPE_HAL,
288                                        WindowHandle(), processingType,
289                                        &d3dParams, NULL, &_d3dDeviceEx)))
290     {
291         log_error("CreateDeviceEx failed\n");
292         _status = DEVICE_FAIL;
293         return DEVICE_FAIL;
294     }
295 
296     _d3dDeviceEx->BeginScene();
297     _d3dDeviceEx->Clear(0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0);
298     _d3dDeviceEx->EndScene();
299 
300     return DEVICE_PASS;
301 }
302 
Destroy()303 void CD3D9ExWrapper::Destroy()
304 {
305     if (_d3dDeviceEx) _d3dDeviceEx->Release();
306     _d3dDeviceEx = 0;
307 }
308 
Status() const309 TDeviceStatus CD3D9ExWrapper::Status() const { return _status; }
310 
AdapterNext()311 bool CD3D9ExWrapper::AdapterNext()
312 {
313     if (DEVICE_FAIL == _status) return false;
314 
315     _adapterFound = false;
316     for (; _adapterIdx < _d3d9Ex->GetAdapterCount();)
317     {
318         ++_adapterIdx;
319         D3DCAPS9 caps;
320         if (FAILED(
321                 _d3d9Ex->GetDeviceCaps(_adapterIdx - 1, D3DDEVTYPE_HAL, &caps)))
322             continue;
323 
324         if (FAILED(
325                 _d3d9Ex->GetAdapterIdentifier(_adapterIdx - 1, 0, &_adapter)))
326         {
327             log_error("D3D9EX: GetAdapterIdentifier failed\n");
328             _status = DEVICE_FAIL;
329             return false;
330         }
331 
332         _adapterFound = true;
333         Destroy();
334         if (!Init())
335         {
336             _status = DEVICE_FAIL;
337             _adapterFound = _status;
338         }
339 
340         break;
341     }
342 
343     return _adapterFound;
344 }
345 
AdapterIdx() const346 unsigned int CD3D9ExWrapper::AdapterIdx() const { return _adapterIdx - 1; }
347 
CDXVAWrapper()348 CDXVAWrapper::CDXVAWrapper()
349     : _dxvaDevice(NULL), _status(DEVICE_PASS), _adapterFound(false)
350 {
351     _status = _d3d9.Status();
352 }
353 
~CDXVAWrapper()354 CDXVAWrapper::~CDXVAWrapper() { DXVAHDDestroy(); }
355 
Device() const356 void *CDXVAWrapper::Device() const { return _dxvaDevice; }
357 
Status() const358 TDeviceStatus CDXVAWrapper::Status() const
359 {
360     if (_status == DEVICE_FAIL || _d3d9.Status() == DEVICE_FAIL)
361         return DEVICE_FAIL;
362     else if (_status == DEVICE_NOTSUPPORTED
363              || _d3d9.Status() == DEVICE_NOTSUPPORTED)
364         return DEVICE_NOTSUPPORTED;
365     else
366         return DEVICE_PASS;
367 }
368 
AdapterNext()369 bool CDXVAWrapper::AdapterNext()
370 {
371     if (DEVICE_PASS != _status) return false;
372 
373     _adapterFound = _d3d9.AdapterNext();
374     _status = _d3d9.Status();
375     if (DEVICE_PASS != _status)
376     {
377         _adapterFound = false;
378         return false;
379     }
380 
381     if (!_adapterFound) return false;
382 
383     DXVAHDDestroy();
384     _status = DXVAHDInit();
385     if (DEVICE_PASS != _status)
386     {
387         _adapterFound = false;
388         return false;
389     }
390 
391     return true;
392 }
393 
DXVAHDInit()394 TDeviceStatus CDXVAWrapper::DXVAHDInit()
395 {
396     if ((_status == DEVICE_FAIL) || (_d3d9.Status() == DEVICE_FAIL)
397         || !_adapterFound)
398         return DEVICE_FAIL;
399 
400     DXVAHD_RATIONAL fps = { VIDEO_FPS, 1 };
401 
402     DXVAHD_CONTENT_DESC desc;
403     desc.InputFrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE;
404     desc.InputFrameRate = fps;
405     desc.InputWidth = WindowWidth();
406     desc.InputHeight = WindowHeight();
407     desc.OutputFrameRate = fps;
408     desc.OutputWidth = WindowWidth();
409     desc.OutputHeight = WindowHeight();
410 
411 #ifdef USE_SOFTWARE_PLUGIN
412     _status = DEVICE_FAIL;
413     return DEVICE_FAIL;
414 #endif
415 
416     HRESULT hr = DXVAHD_CreateDevice(
417         static_cast<IDirect3DDevice9Ex *>(_d3d9.Device()), &desc,
418         DXVAHD_DEVICE_USAGE_PLAYBACK_NORMAL, NULL, &_dxvaDevice);
419     if (FAILED(hr))
420     {
421         if (hr == E_NOINTERFACE)
422         {
423             log_error(
424                 "DXVAHD_CreateDevice skipped due to no supported devices!\n");
425             _status = DEVICE_NOTSUPPORTED;
426         }
427         else
428         {
429             log_error("DXVAHD_CreateDevice failed\n");
430             _status = DEVICE_FAIL;
431         }
432     }
433 
434     return _status;
435 }
436 
DXVAHDDestroy()437 void CDXVAWrapper::DXVAHDDestroy()
438 {
439     if (_dxvaDevice) _dxvaDevice->Release();
440     _dxvaDevice = 0;
441 }
442 
D3D() const443 void *CDXVAWrapper::D3D() const { return _d3d9.D3D(); }
444 
AdapterIdx() const445 unsigned int CDXVAWrapper::AdapterIdx() const { return _d3d9.AdapterIdx(); }
446 
D3D9() const447 const CD3D9ExWrapper &CDXVAWrapper::D3D9() const { return _d3d9; }
448 
CD3D9SurfaceWrapper()449 CD3D9SurfaceWrapper::CD3D9SurfaceWrapper(): mMem(NULL) {}
450 
CD3D9SurfaceWrapper(IDirect3DSurface9 * mem)451 CD3D9SurfaceWrapper::CD3D9SurfaceWrapper(IDirect3DSurface9 *mem): mMem(mem) {}
452 
~CD3D9SurfaceWrapper()453 CD3D9SurfaceWrapper::~CD3D9SurfaceWrapper()
454 {
455     if (mMem != NULL) mMem->Release();
456     mMem = NULL;
457 }
458 
459 #endif
460 
CSurfaceWrapper()461 CSurfaceWrapper::CSurfaceWrapper() {}
462 
~CSurfaceWrapper()463 CSurfaceWrapper::~CSurfaceWrapper() {}
464