Merge pull request #9264 from afedchin/win32_fixes_j
[vuplus_xbmc] / xbmc / rendering / dx / RenderSystemDX.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21
22 #ifdef HAS_DX
23
24 #include <DirectXPackedVector.h>
25 #include "Application.h"
26 #include "RenderSystemDX.h"
27 #include "cores/VideoRenderers/RenderManager.h"
28 #include "guilib/D3DResource.h"
29 #include "guilib/GUIShaderDX.h"
30 #include "guilib/GUITextureD3D.h"
31 #include "guilib/GUIWindowManager.h"
32 #include "settings/AdvancedSettings.h"
33 #include "threads/SingleLock.h"
34 #include "utils/MathUtils.h"
35 #include "utils/TimeUtils.h"
36 #include "utils/log.h"
37 #include "win32/WIN32Util.h"
38 #include "win32/dxerr.h"
39
40 #pragma comment(lib, "d3d11.lib")
41 #pragma comment(lib, "dxgi.lib")
42 #pragma comment(lib, "dxguid.lib")
43
44 #define RATIONAL_TO_FLOAT(rational) ((rational.Denominator != 0) ? (float)rational.Numerator / (float)rational.Denominator : 0.0)
45
46 using namespace DirectX::PackedVector;
47
48 CRenderSystemDX::CRenderSystemDX() : CRenderSystemBase()
49 {
50   m_enumRenderingSystem = RENDERING_SYSTEM_DIRECTX;
51
52   m_hFocusWnd   = NULL;
53   m_hDeviceWnd  = NULL;
54   m_nBackBufferWidth  = 0;
55   m_nBackBufferHeight = 0;
56   m_bFullScreenDevice = false;
57   m_bVSync          = true;
58   m_nDeviceStatus   = S_OK;
59   m_inScene         = false;
60   m_needNewDevice   = false;
61   m_resizeInProgress = false;
62   m_screenHeight    = 0;
63   m_systemFreq      = CurrentHostFrequency();
64
65   m_defaultD3DUsage = D3D11_USAGE_DEFAULT;
66
67   m_featureLevel = D3D_FEATURE_LEVEL_11_1;
68   m_driverType = D3D_DRIVER_TYPE_HARDWARE;
69   m_adapter = NULL;
70   m_adapterIndex = -1;
71   m_pOutput = NULL;
72   m_dxgiFactory = NULL;
73   m_pD3DDev = NULL;
74   m_pImdContext = NULL;
75   m_pContext = NULL;
76
77   m_pSwapChain = NULL;
78   m_pSwapChain1 = NULL;
79   m_pRenderTargetView = NULL;
80   m_depthStencilState = NULL;
81   m_depthStencilView = NULL;
82   m_BlendEnableState = NULL;
83   m_BlendDisableState = NULL;
84   m_BlendEnabled = false;
85   m_RSScissorDisable = NULL;
86   m_RSScissorEnable = NULL;
87   m_ScissorsEnabled = false;
88
89   m_pTextureRight = NULL;
90   m_pRenderTargetViewRight = NULL;
91   m_pShaderResourceViewRight = NULL;
92   m_pGUIShader = NULL;
93   m_bResizeRequred = false;
94   m_bHWStereoEnabled = false;
95   ZeroMemory(&m_cachedMode, sizeof(m_cachedMode));
96   ZeroMemory(&m_viewPort, sizeof(m_viewPort));
97   ZeroMemory(&m_scissor, sizeof(CRect));
98 }
99
100 CRenderSystemDX::~CRenderSystemDX()
101 {
102 }
103
104 bool CRenderSystemDX::InitRenderSystem()
105 {
106   m_bVSync = true;
107   
108   CLog::Log(LOGDEBUG, __FUNCTION__" - Initializing D3D11 Factory...");
109
110   HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&m_dxgiFactory));
111   if (FAILED(hr)) 
112   {
113     CLog::Log(LOGERROR, __FUNCTION__" - D3D11 initialization failed.");
114     return false;
115   }
116   
117   UpdateMonitor();
118   return CreateDevice();
119 }
120
121 void CRenderSystemDX::SetRenderParams(unsigned int width, unsigned int height, bool fullScreen, float refreshRate)
122 {
123   m_nBackBufferWidth  = width;
124   m_nBackBufferHeight = height;
125   m_bFullScreenDevice = fullScreen;
126   m_refreshRate       = refreshRate;
127 }
128
129 void CRenderSystemDX::SetMonitor(HMONITOR monitor)
130 {
131   if (!m_dxgiFactory)
132     return;
133
134   DXGI_OUTPUT_DESC outputDesc;
135   if (m_pOutput && SUCCEEDED(m_pOutput->GetDesc(&outputDesc)) && outputDesc.Monitor == monitor)
136     return;
137
138   // find the appropriate screen
139   IDXGIAdapter1*  pAdapter;
140   for (unsigned i = 0; m_dxgiFactory->EnumAdapters1(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i)
141   {
142     IDXGIOutput* pOutput;
143     for (unsigned j = 0; pAdapter->EnumOutputs(j, &pOutput) != DXGI_ERROR_NOT_FOUND; ++j)
144     {
145       if (FAILED(pOutput->GetDesc(&outputDesc)))
146         break;
147
148       if (outputDesc.Monitor == monitor)
149       {
150         // update monitor info
151         SAFE_RELEASE(m_pOutput);
152         m_pOutput = pOutput;
153
154         CLog::Log(LOGDEBUG, __FUNCTION__" - Selected %S output. ", outputDesc.DeviceName);
155
156         // check if adapter is changed
157         if (m_adapterIndex != i)
158         {
159           pAdapter->GetDesc(&m_adapterDesc);
160
161           CLog::Log(LOGDEBUG, __FUNCTION__" - Selected %S adapter. ", m_adapterDesc.Description);
162
163           SAFE_RELEASE(m_adapter);
164           m_adapter = pAdapter;
165
166           m_needNewDevice = true;
167           m_adapterIndex = i;
168
169           return;
170         }
171
172         return;
173       }
174       pOutput->Release();
175     }
176     pAdapter->Release();
177   }
178 }
179
180 bool CRenderSystemDX::ResetRenderSystem(int width, int height, bool fullScreen, float refreshRate)
181 {
182   if (!m_pD3DDev)
183     return false;
184
185   if (m_hDeviceWnd != NULL)
186   {
187     HMONITOR hMonitor = MonitorFromWindow(m_hDeviceWnd, MONITOR_DEFAULTTONULL);
188     if (hMonitor)
189       SetMonitor(hMonitor);
190   }
191
192   SetRenderParams(width, height, fullScreen, refreshRate);
193
194   CRect rc(0, 0, float(width), float(height));
195   SetViewPort(rc);
196
197   if (!m_needNewDevice)
198   {
199     CreateWindowSizeDependentResources();
200     SetFullScreenInternal();
201     if (m_bResizeRequred)
202       CreateWindowSizeDependentResources();
203   }
204   else 
205   {
206     OnDeviceLost();
207     OnDeviceReset();
208   }
209
210   return true;
211 }
212
213 void CRenderSystemDX::OnMove()
214 {
215   if (!m_bRenderCreated)
216     return;
217
218   DXGI_OUTPUT_DESC outputDesc;
219   m_pOutput->GetDesc(&outputDesc);
220   HMONITOR newMonitor = MonitorFromWindow(m_hDeviceWnd, MONITOR_DEFAULTTONULL);
221
222   if (newMonitor != NULL && outputDesc.Monitor != newMonitor)
223   {
224     SetMonitor(newMonitor);
225     if (m_needNewDevice)
226     {
227       CLog::Log(LOGDEBUG, "%s - Adapter changed, reseting render system.", __FUNCTION__);
228       ResetRenderSystem(m_nBackBufferWidth, m_nBackBufferHeight, m_bFullScreenDevice, m_refreshRate);
229     }
230   }
231 }
232
233 void CRenderSystemDX::OnResize(unsigned int width, unsigned int height)
234 {
235   if (!m_bRenderCreated)
236     return;
237
238   m_nBackBufferWidth = width;
239   m_nBackBufferHeight = height;
240   CreateWindowSizeDependentResources();
241 }
242
243 void CRenderSystemDX::GetClosestDisplayModeToCurrent(IDXGIOutput* output, DXGI_MODE_DESC* outCurrentDisplayMode, bool useCached /*= false*/)
244 {
245   DXGI_OUTPUT_DESC outputDesc;
246   output->GetDesc(&outputDesc);
247   HMONITOR hMonitor = outputDesc.Monitor;
248   MONITORINFOEX monitorInfo;
249   monitorInfo.cbSize = sizeof(MONITORINFOEX);
250   GetMonitorInfo(hMonitor, &monitorInfo);
251   DEVMODE devMode;
252   devMode.dmSize = sizeof(DEVMODE);
253   devMode.dmDriverExtra = 0;
254   EnumDisplaySettings(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &devMode);
255
256   bool useDefaultRefreshRate = 1 == devMode.dmDisplayFrequency || 0 == devMode.dmDisplayFrequency;
257   float refreshRate = RATIONAL_TO_FLOAT(m_cachedMode.RefreshRate);
258
259   // this needed to improve performance for VideoSync bacause FindClosestMatchingMode is very slow
260   if (!useCached
261     || m_cachedMode.Width  != devMode.dmPelsWidth
262     || m_cachedMode.Height != devMode.dmPelsHeight
263     || long(refreshRate)   != devMode.dmDisplayFrequency)
264   {
265     DXGI_MODE_DESC current;
266     current.Width = devMode.dmPelsWidth;
267     current.Height = devMode.dmPelsHeight;
268     current.RefreshRate.Numerator = useDefaultRefreshRate ? 0 : devMode.dmDisplayFrequency;
269     current.RefreshRate.Denominator = useDefaultRefreshRate ? 0 : 1;
270     current.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
271     current.ScanlineOrdering = m_interlaced ? DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST : DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
272     current.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
273
274     output->FindClosestMatchingMode(&current, &m_cachedMode, m_pD3DDev);
275   }
276
277   ZeroMemory(outCurrentDisplayMode, sizeof(DXGI_MODE_DESC));
278   outCurrentDisplayMode->Width = m_cachedMode.Width;
279   outCurrentDisplayMode->Height = m_cachedMode.Height;
280   outCurrentDisplayMode->RefreshRate.Numerator = m_cachedMode.RefreshRate.Numerator;
281   outCurrentDisplayMode->RefreshRate.Denominator = m_cachedMode.RefreshRate.Denominator;
282   outCurrentDisplayMode->Format = m_cachedMode.Format;
283   outCurrentDisplayMode->ScanlineOrdering = m_cachedMode.ScanlineOrdering;
284   outCurrentDisplayMode->Scaling = m_cachedMode.Scaling;
285 }
286
287 void CRenderSystemDX::GetDisplayMode(DXGI_MODE_DESC *mode, bool useCached /*= false*/)
288 {
289   GetClosestDisplayModeToCurrent(m_pOutput, mode, useCached);
290 }
291
292 inline void DXWait(ID3D11Device* pDevice, ID3D11DeviceContext* pContext)
293 {
294   ID3D11Query* wait = NULL;
295   CD3D11_QUERY_DESC qd(D3D11_QUERY_EVENT);
296   if (SUCCEEDED(pDevice->CreateQuery(&qd, &wait)))
297   {
298     pContext->End(wait);
299     while (S_FALSE == pContext->GetData(wait, NULL, 0, 0))
300       Sleep(1);
301   }
302   SAFE_RELEASE(wait);
303 }
304
305 void CRenderSystemDX::SetFullScreenInternal()
306 {
307   if (!m_bRenderCreated)
308     return;
309
310   HRESULT hr;
311   BOOL bFullScreen;
312   m_pSwapChain->GetFullscreenState(&bFullScreen, NULL);
313
314   // full-screen to windowed translation. Only change FS state and return
315   if (!!bFullScreen && m_useWindowedDX)
316   {
317     CLog::Log(LOGDEBUG, "%s - Switching swap chain to windowed mode.", __FUNCTION__);
318     hr = m_pSwapChain->SetFullscreenState(false, NULL);
319     m_bResizeRequred = S_OK == hr;
320
321     if (S_OK != hr)
322       CLog::Log(LOGERROR, "%s - Failed switch full screen state: %s.", __FUNCTION__, GetErrorDescription(hr).c_str());
323     // wait until switching screen state is done
324     DXWait(m_pD3DDev, m_pImdContext);
325     return;
326   }
327
328   // true full-screen
329   if (m_bFullScreenDevice && !m_useWindowedDX)
330   {
331     IDXGIOutput* pOutput = NULL;
332     m_pSwapChain->GetContainingOutput(&pOutput);
333
334     DXGI_OUTPUT_DESC trgDesc, currDesc;
335     m_pOutput->GetDesc(&trgDesc);
336     pOutput->GetDesc(&currDesc);
337
338     if (trgDesc.Monitor != currDesc.Monitor || !bFullScreen)
339     {
340       // swap chain requires to change FS mode after resize or transition from windowed to full-screen.
341       CLog::Log(LOGDEBUG, "%s - Switching swap chain to fullscreen state.", __FUNCTION__);
342       hr = m_pSwapChain->SetFullscreenState(true, m_pOutput);
343       m_bResizeRequred = S_OK == hr;
344
345       if (S_OK != hr)
346         CLog::Log(LOGERROR, "%s - Failed switch full screen state: %s.", __FUNCTION__, GetErrorDescription(hr).c_str());
347     }
348     SAFE_RELEASE(pOutput);
349
350     // do not change modes if hw stereo
351     if (g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_HARDWAREBASED)
352       return;
353
354     DXGI_SWAP_CHAIN_DESC scDesc;
355     m_pSwapChain->GetDesc(&scDesc);
356
357     DXGI_MODE_DESC currentMode, // closest to current mode
358       toMatchMode,              // required mode
359       matchedMode;              // closest to required mode
360
361     // find current mode on target output
362     GetClosestDisplayModeToCurrent(m_pOutput, &currentMode);
363
364     float currentRefreshRate = RATIONAL_TO_FLOAT(currentMode.RefreshRate);
365     CLog::Log(LOGDEBUG, "%s - Current display mode is: %dx%d@%0.3f", __FUNCTION__, currentMode.Width, currentMode.Height, currentRefreshRate);
366
367     // use backbuffer dimention to find required display mode
368     toMatchMode.Width = m_nBackBufferWidth;
369     toMatchMode.Height = m_nBackBufferHeight;
370     bool useDefaultRefreshRate = 0 == m_refreshRate;
371     toMatchMode.RefreshRate.Numerator = useDefaultRefreshRate ? 0 : m_refreshRate;
372     toMatchMode.RefreshRate.Denominator = useDefaultRefreshRate ? 0 : 1;
373     toMatchMode.Format = scDesc.BufferDesc.Format;
374     toMatchMode.Scaling = scDesc.BufferDesc.Scaling;
375     toMatchMode.ScanlineOrdering = scDesc.BufferDesc.ScanlineOrdering;
376
377     // find closest mode
378     m_pOutput->FindClosestMatchingMode(&toMatchMode, &matchedMode, m_pD3DDev);
379
380     float matchedRefreshRate = RATIONAL_TO_FLOAT(matchedMode.RefreshRate);
381     CLog::Log(LOGDEBUG, "%s - Found matched mode: %dx%d@%0.3f", __FUNCTION__, matchedMode.Width, matchedMode.Height, matchedRefreshRate);
382
383     // change mode if required (current != required)
384     if ( currentMode.Width != matchedMode.Width
385       || currentMode.Height != matchedMode.Height
386       || currentRefreshRate != matchedRefreshRate)
387     {
388       CLog::Log(LOGDEBUG, "%s - Switching mode to %dx%d@%0.3f.", __FUNCTION__, matchedMode.Width, matchedMode.Height, matchedRefreshRate);
389
390       // resize window (in windowed mode) or monitor resolution (in fullscreen mode) to required mode
391       hr = m_pSwapChain->ResizeTarget(&matchedMode);
392       m_bResizeRequred = S_OK == hr;
393
394       if (FAILED(hr))
395         CLog::Log(LOGERROR, "%s - Failed to switch output mode: %s", __FUNCTION__, GetErrorDescription(hr).c_str());
396     }
397
398     // wait until switching screen state is done
399     DXWait(m_pD3DDev, m_pImdContext);
400   }
401 }
402
403 bool CRenderSystemDX::IsFormatSupport(DXGI_FORMAT format, unsigned int usage)
404 {
405   UINT supported;
406   m_pD3DDev->CheckFormatSupport(format, &supported);
407   return (supported & usage) != 0;
408 }
409
410 bool CRenderSystemDX::DestroyRenderSystem()
411 {
412   DeleteDevice();
413
414   SAFE_RELEASE(m_pOutput);
415   SAFE_RELEASE(m_adapter);
416   SAFE_RELEASE(m_dxgiFactory);
417   return true;
418 }
419
420 void CRenderSystemDX::DeleteDevice()
421 {
422   CSingleLock lock(m_resourceSection);
423
424   if (m_pGUIShader)
425     m_pGUIShader->End();
426
427   // tell any shared resources
428   for (std::vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
429     (*i)->OnDestroyDevice();
430
431   if (m_pSwapChain)
432     m_pSwapChain->SetFullscreenState(false, NULL);
433
434   SAFE_DELETE(m_pGUIShader);
435   SAFE_RELEASE(m_pTextureRight);
436   SAFE_RELEASE(m_pRenderTargetViewRight);
437   SAFE_RELEASE(m_pShaderResourceViewRight);
438   SAFE_RELEASE(m_BlendEnableState);
439   SAFE_RELEASE(m_BlendDisableState);
440   SAFE_RELEASE(m_RSScissorDisable);
441   SAFE_RELEASE(m_RSScissorEnable);
442   SAFE_RELEASE(m_depthStencilState);
443   SAFE_RELEASE(m_depthStencilView);
444   SAFE_RELEASE(m_pRenderTargetView);
445   if (m_pContext && m_pContext != m_pImdContext)
446   {
447     m_pContext->ClearState();
448     m_pContext->Flush();
449     SAFE_RELEASE(m_pContext);
450   }
451   if (m_pImdContext)
452   {
453     m_pImdContext->ClearState();
454     m_pImdContext->Flush();
455     SAFE_RELEASE(m_pImdContext);
456   }
457   SAFE_RELEASE(m_pSwapChain);
458   SAFE_RELEASE(m_pSwapChain1);
459   SAFE_RELEASE(m_pD3DDev);
460 #ifdef _DEBUG
461   if (m_d3dDebug)
462   {
463     m_d3dDebug->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);
464     SAFE_RELEASE(m_d3dDebug);
465   }
466 #endif
467   m_bResizeRequred = false;
468   m_bHWStereoEnabled = false;
469   m_bRenderCreated = false;
470 }
471
472 void CRenderSystemDX::OnDeviceLost()
473 {
474   CSingleLock lock(m_resourceSection);
475   g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_RENDERER_LOST);
476
477   if (m_needNewDevice)
478     DeleteDevice();
479   else
480   {
481     // just resetting the device
482     for (std::vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
483       (*i)->OnLostDevice();
484   }
485 }
486
487 void CRenderSystemDX::OnDeviceReset()
488 {
489   CSingleLock lock(m_resourceSection);
490
491   if (m_needNewDevice)
492     CreateDevice();
493   
494   if (m_bRenderCreated)
495   {
496     // we're back
497     for (std::vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
498       (*i)->OnResetDevice();
499
500     g_renderManager.Flush();
501     g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_RENDERER_RESET);
502   }
503 }
504
505 bool CRenderSystemDX::CreateDevice()
506 {
507   CSingleLock lock(m_resourceSection);
508
509   HRESULT hr;
510
511   SAFE_RELEASE(m_pD3DDev);
512
513   D3D_FEATURE_LEVEL featureLevels[] =
514   {
515     D3D_FEATURE_LEVEL_11_1,
516     D3D_FEATURE_LEVEL_11_0,
517     D3D_FEATURE_LEVEL_10_1,
518     D3D_FEATURE_LEVEL_10_0,
519     D3D_FEATURE_LEVEL_9_3,
520     D3D_FEATURE_LEVEL_9_2,
521     D3D_FEATURE_LEVEL_9_1,
522   };
523
524   // the VIDEO_SUPPORT flag force lowering feature level if current env not support video on 11_1
525   UINT createDeviceFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT; 
526 #ifdef _DEBUG
527   createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
528 #endif
529
530   // we should specify D3D_DRIVER_TYPE_UNKNOWN if create device with specified adapter.
531   hr = D3D11CreateDevice(m_adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, createDeviceFlags, featureLevels, ARRAYSIZE(featureLevels), 
532                          D3D11_SDK_VERSION, &m_pD3DDev, &m_featureLevel, &m_pImdContext);
533
534   if (FAILED(hr))
535   {
536     // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
537     CLog::Log(LOGDEBUG, "%s - First try to create device failed with error: %s.", __FUNCTION__, GetErrorDescription(hr).c_str());
538     CLog::Log(LOGDEBUG, "%s - Trying to create device with lowest feature level: %#x.", __FUNCTION__, featureLevels[1]);
539
540     hr = D3D11CreateDevice(m_adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, createDeviceFlags, &featureLevels[1], ARRAYSIZE(featureLevels) - 1,
541                            D3D11_SDK_VERSION, &m_pD3DDev, &m_featureLevel, &m_pImdContext);
542     if (FAILED(hr))
543     {
544       // still failed. seems driver doesn't support video API acceleration, try without VIDEO_SUPPORT flag
545       CLog::Log(LOGDEBUG, "%s - Next try to create device failed with error: %s.", __FUNCTION__, GetErrorDescription(hr).c_str());
546       CLog::Log(LOGDEBUG, "%s - Trying to create device without video API support.", __FUNCTION__);
547
548       createDeviceFlags &= ~D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
549       hr = D3D11CreateDevice(m_adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, createDeviceFlags, &featureLevels[1], ARRAYSIZE(featureLevels) - 1,
550                              D3D11_SDK_VERSION, &m_pD3DDev, &m_featureLevel, &m_pImdContext);
551       if (SUCCEEDED(hr))
552         CLog::Log(LOGNOTICE, "%s - Your video driver doesn't support DirectX 11 Video Acceleration API. Application is not be able to use hardware video processing and decoding", __FUNCTION__);
553     }
554   }
555
556   if (FAILED(hr))
557   {
558     CLog::Log(LOGERROR, "%s - D3D11 device creation failure with error %s.", __FUNCTION__, GetErrorDescription(hr).c_str());
559     return false;
560   }
561
562   if ( g_advancedSettings.m_bAllowDeferredRendering 
563     && FAILED(m_pD3DDev->CreateDeferredContext(0, &m_pContext)))
564   {
565     CLog::Log(LOGERROR, "%s - Failed to create deferred context, deferred rendering is not possible, fallback to immediate rendering.", __FUNCTION__);
566   }
567
568   // make immediate context as default context if deferred context was not created
569   if (!m_pContext)
570     m_pContext = m_pImdContext;
571
572   if (m_featureLevel < D3D_FEATURE_LEVEL_9_3)
573     m_maxTextureSize = D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
574   else if (m_featureLevel < D3D_FEATURE_LEVEL_10_0)
575     m_maxTextureSize = D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
576   else if (m_featureLevel < D3D_FEATURE_LEVEL_11_0)
577     m_maxTextureSize = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
578   else 
579     // 11_x and greater feature level. Limit this size to avoid memory overheads
580     m_maxTextureSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION >> 1;
581
582   // use multi-thread protection on the device context to prevent deadlock issues that can sometimes happen
583   // when decoder call ID3D11VideoContext::GetDecoderBuffer or ID3D11VideoContext::ReleaseDecoderBuffer.
584   ID3D10Multithread *pMultiThreading = NULL;
585   if (SUCCEEDED(m_pD3DDev->QueryInterface(__uuidof(ID3D10Multithread), reinterpret_cast<void**>(&pMultiThreading))))
586   {
587     pMultiThreading->SetMultithreadProtected(true);
588     pMultiThreading->Release();
589   }
590
591   IDXGIDevice1* pDXGIDevice = NULL;
592   if (SUCCEEDED(m_pD3DDev->QueryInterface(__uuidof(IDXGIDevice1), reinterpret_cast<void**>(&pDXGIDevice))))
593   {
594     // Not sure the following actually does something but this exists in dx9 implementation
595     pDXGIDevice->SetGPUThreadPriority(7);
596     // Ensure that DXGI does not queue more than one frame at a time. This both reduces
597     // latency and ensures that the application will only render after each VSync
598     pDXGIDevice->SetMaximumFrameLatency(1);
599     SAFE_RELEASE(pDXGIDevice);
600   }
601
602 #ifdef _DEBUG
603   if (SUCCEEDED(m_pD3DDev->QueryInterface(__uuidof(ID3D11Debug), reinterpret_cast<void**>(&m_d3dDebug))))
604   {
605     ID3D11InfoQueue *d3dInfoQueue = nullptr;
606     if (SUCCEEDED(m_d3dDebug->QueryInterface(__uuidof(ID3D11InfoQueue), reinterpret_cast<void**>(&d3dInfoQueue))))
607     {
608       D3D11_MESSAGE_ID hide[] =
609       {
610         D3D11_MESSAGE_ID_GETVIDEOPROCESSORFILTERRANGE_UNSUPPORTED,        // avoid GETVIDEOPROCESSORFILTERRANGE_UNSUPPORTED (dx bug)
611         D3D11_MESSAGE_ID_DEVICE_RSSETSCISSORRECTS_NEGATIVESCISSOR         // avoid warning for some labels out of screen
612         // Add more message IDs here as needed
613       };
614
615       D3D11_INFO_QUEUE_FILTER filter;
616       ZeroMemory(&filter, sizeof(filter));
617       filter.DenyList.NumIDs = _countof(hide);
618       filter.DenyList.pIDList = hide;
619       d3dInfoQueue->AddStorageFilterEntries(&filter);
620       d3dInfoQueue->Release();
621     }
622   }
623 #endif
624
625   m_adapterDesc = {};
626   if (SUCCEEDED(m_adapter->GetDesc(&m_adapterDesc)))
627   {
628     CLog::Log(LOGDEBUG, "%s - on adapter %S (VendorId: %#x DeviceId: %#x) with feature level %#x.", __FUNCTION__, 
629                         m_adapterDesc.Description, m_adapterDesc.VendorId, m_adapterDesc.DeviceId, m_featureLevel);
630
631     m_RenderRenderer = StringUtils::Format("%S", m_adapterDesc.Description);
632     IDXGIFactory2* dxgiFactory2 = nullptr;
633     m_dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2));
634     m_RenderVersion = StringUtils::Format("DirectX %s (FL %d.%d)", 
635                                           dxgiFactory2 != nullptr ? "11.1" : "11.0", 
636                                           (m_featureLevel >> 12) & 0xF, 
637                                           (m_featureLevel >> 8) & 0xF);
638     SAFE_RELEASE(dxgiFactory2);
639   }
640
641   m_renderCaps = 0;
642   unsigned int usage = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
643   if ( IsFormatSupport(DXGI_FORMAT_BC1_UNORM, usage)
644     && IsFormatSupport(DXGI_FORMAT_BC2_UNORM, usage)
645     && IsFormatSupport(DXGI_FORMAT_BC3_UNORM, usage))
646     m_renderCaps |= RENDER_CAPS_DXT;
647
648   // MSDN: At feature levels 9_1, 9_2 and 9_3, the display device supports the use of 2D textures with dimensions that are not powers of two under two conditions.
649   // First, only one MIP-map level for each texture can be created - we are using only 1 mip level)
650   // Second, no wrap sampler modes for textures are allowed - we are using clamp everywhere
651   // At feature levels 10_0, 10_1 and 11_0, the display device unconditionally supports the use of 2D textures with dimensions that are not powers of two.
652   // so, setup caps NPOT
653   m_renderCaps |= RENDER_CAPS_NPOT;
654   if ((m_renderCaps & RENDER_CAPS_DXT) != 0)
655     m_renderCaps |= RENDER_CAPS_DXT_NPOT;
656
657   // Temporary - allow limiting the caps to debug a texture problem
658   if (g_advancedSettings.m_RestrictCapsMask != 0)
659     m_renderCaps &= ~g_advancedSettings.m_RestrictCapsMask;
660
661   if (m_renderCaps & RENDER_CAPS_DXT)
662     CLog::Log(LOGDEBUG, "%s - RENDER_CAPS_DXT", __FUNCTION__);
663   if (m_renderCaps & RENDER_CAPS_NPOT)
664     CLog::Log(LOGDEBUG, "%s - RENDER_CAPS_NPOT", __FUNCTION__);
665   if (m_renderCaps & RENDER_CAPS_DXT_NPOT)
666     CLog::Log(LOGDEBUG, "%s - RENDER_CAPS_DXT_NPOT", __FUNCTION__);
667
668   /* All the following quirks need to be tested
669   // nVidia quirk: some NPOT DXT textures of the GUI display with corruption
670   // when using D3DPOOL_DEFAULT + D3DUSAGE_DYNAMIC textures (no other choice with D3D9Ex for example)
671   // most likely xbmc bug, but no hw to repro & fix properly.
672   // affects lots of hw generations - 6xxx, 7xxx, GT220, ION1
673   // see ticket #9269
674   if (m_adapterDesc.VendorId == PCIV_nVidia)
675   {
676     CLog::Log(LOGDEBUG, __FUNCTION__" - nVidia workaround - disabling RENDER_CAPS_DXT_NPOT");
677     m_renderCaps &= ~RENDER_CAPS_DXT_NPOT;
678   }
679
680   // Intel quirk: DXT texture pitch must be > 64
681   // when using D3DPOOL_DEFAULT + D3DUSAGE_DYNAMIC textures (no other choice with D3D9Ex)
682   // DXT1:   32 pixels wide is the largest non-working texture width
683   // DXT3/5: 16 pixels wide ----------------------------------------
684   // Both equal to a pitch of 64. So far no Intel has DXT NPOT (including i3/i5/i7, so just go with the next higher POT.
685   // See ticket #9578
686   if (m_adapterDesc.VendorId == PCIV_Intel)
687   {
688     CLog::Log(LOGDEBUG, __FUNCTION__" - Intel workaround - specifying minimum pitch for compressed textures.");
689     m_minDXTPitch = 128;
690   }*/
691
692   if (!CreateStates() || !InitGUIShader() || !CreateWindowSizeDependentResources())
693     return false;
694
695   m_bRenderCreated = true;
696   m_needNewDevice = false;
697
698   // tell any shared objects about our resurrection
699   for (std::vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
700     (*i)->OnCreateDevice();
701
702   RestoreViewPort();
703
704   return true;
705 }
706
707 bool CRenderSystemDX::CreateWindowSizeDependentResources()
708 {
709   if (m_resizeInProgress)
710     return false;
711
712   HRESULT hr;
713   DXGI_SWAP_CHAIN_DESC scDesc = { 0 };
714
715   bool bNeedRecreate = false;
716   bool bNeedResize   = false;
717   bool bHWStereoEnabled = RENDER_STEREO_MODE_HARDWAREBASED == g_graphicsContext.GetStereoMode();
718
719   if (m_pSwapChain)
720   {
721     m_pSwapChain->GetDesc(&scDesc);
722     bNeedResize = m_bResizeRequred || m_nBackBufferWidth != scDesc.BufferDesc.Width || m_nBackBufferHeight != scDesc.BufferDesc.Height;
723   }
724   else
725     bNeedResize = true;
726
727   if (m_pSwapChain1)
728   {
729     DXGI_SWAP_CHAIN_DESC1 scDesc;
730     m_pSwapChain1->GetDesc1(&scDesc);
731     bNeedRecreate = (scDesc.Stereo && !bHWStereoEnabled) || (!scDesc.Stereo && bHWStereoEnabled);
732   }
733
734   if (!bNeedRecreate && !bNeedResize)
735   {
736     CheckInterlasedStereoView();
737     return true;
738   }
739
740   m_resizeInProgress = true;
741
742   CLog::Log(LOGDEBUG, "%s - (Re)Create window size (%dx%d) dependent resources.", __FUNCTION__, m_nBackBufferWidth, m_nBackBufferHeight);
743
744   bool bRestoreRTView = false;
745   {
746     ID3D11RenderTargetView* pRTView; ID3D11DepthStencilView* pDSView;
747     m_pContext->OMGetRenderTargets(1, &pRTView, &pDSView);
748
749     bRestoreRTView = NULL != pRTView || NULL != pDSView;
750
751     SAFE_RELEASE(pRTView);
752     SAFE_RELEASE(pDSView);
753   }
754
755   m_pContext->OMSetRenderTargets(0, NULL, NULL);
756   FinishCommandList(false);
757
758   SAFE_RELEASE(m_pRenderTargetView);
759   SAFE_RELEASE(m_depthStencilView);
760   SAFE_RELEASE(m_pRenderTargetViewRight);
761   SAFE_RELEASE(m_pShaderResourceViewRight);
762   SAFE_RELEASE(m_pTextureRight);
763
764   if (bNeedRecreate)
765   {
766     BOOL fullScreen;
767     m_pSwapChain1->GetFullscreenState(&fullScreen, NULL);
768     if (fullScreen)
769       m_pSwapChain1->SetFullscreenState(false, NULL);
770
771     CLog::Log(LOGDEBUG, "%s - Destroying swapchain in order to switch %s stereoscopic 3D.", __FUNCTION__, bHWStereoEnabled ? "to" : "from");
772
773     SAFE_RELEASE(m_pSwapChain);
774     SAFE_RELEASE(m_pSwapChain1);
775     m_pImdContext->Flush();
776
777     // flush command is asynchronous, so wait until destruction is completed
778     // otherwise it can cause problems with flip presentation model swap chains.
779     DXWait(m_pD3DDev, m_pImdContext);
780   }
781
782   if (!m_pSwapChain)
783   {
784     CLog::Log(LOGDEBUG, "%s - Creating swapchain in %s mode.", __FUNCTION__, bHWStereoEnabled ? "Stereoscopic 3D" : "Mono");
785
786     // Create swap chain
787     IDXGIFactory2* dxgiFactory2 = NULL;
788     hr = m_dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2));
789     if (SUCCEEDED(hr) && dxgiFactory2)
790     {
791       // DirectX 11.1 or later
792       DXGI_SWAP_CHAIN_DESC1 scDesc1 = { 0 };
793       scDesc1.Width       = m_nBackBufferWidth;
794       scDesc1.Height      = m_nBackBufferHeight;
795       scDesc1.BufferCount = 2;  // Use double buffering to minimize latency.
796       scDesc1.Format      = DXGI_FORMAT_B8G8R8A8_UNORM;
797       scDesc1.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
798       scDesc1.AlphaMode   = DXGI_ALPHA_MODE_UNSPECIFIED;
799       scDesc1.Stereo      = bHWStereoEnabled;
800       scDesc1.SwapEffect  = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
801       scDesc1.Flags       = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
802
803       scDesc1.SampleDesc.Count = 1;
804       scDesc1.SampleDesc.Quality = 0;
805
806       DXGI_SWAP_CHAIN_FULLSCREEN_DESC scFSDesc = { 0 };
807       scFSDesc.ScanlineOrdering = m_interlaced ? DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST : DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
808       scFSDesc.Windowed         = m_useWindowedDX;
809
810       hr = dxgiFactory2->CreateSwapChainForHwnd(m_pD3DDev, m_hFocusWnd, &scDesc1, &scFSDesc, NULL, &m_pSwapChain1);
811
812       if (SUCCEEDED(hr))
813       {
814         m_pSwapChain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&m_pSwapChain));
815         // this hackish way to disable stereo in windowed mode:
816         // - restart presenting, 0 in sync interval discards current frame also
817         // - wait until new frame will be drawn
818         // sleep value possible depends on hardware m.b. need a setting in as.xml
819         if (m_useWindowedDX && !bHWStereoEnabled && m_bHWStereoEnabled)
820         {
821           DXGI_PRESENT_PARAMETERS presentParams = {};
822           presentParams.DirtyRectsCount = 0;
823           presentParams.pDirtyRects = NULL;
824           presentParams.pScrollRect = NULL;
825           m_pSwapChain1->Present1(0, DXGI_PRESENT_RESTART, &presentParams);
826
827           Sleep(100);
828         }
829         m_bHWStereoEnabled = bHWStereoEnabled;
830       }
831       dxgiFactory2->Release();
832     }
833     else
834     {
835       // DirectX 11.0 systems
836       scDesc.BufferCount  = 2;  // Use double buffering to minimize latency.
837       scDesc.BufferUsage  = DXGI_USAGE_RENDER_TARGET_OUTPUT;
838       scDesc.OutputWindow = m_hFocusWnd;
839       scDesc.Windowed     = m_useWindowedDX;
840       scDesc.SwapEffect   = DXGI_SWAP_EFFECT_SEQUENTIAL;
841       scDesc.Flags        = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
842
843       scDesc.BufferDesc.Width   = m_nBackBufferWidth;
844       scDesc.BufferDesc.Height  = m_nBackBufferHeight;
845       scDesc.BufferDesc.Format  = DXGI_FORMAT_B8G8R8A8_UNORM;
846       scDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
847       scDesc.BufferDesc.ScanlineOrdering = m_interlaced ? DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST : DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
848       scDesc.SampleDesc.Count = 1;
849       scDesc.SampleDesc.Quality = 0;
850
851       hr = m_dxgiFactory->CreateSwapChain(m_pD3DDev, &scDesc, &m_pSwapChain);
852     }
853
854     if (FAILED(hr))
855     {
856       CLog::Log(LOGERROR, "%s - Creating swap chain failed with error: %s.", __FUNCTION__, GetErrorDescription(hr).c_str());
857       m_bRenderCreated = false;
858       return false;
859     }
860
861     // tell DXGI to not interfere with application's handling of window mode changes
862     m_dxgiFactory->MakeWindowAssociation(m_hFocusWnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER);
863   }
864   else
865   {
866     // resize swap chain buffers with preserving the existing buffer count and format.
867     hr = m_pSwapChain->ResizeBuffers(scDesc.BufferCount, m_nBackBufferWidth, m_nBackBufferHeight, scDesc.BufferDesc.Format, scDesc.Flags);
868     if (FAILED(hr))
869     {
870       CLog::Log(LOGERROR, "%s - Failed to resize buffers (%s).", __FUNCTION__, GetErrorDescription(hr).c_str());
871       if (DXGI_ERROR_DEVICE_REMOVED == hr)
872         OnDeviceLost();
873
874       return false;
875     }
876   }
877
878   // Create a render target view
879   ID3D11Texture2D* pBackBuffer = nullptr;
880   hr = m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer));
881   if (FAILED(hr))
882   {
883     CLog::Log(LOGERROR, "%s - Failed to get back buffer (%s).", __FUNCTION__, GetErrorDescription(hr).c_str());
884     return false;
885   }
886
887   // Create a view interface on the rendertarget to use on bind for mono or left eye view.
888   CD3D11_RENDER_TARGET_VIEW_DESC rtDesc(D3D11_RTV_DIMENSION_TEXTURE2DARRAY, DXGI_FORMAT_UNKNOWN, 0, 0, 1);
889   hr = m_pD3DDev->CreateRenderTargetView(pBackBuffer, &rtDesc, &m_pRenderTargetView);
890   if (FAILED(hr))
891   {
892     CLog::Log(LOGERROR, "%s - Failed to create render target view (%s).", __FUNCTION__, GetErrorDescription(hr).c_str());
893     pBackBuffer->Release();
894     return false;
895   }
896
897   if (m_bHWStereoEnabled)
898   {
899     // Stereo swapchains have an arrayed resource, so create a second Render Target for the right eye buffer.
900     CD3D11_RENDER_TARGET_VIEW_DESC rtDesc(D3D11_RTV_DIMENSION_TEXTURE2DARRAY, DXGI_FORMAT_UNKNOWN, 0, 1, 1);
901     hr = m_pD3DDev->CreateRenderTargetView(pBackBuffer, &rtDesc, &m_pRenderTargetViewRight);
902     if (FAILED(hr))
903     {
904       CLog::Log(LOGERROR, "%s - Failed to create right eye buffer (%s).", __FUNCTION__, GetErrorDescription(hr).c_str());
905       pBackBuffer->Release();
906       g_graphicsContext.SetStereoMode(RENDER_STEREO_MODE_OFF); // try fallback to mono
907     }
908   }
909   pBackBuffer->Release();
910
911   DXGI_FORMAT zFormat = DXGI_FORMAT_D16_UNORM;
912   if      (IsFormatSupport(DXGI_FORMAT_D32_FLOAT, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL))          zFormat = DXGI_FORMAT_D32_FLOAT;
913   else if (IsFormatSupport(DXGI_FORMAT_D24_UNORM_S8_UINT, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL))  zFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
914   else if (IsFormatSupport(DXGI_FORMAT_D16_UNORM, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL))          zFormat = DXGI_FORMAT_D16_UNORM;
915
916   ID3D11Texture2D* depthStencilBuffer = NULL;
917   // Initialize the description of the depth buffer.
918   CD3D11_TEXTURE2D_DESC depthBufferDesc(zFormat, m_nBackBufferWidth, m_nBackBufferHeight, 1, 1, D3D11_BIND_DEPTH_STENCIL);
919   // Create the texture for the depth buffer using the filled out description.
920   hr = m_pD3DDev->CreateTexture2D(&depthBufferDesc, NULL, &depthStencilBuffer);
921   if (FAILED(hr))
922   {
923     CLog::Log(LOGERROR, "%s - Failed to create depth stencil buffer (%s).", __FUNCTION__, GetErrorDescription(hr).c_str());
924     return false;
925   }
926
927   // Create the depth stencil view.
928   CD3D11_DEPTH_STENCIL_VIEW_DESC viewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
929   hr = m_pD3DDev->CreateDepthStencilView(depthStencilBuffer, &viewDesc, &m_depthStencilView);
930   depthStencilBuffer->Release();
931
932   if (FAILED(hr))
933   {
934     CLog::Log(LOGERROR, "%s - Failed to create depth stencil view (%s).", __FUNCTION__, GetErrorDescription(hr).c_str());
935     return false;
936   }
937
938   if (m_viewPort.Height == 0 || m_viewPort.Width == 0)
939   {
940     CRect rect(0, 0, m_nBackBufferWidth, m_nBackBufferHeight);
941     SetViewPort(rect);
942   }
943
944   // set camera to center of screen
945   CPoint camPoint = { m_nBackBufferWidth * 0.5f, m_nBackBufferHeight * 0.5f };
946   SetCameraPosition(camPoint, m_nBackBufferWidth, m_nBackBufferHeight);
947
948   CheckInterlasedStereoView();
949
950   if (bRestoreRTView)
951     m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, m_depthStencilView);
952
953   m_resizeInProgress = false;
954   m_bResizeRequred = false;
955
956   return true;
957 }
958
959 void CRenderSystemDX::CheckInterlasedStereoView(void)
960 {
961   RENDER_STEREO_MODE stereoMode = g_graphicsContext.GetStereoMode();
962
963   if ( m_pRenderTargetViewRight 
964     && RENDER_STEREO_MODE_INTERLACED    != stereoMode
965     && RENDER_STEREO_MODE_CHECKERBOARD  != stereoMode
966     && RENDER_STEREO_MODE_HARDWAREBASED != stereoMode)
967   {
968     // release resources
969     SAFE_RELEASE(m_pRenderTargetViewRight);
970     SAFE_RELEASE(m_pShaderResourceViewRight);
971     SAFE_RELEASE(m_pTextureRight);
972   }
973
974   if ( !m_pRenderTargetViewRight
975     && ( RENDER_STEREO_MODE_INTERLACED   == stereoMode 
976       || RENDER_STEREO_MODE_CHECKERBOARD == stereoMode))
977   {
978     // Create a second Render Target for the right eye buffer
979     HRESULT hr;
980     CD3D11_TEXTURE2D_DESC texDesc(DXGI_FORMAT_B8G8R8A8_UNORM, m_nBackBufferWidth, m_nBackBufferHeight, 1, 1,
981                                   D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
982     hr = m_pD3DDev->CreateTexture2D(&texDesc, NULL, &m_pTextureRight);
983     if (SUCCEEDED(hr))
984     {
985       CD3D11_RENDER_TARGET_VIEW_DESC rtDesc(D3D11_RTV_DIMENSION_TEXTURE2D);
986       hr = m_pD3DDev->CreateRenderTargetView(m_pTextureRight, &rtDesc, &m_pRenderTargetViewRight);
987
988       if (SUCCEEDED(hr))
989       {
990         CD3D11_SHADER_RESOURCE_VIEW_DESC srDesc(D3D11_SRV_DIMENSION_TEXTURE2D);
991         hr = m_pD3DDev->CreateShaderResourceView(m_pTextureRight, &srDesc, &m_pShaderResourceViewRight);
992
993         if (FAILED(hr))
994           CLog::Log(LOGERROR, "%s - Failed to create right view shader resource.", __FUNCTION__);
995       }
996       else
997         CLog::Log(LOGERROR, "%s - Failed to create right view render target.", __FUNCTION__);
998     }
999
1000     if (FAILED(hr))
1001     {
1002       SAFE_RELEASE(m_pShaderResourceViewRight);
1003       SAFE_RELEASE(m_pRenderTargetViewRight);
1004       SAFE_RELEASE(m_pTextureRight);
1005
1006       CLog::Log(LOGERROR, "%s - Failed to create right eye buffer.", __FUNCTION__);
1007       g_graphicsContext.SetStereoMode(RENDER_STEREO_MODE_OFF); // try fallback to mono
1008     }
1009   }
1010 }
1011
1012 bool CRenderSystemDX::CreateStates()
1013 {
1014   if (!m_pD3DDev)
1015     return false;
1016
1017   SAFE_RELEASE(m_depthStencilState);
1018   SAFE_RELEASE(m_BlendEnableState);
1019   SAFE_RELEASE(m_BlendDisableState);
1020
1021   // Initialize the description of the stencil state.
1022   D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
1023   ZeroMemory(&depthStencilDesc, sizeof(D3D11_DEPTH_STENCIL_DESC));
1024
1025   // Set up the description of the stencil state.
1026   depthStencilDesc.DepthEnable = false;
1027   depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
1028   depthStencilDesc.DepthFunc = D3D11_COMPARISON_NEVER;
1029   depthStencilDesc.StencilEnable = false;
1030   depthStencilDesc.StencilReadMask = 0xFF;
1031   depthStencilDesc.StencilWriteMask = 0xFF;
1032
1033   // Stencil operations if pixel is front-facing.
1034   depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
1035   depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
1036   depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
1037   depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
1038
1039   // Stencil operations if pixel is back-facing.
1040   depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
1041   depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
1042   depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
1043   depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
1044
1045   // Create the depth stencil state.
1046   HRESULT hr = m_pD3DDev->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
1047   if(FAILED(hr))
1048     return false;
1049
1050   // Set the depth stencil state.
1051         m_pContext->OMSetDepthStencilState(m_depthStencilState, 0);
1052
1053   D3D11_RASTERIZER_DESC rasterizerState;
1054   rasterizerState.CullMode = D3D11_CULL_NONE; 
1055   rasterizerState.FillMode = D3D11_FILL_SOLID;// DEBUG - D3D11_FILL_WIREFRAME
1056   rasterizerState.FrontCounterClockwise = false;
1057   rasterizerState.DepthBias = 0;
1058   rasterizerState.DepthBiasClamp = 0.0f;
1059   rasterizerState.DepthClipEnable = true;
1060   rasterizerState.SlopeScaledDepthBias = 0.0f;
1061   rasterizerState.ScissorEnable = false;
1062   rasterizerState.MultisampleEnable = false;
1063   rasterizerState.AntialiasedLineEnable = false;
1064
1065   if (FAILED(m_pD3DDev->CreateRasterizerState(&rasterizerState, &m_RSScissorDisable)))
1066     return false;
1067
1068   rasterizerState.ScissorEnable = true;
1069   if (FAILED(m_pD3DDev->CreateRasterizerState(&rasterizerState, &m_RSScissorEnable)))
1070     return false;
1071
1072   m_pContext->RSSetState(m_RSScissorDisable); // by default
1073
1074   D3D11_BLEND_DESC blendState = { 0 };
1075   ZeroMemory(&blendState, sizeof(D3D11_BLEND_DESC));
1076   blendState.RenderTarget[0].BlendEnable = true;
1077   blendState.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; // D3D11_BLEND_SRC_ALPHA;
1078   blendState.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; // D3D11_BLEND_INV_SRC_ALPHA;
1079   blendState.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
1080   blendState.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
1081   blendState.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
1082   blendState.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
1083   blendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
1084
1085   m_pD3DDev->CreateBlendState(&blendState, &m_BlendEnableState);
1086
1087   blendState.RenderTarget[0].BlendEnable = false;
1088   m_pD3DDev->CreateBlendState(&blendState, &m_BlendDisableState);
1089
1090   // by default
1091   m_pContext->OMSetBlendState(m_BlendEnableState, nullptr, 0xFFFFFFFF);
1092   m_BlendEnabled = true;
1093
1094   return true;
1095 }
1096
1097 bool CRenderSystemDX::PresentRenderImpl(const CDirtyRegionList &dirty)
1098 {
1099   HRESULT hr;
1100
1101   if (!m_bRenderCreated)
1102     return false;
1103
1104   if (m_nDeviceStatus != S_OK)
1105   {
1106     // if DXGI_STATUS_OCCLUDED occurred we just clear command queue and return
1107     if (m_nDeviceStatus == DXGI_STATUS_OCCLUDED)
1108       FinishCommandList(false);
1109     return false;
1110   }
1111
1112   if ( m_stereoMode == RENDER_STEREO_MODE_INTERLACED
1113     || m_stereoMode == RENDER_STEREO_MODE_CHECKERBOARD)
1114   {
1115     // all views prepared, let's merge them before present
1116     m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, m_depthStencilView);
1117     CRect destRect = { 0.0f, 0.0f, float(m_nBackBufferWidth), float(m_nBackBufferHeight) };
1118     SHADER_METHOD method = RENDER_STEREO_MODE_INTERLACED == m_stereoMode
1119                            ? SHADER_METHOD_RENDER_STEREO_INTERLACED_RIGHT
1120                            : SHADER_METHOD_RENDER_STEREO_CHECKERBOARD_RIGHT;
1121     SetAlphaBlendEnable(true);
1122     CD3DTexture::DrawQuad(destRect, 0, 1, &m_pShaderResourceViewRight, NULL, method);
1123     CD3DHelper::PSClearShaderResources(m_pContext);
1124   }
1125
1126   FinishCommandList();
1127
1128   if (m_pSwapChain1)
1129   {
1130     // will use optimized present with dirty regions.
1131     DXGI_PRESENT_PARAMETERS presentParams = {};
1132     presentParams.DirtyRectsCount = 0;
1133     presentParams.pDirtyRects = NULL;
1134     presentParams.pScrollRect = NULL;
1135     hr = m_pSwapChain1->Present1((m_bVSync ? 1 : 0), 0, &presentParams);
1136   }
1137   else 
1138     hr = m_pSwapChain->Present((m_bVSync ? 1 : 0), 0);
1139
1140   if (DXGI_ERROR_DEVICE_REMOVED == hr)
1141   {
1142     CLog::Log(LOGDEBUG, "%s - device removed", __FUNCTION__);
1143     return false;
1144   }
1145
1146   if (DXGI_ERROR_INVALID_CALL == hr)
1147   {
1148     m_bResizeRequred = true;
1149     if (CreateWindowSizeDependentResources())
1150       hr = S_OK;
1151   }
1152
1153   if (FAILED(hr))
1154   {
1155     CLog::Log(LOGDEBUG, "%s - Present failed. %s", __FUNCTION__, GetErrorDescription(hr).c_str());
1156     return false;
1157   }
1158
1159   // after present swapchain unbinds RT view from immediate context, need to restore it because it can be used by something else
1160   if (m_pContext == m_pImdContext)
1161     m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, m_depthStencilView);
1162
1163   return true;
1164 }
1165
1166 bool CRenderSystemDX::BeginRender()
1167 {
1168   if (!m_bRenderCreated)
1169     return false;
1170
1171   HRESULT oldStatus = m_nDeviceStatus;
1172   if (m_pSwapChain1)
1173   {
1174     DXGI_PRESENT_PARAMETERS presentParams = {};
1175     presentParams.DirtyRectsCount = 0;
1176     presentParams.pDirtyRects = NULL;
1177     presentParams.pScrollRect = NULL;
1178     m_nDeviceStatus = m_pSwapChain1->Present1(0, DXGI_PRESENT_TEST, &presentParams);
1179   }
1180   else
1181   {
1182     m_nDeviceStatus = m_pSwapChain->Present(0, DXGI_PRESENT_TEST);
1183   }
1184
1185   // handling of return values. 
1186   switch (m_nDeviceStatus)
1187   {
1188   case DXGI_ERROR_DEVICE_REMOVED: // GPU has been physically removed from the system, or a driver upgrade occurred. 
1189     CLog::Log(LOGERROR, "DXGI_ERROR_DEVICE_REMOVED");
1190     m_needNewDevice = true;
1191     break;
1192   case DXGI_ERROR_DEVICE_RESET: // This is an run-time issue that should be investigated and fixed.
1193     CLog::Log(LOGERROR, "DXGI_ERROR_DEVICE_RESET");
1194     m_nDeviceStatus = DXGI_ERROR_DEVICE_REMOVED;
1195     m_needNewDevice = true;
1196     break;
1197   case DXGI_ERROR_INVALID_CALL: // application provided invalid parameter data. Try to return after resize buffers
1198     CLog::Log(LOGERROR, "DXGI_ERROR_INVALID_CALL");
1199     m_bResizeRequred = true;
1200     if (CreateWindowSizeDependentResources())
1201       m_nDeviceStatus = S_OK;
1202     break;
1203   case DXGI_STATUS_OCCLUDED: // decide what we should do when windows content is not visible
1204     // do not spam to log file
1205     if (m_nDeviceStatus != oldStatus)
1206       CLog::Log(LOGDEBUG, "DXGI_STATUS_OCCLUDED");
1207     // Status OCCLUDED is not an error and not handled by FAILED macro, 
1208     // but if it occurs we should not render anything, this status will be accounted on present stage
1209   }
1210
1211   if (FAILED(m_nDeviceStatus))
1212   {
1213     if (DXGI_ERROR_DEVICE_REMOVED == m_nDeviceStatus)
1214     {
1215       OnDeviceLost();
1216       OnDeviceReset();
1217     }
1218     return false;
1219   }
1220
1221   m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, m_depthStencilView);
1222   m_inScene = true;
1223
1224   return true;
1225 }
1226
1227 bool CRenderSystemDX::EndRender()
1228 {
1229   m_inScene = false;
1230
1231   if (!m_bRenderCreated)
1232     return false;
1233   
1234   if(m_nDeviceStatus != S_OK)
1235     return false;
1236
1237   return true;
1238 }
1239
1240 bool CRenderSystemDX::ClearBuffers(color_t color)
1241 {
1242   if (!m_bRenderCreated || m_resizeInProgress)
1243     return false;
1244
1245   float fColor[4];
1246   CD3DHelper::XMStoreColor(fColor, color);
1247   ID3D11RenderTargetView* pRTView = m_pRenderTargetView;
1248
1249   if ( m_stereoMode != RENDER_STEREO_MODE_OFF
1250     && m_stereoMode != RENDER_STEREO_MODE_MONO)
1251   {
1252     // if stereo anaglyph/tab/sbs, data was cleared when left view was rendererd
1253     if (m_stereoView == RENDER_STEREO_VIEW_RIGHT)
1254     {
1255       // execute command's queue
1256       FinishCommandList();
1257
1258       // do not clear RT for anaglyph modes
1259       if ( m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA
1260         || m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
1261         || m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE)
1262       {
1263         pRTView = nullptr;
1264       }
1265       // for interlaced/checkerboard/hw clear right view
1266       else if (m_pRenderTargetViewRight)
1267         pRTView = m_pRenderTargetViewRight;
1268
1269       // for hw stereo clear depth view also
1270       if (m_stereoMode == RENDER_STEREO_MODE_HARDWAREBASED)
1271         m_pContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0, 0);
1272     }
1273   }
1274  
1275   if (pRTView == nullptr)
1276     return true;
1277
1278   CRect clRect(0, 0, m_nBackBufferWidth, m_nBackBufferHeight);
1279
1280   // Unlike Direct3D 9, D3D11 ClearRenderTargetView always clears full extent of the resource view. 
1281   // Viewport and scissor settings are not applied. So clear RT by drawing full sized rect with clear color
1282   if (m_ScissorsEnabled && m_scissor != clRect)
1283   {
1284     bool alphaEnabled = m_BlendEnabled;
1285     if (alphaEnabled)
1286       SetAlphaBlendEnable(false);
1287
1288     CGUITextureD3D::DrawQuad(clRect, color);
1289
1290     if (alphaEnabled)
1291       SetAlphaBlendEnable(true);
1292   }
1293   else
1294     m_pContext->ClearRenderTargetView(pRTView, fColor);
1295
1296   m_pContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0, 0);
1297   return true;
1298 }
1299
1300 bool CRenderSystemDX::IsExtSupported(const char* extension)
1301 {
1302   return false;
1303 }
1304
1305 bool CRenderSystemDX::PresentRender(const CDirtyRegionList &dirty)
1306 {
1307   if (!m_bRenderCreated || m_resizeInProgress)
1308     return false;
1309
1310   bool result = PresentRenderImpl(dirty);
1311
1312   return result;
1313 }
1314
1315 void CRenderSystemDX::SetVSync(bool enable)
1316 {
1317   m_bVSync = enable;
1318 }
1319
1320 void CRenderSystemDX::CaptureStateBlock()
1321 {
1322   if (!m_bRenderCreated)
1323     return;
1324 }
1325
1326 void CRenderSystemDX::ApplyStateBlock()
1327 {
1328   if (!m_bRenderCreated)
1329     return;
1330
1331   m_pContext->RSSetState(m_ScissorsEnabled ? m_RSScissorEnable : m_RSScissorDisable);
1332   m_pContext->OMSetDepthStencilState(m_depthStencilState, 0);
1333   float factors[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
1334   m_pContext->OMSetBlendState(m_BlendEnabled ? m_BlendEnableState : m_BlendDisableState, factors, 0xFFFFFFFF);
1335
1336   m_pGUIShader->ApplyStateBlock();
1337 }
1338
1339 void CRenderSystemDX::SetCameraPosition(const CPoint &camera, int screenWidth, int screenHeight, float stereoFactor)
1340 {
1341   if (!m_bRenderCreated)
1342     return;
1343
1344   // grab the viewport dimensions and location
1345   float w = m_viewPort.Width*0.5f;
1346   float h = m_viewPort.Height*0.5f;
1347
1348   XMFLOAT2 offset = XMFLOAT2(camera.x - screenWidth*0.5f, camera.y - screenHeight*0.5f);
1349
1350   // world view.  Until this is moved onto the GPU (via a vertex shader for instance), we set it to the identity here.
1351   m_pGUIShader->SetWorld(XMMatrixIdentity());
1352
1353   // Initialize the view matrix
1354   // camera view.  Multiply the Y coord by -1 then translate so that everything is relative to the camera
1355   // position.
1356   XMMATRIX flipY, translate;
1357   flipY = XMMatrixScaling(1.0, -1.0f, 1.0f);
1358   translate = XMMatrixTranslation(-(w + offset.x - stereoFactor), -(h + offset.y), 2 * h);
1359   m_pGUIShader->SetView(XMMatrixMultiply(translate, flipY));
1360
1361   // projection onto screen space
1362   m_pGUIShader->SetProjection(XMMatrixPerspectiveOffCenterLH((-w - offset.x)*0.5f, (w - offset.x)*0.5f, (-h + offset.y)*0.5f, (h + offset.y)*0.5f, h, 100 * h));
1363 }
1364
1365 void CRenderSystemDX::Project(float &x, float &y, float &z)
1366 {
1367   if (!m_bRenderCreated)
1368     return;
1369
1370   m_pGUIShader->Project(x, y, z);
1371 }
1372
1373 bool CRenderSystemDX::TestRender()
1374 {
1375   /*
1376   static unsigned int lastTime = 0;
1377   static float delta = 0;
1378
1379   unsigned int thisTime = XbmcThreads::SystemClockMillis();
1380
1381   if(thisTime - lastTime > 10)
1382   {
1383     lastTime = thisTime;
1384     delta++;
1385   }
1386
1387   CLog::Log(LOGINFO, "Delta =  %d", delta);
1388
1389   if(delta > m_nBackBufferWidth)
1390     delta = 0;
1391
1392   LPDIRECT3DVERTEXBUFFER9 pVB = NULL;
1393
1394   // A structure for our custom vertex type
1395   struct CUSTOMVERTEX
1396   {
1397     FLOAT x, y, z, rhw; // The transformed position for the vertex
1398     DWORD color;        // The vertex color
1399   };
1400
1401   // Our custom FVF, which describes our custom vertex structure
1402 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
1403
1404   // Initialize three vertices for rendering a triangle
1405   CUSTOMVERTEX vertices[] =
1406   {
1407     { delta + 100.0f,  50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color
1408     { delta+200.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },
1409     {  delta, 250.0f, 0.5f, 1.0f, 0xff00ffff, },
1410   };
1411
1412   // Create the vertex buffer. Here we are allocating enough memory
1413   // (from the default pool) to hold all our 3 custom vertices. We also
1414   // specify the FVF, so the vertex buffer knows what data it contains.
1415   if( FAILED( m_pD3DDevice->CreateVertexBuffer( 3 * sizeof( CUSTOMVERTEX ),
1416     0, D3DFVF_CUSTOMVERTEX,
1417     D3DPOOL_DEFAULT, &pVB, NULL ) ) )
1418   {
1419     return false;
1420   }
1421
1422   // Now we fill the vertex buffer. To do this, we need to Lock() the VB to
1423   // gain access to the vertices. This mechanism is required becuase vertex
1424   // buffers may be in device memory.
1425   VOID* pVertices;
1426   if( FAILED( pVB->Lock( 0, sizeof( vertices ), ( void** )&pVertices, 0 ) ) )
1427     return false;
1428   memcpy( pVertices, vertices, sizeof( vertices ) );
1429   pVB->Unlock();
1430
1431   m_pD3DDevice->SetStreamSource( 0, pVB, 0, sizeof( CUSTOMVERTEX ) );
1432   m_pD3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
1433   m_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );
1434
1435   pVB->Release();
1436   */
1437   return true;
1438 }
1439
1440 void CRenderSystemDX::ApplyHardwareTransform(const TransformMatrix &finalMatrix)
1441 {
1442   if (!m_bRenderCreated)
1443     return;
1444 }
1445
1446 void CRenderSystemDX::RestoreHardwareTransform()
1447 {
1448   if (!m_bRenderCreated)
1449     return;
1450 }
1451
1452 void CRenderSystemDX::GetViewPort(CRect& viewPort)
1453 {
1454   if (!m_bRenderCreated)
1455     return;
1456
1457   viewPort.x1 = m_viewPort.TopLeftX;
1458   viewPort.y1 = m_viewPort.TopLeftY;
1459   viewPort.x2 = m_viewPort.TopLeftX + m_viewPort.Width;
1460   viewPort.y2 = m_viewPort.TopLeftY + m_viewPort.Height;
1461 }
1462
1463 void CRenderSystemDX::SetViewPort(CRect& viewPort)
1464 {
1465   if (!m_bRenderCreated)
1466     return;
1467
1468   m_viewPort.MinDepth   = 0.0f;
1469   m_viewPort.MaxDepth   = 1.0f;
1470   m_viewPort.TopLeftX   = viewPort.x1;
1471   m_viewPort.TopLeftY   = viewPort.y1;
1472   m_viewPort.Width      = viewPort.x2 - viewPort.x1;
1473   m_viewPort.Height     = viewPort.y2 - viewPort.y1;
1474
1475   m_pContext->RSSetViewports(1, &m_viewPort);
1476   m_pGUIShader->SetViewPort(m_viewPort);
1477 }
1478
1479 void CRenderSystemDX::RestoreViewPort()
1480 {
1481   if (!m_bRenderCreated)
1482     return;
1483
1484   m_pContext->RSSetViewports(1, &m_viewPort);
1485   m_pGUIShader->SetViewPort(m_viewPort);
1486 }
1487
1488 bool CRenderSystemDX::ScissorsCanEffectClipping()
1489 {
1490   if (!m_bRenderCreated)
1491     return false;
1492
1493   return m_pGUIShader != NULL && m_pGUIShader->HardwareClipIsPossible();
1494 }
1495
1496 CRect CRenderSystemDX::ClipRectToScissorRect(const CRect &rect)
1497 {
1498   if (!m_bRenderCreated)
1499     return CRect();
1500
1501   float xFactor = m_pGUIShader->GetClipXFactor();
1502   float xOffset = m_pGUIShader->GetClipXOffset();
1503   float yFactor = m_pGUIShader->GetClipYFactor();
1504   float yOffset = m_pGUIShader->GetClipYOffset();
1505
1506   return CRect(rect.x1 * xFactor + xOffset,
1507                rect.y1 * yFactor + yOffset,
1508                rect.x2 * xFactor + xOffset,
1509                rect.y2 * yFactor + yOffset);
1510 }
1511
1512 void CRenderSystemDX::SetScissors(const CRect& rect)
1513 {
1514   if (!m_bRenderCreated)
1515     return;
1516
1517   m_scissor = rect;
1518   CD3D11_RECT scissor(MathUtils::round_int(rect.x1)
1519                     , MathUtils::round_int(rect.y1)
1520                     , MathUtils::round_int(rect.x2)
1521                     , MathUtils::round_int(rect.y2));
1522
1523   m_pContext->RSSetScissorRects(1, &scissor);
1524   m_pContext->RSSetState(m_RSScissorEnable);
1525   m_ScissorsEnabled = true;
1526 }
1527
1528 void CRenderSystemDX::ResetScissors()
1529 {
1530   if (!m_bRenderCreated)
1531     return;
1532
1533   m_scissor.SetRect(0, 0, m_nBackBufferWidth, m_nBackBufferHeight);
1534
1535   m_pContext->RSSetState(m_RSScissorDisable);
1536   m_ScissorsEnabled = false;
1537 }
1538
1539 void CRenderSystemDX::Register(ID3DResource *resource)
1540 {
1541   CSingleLock lock(m_resourceSection);
1542   m_resources.push_back(resource);
1543 }
1544
1545 void CRenderSystemDX::Unregister(ID3DResource* resource)
1546 {
1547   CSingleLock lock(m_resourceSection);
1548   std::vector<ID3DResource*>::iterator i = find(m_resources.begin(), m_resources.end(), resource);
1549   if (i != m_resources.end())
1550     m_resources.erase(i);
1551 }
1552
1553 std::string CRenderSystemDX::GetErrorDescription(HRESULT hr)
1554 {
1555   WCHAR buff[1024];
1556   DXGetErrorDescription(hr, buff, 1024);
1557   std::wstring error(DXGetErrorString(hr));
1558   std::wstring descr(buff);
1559   return StringUtils::Format("%X - %ls (%ls)", hr, error.c_str(), descr.c_str());
1560 }
1561
1562 void CRenderSystemDX::SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view)
1563 {
1564   CRenderSystemBase::SetStereoMode(mode, view);
1565
1566   if (!m_bRenderCreated)
1567     return;
1568
1569   UINT writeMask = D3D11_COLOR_WRITE_ENABLE_ALL;
1570   if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN)
1571   {
1572     if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
1573       writeMask = D3D11_COLOR_WRITE_ENABLE_RED;
1574     else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
1575       writeMask = D3D11_COLOR_WRITE_ENABLE_BLUE | D3D11_COLOR_WRITE_ENABLE_GREEN;
1576   }
1577   if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA)
1578   {
1579     if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
1580       writeMask = D3D11_COLOR_WRITE_ENABLE_GREEN;
1581     else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
1582       writeMask = D3D11_COLOR_WRITE_ENABLE_BLUE | D3D11_COLOR_WRITE_ENABLE_RED;
1583   }
1584   if (m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE)
1585   {
1586     if (m_stereoView == RENDER_STEREO_VIEW_LEFT)
1587       writeMask = D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN;
1588     else if (m_stereoView == RENDER_STEREO_VIEW_RIGHT)
1589       writeMask = D3D11_COLOR_WRITE_ENABLE_BLUE;
1590   }
1591   if ( RENDER_STEREO_MODE_INTERLACED    == m_stereoMode
1592     || RENDER_STEREO_MODE_CHECKERBOARD  == m_stereoMode
1593     || RENDER_STEREO_MODE_HARDWAREBASED == m_stereoMode)
1594   {
1595     if (m_stereoView == RENDER_STEREO_VIEW_RIGHT)
1596     {
1597       // render right eye view to right render target
1598       m_pContext->OMSetRenderTargets(1, &m_pRenderTargetViewRight, m_depthStencilView);
1599     }
1600   }
1601
1602   D3D11_BLEND_DESC desc;
1603   m_BlendEnableState->GetDesc(&desc);
1604   // update blend state
1605   if (desc.RenderTarget[0].RenderTargetWriteMask != writeMask)
1606   {
1607     SAFE_RELEASE(m_BlendDisableState);
1608     SAFE_RELEASE(m_BlendEnableState);
1609
1610     desc.RenderTarget[0].RenderTargetWriteMask = writeMask;
1611     m_pD3DDev->CreateBlendState(&desc, &m_BlendEnableState);
1612
1613     desc.RenderTarget[0].BlendEnable = false;
1614     m_pD3DDev->CreateBlendState(&desc, &m_BlendDisableState);
1615
1616     float blendFactors[] = { 0.0f, 0.0f, 0.0f, 0.0f };
1617     m_pContext->OMSetBlendState(m_BlendEnabled ? m_BlendEnableState : m_BlendDisableState, blendFactors, 0xFFFFFFFF);
1618   }
1619 }
1620
1621 bool CRenderSystemDX::SupportsStereo(RENDER_STEREO_MODE mode) const
1622 {
1623   bool isHWStereoSupport = false;
1624   IDXGIFactory2* dxgiFactory2 = NULL;
1625   if (SUCCEEDED(m_dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2))))
1626   {
1627     isHWStereoSupport = dxgiFactory2 && dxgiFactory2->IsWindowedStereoEnabled();
1628   }
1629   SAFE_RELEASE(dxgiFactory2);
1630
1631   switch (mode)
1632   {
1633     case RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN:
1634     case RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA:
1635     case RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE:
1636     case RENDER_STEREO_MODE_INTERLACED:
1637     case RENDER_STEREO_MODE_CHECKERBOARD:
1638       return true;
1639     case RENDER_STEREO_MODE_HARDWAREBASED:
1640       return isHWStereoSupport;
1641     default:
1642       return CRenderSystemBase::SupportsStereo(mode);
1643   }
1644 }
1645
1646 void CRenderSystemDX::FlushGPU()
1647 {
1648   if (!m_bRenderCreated)
1649     return;
1650
1651   FinishCommandList();
1652   m_pImdContext->Flush();
1653 }
1654
1655 bool CRenderSystemDX::InitGUIShader()
1656 {
1657   if (!m_pD3DDev)
1658     return false;
1659
1660   SAFE_DELETE(m_pGUIShader);
1661   m_pGUIShader = new CGUIShaderDX();
1662   if (!m_pGUIShader->Initialize())
1663   {
1664     CLog::Log(LOGERROR, __FUNCTION__ " - Failed to initialize GUI shader.");
1665     return false;
1666   }
1667
1668   m_pGUIShader->ApplyStateBlock();
1669
1670   return true;
1671 }
1672
1673 void CRenderSystemDX::SetAlphaBlendEnable(bool enable)
1674 {
1675   if (!m_bRenderCreated)
1676     return;
1677
1678   float blendFactors[] = { 0.0f, 0.0f, 0.0f, 0.0f };
1679   m_pContext->OMSetBlendState(enable ? m_BlendEnableState : m_BlendDisableState, 0, 0xFFFFFFFF);
1680   m_BlendEnabled = enable;
1681 }
1682
1683 void CRenderSystemDX::FinishCommandList(bool bExecute /*= true*/)
1684 {
1685   if (m_pImdContext == m_pContext)
1686     return;
1687
1688   ID3D11CommandList* pCommandList = NULL;
1689   if (FAILED(m_pContext->FinishCommandList(true, &pCommandList)))
1690   {
1691     CLog::Log(LOGERROR, "%s - Failed to finish command queue.", __FUNCTION__);
1692     return;
1693   }
1694
1695   if (bExecute)
1696     m_pImdContext->ExecuteCommandList(pCommandList, false);
1697
1698   SAFE_RELEASE(pCommandList);
1699 }
1700
1701 #endif