aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartijn Kaijser <martijn@xbmc.org>2016-03-21 21:27:17 +0100
committerMartijn Kaijser <martijn@xbmc.org>2016-03-21 21:27:17 +0100
commit47d207a96b141a40fb7435e7767f8abb75ddaa8b (patch)
tree7e2916a5e6dd49acd1a4a628a702cf4908efbc2c
parenta7caa16680f09810b730e88b3368f221465c9eee (diff)
parenta505943f9b572b093a2a24e05f278557fc49ea3a (diff)
Merge pull request #9409 from afedchin/winrendererj
[Backport][Win32] A sef of fixes for windows.
-rw-r--r--system/shaders/testshader.fx32
-rw-r--r--system/shaders/yuv2rgb_d3d.fx31
-rw-r--r--xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.cpp50
-rw-r--r--xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.h3
-rw-r--r--xbmc/guilib/D3DResource.cpp11
-rw-r--r--xbmc/guilib/D3DResource.h1
-rw-r--r--xbmc/rendering/dx/RenderSystemDX.cpp205
-rw-r--r--xbmc/rendering/dx/RenderSystemDX.h2
-rw-r--r--xbmc/windowing/windows/WinSystemWin32DX.cpp5
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);
}
}