diff options
author | Martijn Kaijser <martijn@xbmc.org> | 2016-03-21 21:27:17 +0100 |
---|---|---|
committer | Martijn Kaijser <martijn@xbmc.org> | 2016-03-21 21:27:17 +0100 |
commit | 47d207a96b141a40fb7435e7767f8abb75ddaa8b (patch) | |
tree | 7e2916a5e6dd49acd1a4a628a702cf4908efbc2c | |
parent | a7caa16680f09810b730e88b3368f221465c9eee (diff) | |
parent | a505943f9b572b093a2a24e05f278557fc49ea3a (diff) |
Merge pull request #9409 from afedchin/winrendererj
[Backport][Win32] A sef of fixes for windows.
-rw-r--r-- | system/shaders/testshader.fx | 32 | ||||
-rw-r--r-- | system/shaders/yuv2rgb_d3d.fx | 31 | ||||
-rw-r--r-- | xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.cpp | 50 | ||||
-rw-r--r-- | xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.h | 3 | ||||
-rw-r--r-- | xbmc/guilib/D3DResource.cpp | 11 | ||||
-rw-r--r-- | xbmc/guilib/D3DResource.h | 1 | ||||
-rw-r--r-- | xbmc/rendering/dx/RenderSystemDX.cpp | 205 | ||||
-rw-r--r-- | xbmc/rendering/dx/RenderSystemDX.h | 2 | ||||
-rw-r--r-- | xbmc/windowing/windows/WinSystemWin32DX.cpp | 5 |
9 files changed, 194 insertions, 146 deletions
diff --git a/system/shaders/testshader.fx b/system/shaders/testshader.fx deleted file mode 100644 index cefee8c983..0000000000 --- a/system/shaders/testshader.fx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2010-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * <http://www.gnu.org/licenses/>. - * - */ - -float4 TEST() : SV_TARGET -{ - return float4(0.0, 0.0, 0.0, 0.0); -} - -technique11 TEST_T -{ - pass P0 - { - SetPixelShader( CompileShader( ps_4_0_level_9_1, TEST() ) ); - } -}; diff --git a/system/shaders/yuv2rgb_d3d.fx b/system/shaders/yuv2rgb_d3d.fx index 6fb9cf3829..221de95e7f 100644 --- a/system/shaders/yuv2rgb_d3d.fx +++ b/system/shaders/yuv2rgb_d3d.fx @@ -18,9 +18,7 @@ * */ -texture2D g_YTexture; -texture2D g_UTexture; -texture2D g_VTexture; +texture2D g_Texture[3]; float4x4 g_ColorMatrix; float2 g_StepXY; float2 g_viewPort; @@ -45,15 +43,13 @@ struct VS_INPUT { float4 Position : POSITION; float2 TextureY : TEXCOORD0; - float2 TextureU : TEXCOORD1; - float2 TextureV : TEXCOORD2; + float2 TextureUV : TEXCOORD1; }; struct VS_OUTPUT { float2 TextureY : TEXCOORD0; - float2 TextureU : TEXCOORD1; - float2 TextureV : TEXCOORD2; + float2 TextureUV : TEXCOORD1; float4 Position : SV_POSITION; }; @@ -65,8 +61,7 @@ VS_OUTPUT VS(VS_INPUT In) output.Position.z = output.Position.z; output.Position.w = 1.0; output.TextureY = In.TextureY; - output.TextureU = In.TextureU; - output.TextureV = In.TextureV; + output.TextureUV = In.TextureUV; return output; } @@ -87,16 +82,16 @@ inline float2 unormUV(float2 rg) float4 YUV2RGB(VS_OUTPUT In) : SV_TARGET { #if defined(XBMC_YV12) //|| defined(XBMC_NV12) - float4 YUV = float4(g_YTexture.Sample(YUVSampler, In.TextureY).r - , g_UTexture.Sample(YUVSampler, In.TextureU).r - , g_VTexture.Sample(YUVSampler, In.TextureV).r + float4 YUV = float4(g_Texture[0].Sample(YUVSampler, In.TextureY ).r + , g_Texture[1].Sample(YUVSampler, In.TextureUV).r + , g_Texture[2].Sample(YUVSampler, In.TextureUV).r , 1.0); #elif defined(XBMC_NV12) - float4 YUV = float4(g_YTexture.Sample(YUVSampler, In.TextureY).r + float4 YUV = float4(g_Texture[0].Sample(YUVSampler, In.TextureY).r #if defined(NV12_SNORM_UV) - , unormUV(g_UTexture.Sample(UVSamplerSNORM, In.TextureU).rg) + , unormUV(g_Texture[1].Sample(UVSamplerSNORM, In.TextureUV).rg) #else - , g_UTexture.Sample(YUVSampler, In.TextureU).rg + , g_Texture[1].Sample(YUVSampler, In.TextureUV).rg #endif , 1.0); #elif defined(XBMC_YUY2) || defined(XBMC_UYVY) @@ -109,8 +104,8 @@ float4 YUV2RGB(VS_OUTPUT In) : SV_TARGET //y axis will be correctly interpolated by opengl //x axis will not, so we grab two pixels at the center of two columns and interpolate ourselves - float4 c1 = g_YTexture.Sample(YUVSampler, float2(pos.x + ((0.5 - f.x) * stepxy.x), pos.y)); - float4 c2 = g_YTexture.Sample(YUVSampler, float2(pos.x + ((1.5 - f.x) * stepxy.x), pos.y)); + float4 c1 = g_Texture[0].Sample(YUVSampler, float2(pos.x + ((0.5 - f.x) * stepxy.x), pos.y)); + float4 c2 = g_Texture[0].Sample(YUVSampler, float2(pos.x + ((1.5 - f.x) * stepxy.x), pos.y)); /* each pixel has two Y subpixels and one UV subpixel YUV Y YUV @@ -128,7 +123,7 @@ float4 YUV2RGB(VS_OUTPUT In) : SV_TARGET float4 YUV = float4(outY, outUV, 1.0); #endif - return float4(mul(YUV, g_ColorMatrix).rgb, 1.0); + return mul(YUV, g_ColorMatrix); } technique11 YUV2RGB_T diff --git a/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.cpp b/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.cpp index 55ac58676c..a90412db80 100644 --- a/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.cpp +++ b/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.cpp @@ -300,7 +300,6 @@ bool CYUV2RGBShader::Create(unsigned int sourceWidth, unsigned int sourceHeight, { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; if (!CWinShader::CreateInputLayout(layout, ARRAYSIZE(layout))) @@ -349,32 +348,32 @@ void CYUV2RGBShader::PrepareParameters(CRect sourceRect, v[0].z = 0.0f; v[0].tu = sourceRect.x1 / m_sourceWidth; v[0].tv = sourceRect.y1 / m_sourceHeight; - v[0].tu2 = v[0].tu3 = (sourceRect.x1 / 2.0f) / (m_sourceWidth>>1); - v[0].tv2 = v[0].tv3 = (sourceRect.y1 / 2.0f) / (m_sourceHeight>>1); + v[0].tu2 = (sourceRect.x1 / 2.0f) / (m_sourceWidth>>1); + v[0].tv2 = (sourceRect.y1 / 2.0f) / (m_sourceHeight>>1); v[1].x = m_dest[1].x; v[1].y = m_dest[1].y; v[1].z = 0.0f; v[1].tu = sourceRect.x2 / m_sourceWidth; v[1].tv = sourceRect.y1 / m_sourceHeight; - v[1].tu2 = v[1].tu3 = (sourceRect.x2 / 2.0f) / (m_sourceWidth>>1); - v[1].tv2 = v[1].tv3 = (sourceRect.y1 / 2.0f) / (m_sourceHeight>>1); + v[1].tu2 = (sourceRect.x2 / 2.0f) / (m_sourceWidth>>1); + v[1].tv2 = (sourceRect.y1 / 2.0f) / (m_sourceHeight>>1); v[2].x = m_dest[2].x; v[2].y = m_dest[2].y; v[2].z = 0.0f; v[2].tu = sourceRect.x2 / m_sourceWidth; v[2].tv = sourceRect.y2 / m_sourceHeight; - v[2].tu2 = v[2].tu3 = (sourceRect.x2 / 2.0f) / (m_sourceWidth>>1); - v[2].tv2 = v[2].tv3 = (sourceRect.y2 / 2.0f) / (m_sourceHeight>>1); + v[2].tu2 = (sourceRect.x2 / 2.0f) / (m_sourceWidth>>1); + v[2].tv2 = (sourceRect.y2 / 2.0f) / (m_sourceHeight>>1); v[3].x = m_dest[3].x; v[3].y = m_dest[3].y; v[3].z = 0.0f; v[3].tu = sourceRect.x1 / m_sourceWidth; v[3].tv = sourceRect.y2 / m_sourceHeight; - v[3].tu2 = v[3].tu3 = (sourceRect.x1 / 2.0f) / (m_sourceWidth>>1); - v[3].tv2 = v[3].tv3 = (sourceRect.y2 / 2.0f) / (m_sourceHeight>>1); + v[3].tu2 = (sourceRect.x1 / 2.0f) / (m_sourceWidth>>1); + v[3].tv2 = (sourceRect.y2 / 2.0f) / (m_sourceHeight>>1); CWinShader::UnlockVertexBuffer(); } @@ -388,12 +387,15 @@ void CYUV2RGBShader::PrepareParameters(CRect sourceRect, void CYUV2RGBShader::SetShaderParameters(YUVBuffer* YUVbuf) { m_effect.SetTechnique("YUV2RGB_T"); + SVideoPlane *planes = YUVbuf->planes; + ID3D11ShaderResourceView* ppSRView[3] = + { + planes[0].texture.GetShaderResource(), + planes[1].texture.GetShaderResource(), + planes[2].texture.GetShaderResource(), + }; + m_effect.SetResources("g_Texture", ppSRView, YUVbuf->GetActivePlanes()); m_effect.SetMatrix("g_ColorMatrix", m_matrix.Matrix()); - m_effect.SetTexture("g_YTexture", YUVbuf->planes[0].texture); - if (YUVbuf->GetActivePlanes() > 1) - m_effect.SetTexture("g_UTexture", YUVbuf->planes[1].texture); - if (YUVbuf->GetActivePlanes() > 2) - m_effect.SetTexture("g_VTexture", YUVbuf->planes[2].texture); m_effect.SetFloatArray("g_StepXY", m_texSteps, ARRAY_SIZE(m_texSteps)); UINT numPorts = 1; @@ -897,14 +899,28 @@ void CConvolutionShaderSeparable::SetStepParams(UINT iPass) } //========================================================== +#define SHADER_SOURCE(...) #__VA_ARGS__ bool CTestShader::Create() { - std::string effectString = "special://xbmc/system/shaders/testshader.fx"; + std::string strShader = SHADER_SOURCE( + float4 TEST() : SV_TARGET + { + return float4(0.0, 0.0, 0.0, 0.0); + } - if(!LoadEffect(effectString, nullptr)) + technique11 TEST_T + { + pass P0 + { + SetPixelShader(CompileShader(ps_4_0_level_9_1, TEST())); + } + }; + ); + + if (!m_effect.Create(strShader, nullptr)) { - CLog::Log(LOGERROR, __FUNCTION__": Failed to load shader %s.", effectString.c_str()); + CLog::Log(LOGERROR, __FUNCTION__": Failed to create test shader: %s", strShader.c_str()); return false; } return true; diff --git a/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.h b/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.h index 41aed5fe60..a12fdf0f11 100644 --- a/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.h +++ b/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.h @@ -111,8 +111,7 @@ private: struct CUSTOMVERTEX { FLOAT x, y, z; FLOAT tu, tv; // Y Texture coordinates - FLOAT tu2, tv2; // U Texture coordinates - FLOAT tu3, tv3; // V Texture coordinates + FLOAT tu2, tv2; // U and V Textures coordinates }; }; diff --git a/xbmc/guilib/D3DResource.cpp b/xbmc/guilib/D3DResource.cpp index 8aa8125918..36aa6a8174 100644 --- a/xbmc/guilib/D3DResource.cpp +++ b/xbmc/guilib/D3DResource.cpp @@ -561,6 +561,17 @@ bool CD3DEffect::SetTexture(LPCSTR handle, CD3DTexture &texture) return false; } +bool CD3DEffect::SetResources(LPCSTR handle, ID3D11ShaderResourceView** ppSRViews, size_t count) +{ + if (m_effect) + { + ID3DX11EffectShaderResourceVariable* var = m_effect->GetVariableByName(handle)->AsShaderResource(); + if (var->IsValid()) + return SUCCEEDED(var->SetResourceArray(ppSRViews, 0, count)); + } + return false; +} + bool CD3DEffect::SetConstantBuffer(LPCSTR handle, ID3D11Buffer *buffer) { if (m_effect) diff --git a/xbmc/guilib/D3DResource.h b/xbmc/guilib/D3DResource.h index ed6cf96d51..dc2b2ba33a 100644 --- a/xbmc/guilib/D3DResource.h +++ b/xbmc/guilib/D3DResource.h @@ -180,6 +180,7 @@ public: bool SetMatrix(LPCSTR handle, const XMFLOAT4X4* mat); bool SetTechnique(LPCSTR handle); bool SetTexture(LPCSTR handle, CD3DTexture &texture); + bool SetResources(LPCSTR handle, ID3D11ShaderResourceView** ppSRViews, size_t count); bool SetConstantBuffer(LPCSTR handle, ID3D11Buffer *buffer); bool SetScalar(LPCSTR handle, float value); bool Begin(UINT *passes, DWORD flags); diff --git a/xbmc/rendering/dx/RenderSystemDX.cpp b/xbmc/rendering/dx/RenderSystemDX.cpp index b1b9d1c387..9060b1eb82 100644 --- a/xbmc/rendering/dx/RenderSystemDX.cpp +++ b/xbmc/rendering/dx/RenderSystemDX.cpp @@ -49,52 +49,50 @@ CRenderSystemDX::CRenderSystemDX() : CRenderSystemBase() { m_enumRenderingSystem = RENDERING_SYSTEM_DIRECTX; - m_hFocusWnd = NULL; - m_hDeviceWnd = NULL; + m_hFocusWnd = nullptr; + m_hDeviceWnd = nullptr; m_nBackBufferWidth = 0; m_nBackBufferHeight = 0; m_bFullScreenDevice = false; - m_bVSync = true; - m_nDeviceStatus = S_OK; - m_inScene = false; - m_needNewDevice = false; + m_bVSync = true; + m_nDeviceStatus = S_OK; + m_inScene = false; + m_needNewDevice = false; m_resizeInProgress = false; - m_screenHeight = 0; - m_systemFreq = CurrentHostFrequency(); - + m_screenHeight = 0; + m_systemFreq = CurrentHostFrequency(); m_defaultD3DUsage = D3D11_USAGE_DEFAULT; - m_featureLevel = D3D_FEATURE_LEVEL_11_1; m_driverType = D3D_DRIVER_TYPE_HARDWARE; - m_adapter = NULL; - m_adapterIndex = -1; - m_pOutput = NULL; - m_dxgiFactory = NULL; - m_pD3DDev = NULL; - m_pImdContext = NULL; - m_pContext = NULL; - - m_pSwapChain = NULL; - m_pSwapChain1 = NULL; - m_pRenderTargetView = NULL; - m_depthStencilState = NULL; - m_depthStencilView = NULL; - m_BlendEnableState = NULL; - m_BlendDisableState = NULL; + m_adapter = nullptr; + m_pOutput = nullptr; + m_dxgiFactory = nullptr; + m_pD3DDev = nullptr; + m_pImdContext = nullptr; + m_pContext = nullptr; + + m_pSwapChain = nullptr; + m_pSwapChain1 = nullptr; + m_pRenderTargetView = nullptr; + m_depthStencilState = nullptr; + m_depthStencilView = nullptr; + m_BlendEnableState = nullptr; + m_BlendDisableState = nullptr; m_BlendEnabled = false; - m_RSScissorDisable = NULL; - m_RSScissorEnable = NULL; + m_RSScissorDisable = nullptr; + m_RSScissorEnable = nullptr; m_ScissorsEnabled = false; - m_pTextureRight = NULL; - m_pRenderTargetViewRight = NULL; - m_pShaderResourceViewRight = NULL; - m_pGUIShader = NULL; + m_pTextureRight = nullptr; + m_pRenderTargetViewRight = nullptr; + m_pShaderResourceViewRight = nullptr; + m_pGUIShader = nullptr; m_bResizeRequred = false; m_bHWStereoEnabled = false; ZeroMemory(&m_cachedMode, sizeof(m_cachedMode)); ZeroMemory(&m_viewPort, sizeof(m_viewPort)); ZeroMemory(&m_scissor, sizeof(CRect)); + ZeroMemory(&m_adapterDesc, sizeof(DXGI_ADAPTER_DESC)); } CRenderSystemDX::~CRenderSystemDX() @@ -139,33 +137,31 @@ void CRenderSystemDX::SetMonitor(HMONITOR monitor) IDXGIAdapter1* pAdapter; for (unsigned i = 0; m_dxgiFactory->EnumAdapters1(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i) { + DXGI_ADAPTER_DESC1 adaperDesc; + pAdapter->GetDesc1(&adaperDesc); + IDXGIOutput* pOutput; for (unsigned j = 0; pAdapter->EnumOutputs(j, &pOutput) != DXGI_ERROR_NOT_FOUND; ++j) { - if (FAILED(pOutput->GetDesc(&outputDesc))) - break; - + pOutput->GetDesc(&outputDesc); if (outputDesc.Monitor == monitor) { + CLog::Log(LOGDEBUG, __FUNCTION__" - Selected %S output. ", outputDesc.DeviceName); + // update monitor info SAFE_RELEASE(m_pOutput); m_pOutput = pOutput; - CLog::Log(LOGDEBUG, __FUNCTION__" - Selected %S output. ", outputDesc.DeviceName); - // check if adapter is changed - if (m_adapterIndex != i) + if ( m_adapterDesc.AdapterLuid.HighPart != adaperDesc.AdapterLuid.HighPart + || m_adapterDesc.AdapterLuid.LowPart != adaperDesc.AdapterLuid.LowPart) { - pAdapter->GetDesc(&m_adapterDesc); - CLog::Log(LOGDEBUG, __FUNCTION__" - Selected %S adapter. ", m_adapterDesc.Description); + pAdapter->GetDesc(&m_adapterDesc); SAFE_RELEASE(m_adapter); m_adapter = pAdapter; - m_needNewDevice = true; - m_adapterIndex = i; - return; } @@ -182,7 +178,7 @@ bool CRenderSystemDX::ResetRenderSystem(int width, int height, bool fullScreen, if (!m_pD3DDev) return false; - if (m_hDeviceWnd != NULL) + if (m_hDeviceWnd != nullptr) { HMONITOR hMonitor = MonitorFromWindow(m_hDeviceWnd, MONITOR_DEFAULTTONULL); if (hMonitor) @@ -196,10 +192,8 @@ bool CRenderSystemDX::ResetRenderSystem(int width, int height, bool fullScreen, if (!m_needNewDevice) { - CreateWindowSizeDependentResources(); SetFullScreenInternal(); - if (m_bResizeRequred) - CreateWindowSizeDependentResources(); + CreateWindowSizeDependentResources(); } else { @@ -348,8 +342,8 @@ void CRenderSystemDX::SetFullScreenInternal() SAFE_RELEASE(pOutput); // do not change modes if hw stereo - if (g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_HARDWAREBASED) - return; + if (m_bHWStereoEnabled) + goto end; DXGI_SWAP_CHAIN_DESC scDesc; m_pSwapChain->GetDesc(&scDesc); @@ -373,6 +367,14 @@ void CRenderSystemDX::SetFullScreenInternal() toMatchMode.Format = scDesc.BufferDesc.Format; toMatchMode.Scaling = scDesc.BufferDesc.Scaling; toMatchMode.ScanlineOrdering = scDesc.BufferDesc.ScanlineOrdering; + // force switch to 1080p23 before hardware stereo + if (RENDER_STEREO_MODE_HARDWAREBASED == g_graphicsContext.GetStereoMode()) + { + toMatchMode.RefreshRate.Numerator = 24000; + toMatchMode.RefreshRate.Denominator = 1001; + toMatchMode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; + m_refreshRate = RATIONAL_TO_FLOAT(toMatchMode.RefreshRate); + } // find closest mode m_pOutput->FindClosestMatchingMode(&toMatchMode, &matchedMode, m_pD3DDev); @@ -394,10 +396,12 @@ void CRenderSystemDX::SetFullScreenInternal() if (FAILED(hr)) CLog::Log(LOGERROR, "%s - Failed to switch output mode: %s", __FUNCTION__, GetErrorDescription(hr).c_str()); } - - // wait until switching screen state is done DXWait(m_pD3DDev, m_pImdContext); } +end: + // in windowed mode DWM uses triple buffering in any case. + // for FSEM we use double buffering + SetMaximumFrameLatency(2 - m_useWindowedDX); } bool CRenderSystemDX::IsFormatSupport(DXGI_FORMAT format, unsigned int usage) @@ -507,7 +511,6 @@ bool CRenderSystemDX::CreateDevice() CSingleLock lock(m_resourceSection); HRESULT hr; - SAFE_RELEASE(m_pD3DDev); D3D_FEATURE_LEVEL featureLevels[] = @@ -526,9 +529,9 @@ bool CRenderSystemDX::CreateDevice() #ifdef _DEBUG createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif - + D3D_DRIVER_TYPE driverType = m_adapter == nullptr ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_UNKNOWN; // we should specify D3D_DRIVER_TYPE_UNKNOWN if create device with specified adapter. - hr = D3D11CreateDevice(m_adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, createDeviceFlags, featureLevels, ARRAYSIZE(featureLevels), + hr = D3D11CreateDevice(m_adapter, driverType, nullptr, createDeviceFlags, featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION, &m_pD3DDev, &m_featureLevel, &m_pImdContext); if (FAILED(hr)) @@ -537,7 +540,7 @@ bool CRenderSystemDX::CreateDevice() CLog::Log(LOGDEBUG, "%s - First try to create device failed with error: %s.", __FUNCTION__, GetErrorDescription(hr).c_str()); CLog::Log(LOGDEBUG, "%s - Trying to create device with lowest feature level: %#x.", __FUNCTION__, featureLevels[1]); - hr = D3D11CreateDevice(m_adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, createDeviceFlags, &featureLevels[1], ARRAYSIZE(featureLevels) - 1, + hr = D3D11CreateDevice(m_adapter, driverType, nullptr, createDeviceFlags, &featureLevels[1], ARRAYSIZE(featureLevels) - 1, D3D11_SDK_VERSION, &m_pD3DDev, &m_featureLevel, &m_pImdContext); if (FAILED(hr)) { @@ -546,7 +549,7 @@ bool CRenderSystemDX::CreateDevice() CLog::Log(LOGDEBUG, "%s - Trying to create device without video API support.", __FUNCTION__); createDeviceFlags &= ~D3D11_CREATE_DEVICE_VIDEO_SUPPORT; - hr = D3D11CreateDevice(m_adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, createDeviceFlags, &featureLevels[1], ARRAYSIZE(featureLevels) - 1, + hr = D3D11CreateDevice(m_adapter, driverType, nullptr, createDeviceFlags, &featureLevels[1], ARRAYSIZE(featureLevels) - 1, D3D11_SDK_VERSION, &m_pD3DDev, &m_featureLevel, &m_pImdContext); if (SUCCEEDED(hr)) 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__); @@ -559,6 +562,42 @@ bool CRenderSystemDX::CreateDevice() return false; } + if (!m_adapter) + { + // get adapter from device if it was not detected previously + IDXGIDevice1* pDXGIDevice = nullptr; + if (SUCCEEDED(m_pD3DDev->QueryInterface(__uuidof(IDXGIDevice1), reinterpret_cast<void**>(&pDXGIDevice)))) + { + IDXGIAdapter *pAdapter = nullptr; + if (SUCCEEDED(pDXGIDevice->GetAdapter(&pAdapter))) + { + hr = pAdapter->QueryInterface(__uuidof(IDXGIAdapter1), reinterpret_cast<void**>(&m_adapter)); + SAFE_RELEASE(pAdapter); + if (FAILED(hr)) + return false; + + m_adapter->GetDesc(&m_adapterDesc); + CLog::Log(LOGDEBUG, __FUNCTION__" - Selected %S adapter. ", m_adapterDesc.Description); + } + SAFE_RELEASE(pDXGIDevice); + } + } + + if (!m_adapter) + { + CLog::Log(LOGERROR, "%s - Failed to find adapter.", __FUNCTION__); + return false; + } + + SAFE_RELEASE(m_dxgiFactory); + m_adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&m_dxgiFactory)); + + if (!m_pOutput) + { + HMONITOR hMonitor = MonitorFromWindow(m_hDeviceWnd, MONITOR_DEFAULTTONULL); + SetMonitor(hMonitor); + } + if ( g_advancedSettings.m_bAllowDeferredRendering && FAILED(m_pD3DDev->CreateDeferredContext(0, &m_pContext))) { @@ -588,16 +627,9 @@ bool CRenderSystemDX::CreateDevice() pMultiThreading->Release(); } - IDXGIDevice1* pDXGIDevice = NULL; - if (SUCCEEDED(m_pD3DDev->QueryInterface(__uuidof(IDXGIDevice1), reinterpret_cast<void**>(&pDXGIDevice)))) - { - // Not sure the following actually does something but this exists in dx9 implementation - pDXGIDevice->SetGPUThreadPriority(7); - // Ensure that DXGI does not queue more than one frame at a time. This both reduces - // latency and ensures that the application will only render after each VSync - pDXGIDevice->SetMaximumFrameLatency(1); - SAFE_RELEASE(pDXGIDevice); - } + // in windowed mode DWM uses triple buffering in any case. + // for FSEM we use double buffering + SetMaximumFrameLatency(2 - m_useWindowedDX); #ifdef _DEBUG if (SUCCEEDED(m_pD3DDev->QueryInterface(__uuidof(ID3D11Debug), reinterpret_cast<void**>(&m_d3dDebug)))) @@ -779,6 +811,7 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() DXWait(m_pD3DDev, m_pImdContext); } + uint32_t scFlags = m_useWindowedDX ? 0 : DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; if (!m_pSwapChain) { CLog::Log(LOGDEBUG, "%s - Creating swapchain in %s mode.", __FUNCTION__, bHWStereoEnabled ? "Stereoscopic 3D" : "Mono"); @@ -798,7 +831,7 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() scDesc1.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; scDesc1.Stereo = bHWStereoEnabled; scDesc1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; - scDesc1.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + scDesc1.Flags = scFlags; scDesc1.SampleDesc.Count = 1; scDesc1.SampleDesc.Quality = 0; @@ -828,6 +861,17 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() } m_bHWStereoEnabled = bHWStereoEnabled; } + else if (bHWStereoEnabled) + { + // switch to stereo mode failed, create mono swapchain + CLog::Log(LOGERROR, "%s - Creating swap chain failed with error: %s.", __FUNCTION__, GetErrorDescription(hr).c_str()); + + scDesc1.Stereo = false; + hr = dxgiFactory2->CreateSwapChainForHwnd(m_pD3DDev, m_hFocusWnd, &scDesc1, &scFSDesc, NULL, &m_pSwapChain1); + + // fallback to split_horisontal mode. + g_graphicsContext.SetStereoMode(RENDER_STEREO_MODE_SPLIT_HORIZONTAL); + } dxgiFactory2->Release(); } else @@ -838,7 +882,7 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() scDesc.OutputWindow = m_hFocusWnd; scDesc.Windowed = m_useWindowedDX; scDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL; - scDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + scDesc.Flags = scFlags; scDesc.BufferDesc.Width = m_nBackBufferWidth; scDesc.BufferDesc.Height = m_nBackBufferHeight; @@ -864,7 +908,7 @@ bool CRenderSystemDX::CreateWindowSizeDependentResources() else { // resize swap chain buffers with preserving the existing buffer count and format. - hr = m_pSwapChain->ResizeBuffers(scDesc.BufferCount, m_nBackBufferWidth, m_nBackBufferHeight, scDesc.BufferDesc.Format, scDesc.Flags); + hr = m_pSwapChain->ResizeBuffers(scDesc.BufferCount, m_nBackBufferWidth, m_nBackBufferHeight, scDesc.BufferDesc.Format, scFlags); if (FAILED(hr)) { CLog::Log(LOGERROR, "%s - Failed to resize buffers (%s).", __FUNCTION__, GetErrorDescription(hr).c_str()); @@ -1145,9 +1189,9 @@ bool CRenderSystemDX::PresentRenderImpl(const CDirtyRegionList &dirty) if (DXGI_ERROR_INVALID_CALL == hr) { - m_bResizeRequred = true; - if (CreateWindowSizeDependentResources()) - hr = S_OK; + SetFullScreenInternal(); + CreateWindowSizeDependentResources(); + hr = S_OK; } if (FAILED(hr)) @@ -1196,9 +1240,9 @@ bool CRenderSystemDX::BeginRender() break; case DXGI_ERROR_INVALID_CALL: // application provided invalid parameter data. Try to return after resize buffers CLog::Log(LOGERROR, "DXGI_ERROR_INVALID_CALL"); - m_bResizeRequred = true; - if (CreateWindowSizeDependentResources()) - m_nDeviceStatus = S_OK; + SetFullScreenInternal(); + CreateWindowSizeDependentResources(); + m_nDeviceStatus = S_OK; break; case DXGI_STATUS_OCCLUDED: // decide what we should do when windows content is not visible // do not spam to log file @@ -1698,4 +1742,17 @@ void CRenderSystemDX::FinishCommandList(bool bExecute /*= true*/) SAFE_RELEASE(pCommandList); } +void CRenderSystemDX::SetMaximumFrameLatency(uint32_t latency) +{ + if (!m_pD3DDev) + return; + + IDXGIDevice1* pDXGIDevice = nullptr; + if (SUCCEEDED(m_pD3DDev->QueryInterface(__uuidof(IDXGIDevice1), reinterpret_cast<void**>(&pDXGIDevice)))) + { + pDXGIDevice->SetMaximumFrameLatency(latency); + SAFE_RELEASE(pDXGIDevice); + } +} + #endif diff --git a/xbmc/rendering/dx/RenderSystemDX.h b/xbmc/rendering/dx/RenderSystemDX.h index cf58be2302..5b0e1ad211 100644 --- a/xbmc/rendering/dx/RenderSystemDX.h +++ b/xbmc/rendering/dx/RenderSystemDX.h @@ -138,6 +138,7 @@ protected: void SetFullScreenInternal(); void GetClosestDisplayModeToCurrent(IDXGIOutput* output, DXGI_MODE_DESC* outCurrentDisplayMode, bool useCached = false); void CheckInterlasedStereoView(void); + void SetMaximumFrameLatency(uint32_t latency); virtual void UpdateMonitor() {}; @@ -169,7 +170,6 @@ protected: IDXGIFactory1* m_dxgiFactory; ID3D11Device* m_pD3DDev; IDXGIAdapter1* m_adapter; - int m_adapterIndex; IDXGIOutput* m_pOutput; ID3D11DeviceContext* m_pContext; ID3D11DeviceContext* m_pImdContext; diff --git a/xbmc/windowing/windows/WinSystemWin32DX.cpp b/xbmc/windowing/windows/WinSystemWin32DX.cpp index c2692275c8..9ca881220e 100644 --- a/xbmc/windowing/windows/WinSystemWin32DX.cpp +++ b/xbmc/windowing/windows/WinSystemWin32DX.cpp @@ -168,11 +168,12 @@ void CWinSystemWin32DX::NotifyAppFocusChange(bool bGaining) { CRenderSystemDX::m_useWindowedDX = !bGaining; CRenderSystemDX::SetFullScreenInternal(); - CRenderSystemDX::CreateWindowSizeDependentResources(); + if (bGaining) + CRenderSystemDX::CreateWindowSizeDependentResources(); // minimize window on lost focus if (!bGaining) - ShowWindow(m_hWnd, SW_SHOWMINIMIZED); + ShowWindow(m_hWnd, SW_FORCEMINIMIZE); } } |