#define M_PI 3.14159265358979323846
#endif
-#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
-
CGUIWindowTestPatternDX::CGUIWindowTestPatternDX(void) : CGUIWindowTestPattern()
{
+ m_vb = NULL;
+ m_bufferWidth = 0;
}
CGUIWindowTestPatternDX::~CGUIWindowTestPatternDX(void)
{
+ SAFE_RELEASE(m_vb);
+ m_bufferWidth = 0;
}
void CGUIWindowTestPatternDX::DrawVerticalLines(int top, int left, int bottom, int right)
{
- CUSTOMVERTEX* vert = new CUSTOMVERTEX[2+(right-left)];
+ Vertex* vert = new Vertex[2 + (right - left)];
int p = 0;
for (int i = left; i <= right; i += 2)
{
- vert[p].x = (float)i;
- vert[p].y = (float)top;
- vert[p].z = 0.5f;
- vert[p].rhw = 1.0f;
- vert[p].color = D3DCOLOR_COLORVALUE(m_white, m_white, m_white, 1.0f);
+ vert[p].pos.x = (float)i;
+ vert[p].pos.y = (float)top;
+ vert[p].pos.z = 0.5f;
+ vert[p].color = XMFLOAT4(m_white, m_white, m_white, 1.0f);
++p;
- vert[p].x = (float)i;
- vert[p].y = (float)bottom;
- vert[p].z = 0.5f;
- vert[p].rhw = 1.0f;
- vert[p].color = D3DCOLOR_COLORVALUE(m_white, m_white, m_white, 1.0f);
+ vert[p].pos.x = (float)i;
+ vert[p].pos.y = (float)bottom;
+ vert[p].pos.z = 0.5f;
+ vert[p].color = XMFLOAT4(m_white, m_white, m_white, 1.0f);
++p;
}
- g_Windowing.Get3DDevice()->SetFVF(D3DFVF_CUSTOMVERTEX);
- g_Windowing.Get3DDevice()->DrawPrimitiveUP(D3DPT_LINELIST, p/2, vert, sizeof(CUSTOMVERTEX));
+ UpdateVertexBuffer(vert, p);
+
+ ID3D11DeviceContext* pContext = g_Windowing.Get3D11Context();
+ CGUIShaderDX* pGUIShader = g_Windowing.GetGUIShader();
+
+ pGUIShader->Begin(SHADER_METHOD_RENDER_DEFAULT);
+ unsigned stride = sizeof(Vertex), offset = 0;
+ pContext->IASetVertexBuffers(0, 1, &m_vb, &stride, &offset);
+ pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
+ pGUIShader->Draw(p, 0);
delete [] vert;
}
void CGUIWindowTestPatternDX::DrawHorizontalLines(int top, int left, int bottom, int right)
{
- CUSTOMVERTEX* vert = new CUSTOMVERTEX[2+(bottom-top)];
+ Vertex* vert = new Vertex[2 + (bottom - top)];
int p = 0;
for (int i = top; i <= bottom; i += 2)
{
- vert[p].x = (float)left;
- vert[p].y = (float)i;
- vert[p].z = 0.5f;
- vert[p].rhw = 1.0f;
- vert[p].color = D3DCOLOR_COLORVALUE(m_white, m_white, m_white, 1.0f);
+ vert[p].pos.x = (float)left;
+ vert[p].pos.y = (float)i;
+ vert[p].pos.z = 0.5f;
+ vert[p].color = XMFLOAT4(m_white, m_white, m_white, 1.0f);
++p;
- vert[p].x = (float)right;
- vert[p].y = (float)i;
- vert[p].z = 0.5f;
- vert[p].rhw = 1.0f;
- vert[p].color = D3DCOLOR_COLORVALUE(m_white, m_white, m_white, 1.0f);
+ vert[p].pos.x = (float)right;
+ vert[p].pos.y = (float)i;
+ vert[p].pos.z = 0.5f;
+ vert[p].color = XMFLOAT4(m_white, m_white, m_white, 1.0f);
++p;
}
- g_Windowing.Get3DDevice()->SetFVF(D3DFVF_CUSTOMVERTEX);
- g_Windowing.Get3DDevice()->DrawPrimitiveUP(D3DPT_LINELIST, p/2, vert, sizeof(CUSTOMVERTEX));
+ UpdateVertexBuffer(vert, p);
+
+ ID3D11DeviceContext* pContext = g_Windowing.Get3D11Context();
+ CGUIShaderDX* pGUIShader = g_Windowing.GetGUIShader();
+
+ pGUIShader->Begin(SHADER_METHOD_RENDER_DEFAULT);
+ unsigned stride = sizeof(Vertex), offset = 0;
+ pContext->IASetVertexBuffers(0, 1, &m_vb, &stride, &offset);
+ pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
+ pGUIShader->Draw(p, 0);
delete [] vert;
}
int c = (bottom-top+1)*(1+(right-left)/2);
if (c < 1)
return;
- CUSTOMVERTEX* vert = new CUSTOMVERTEX[c];
+ Vertex* vert = new Vertex[c];
int i=0;
for (int y = top; y <= bottom; y++)
{
{
if (y % 2 == 0)
{
- vert[i].x = (float)x;
- vert[i].y = (float)y;
- vert[i].z = 0.5f;
- vert[i].rhw = 1.0f;
- vert[i].color = D3DCOLOR_COLORVALUE(m_white, m_white, m_white, 1.0f);
+ vert[i].pos.x = (float)x;
+ vert[i].pos.y = (float)y;
+ vert[i].pos.z = 0.5f;
+ vert[i].color = XMFLOAT4(m_white, m_white, m_white, 1.0f);
}
else
{
- vert[i].x = (float)x+1.0f;
- vert[i].y = (float)y;
- vert[i].z = 0.5f;
- vert[i].rhw = 1.0f;
- vert[i].color = D3DCOLOR_COLORVALUE(m_white, m_white, m_white, 1.0f);
+ vert[i].pos.x = (float)x+1.0f;
+ vert[i].pos.y = (float)y;
+ vert[i].pos.z = 0.5f;
+ vert[i].color = XMFLOAT4(m_white, m_white, m_white, 1.0f);
}
++i;
}
}
- g_Windowing.Get3DDevice()->SetFVF(D3DFVF_CUSTOMVERTEX);
- g_Windowing.Get3DDevice()->DrawPrimitiveUP(D3DPT_POINTLIST, i, vert, sizeof(CUSTOMVERTEX));
+ UpdateVertexBuffer(vert, i);
+
+ ID3D11DeviceContext* pContext = g_Windowing.Get3D11Context();
+ CGUIShaderDX* pGUIShader = g_Windowing.GetGUIShader();
+
+ pGUIShader->Begin(SHADER_METHOD_RENDER_DEFAULT);
+ unsigned stride = sizeof(Vertex), offset = 0;
+ pContext->IASetVertexBuffers(0, 1, &m_vb, &stride, &offset);
+ pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
+ pGUIShader->Draw(i, 0);
delete [] vert;
}
DrawRectangle(x50p, (float)top, (float)right, y50p, color_white);
DrawRectangle((float)left, (float)y50p, x50p, (float)bottom, color_white);
+ XMFLOAT4 xcolor_white, xcolor_black;
+ CD3DHelper::XMStoreColor(&xcolor_white, color_white);
+ CD3DHelper::XMStoreColor(&xcolor_black, color_black);
+
// draw border lines
- CUSTOMVERTEX vert[] =
+ Vertex vert[] =
{
- {(float)left, y5p, 0.5f, 1.0f, color_white},
- {x50p, y5p, 0.5f, 1.0f, color_white},
- {x5p, (float)top, 0.5f, 1.0f, color_white},
- {x5p, y50p, 0.5f, 1.0f, color_white},
- {x50p, y95p, 0.5f, 1.0f, color_white},
- {(float)right, y95p, 0.5f, 1.0f, color_white},
- {x95p, y50p, 0.5f, 1.0f, color_white},
- {x95p, (float)bottom, 0.5f, 1.0f, color_white},
-
- {x50p, y5p, 0.5f, 1.0f, color_black},
- {(float)right, y5p, 0.5f, 1.0f, color_black},
- {x5p, y50p, 0.5f, 1.0f, color_black},
- {x5p, (float)bottom, 0.5f, 1.0f, color_black},
- {(float)left, y95p, 0.5f, 1.0f, color_black},
- {x50p, y95p, 0.5f, 1.0f, color_black},
- {x95p, (float)top, 0.5f, 1.0f, color_black},
- {x95p, y50p, 0.5f, 1.0f, color_black}
+ { XMFLOAT3((float)left, y5p, 0.5f), xcolor_white, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x50p, y5p, 0.5f), xcolor_white, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x5p, (float)top, 0.5f), xcolor_white, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x5p, y50p, 0.5f), xcolor_white, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x50p, y95p, 0.5f), xcolor_white, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3((float)right, y95p, 0.5f), xcolor_white, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x95p, y50p, 0.5f), xcolor_white, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x95p, (float)bottom, 0.5f), xcolor_white, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+
+ { XMFLOAT3(x50p, y5p, 0.5f), xcolor_black, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3((float)right, y5p, 0.5f), xcolor_black, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x5p, y50p, 0.5f), xcolor_black, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x5p, (float)bottom, 0.5f), xcolor_black, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3((float)left, y95p, 0.5f), xcolor_black, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x50p, y95p, 0.5f), xcolor_black, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x95p, (float)top, 0.5f), xcolor_black, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x95p, y50p, 0.5f), xcolor_black, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
};
- g_Windowing.Get3DDevice()->SetFVF(D3DFVF_CUSTOMVERTEX);
- g_Windowing.Get3DDevice()->DrawPrimitiveUP(D3DPT_LINELIST, 8, vert, sizeof(CUSTOMVERTEX));
+ UpdateVertexBuffer(vert, ARRAYSIZE(vert));
+
+ ID3D11DeviceContext* pContext = g_Windowing.Get3D11Context();
+ CGUIShaderDX* pGUIShader = g_Windowing.GetGUIShader();
+
+ pGUIShader->Begin(SHADER_METHOD_RENDER_DEFAULT);
+ unsigned stride = sizeof(Vertex), offset = 0;
+ pContext->IASetVertexBuffers(0, 1, &m_vb, &stride, &offset);
+ pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
+ pGUIShader->Draw(ARRAYSIZE(vert), 0);
// draw inner rectangles
DrawRectangle(x12p, y12p, x37p, y37p, color_white);
float vectorY;
float vectorY1 = originY;
float vectorX1 = originX;
- CUSTOMVERTEX vert[1083]; // 361*3
+ Vertex vert[1084]; // 361*3 + 1
int p = 0;
for (int i = 0; i <= 360; i++)
angle = (float)(((double)i)/57.29577957795135);
vectorX = originX + (radius*(float)sin((double)angle));
vectorY = originY + (radius*(float)cos((double)angle));
- vert[p].x = originX;
- vert[p].y = originY;
- vert[p].z = 0.5f;
- vert[p].rhw = 1.0f;
- vert[p].color = color;
+ vert[p].pos.x = originX;
+ vert[p].pos.y = originY;
+ vert[p].pos.z = 0.5f;
+ CD3DHelper::XMStoreColor(&vert[p].color, color);
++p;
- vert[p].x = vectorX1;
- vert[p].y = vectorY1;
- vert[p].z = 0.5f;
- vert[p].rhw = 1.0f;
- vert[p].color = color;
+ vert[p].pos.x = vectorX1;
+ vert[p].pos.y = vectorY1;
+ vert[p].pos.z = 0.5f;
+ CD3DHelper::XMStoreColor(&vert[p].color, color);
++p;
- vert[p].x = vectorX;
- vert[p].y = vectorY;
- vert[p].z = 0.5f;
- vert[p].rhw = 1.0f;
- vert[p].color = color;
+ vert[p].pos.x = vectorX;
+ vert[p].pos.y = vectorY;
+ vert[p].pos.z = 0.5f;
+ CD3DHelper::XMStoreColor(&vert[p].color, color);
++p;
vectorY1 = vectorY;
vectorX1 = vectorX;
}
- g_Windowing.Get3DDevice()->SetFVF(D3DFVF_CUSTOMVERTEX);
- g_Windowing.Get3DDevice()->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 361, vert, sizeof(CUSTOMVERTEX));
+ vert[1083] = vert[0];
+
+ UpdateVertexBuffer(vert, ARRAYSIZE(vert));
+
+ ID3D11DeviceContext* pContext = g_Windowing.Get3D11Context();
+ CGUIShaderDX* pGUIShader = g_Windowing.GetGUIShader();
+
+ pGUIShader->Begin(SHADER_METHOD_RENDER_DEFAULT);
+ unsigned stride = sizeof(Vertex), offset = 0;
+ pContext->IASetVertexBuffers(0, 1, &m_vb, &stride, &offset);
+ pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+ pGUIShader->Draw(ARRAYSIZE(vert), 0);
}
void CGUIWindowTestPatternDX::BeginRender()
{
- g_Windowing.Get3DDevice()->Clear(0, NULL, D3DCLEAR_TARGET, 0, 0, 0);
+ ID3D11DeviceContext* pContext = g_Windowing.Get3D11Context();
+ ID3D11RenderTargetView* renderTarget;
+
+ pContext->OMGetRenderTargets(1, &renderTarget, NULL);
+ float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ pContext->ClearRenderTargetView(renderTarget, color);
+ renderTarget->Release();
}
void CGUIWindowTestPatternDX::EndRender()
{
+ g_Windowing.GetGUIShader()->RestoreBuffers();
}
void CGUIWindowTestPatternDX::DrawRectangle(float x, float y, float x2, float y2, DWORD color)
{
- CUSTOMVERTEX vert[] =
+ XMFLOAT4 float4;
+ CD3DHelper::XMStoreColor(&float4, color);
+
+ Vertex vert[] =
{
- {x, y, 0.5f, 1.0f, color},
- {x2, y, 0.5f, 1.0f, color},
- {x2, y2, 0.5f, 1.0f, color},
- {x, y2, 0.5f, 1.0f, color},
- {x, y, 0.5f, 1.0f, color},
+ { XMFLOAT3( x, y, 0.5f), float4, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x2, y, 0.5f), float4, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x2, y2, 0.5f), float4, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x2, y2, 0.5f), float4, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3(x, y2, 0.5f), float4, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
+ { XMFLOAT3( x, y, 0.5f), float4, XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) },
};
- g_Windowing.Get3DDevice()->SetFVF(D3DFVF_CUSTOMVERTEX);
- g_Windowing.Get3DDevice()->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 3, vert, sizeof(CUSTOMVERTEX));
+
+ UpdateVertexBuffer(vert, ARRAYSIZE(vert));
+
+ ID3D11DeviceContext* pContext = g_Windowing.Get3D11Context();
+ CGUIShaderDX* pGUIShader = g_Windowing.GetGUIShader();
+
+ pGUIShader->Begin(SHADER_METHOD_RENDER_DEFAULT);
+ unsigned stride = sizeof(Vertex), offset = 0;
+ pContext->IASetVertexBuffers(0, 1, &m_vb, &stride, &offset);
+ pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ pGUIShader->Draw(ARRAYSIZE(vert), 0);
+}
+
+void CGUIWindowTestPatternDX::UpdateVertexBuffer(Vertex *vertecies, unsigned count)
+{
+ unsigned width = sizeof(Vertex) * count;
+
+ if (!m_vb || width > m_bufferWidth) // create new
+ {
+ SAFE_RELEASE(m_vb);
+
+ CD3D11_BUFFER_DESC desc(width, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
+ D3D11_SUBRESOURCE_DATA initData = {};
+ initData.pSysMem = vertecies;
+ initData.SysMemPitch = width;
+ if (SUCCEEDED(g_Windowing.Get3D11Device()->CreateBuffer(&desc, &initData, &m_vb)))
+ {
+ m_bufferWidth = width;
+ }
+ return;
+ }
+ else // update
+ {
+ ID3D11DeviceContext* pContext = g_Windowing.Get3D11Context();
+ D3D11_MAPPED_SUBRESOURCE res;
+ if (SUCCEEDED(pContext->Map(m_vb, 0, D3D11_MAP_WRITE_DISCARD, 0, &res)))
+ {
+ memcpy(res.pData, vertecies, sizeof(Vertex) * count);
+ pContext->Unmap(m_vb, 0);
+ }
+ }
}
#ifdef HAS_DX
-#include "threads/SystemClock.h"
+#include <DirectXPackedVector.h>
+#include "Application.h"
#include "RenderSystemDX.h"
-#include "utils/log.h"
-#include "utils/TimeUtils.h"
-#include "utils/MathUtils.h"
-#include "guilib/GUIWindowManager.h"
-#include "threads/SingleLock.h"
+#include "cores/VideoRenderers/RenderManager.h"
#include "guilib/D3DResource.h"
+#include "guilib/GUIShaderDX.h"
+#include "guilib/GUIWindowManager.h"
#include "settings/AdvancedSettings.h"
-#include "Application.h"
-#include "video/VideoReferenceClock.h"
-#include "cores/VideoRenderers/RenderManager.h"
-#if (D3DX_SDK_VERSION >= 42) //aug 2009 sdk and up use dxerr
- #include <Dxerr.h>
-#else
- #include <dxerr9.h>
- #define DXGetErrorString(hr) DXGetErrorString9(hr)
- #define DXGetErrorDescription(hr) DXGetErrorDescription9(hr)
-#endif
+#include "threads/SingleLock.h"
+#include "utils/MathUtils.h"
+#include "utils/TimeUtils.h"
+#include "utils/log.h"
+#include "win32/WIN32Util.h"
+#include "win32/dxerr.h"
-using namespace std;
+#pragma comment(lib, "d3d11.lib")
+#pragma comment(lib, "dxgi.lib")
+#pragma comment(lib, "dxguid.lib")
-// Dynamic loading of Direct3DCreate9Ex to keep compatibility with 2000/XP.
-typedef HRESULT (WINAPI *LPDIRECT3DCREATE9EX)( UINT SDKVersion, IDirect3D9Ex **ppD3D);
-static LPDIRECT3DCREATE9EX g_Direct3DCreate9Ex;
-static HMODULE g_D3D9ExHandle;
+#define RATIONAL_TO_FLOAT(rational) ((rational.Denominator != 0) ? (float)rational.Numerator / (float)rational.Denominator : 0.0)
-static bool LoadD3D9Ex()
-{
- HMODULE hD3d9Dll = GetModuleHandle("d3d9.dll");
- if (!hD3d9Dll)
- return false;
- g_Direct3DCreate9Ex = (LPDIRECT3DCREATE9EX)GetProcAddress(hD3d9Dll, "Direct3DCreate9Ex" );
- if(g_Direct3DCreate9Ex == NULL)
- return false;
- return true;
-}
+using namespace DirectX::PackedVector;
CRenderSystemDX::CRenderSystemDX() : CRenderSystemBase()
{
m_enumRenderingSystem = RENDERING_SYSTEM_DIRECTX;
- m_pD3D = NULL;
- m_pD3DDevice = NULL;
- m_devType = D3DDEVTYPE_HAL;
-#if defined(DEBUG_PS) || defined (DEBUG_VS)
- m_devType = D3DDEVTYPE_REF
-#endif
m_hFocusWnd = NULL;
m_hDeviceWnd = NULL;
m_nBackBufferWidth = 0;
m_bFullScreenDevice = false;
m_bVSync = true;
m_nDeviceStatus = S_OK;
- m_stateBlock = NULL;
m_inScene = false;
m_needNewDevice = false;
- m_adapter = D3DADAPTER_DEFAULT;
+ m_resizeInProgress = false;
m_screenHeight = 0;
m_systemFreq = CurrentHostFrequency();
- m_useD3D9Ex = false;
- m_defaultD3DUsage = 0;
- m_defaultD3DPool = D3DPOOL_MANAGED;
- ZeroMemory(&m_D3DPP, sizeof(D3DPRESENT_PARAMETERS));
+ 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_BlendEnabled = false;
+ m_RSScissorDisable = NULL;
+ m_RSScissorEnable = NULL;
+ m_ScissorsEnabled = false;
+
+ m_pTextureRight = NULL;
+ m_pRenderTargetViewRight = NULL;
+ m_pShaderResourceViewRight = NULL;
+ m_pGUIShader = NULL;
+ m_bResizeRequred = false;
+ m_bHWStereoEnabled = false;
+ ZeroMemory(&m_cachedMode, sizeof(m_cachedMode));
+ ZeroMemory(&m_viewPort, sizeof(m_viewPort));
}
CRenderSystemDX::~CRenderSystemDX()
bool CRenderSystemDX::InitRenderSystem()
{
m_bVSync = true;
+
+ CLog::Log(LOGDEBUG, __FUNCTION__" - Initializing D3D11 Factory...");
- m_useD3D9Ex = (g_advancedSettings.m_AllowD3D9Ex && LoadD3D9Ex());
- m_pD3D = NULL;
-
- if (m_useD3D9Ex)
- {
- CLog::Log(LOGDEBUG, __FUNCTION__" - trying D3D9Ex...");
- if (FAILED(g_Direct3DCreate9Ex(D3D_SDK_VERSION, (IDirect3D9Ex**) &m_pD3D)))
- {
- CLog::Log(LOGDEBUG, __FUNCTION__" - D3D9Ex creation failure, falling back to D3D9");
- m_useD3D9Ex = false;
- }
- else
- {
- D3DCAPS9 caps;
- memset(&caps, 0, sizeof(caps));
- m_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, m_devType, &caps);
- // Evaluate if the driver is WDDM - this detection method is not guaranteed 100%
- if (!g_advancedSettings.m_ForceD3D9Ex && (!(caps.Caps2 & D3DCAPS2_CANSHARERESOURCE) || !(caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES)))
- {
- CLog::Log(LOGDEBUG, __FUNCTION__" - driver looks like XPDM or earlier, falling back to D3D9");
- m_useD3D9Ex = false;
- m_pD3D->Release();
- }
- else
- {
- CLog::Log(LOGDEBUG, __FUNCTION__" - using D3D9Ex");
- }
- }
- }
-
- if (!m_useD3D9Ex)
+ HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&m_dxgiFactory));
+ if (FAILED(hr))
{
- m_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
- if(m_pD3D == NULL)
- return false;
+ CLog::Log(LOGERROR, __FUNCTION__" - D3D11 initialization failed.");
+ return false;
}
-
+
UpdateMonitor();
-
- if(CreateDevice()==false)
- return false;
-
- return true;
+ return CreateDevice();
}
void CRenderSystemDX::SetRenderParams(unsigned int width, unsigned int height, bool fullScreen, float refreshRate)
void CRenderSystemDX::SetMonitor(HMONITOR monitor)
{
- if (!m_pD3D)
+ if (!m_dxgiFactory)
+ return;
+
+ DXGI_OUTPUT_DESC outputDesc;
+ if (m_pOutput && SUCCEEDED(m_pOutput->GetDesc(&outputDesc)) && outputDesc.Monitor == monitor)
return;
// find the appropriate screen
- for (unsigned int adapter = 0; adapter < m_pD3D->GetAdapterCount(); adapter++)
+ IDXGIAdapter1* pAdapter;
+ for (unsigned i = 0; m_dxgiFactory->EnumAdapters1(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i)
{
- HMONITOR hMonitor = m_pD3D->GetAdapterMonitor(adapter);
- if (hMonitor == monitor && adapter != m_adapter)
+ IDXGIOutput* pOutput;
+ for (unsigned j = 0; pAdapter->EnumOutputs(j, &pOutput) != DXGI_ERROR_NOT_FOUND; ++j)
{
- m_adapter = adapter;
- m_needNewDevice = true;
- break;
+ if (FAILED(pOutput->GetDesc(&outputDesc)))
+ break;
+
+ if (outputDesc.Monitor == monitor)
+ {
+ // 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)
+ {
+ pAdapter->GetDesc(&m_adapterDesc);
+
+ CLog::Log(LOGDEBUG, __FUNCTION__" - Selected %S adapter. ", m_adapterDesc.Description, outputDesc.DeviceName);
+
+ SAFE_RELEASE(m_adapter);
+ m_adapter = pAdapter;
+
+ m_needNewDevice = true;
+ m_adapterIndex = i;
+
+ return;
+ }
+
+ return;
+ }
+ pOutput->Release();
}
+ pAdapter->Release();
}
}
bool CRenderSystemDX::ResetRenderSystem(int width, int height, bool fullScreen, float refreshRate)
{
- if (!m_pD3DDevice)
+ if (!m_pD3DDev)
return false;
if (m_hDeviceWnd != NULL)
SetRenderParams(width, height, fullScreen, refreshRate);
- CRect rc;
- rc.SetRect(0, 0, (float)width, (float)height);
+ CRect rc(0, 0, float(width), float(height));
SetViewPort(rc);
- BuildPresentParameters();
-
- if (m_useD3D9Ex && !m_needNewDevice)
- m_nDeviceStatus = ((IDirect3DDevice9Ex*)m_pD3DDevice)->ResetEx(&m_D3DPP, m_D3DPP.Windowed ? NULL : &m_D3DDMEX);
- else
+ if (!m_needNewDevice)
+ {
+ CreateWindowSizeDependentResources();
+ SetFullScreenInternal();
+ if (m_bResizeRequred)
+ CreateWindowSizeDependentResources();
+ }
+ else
{
OnDeviceLost();
OnDeviceReset();
if (!m_bRenderCreated)
return;
- HMONITOR currentMonitor = m_pD3D->GetAdapterMonitor(m_adapter);
+ DXGI_OUTPUT_DESC outputDesc;
+ m_pOutput->GetDesc(&outputDesc);
HMONITOR newMonitor = MonitorFromWindow(m_hDeviceWnd, MONITOR_DEFAULTTONULL);
- if (newMonitor != NULL && currentMonitor != newMonitor)
- ResetRenderSystem(m_nBackBufferWidth, m_nBackBufferHeight, m_bFullScreenDevice, m_refreshRate);
-}
+ if (newMonitor != NULL && outputDesc.Monitor != newMonitor)
+ {
+ SetMonitor(newMonitor);
+ if (m_needNewDevice)
+ {
+ CLog::Log(LOGDEBUG, "%s - Adapter changed, reseting render system.", __FUNCTION__);
+ ResetRenderSystem(m_nBackBufferWidth, m_nBackBufferHeight, m_bFullScreenDevice, m_refreshRate);
+ }
+ }
+}
-bool CRenderSystemDX::IsSurfaceFormatOk(D3DFORMAT surfFormat, DWORD usage)
+void CRenderSystemDX::OnResize(unsigned int width, unsigned int height)
{
- // Verify the compatibility
- HRESULT hr = m_pD3D->CheckDeviceFormat(m_adapter,
- m_devType,
- m_D3DPP.BackBufferFormat,
- usage,
- D3DRTYPE_SURFACE,
- surfFormat);
-
- return (SUCCEEDED(hr)) ? true : false;
+ if (!m_bRenderCreated)
+ return;
+
+ m_nBackBufferWidth = width;
+ m_nBackBufferHeight = height;
+ CreateWindowSizeDependentResources();
}
-bool CRenderSystemDX::IsTextureFormatOk(D3DFORMAT texFormat, DWORD usage)
+void CRenderSystemDX::GetClosestDisplayModeToCurrent(IDXGIOutput* output, DXGI_MODE_DESC* outCurrentDisplayMode, bool useCached /*= false*/)
{
- // Verify the compatibility
- HRESULT hr = m_pD3D->CheckDeviceFormat(m_adapter,
- m_devType,
- m_D3DPP.BackBufferFormat,
- usage,
- D3DRTYPE_TEXTURE,
- texFormat);
-
- return (SUCCEEDED(hr)) ? true : false;
+ DXGI_OUTPUT_DESC outputDesc;
+ output->GetDesc(&outputDesc);
+ HMONITOR hMonitor = outputDesc.Monitor;
+ MONITORINFOEX monitorInfo;
+ monitorInfo.cbSize = sizeof(MONITORINFOEX);
+ GetMonitorInfo(hMonitor, &monitorInfo);
+ DEVMODE devMode;
+ devMode.dmSize = sizeof(DEVMODE);
+ devMode.dmDriverExtra = 0;
+ EnumDisplaySettings(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &devMode);
+
+ bool useDefaultRefreshRate = 1 == devMode.dmDisplayFrequency || 0 == devMode.dmDisplayFrequency;
+ float refreshRate = RATIONAL_TO_FLOAT(m_cachedMode.RefreshRate);
+
+ // this needed to improve performance for VideoSync bacause FindClosestMatchingMode is very slow
+ if (!useCached
+ || m_cachedMode.Width != devMode.dmPelsWidth
+ || m_cachedMode.Height != devMode.dmPelsHeight
+ || long(refreshRate) != devMode.dmDisplayFrequency)
+ {
+ DXGI_MODE_DESC current;
+ current.Width = devMode.dmPelsWidth;
+ current.Height = devMode.dmPelsHeight;
+ current.RefreshRate.Numerator = useDefaultRefreshRate ? 0 : devMode.dmDisplayFrequency;
+ current.RefreshRate.Denominator = useDefaultRefreshRate ? 0 : 1;
+ current.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ current.ScanlineOrdering = m_interlaced ? DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST : DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
+ current.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+
+ output->FindClosestMatchingMode(¤t, &m_cachedMode, m_pD3DDev);
+ }
+
+ ZeroMemory(outCurrentDisplayMode, sizeof(DXGI_MODE_DESC));
+ outCurrentDisplayMode->Width = m_cachedMode.Width;
+ outCurrentDisplayMode->Height = m_cachedMode.Height;
+ outCurrentDisplayMode->RefreshRate.Numerator = m_cachedMode.RefreshRate.Numerator;
+ outCurrentDisplayMode->RefreshRate.Denominator = m_cachedMode.RefreshRate.Denominator;
+ outCurrentDisplayMode->Format = m_cachedMode.Format;
+ outCurrentDisplayMode->ScanlineOrdering = m_cachedMode.ScanlineOrdering;
+ outCurrentDisplayMode->Scaling = m_cachedMode.Scaling;
}
-BOOL CRenderSystemDX::IsDepthFormatOk(D3DFORMAT DepthFormat, D3DFORMAT RenderTargetFormat)
+void CRenderSystemDX::GetDisplayMode(DXGI_MODE_DESC *mode, bool useCached /*= false*/)
{
- // Verify that the depth format exists
- if (!IsSurfaceFormatOk(DepthFormat, D3DUSAGE_DEPTHSTENCIL))
- return false;
-
- // Verify that the depth format is compatible
- HRESULT hr = m_pD3D->CheckDepthStencilMatch(m_adapter,
- m_devType,
- m_D3DPP.BackBufferFormat,
- RenderTargetFormat,
- DepthFormat);
+ GetClosestDisplayModeToCurrent(m_pOutput, mode, useCached);
+}
- return SUCCEEDED(hr);
+inline void DXWait(ID3D11Device* pDevice, ID3D11DeviceContext* pContext)
+{
+ ID3D11Query* wait = NULL;
+ CD3D11_QUERY_DESC qd(D3D11_QUERY_EVENT);
+ if (SUCCEEDED(pDevice->CreateQuery(&qd, &wait)))
+ {
+ pContext->End(wait);
+ while (S_FALSE == pContext->GetData(wait, NULL, 0, 0))
+ Sleep(1);
+ }
+ SAFE_RELEASE(wait);
}
-void CRenderSystemDX::BuildPresentParameters()
+void CRenderSystemDX::SetFullScreenInternal()
{
- OSVERSIONINFOEX osvi;
- ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
- osvi.dwOSVersionInfoSize = sizeof(osvi);
- GetVersionEx((OSVERSIONINFO *)&osvi);
+ if (!m_bRenderCreated)
+ return;
- ZeroMemory( &m_D3DPP, sizeof(D3DPRESENT_PARAMETERS) );
- m_D3DPP.Windowed = m_useWindowedDX;
- m_D3DPP.SwapEffect = D3DSWAPEFFECT_FLIP;
- m_D3DPP.BackBufferCount = 2;
+ HRESULT hr;
+ BOOL bFullScreen;
+ m_pSwapChain->GetFullscreenState(&bFullScreen, NULL);
- if(m_useD3D9Ex && (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion >= 1 || osvi.dwMajorVersion > 6))
+ // full-screen to windowed translation. Only change FS state and return
+ if (!!bFullScreen && m_useWindowedDX)
{
-#if D3DX_SDK_VERSION >= 42
- //m_D3DPP.SwapEffect = D3DSWAPEFFECT_FLIPEX;
-#else
-# pragma message("D3D SDK version is too old to support D3DSWAPEFFECT_FLIPEX")
- CLog::Log(LOGWARNING, "CRenderSystemDX::BuildPresentParameters - xbmc compiled with an d3d sdk not supporting D3DSWAPEFFECT_FLIPEX");
-#endif
+ CLog::Log(LOGDEBUG, "%s - Switching swap chain to windowed mode.", __FUNCTION__);
+ hr = m_pSwapChain->SetFullscreenState(false, NULL);
+ m_bResizeRequred = S_OK == hr;
+
+ if (S_OK != hr)
+ CLog::Log(LOGERROR, "%s - Failed switch full screen state: %s.", __FUNCTION__, GetErrorDescription(hr).c_str());
+ // wait until switching screen state is done
+ DXWait(m_pD3DDev, m_pImdContext);
+ return;
}
- m_D3DPP.hDeviceWindow = m_hDeviceWnd;
- m_D3DPP.BackBufferWidth = m_nBackBufferWidth;
- m_D3DPP.BackBufferHeight = m_nBackBufferHeight;
- m_D3DPP.Flags = D3DPRESENTFLAG_VIDEO;
- m_D3DPP.PresentationInterval = (m_bVSync) ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
- m_D3DPP.FullScreen_RefreshRateInHz = (m_useWindowedDX) ? 0 : (int)m_refreshRate;
- m_D3DPP.BackBufferFormat = D3DFMT_X8R8G8B8;
- m_D3DPP.MultiSampleType = D3DMULTISAMPLE_NONE;
- m_D3DPP.MultiSampleQuality = 0;
-
- D3DFORMAT zFormat = D3DFMT_D16;
- if (IsDepthFormatOk(D3DFMT_D32, m_D3DPP.BackBufferFormat)) zFormat = D3DFMT_D32;
- else if (IsDepthFormatOk(D3DFMT_D24S8, m_D3DPP.BackBufferFormat)) zFormat = D3DFMT_D24S8;
- else if (IsDepthFormatOk(D3DFMT_D24X4S4, m_D3DPP.BackBufferFormat)) zFormat = D3DFMT_D24X4S4;
- else if (IsDepthFormatOk(D3DFMT_D24X8, m_D3DPP.BackBufferFormat)) zFormat = D3DFMT_D24X8;
- else if (IsDepthFormatOk(D3DFMT_D16, m_D3DPP.BackBufferFormat)) zFormat = D3DFMT_D16;
- else if (IsDepthFormatOk(D3DFMT_D15S1, m_D3DPP.BackBufferFormat)) zFormat = D3DFMT_D15S1;
-
- m_D3DPP.EnableAutoDepthStencil = TRUE;
- m_D3DPP.AutoDepthStencilFormat = zFormat;
-
- if (m_useD3D9Ex)
+ // true full-screen
+ if (m_bFullScreenDevice && !m_useWindowedDX)
{
- ZeroMemory( &m_D3DDMEX, sizeof(D3DDISPLAYMODEEX) );
- m_D3DDMEX.Size = sizeof(D3DDISPLAYMODEEX);
- m_D3DDMEX.Width = m_D3DPP.BackBufferWidth;
- m_D3DDMEX.Height = m_D3DPP.BackBufferHeight;
- m_D3DDMEX.RefreshRate = m_D3DPP.FullScreen_RefreshRateInHz;
- m_D3DDMEX.Format = m_D3DPP.BackBufferFormat;
- m_D3DDMEX.ScanLineOrdering = m_interlaced ? D3DSCANLINEORDERING_INTERLACED : D3DSCANLINEORDERING_PROGRESSIVE;
+ IDXGIOutput* pOutput = NULL;
+ m_pSwapChain->GetContainingOutput(&pOutput);
+
+ DXGI_OUTPUT_DESC trgDesc, currDesc;
+ m_pOutput->GetDesc(&trgDesc);
+ pOutput->GetDesc(&currDesc);
+
+ if (trgDesc.Monitor != currDesc.Monitor || !bFullScreen)
+ {
+ // swap chain requires to change FS mode after resize or transition from windowed to full-screen.
+ CLog::Log(LOGDEBUG, "%s - Switching swap chain to fullscreen state.", __FUNCTION__);
+ hr = m_pSwapChain->SetFullscreenState(true, m_pOutput);
+ m_bResizeRequred = S_OK == hr;
+
+ if (S_OK != hr)
+ CLog::Log(LOGERROR, "%s - Failed switch full screen state: %s.", __FUNCTION__, GetErrorDescription(hr).c_str());
+ }
+ SAFE_RELEASE(pOutput);
+
+ // do not change modes if hw stereo
+ if (g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_HARDWAREBASED)
+ return;
+
+ DXGI_SWAP_CHAIN_DESC scDesc;
+ m_pSwapChain->GetDesc(&scDesc);
+
+ DXGI_MODE_DESC currentMode, // closest to current mode
+ toMatchMode, // required mode
+ matchedMode; // closest to required mode
+
+ // find current mode on target output
+ GetClosestDisplayModeToCurrent(m_pOutput, ¤tMode);
+
+ float currentRefreshRate = RATIONAL_TO_FLOAT(currentMode.RefreshRate);
+ CLog::Log(LOGDEBUG, "%s - Current display mode is: %dx%d@%0.3f", __FUNCTION__, currentMode.Width, currentMode.Height, currentRefreshRate);
+
+ // use backbuffer dimention to find required display mode
+ toMatchMode.Width = m_nBackBufferWidth;
+ toMatchMode.Height = m_nBackBufferHeight;
+ bool useDefaultRefreshRate = 0 == m_refreshRate;
+ toMatchMode.RefreshRate.Numerator = useDefaultRefreshRate ? 0 : m_refreshRate;
+ toMatchMode.RefreshRate.Denominator = useDefaultRefreshRate ? 0 : 1;
+ toMatchMode.Format = scDesc.BufferDesc.Format;
+ toMatchMode.Scaling = scDesc.BufferDesc.Scaling;
+ toMatchMode.ScanlineOrdering = scDesc.BufferDesc.ScanlineOrdering;
+
+ // find closest mode
+ m_pOutput->FindClosestMatchingMode(&toMatchMode, &matchedMode, m_pD3DDev);
+
+ float matchedRefreshRate = RATIONAL_TO_FLOAT(matchedMode.RefreshRate);
+ CLog::Log(LOGDEBUG, "%s - Found matched mode: %dx%d@%0.3f", __FUNCTION__, matchedMode.Width, matchedMode.Height, matchedRefreshRate);
+
+ // change mode if required (current != required)
+ if ( currentMode.Width != matchedMode.Width
+ || currentMode.Height != matchedMode.Height
+ || currentRefreshRate != matchedRefreshRate)
+ {
+ CLog::Log(LOGDEBUG, "%s - Switching mode to %dx%d@%0.3f.", __FUNCTION__, matchedMode.Width, matchedMode.Height, matchedRefreshRate);
+
+ // resize window (in windowed mode) or monitor resolution (in fullscreen mode) to required mode
+ hr = m_pSwapChain->ResizeTarget(&matchedMode);
+ m_bResizeRequred = S_OK == hr;
+
+ 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);
}
}
-bool CRenderSystemDX::DestroyRenderSystem()
+bool CRenderSystemDX::IsFormatSupport(DXGI_FORMAT format, unsigned int usage)
{
- DeleteDevice();
+ UINT supported;
+ m_pD3DDev->CheckFormatSupport(format, &supported);
+ return (supported & usage) != 0;
+}
- SAFE_RELEASE(m_stateBlock);
- SAFE_RELEASE(m_pD3D);
- SAFE_RELEASE(m_pD3DDevice);
+bool CRenderSystemDX::DestroyRenderSystem()
+{
+ if (m_pSwapChain)
+ m_pSwapChain->SetFullscreenState(false, NULL);
- m_bRenderCreated = false;
+ DeleteDevice();
+ SAFE_RELEASE(m_pOutput);
+ SAFE_RELEASE(m_adapter);
+ SAFE_RELEASE(m_dxgiFactory);
+#ifdef _DEBUG
+ if (m_d3dDebug)
+ {
+ m_d3dDebug->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);
+ m_d3dDebug->Release();
+ }
+#endif
return true;
}
{
CSingleLock lock(m_resourceSection);
+ if (m_pGUIShader)
+ m_pGUIShader->End();
+
// tell any shared resources
- for (vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
+ for (std::vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
(*i)->OnDestroyDevice();
- SAFE_RELEASE(m_pD3DDevice);
+ SAFE_DELETE(m_pGUIShader);
+ SAFE_RELEASE(m_pTextureRight);
+ SAFE_RELEASE(m_pRenderTargetViewRight);
+ SAFE_RELEASE(m_pShaderResourceViewRight);
+ SAFE_RELEASE(m_BlendEnableState);
+ SAFE_RELEASE(m_BlendDisableState);
+ SAFE_RELEASE(m_RSScissorDisable);
+ SAFE_RELEASE(m_RSScissorEnable);
+ SAFE_RELEASE(m_depthStencilState);
+ SAFE_RELEASE(m_depthStencilView);
+ SAFE_RELEASE(m_pRenderTargetView);
+ SAFE_RELEASE(m_pSwapChain);
+ SAFE_RELEASE(m_pSwapChain1);
+ SAFE_RELEASE(m_pD3DDev);
+ if (m_pContext && m_pContext != m_pImdContext)
+ {
+ FinishCommandList(false);
+ m_pContext->ClearState();
+ m_pContext->Flush();
+ SAFE_RELEASE(m_pContext);
+ }
+ if (m_pImdContext)
+ {
+ m_pImdContext->ClearState();
+ m_pImdContext->Flush();
+ SAFE_RELEASE(m_pImdContext);
+ }
+ m_bResizeRequred = false;
+ m_bHWStereoEnabled = false;
m_bRenderCreated = false;
}
{
CSingleLock lock(m_resourceSection);
g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_RENDERER_LOST);
- SAFE_RELEASE(m_stateBlock);
if (m_needNewDevice)
DeleteDevice();
else
{
// just resetting the device
- for (vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
+ for (std::vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
(*i)->OnLostDevice();
}
}
if (m_needNewDevice)
CreateDevice();
else
- {
- // just need a reset
- if (m_useD3D9Ex)
- m_nDeviceStatus = ((IDirect3DDevice9Ex*)m_pD3DDevice)->ResetEx(&m_D3DPP, m_D3DPP.Windowed ? NULL : &m_D3DDMEX);
- else
- m_nDeviceStatus = m_pD3DDevice->Reset(&m_D3DPP);
- }
-
- if (m_nDeviceStatus == S_OK)
{ // we're back
- for (vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
+ for (std::vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
(*i)->OnResetDevice();
g_renderManager.Flush();
-
g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_RENDERER_RESET);
}
- else
- {
- for (vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
- (*i)->OnLostDevice();
- }
}
bool CRenderSystemDX::CreateDevice()
{
- // Code based on Ogre 3D engine
CSingleLock lock(m_resourceSection);
HRESULT hr;
- if(m_pD3D == NULL)
- return false;
-
- if(m_hDeviceWnd == NULL)
- return false;
+ SAFE_RELEASE(m_pD3DDev);
- CLog::Log(LOGDEBUG, __FUNCTION__" on adapter %d", m_adapter);
+ D3D_FEATURE_LEVEL featureLevels[] =
+ {
+ D3D_FEATURE_LEVEL_11_1,
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_9_3,
+ D3D_FEATURE_LEVEL_9_2,
+ D3D_FEATURE_LEVEL_9_1,
+ };
- BuildPresentParameters();
+ // the VIDEO_SUPPORT flag force lowering feature level if current env not support video on 11_1
+ UINT createDeviceFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
+#ifdef _DEBUG
+ createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
- D3DCAPS9 caps;
- memset(&caps, 0, sizeof(caps));
- m_pD3D->GetDeviceCaps(m_adapter, m_devType, &caps);
+ // 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),
+ D3D11_SDK_VERSION, &m_pD3DDev, &m_featureLevel, &m_pImdContext);
- DWORD VertexProcessingFlags = 0;
- if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
- {
- /* Activate when the state management of the fixed pipeline is in order,
- to get a bit more performance
- if (caps.DevCaps & D3DDEVCAPS_PUREDEVICE)
- VertexProcessingFlags = D3DCREATE_PUREDEVICE;
- */
- VertexProcessingFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
- CLog::Log(LOGDEBUG, __FUNCTION__" - using hardware vertex processing");
- }
- else
+ if (FAILED(hr))
{
- VertexProcessingFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
- CLog::Log(LOGDEBUG, __FUNCTION__" - using software vertex processing");
- }
+ CLog::Log(LOGDEBUG, "%s - First try to create device failed with error: %s.", __FUNCTION__, GetErrorDescription(hr).c_str());
- if (m_useD3D9Ex)
- {
- hr = ((IDirect3D9Ex*)m_pD3D)->CreateDeviceEx(m_adapter, m_devType, m_hFocusWnd,
- VertexProcessingFlags | D3DCREATE_MULTITHREADED, &m_D3DPP, m_D3DPP.Windowed ? NULL : &m_D3DDMEX, (IDirect3DDevice9Ex**)&m_pD3DDevice );
- if (FAILED(hr))
+ for (int i = 1; i < ARRAYSIZE(featureLevels); i++)
{
- CLog::Log(LOGWARNING, __FUNCTION__" - initial wanted device config failed");
- // Try a second time, may fail the first time due to back buffer count,
- // which will be corrected down to 1 by the runtime
- hr = ((IDirect3D9Ex*)m_pD3D)->CreateDeviceEx( m_adapter, m_devType, m_hFocusWnd,
- VertexProcessingFlags | D3DCREATE_MULTITHREADED, &m_D3DPP, m_D3DPP.Windowed ? NULL : &m_D3DDMEX, (IDirect3DDevice9Ex**)&m_pD3DDevice );
- if( FAILED( hr ) )
- {
- CLog::Log(LOGERROR, __FUNCTION__" - unable to create a device. %s", GetErrorDescription(hr).c_str());
- return false;
- }
+ CLog::Log(LOGDEBUG, "%s - Trying to create device with lowest feature level: %#x.", __FUNCTION__, featureLevels[i]);
+ // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
+ hr = D3D11CreateDevice(m_adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, createDeviceFlags, &featureLevels[i], ARRAYSIZE(featureLevels) - i,
+ D3D11_SDK_VERSION, &m_pD3DDev, &m_featureLevel, &m_pImdContext);
+ if (SUCCEEDED(hr))
+ break;
+
+ CLog::Log(LOGDEBUG, "%s - Next try to create device failed with error: %s.", __FUNCTION__, GetErrorDescription(hr).c_str());
}
- // Not sure the following actually does something
- ((IDirect3DDevice9Ex*)m_pD3DDevice)->SetGPUThreadPriority(7);
}
- else
+
+ if (FAILED(hr))
{
- hr = m_pD3D->CreateDevice(m_adapter, m_devType, m_hFocusWnd,
- VertexProcessingFlags | D3DCREATE_MULTITHREADED, &m_D3DPP, &m_pD3DDevice );
- if (FAILED(hr))
- {
- CLog::Log(LOGWARNING, __FUNCTION__" - initial wanted device config failed");
- // Try a second time, may fail the first time due to back buffer count,
- // which will be corrected down to 1 by the runtime
- hr = m_pD3D->CreateDevice( m_adapter, m_devType, m_hFocusWnd,
- VertexProcessingFlags | D3DCREATE_MULTITHREADED, &m_D3DPP, &m_pD3DDevice );
- if( FAILED( hr ) )
- {
- CLog::Log(LOGERROR, __FUNCTION__" - unable to create a device. %s", GetErrorDescription(hr).c_str());
- return false;
- }
- }
+ CLog::Log(LOGERROR, "%s - D3D11 device creation failure with error %s.", __FUNCTION__, GetErrorDescription(hr).c_str());
+ return false;
}
- if(m_pD3D->GetAdapterIdentifier(m_adapter, 0, &m_AIdentifier) == D3D_OK)
+ if ( g_advancedSettings.m_bAllowDeferredRendering
+ && FAILED(m_pD3DDev->CreateDeferredContext(0, &m_pContext)))
{
- m_RenderRenderer = (const char*)m_AIdentifier.Description;
- m_RenderVendor = (const char*)m_AIdentifier.Driver;
- m_RenderVersion = StringUtils::Format("%d.%d.%d.%04d", HIWORD(m_AIdentifier.DriverVersion.HighPart), LOWORD(m_AIdentifier.DriverVersion.HighPart),
- HIWORD(m_AIdentifier.DriverVersion.LowPart) , LOWORD(m_AIdentifier.DriverVersion.LowPart));
+ CLog::Log(LOGERROR, "%s - Failed to create deferred context, deferred rendering is not possible, fallback to immediate rendering.", __FUNCTION__);
}
- CLog::Log(LOGDEBUG, __FUNCTION__" - adapter %d: %s, %s, VendorId %lu, DeviceId %lu",
- m_adapter, m_AIdentifier.Driver, m_AIdentifier.Description, m_AIdentifier.VendorId, m_AIdentifier.DeviceId);
-
- // get our render capabilities
- // re-read caps, there may be changes depending on the vertex processing type
- m_pD3DDevice->GetDeviceCaps(&caps);
+ // make immediate context as default context if deferred context was not created
+ if (!m_pContext)
+ m_pContext = m_pImdContext;
+
+ if (m_featureLevel < D3D_FEATURE_LEVEL_9_3)
+ m_maxTextureSize = D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ else if (m_featureLevel < D3D_FEATURE_LEVEL_10_0)
+ m_maxTextureSize = D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ else if (m_featureLevel < D3D_FEATURE_LEVEL_11_0)
+ m_maxTextureSize = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ else
+ // 11_x and greater feature level. Limit this size to avoid memory overheads
+ m_maxTextureSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION >> 1;
+
+ // use multi-thread protection on the device context to prevent deadlock issues that can sometimes happen
+ // when decoder call ID3D11VideoContext::GetDecoderBuffer or ID3D11VideoContext::ReleaseDecoderBuffer.
+ ID3D10Multithread *pMultiThreading = NULL;
+ if (SUCCEEDED(m_pD3DDev->QueryInterface(__uuidof(ID3D10Multithread), reinterpret_cast<void**>(&pMultiThreading))))
+ {
+ pMultiThreading->SetMultithreadProtected(true);
+ pMultiThreading->Release();
+ }
- m_maxTextureSize = min(caps.MaxTextureWidth, caps.MaxTextureHeight);
+ 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);
+ }
- if (g_advancedSettings.m_AllowDynamicTextures && m_useD3D9Ex && (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES))
+#ifdef _DEBUG
+ if (SUCCEEDED(m_pD3DDev->QueryInterface(__uuidof(ID3D11Debug), reinterpret_cast<void**>(&m_d3dDebug))))
{
- m_defaultD3DUsage = D3DUSAGE_DYNAMIC;
- m_defaultD3DPool = D3DPOOL_DEFAULT;
- CLog::Log(LOGDEBUG, __FUNCTION__" - using D3DCAPS2_DYNAMICTEXTURES");
+ ID3D11InfoQueue *d3dInfoQueue = nullptr;
+ if (SUCCEEDED(m_d3dDebug->QueryInterface(__uuidof(ID3D11InfoQueue), reinterpret_cast<void**>(&d3dInfoQueue))))
+ {
+ D3D11_MESSAGE_ID hide[] =
+ {
+ D3D11_MESSAGE_ID_DEVICE_DRAW_RESOURCE_FORMAT_SAMPLE_UNSUPPORTED, // avoid DXGI_FORMAT_A8_UNORM error
+ D3D11_MESSAGE_ID_GETVIDEOPROCESSORFILTERRANGE_UNSUPPORTED, // avoid GETVIDEOPROCESSORFILTERRANGE_UNSUPPORTED (dx bug)
+ D3D11_MESSAGE_ID_DEVICE_RSSETSCISSORRECTS_NEGATIVESCISSOR // avoid warning for some labels out of screen
+ // Add more message IDs here as needed
+ };
+
+ D3D11_INFO_QUEUE_FILTER filter;
+ ZeroMemory(&filter, sizeof(filter));
+ filter.DenyList.NumIDs = _countof(hide);
+ filter.DenyList.pIDList = hide;
+ d3dInfoQueue->AddStorageFilterEntries(&filter);
+ d3dInfoQueue->Release();
+ }
}
- else
+#endif
+
+ m_adapterDesc = {};
+ if (SUCCEEDED(m_adapter->GetDesc(&m_adapterDesc)))
{
- m_defaultD3DUsage = 0;
- m_defaultD3DPool = D3DPOOL_MANAGED;
+ CLog::Log(LOGDEBUG, "%s - on adapter %S (VendorId: %#x DeviceId: %#x) with feature level %#x.", __FUNCTION__,
+ m_adapterDesc.Description, m_adapterDesc.VendorId, m_adapterDesc.DeviceId, m_featureLevel);
+
+ m_RenderRenderer = StringUtils::Format("%S", m_adapterDesc.Description);
+ IDXGIFactory2* dxgiFactory2 = nullptr;
+ m_dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2));
+ m_RenderVersion = StringUtils::Format("DirectX %s (FL %d.%d)",
+ dxgiFactory2 != nullptr ? "11.1" : "11.0",
+ (m_featureLevel >> 12) & 0xF,
+ (m_featureLevel >> 8) & 0xF);
+ SAFE_RELEASE(dxgiFactory2);
}
m_renderCaps = 0;
-
- CLog::Log(LOGDEBUG, __FUNCTION__" - texture caps: 0x%08X", caps.TextureCaps);
-
- if(IsTextureFormatOk(D3DFMT_DXT1, m_defaultD3DUsage)
- && IsTextureFormatOk(D3DFMT_DXT3, m_defaultD3DUsage)
- && IsTextureFormatOk(D3DFMT_DXT5, m_defaultD3DUsage))
+ unsigned int usage = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
+ if ( IsFormatSupport(DXGI_FORMAT_BC1_UNORM, usage)
+ && IsFormatSupport(DXGI_FORMAT_BC2_UNORM, usage)
+ && IsFormatSupport(DXGI_FORMAT_BC3_UNORM, usage))
m_renderCaps |= RENDER_CAPS_DXT;
- if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) == 0)
- { // we're allowed NPOT textures
- m_renderCaps |= RENDER_CAPS_NPOT;
- if (((m_renderCaps & RENDER_CAPS_DXT) != 0) && ((caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) == 0))
- m_renderCaps |= RENDER_CAPS_DXT_NPOT;
- }
- else if ((caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) != 0)
- { // we're allowed _some_ NPOT textures (namely non-DXT and only with D3DTADDRESS_CLAMP and no wrapping)
- m_renderCaps |= RENDER_CAPS_NPOT;
- }
+ // 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.
+ // First, only one MIP-map level for each texture can be created - we are using only 1 mip level)
+ // Second, no wrap sampler modes for textures are allowed - we are using clamp everywhere
+ // 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.
+ // so, setup caps NPOT
+ m_renderCaps |= RENDER_CAPS_NPOT;
+ if ((m_renderCaps & RENDER_CAPS_DXT) != 0)
+ m_renderCaps |= RENDER_CAPS_DXT_NPOT;
// Temporary - allow limiting the caps to debug a texture problem
if (g_advancedSettings.m_RestrictCapsMask != 0)
m_renderCaps &= ~g_advancedSettings.m_RestrictCapsMask;
if (m_renderCaps & RENDER_CAPS_DXT)
- CLog::Log(LOGDEBUG, __FUNCTION__" - RENDER_CAPS_DXT");
+ CLog::Log(LOGDEBUG, "%s - RENDER_CAPS_DXT", __FUNCTION__);
if (m_renderCaps & RENDER_CAPS_NPOT)
- CLog::Log(LOGDEBUG, __FUNCTION__" - RENDER_CAPS_NPOT");
+ CLog::Log(LOGDEBUG, "%s - RENDER_CAPS_NPOT", __FUNCTION__);
if (m_renderCaps & RENDER_CAPS_DXT_NPOT)
- CLog::Log(LOGDEBUG, __FUNCTION__" - RENDER_CAPS_DXT_NPOT");
+ CLog::Log(LOGDEBUG, "%s - RENDER_CAPS_DXT_NPOT", __FUNCTION__);
+ /* All the following quirks need to be tested
// nVidia quirk: some NPOT DXT textures of the GUI display with corruption
// when using D3DPOOL_DEFAULT + D3DUSAGE_DYNAMIC textures (no other choice with D3D9Ex for example)
// most likely xbmc bug, but no hw to repro & fix properly.
// affects lots of hw generations - 6xxx, 7xxx, GT220, ION1
// see ticket #9269
- if(m_defaultD3DUsage == D3DUSAGE_DYNAMIC
- && m_defaultD3DPool == D3DPOOL_DEFAULT
- && m_AIdentifier.VendorId == PCIV_nVidia)
+ if (m_adapterDesc.VendorId == PCIV_nVidia)
{
CLog::Log(LOGDEBUG, __FUNCTION__" - nVidia workaround - disabling RENDER_CAPS_DXT_NPOT");
m_renderCaps &= ~RENDER_CAPS_DXT_NPOT;
// DXT3/5: 16 pixels wide ----------------------------------------
// 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.
// See ticket #9578
- if(m_defaultD3DUsage == D3DUSAGE_DYNAMIC
- && m_defaultD3DPool == D3DPOOL_DEFAULT
- && m_AIdentifier.VendorId == PCIV_Intel)
+ if (m_adapterDesc.VendorId == PCIV_Intel)
{
CLog::Log(LOGDEBUG, __FUNCTION__" - Intel workaround - specifying minimum pitch for compressed textures.");
m_minDXTPitch = 128;
- }
-
- D3DDISPLAYMODE mode;
- if (SUCCEEDED(m_pD3DDevice->GetDisplayMode(0, &mode)))
- m_screenHeight = mode.Height;
- else
- m_screenHeight = m_nBackBufferHeight;
+ }*/
- m_pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
- m_pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
+ if (!CreateStates() || !InitGUIShader() || !CreateWindowSizeDependentResources())
+ return false;
m_bRenderCreated = true;
m_needNewDevice = false;
// tell any shared objects about our resurrection
- for (vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
+ for (std::vector<ID3DResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i)
(*i)->OnCreateDevice();
+ RestoreViewPort();
+
return true;
}
-bool CRenderSystemDX::PresentRenderImpl(const CDirtyRegionList &dirty)
+bool CRenderSystemDX::CreateWindowSizeDependentResources()
{
+ if (m_resizeInProgress)
+ return false;
+
HRESULT hr;
+ DXGI_SWAP_CHAIN_DESC scDesc = { 0 };
- if (!m_bRenderCreated)
- return false;
+ bool bNeedRecreate = false;
+ bool bNeedResize = false;
+ bool bHWStereoEnabled = RENDER_STEREO_MODE_HARDWAREBASED == g_graphicsContext.GetStereoMode();
- if(m_nDeviceStatus != S_OK)
- return false;
+ if (m_pSwapChain)
+ {
+ m_pSwapChain->GetDesc(&scDesc);
+ bNeedResize = m_bResizeRequred || m_nBackBufferWidth != scDesc.BufferDesc.Width || m_nBackBufferHeight != scDesc.BufferDesc.Height;
+ }
+ else
+ bNeedResize = true;
- //CVideoReferenceClock polls GetRasterStatus too,
- //polling it from two threads at the same time is bad
- if (g_advancedSettings.m_sleepBeforeFlip > 0 && !g_VideoReferenceClock.IsRunning())
+ if (m_pSwapChain1)
{
- //save current thread priority and set thread priority to THREAD_PRIORITY_TIME_CRITICAL
- int priority = GetThreadPriority(GetCurrentThread());
- if (priority != THREAD_PRIORITY_ERROR_RETURN)
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+ DXGI_SWAP_CHAIN_DESC1 scDesc;
+ m_pSwapChain1->GetDesc1(&scDesc);
+ bNeedRecreate = (scDesc.Stereo && !bHWStereoEnabled) || (!scDesc.Stereo && bHWStereoEnabled);
+ }
+
+ if (!bNeedRecreate && !bNeedResize)
+ {
+ CheckInterlasedStereoView();
+ return true;
+ }
- D3DRASTER_STATUS rasterStatus;
- int64_t prev = CurrentHostCounter();
+ m_resizeInProgress = true;
+
+ CLog::Log(LOGDEBUG, "%s - (Re)Create window size (%dx%d) dependent resources.", __FUNCTION__, m_nBackBufferWidth, m_nBackBufferHeight);
+
+ bool bRestoreRTView = false;
+ {
+ ID3D11RenderTargetView* pRTView; ID3D11DepthStencilView* pDSView;
+ m_pContext->OMGetRenderTargets(1, &pRTView, &pDSView);
- while (SUCCEEDED(m_pD3DDevice->GetRasterStatus(0, &rasterStatus)))
+ bRestoreRTView = NULL != pRTView || NULL != pDSView;
+
+ SAFE_RELEASE(pRTView);
+ SAFE_RELEASE(pDSView);
+ }
+
+ m_pContext->OMSetRenderTargets(0, NULL, NULL);
+ FinishCommandList(false);
+
+ SAFE_RELEASE(m_pRenderTargetView);
+ SAFE_RELEASE(m_depthStencilView);
+ SAFE_RELEASE(m_pRenderTargetViewRight);
+ SAFE_RELEASE(m_pShaderResourceViewRight);
+ SAFE_RELEASE(m_pTextureRight);
+
+ if (bNeedRecreate)
+ {
+ BOOL fullScreen;
+ m_pSwapChain1->GetFullscreenState(&fullScreen, NULL);
+ if (fullScreen)
+ m_pSwapChain1->SetFullscreenState(false, NULL);
+
+ CLog::Log(LOGDEBUG, "%s - Destroying swapchain in order to switch %s stereoscopic 3D.", __FUNCTION__, bHWStereoEnabled ? "to" : "from");
+
+ SAFE_RELEASE(m_pSwapChain);
+ SAFE_RELEASE(m_pSwapChain1);
+ m_pImdContext->Flush();
+
+ // flush command is asynchronous, so wait until destruction is completed
+ // otherwise it can cause problems with flip presentation model swap chains.
+ DXWait(m_pD3DDev, m_pImdContext);
+ }
+
+ if (!m_pSwapChain)
+ {
+ CLog::Log(LOGDEBUG, "%s - Creating swapchain in %s mode.", __FUNCTION__, bHWStereoEnabled ? "Stereoscopic 3D" : "Mono");
+
+ // Create swap chain
+ IDXGIFactory2* dxgiFactory2 = NULL;
+ hr = m_dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2));
+ if (SUCCEEDED(hr) && dxgiFactory2)
{
- //wait for the scanline to go over the given proportion of m_screenHeight mark
- if (!rasterStatus.InVBlank && rasterStatus.ScanLine >= g_advancedSettings.m_sleepBeforeFlip * m_screenHeight)
- break;
+ // DirectX 11.1 or later
+ DXGI_SWAP_CHAIN_DESC1 scDesc1 = { 0 };
+ scDesc1.Width = m_nBackBufferWidth;
+ scDesc1.Height = m_nBackBufferHeight;
+ scDesc1.BufferCount = 2; // Use double buffering to minimize latency.
+ scDesc1.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ scDesc1.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ 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.SampleDesc.Count = 1;
+ scDesc1.SampleDesc.Quality = 0;
+
+ DXGI_SWAP_CHAIN_FULLSCREEN_DESC scFSDesc = { 0 };
+ scFSDesc.ScanlineOrdering = m_interlaced ? DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST : DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
+ scFSDesc.Windowed = m_useWindowedDX;
+
+ hr = dxgiFactory2->CreateSwapChainForHwnd(m_pD3DDev, m_hFocusWnd, &scDesc1, &scFSDesc, NULL, &m_pSwapChain1);
+
+ if (SUCCEEDED(hr))
+ {
+ m_pSwapChain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&m_pSwapChain));
+ m_bHWStereoEnabled = bHWStereoEnabled;
+ }
+ dxgiFactory2->Release();
- //in theory it's possible this loop never exits, so don't let it run for longer than 100 ms
- int64_t now = CurrentHostCounter();
- if ((now - prev) * 10 > m_systemFreq)
- break;
+ // this hackish way to disable stereo in windowed mode:
+ // - restart presenting, 0 in sync interval discards current frame also
+ // - wait until new frame will be drawn
+ // sleep value possible depends on hardware m.b. need a setting in as.xml
+ if (!bHWStereoEnabled && m_useWindowedDX && bNeedRecreate)
+ {
+ DXGI_PRESENT_PARAMETERS presentParams = {};
+ presentParams.DirtyRectsCount = 0;
+ presentParams.pDirtyRects = NULL;
+ presentParams.pScrollRect = NULL;
+ m_pSwapChain1->Present1(0, DXGI_PRESENT_RESTART, &presentParams);
- Sleep(1);
+ Sleep(100);
+ }
+ }
+ else
+ {
+ // DirectX 11.0 systems
+ scDesc.BufferCount = 2; // Use double buffering to minimize latency.
+ scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ scDesc.OutputWindow = m_hFocusWnd;
+ scDesc.Windowed = m_useWindowedDX;
+ scDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
+ scDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+
+ scDesc.BufferDesc.Width = m_nBackBufferWidth;
+ scDesc.BufferDesc.Height = m_nBackBufferHeight;
+ scDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ scDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+ scDesc.BufferDesc.ScanlineOrdering = m_interlaced ? DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST : DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
+ scDesc.SampleDesc.Count = 1;
+ scDesc.SampleDesc.Quality = 0;
+
+ hr = m_dxgiFactory->CreateSwapChain(m_pD3DDev, &scDesc, &m_pSwapChain);
}
- //restore thread priority
- if (priority != THREAD_PRIORITY_ERROR_RETURN)
- SetThreadPriority(GetCurrentThread(), priority);
+ if (FAILED(hr))
+ {
+ CLog::Log(LOGERROR, "%s - Creating swap chain failed with error: %s.", __FUNCTION__, GetErrorDescription(hr).c_str());
+ m_bRenderCreated = false;
+ return false;
+ }
+
+ // tell DXGI to not interfere with application's handling of window mode changes
+ m_dxgiFactory->MakeWindowAssociation(m_hFocusWnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER);
}
+ 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);
+ if (FAILED(hr))
+ {
+ CLog::Log(LOGERROR, "%s - Failed to resize buffers (%s).", __FUNCTION__, GetErrorDescription(hr).c_str());
+ if (DXGI_ERROR_DEVICE_REMOVED == hr)
+ OnDeviceLost();
- hr = m_pD3DDevice->Present( NULL, NULL, 0, NULL );
+ return false;
+ }
+ }
- if( D3DERR_DEVICELOST == hr )
+ // Create a render target view
+ ID3D11Texture2D* pBackBuffer = nullptr;
+ hr = m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer));
+ if (FAILED(hr))
{
- CLog::Log(LOGDEBUG, "%s - lost device", __FUNCTION__);
+ CLog::Log(LOGERROR, "%s - Failed to get back buffer (%s).", __FUNCTION__, GetErrorDescription(hr).c_str());
return false;
}
- if(FAILED(hr))
+ // Create a view interface on the rendertarget to use on bind for mono or left eye view.
+ CD3D11_RENDER_TARGET_VIEW_DESC rtDesc(D3D11_RTV_DIMENSION_TEXTURE2DARRAY, DXGI_FORMAT_UNKNOWN, 0, 0, 1);
+ hr = m_pD3DDev->CreateRenderTargetView(pBackBuffer, &rtDesc, &m_pRenderTargetView);
+ if (FAILED(hr))
{
- CLog::Log(LOGDEBUG, "%s - Present failed. %s", __FUNCTION__, GetErrorDescription(hr).c_str());
+ CLog::Log(LOGERROR, "%s - Failed to create render target view (%s).", __FUNCTION__, GetErrorDescription(hr).c_str());
+ pBackBuffer->Release();
return false;
}
- return true;
-}
+ if (m_bHWStereoEnabled)
+ {
+ // Stereo swapchains have an arrayed resource, so create a second Render Target for the right eye buffer.
+ CD3D11_RENDER_TARGET_VIEW_DESC rtDesc(D3D11_RTV_DIMENSION_TEXTURE2DARRAY, DXGI_FORMAT_UNKNOWN, 0, 1, 1);
+ hr = m_pD3DDev->CreateRenderTargetView(pBackBuffer, &rtDesc, &m_pRenderTargetViewRight);
+ if (FAILED(hr))
+ {
+ CLog::Log(LOGERROR, "%s - Failed to create right eye buffer (%s).", __FUNCTION__, GetErrorDescription(hr).c_str());
+ pBackBuffer->Release();
+ g_graphicsContext.SetStereoMode(RENDER_STEREO_MODE_OFF); // try fallback to mono
+ }
+ }
+ pBackBuffer->Release();
-bool CRenderSystemDX::BeginRender()
-{
- if (!m_bRenderCreated)
+ DXGI_FORMAT zFormat = DXGI_FORMAT_D16_UNORM;
+ if (IsFormatSupport(DXGI_FORMAT_D32_FLOAT, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL)) zFormat = DXGI_FORMAT_D32_FLOAT;
+ else if (IsFormatSupport(DXGI_FORMAT_D24_UNORM_S8_UINT, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL)) zFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ else if (IsFormatSupport(DXGI_FORMAT_D16_UNORM, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL)) zFormat = DXGI_FORMAT_D16_UNORM;
+
+ ID3D11Texture2D* depthStencilBuffer = NULL;
+ // Initialize the description of the depth buffer.
+ CD3D11_TEXTURE2D_DESC depthBufferDesc(zFormat, m_nBackBufferWidth, m_nBackBufferHeight, 1, 1, D3D11_BIND_DEPTH_STENCIL);
+ // Create the texture for the depth buffer using the filled out description.
+ hr = m_pD3DDev->CreateTexture2D(&depthBufferDesc, NULL, &depthStencilBuffer);
+ if (FAILED(hr))
+ {
+ CLog::Log(LOGERROR, "%s - Failed to create depth stencil buffer (%s).", __FUNCTION__, GetErrorDescription(hr).c_str());
return false;
+ }
- HRESULT oldStatus = m_nDeviceStatus;
- if (m_useD3D9Ex)
+ // Create the depth stencil view.
+ CD3D11_DEPTH_STENCIL_VIEW_DESC viewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
+ hr = m_pD3DDev->CreateDepthStencilView(depthStencilBuffer, &viewDesc, &m_depthStencilView);
+ depthStencilBuffer->Release();
+
+ if (FAILED(hr))
{
- m_nDeviceStatus = ((IDirect3DDevice9Ex*)m_pD3DDevice)->CheckDeviceState(m_hDeviceWnd);
+ CLog::Log(LOGERROR, "%s - Failed to create depth stencil view (%s).", __FUNCTION__, GetErrorDescription(hr).c_str());
+ return false;
+ }
- // handling of new D3D9 extensions return values. Others fallback to regular D3D9 handling.
- switch(m_nDeviceStatus)
- {
- case S_PRESENT_MODE_CHANGED:
- // Timing leads us here on occasion.
- BuildPresentParameters();
- m_nDeviceStatus = ((IDirect3DDevice9Ex*)m_pD3DDevice)->ResetEx(&m_D3DPP, m_D3DPP.Windowed ? NULL : &m_D3DDMEX);
- break;
- case S_PRESENT_OCCLUDED:
- m_nDeviceStatus = D3D_OK;
- break;
- case D3DERR_DEVICEHUNG:
- CLog::Log(LOGERROR, "D3DERR_DEVICEHUNG");
- m_nDeviceStatus = D3DERR_DEVICELOST;
- m_needNewDevice = true;
- break;
- case D3DERR_OUTOFVIDEOMEMORY:
- CLog::Log(LOGERROR, "D3DERR_OUTOFVIDEOMEMORY");
- m_nDeviceStatus = D3DERR_DEVICELOST;
- m_needNewDevice = true;
- break;
- case D3DERR_DEVICEREMOVED:
- CLog::Log(LOGERROR, "D3DERR_DEVICEREMOVED");
- m_nDeviceStatus = D3DERR_DEVICELOST;
- m_needNewDevice = true;
- // fixme: also needs to re-enumerate and switch to another screen
- break;
- }
+ if (m_viewPort.Height == 0 || m_viewPort.Width == 0)
+ {
+ CRect rect(0, 0, m_nBackBufferWidth, m_nBackBufferHeight);
+ SetViewPort(rect);
}
- else
+
+ // set camera to center of screen
+ CPoint camPoint = { m_nBackBufferWidth * 0.5f, m_nBackBufferHeight * 0.5f };
+ SetCameraPosition(camPoint, m_nBackBufferWidth, m_nBackBufferHeight);
+
+ CheckInterlasedStereoView();
+
+ if (bRestoreRTView)
+ m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, m_depthStencilView);
+
+ m_resizeInProgress = false;
+ m_bResizeRequred = false;
+
+ return true;
+}
+
+void CRenderSystemDX::CheckInterlasedStereoView(void)
+{
+ RENDER_STEREO_MODE stereoMode = g_graphicsContext.GetStereoMode();
+
+ if ( m_pRenderTargetViewRight
+ && RENDER_STEREO_MODE_INTERLACED != stereoMode
+ && RENDER_STEREO_MODE_CHECKERBOARD != stereoMode
+ && RENDER_STEREO_MODE_HARDWAREBASED != stereoMode)
{
- m_nDeviceStatus = m_pD3DDevice->TestCooperativeLevel();
+ // release resources
+ SAFE_RELEASE(m_pRenderTargetViewRight);
+ SAFE_RELEASE(m_pShaderResourceViewRight);
+ SAFE_RELEASE(m_pTextureRight);
}
- if( FAILED( m_nDeviceStatus ) )
+ if ( !m_pRenderTargetViewRight
+ && ( RENDER_STEREO_MODE_INTERLACED == stereoMode
+ || RENDER_STEREO_MODE_CHECKERBOARD == stereoMode))
{
- // The device has been lost but cannot be reset at this time.
- // Therefore, rendering is not possible and we'll have to return
- // and try again at a later time.
- if( m_nDeviceStatus == D3DERR_DEVICELOST )
+ // Create a second Render Target for the right eye buffer
+ HRESULT hr;
+ CD3D11_TEXTURE2D_DESC texDesc(DXGI_FORMAT_B8G8R8A8_UNORM, m_nBackBufferWidth, m_nBackBufferHeight, 1, 1,
+ D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
+ hr = m_pD3DDev->CreateTexture2D(&texDesc, NULL, &m_pTextureRight);
+ if (SUCCEEDED(hr))
{
- if (m_nDeviceStatus != oldStatus)
- CLog::Log(LOGDEBUG, "D3DERR_DEVICELOST");
- OnDeviceLost();
- return false;
- }
+ CD3D11_RENDER_TARGET_VIEW_DESC rtDesc(D3D11_RTV_DIMENSION_TEXTURE2D);
+ hr = m_pD3DDev->CreateRenderTargetView(m_pTextureRight, &rtDesc, &m_pRenderTargetViewRight);
- // The device has been lost but it can be reset at this time.
- if( m_nDeviceStatus == D3DERR_DEVICENOTRESET )
- {
- OnDeviceReset();
- if( FAILED(m_nDeviceStatus ) )
+ if (SUCCEEDED(hr))
{
- CLog::Log(LOGINFO, "m_pD3DDevice->Reset failed");
- return false;
+ CD3D11_SHADER_RESOURCE_VIEW_DESC srDesc(D3D11_SRV_DIMENSION_TEXTURE2D);
+ hr = m_pD3DDev->CreateShaderResourceView(m_pTextureRight, &srDesc, &m_pShaderResourceViewRight);
+
+ if (FAILED(hr))
+ CLog::Log(LOGERROR, "%s - Failed to create right view shader resource.", __FUNCTION__);
}
+ else
+ CLog::Log(LOGERROR, "%s - Failed to create right view render target.", __FUNCTION__);
+ }
+
+ if (FAILED(hr))
+ {
+ SAFE_RELEASE(m_pShaderResourceViewRight);
+ SAFE_RELEASE(m_pRenderTargetViewRight);
+ SAFE_RELEASE(m_pTextureRight);
+
+ CLog::Log(LOGERROR, "%s - Failed to create right eye buffer.", __FUNCTION__);
+ g_graphicsContext.SetStereoMode(RENDER_STEREO_MODE_OFF); // try fallback to mono
}
}
+}
+
+bool CRenderSystemDX::CreateStates()
+{
+ if (!m_pD3DDev)
+ return false;
+ SAFE_RELEASE(m_depthStencilState);
+ SAFE_RELEASE(m_BlendEnableState);
+ SAFE_RELEASE(m_BlendDisableState);
+
+ // Initialize the description of the stencil state.
+ D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
+ ZeroMemory(&depthStencilDesc, sizeof(D3D11_DEPTH_STENCIL_DESC));
+
+ // Set up the description of the stencil state.
+ depthStencilDesc.DepthEnable = false;
+ depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
+ depthStencilDesc.DepthFunc = D3D11_COMPARISON_NEVER;
+ depthStencilDesc.StencilEnable = false;
+ depthStencilDesc.StencilReadMask = 0xFF;
+ depthStencilDesc.StencilWriteMask = 0xFF;
+
+ // Stencil operations if pixel is front-facing.
+ depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
+ depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+
+ // Stencil operations if pixel is back-facing.
+ depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
+ depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+
+ // Create the depth stencil state.
+ HRESULT hr = m_pD3DDev->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
+ if(FAILED(hr))
+ return false;
+
+ // Set the depth stencil state.
+ m_pContext->OMSetDepthStencilState(m_depthStencilState, 0);
+
+ D3D11_RASTERIZER_DESC rasterizerState;
+ rasterizerState.CullMode = D3D11_CULL_BACK;
+ rasterizerState.FillMode = D3D11_FILL_SOLID;// DEBUG - D3D11_FILL_WIREFRAME
+ rasterizerState.FrontCounterClockwise = false;
+ rasterizerState.DepthBias = 0;
+ rasterizerState.DepthBiasClamp = 0.0f;
+ rasterizerState.DepthClipEnable = true;
+ rasterizerState.SlopeScaledDepthBias = 0.0f;
+ rasterizerState.ScissorEnable = false;
+ rasterizerState.MultisampleEnable = false;
+ rasterizerState.AntialiasedLineEnable = false;
+
+ if (FAILED(m_pD3DDev->CreateRasterizerState(&rasterizerState, &m_RSScissorDisable)))
+ return false;
+
+ rasterizerState.ScissorEnable = true;
+ if (FAILED(m_pD3DDev->CreateRasterizerState(&rasterizerState, &m_RSScissorEnable)))
+ return false;
+
+ m_pContext->RSSetState(m_RSScissorDisable); // by default
+
+ D3D11_BLEND_DESC blendState = { 0 };
+ ZeroMemory(&blendState, sizeof(D3D11_BLEND_DESC));
+ blendState.RenderTarget[0].BlendEnable = true;
+ blendState.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; // D3D11_BLEND_SRC_ALPHA;
+ blendState.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; // D3D11_BLEND_INV_SRC_ALPHA;
+ blendState.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
+ blendState.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
+ blendState.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
+ blendState.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ blendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
+
+ m_pD3DDev->CreateBlendState(&blendState, &m_BlendEnableState);
+
+ blendState.RenderTarget[0].BlendEnable = false;
+ m_pD3DDev->CreateBlendState(&blendState, &m_BlendDisableState);
+
+ // by default
+ m_pContext->OMSetBlendState(m_BlendEnableState, nullptr, 0xFFFFFFFF);
+ m_BlendEnabled = true;
+
+ return true;
+}
+
+bool CRenderSystemDX::PresentRenderImpl(const CDirtyRegionList &dirty)
+{
HRESULT hr;
- if(FAILED(hr = m_pD3DDevice->BeginScene()))
+ if (!m_bRenderCreated)
+ return false;
+
+ if (m_nDeviceStatus != S_OK)
+ return false;
+
+ if ( m_stereoMode == RENDER_STEREO_MODE_INTERLACED
+ || m_stereoMode == RENDER_STEREO_MODE_CHECKERBOARD)
+ {
+ // all views prepared, let's merge them before present
+ m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, m_depthStencilView);
+ CRect destRect = { 0.0f, 0.0f, float(m_nBackBufferWidth), float(m_nBackBufferHeight) };
+ SHADER_METHOD method = RENDER_STEREO_MODE_INTERLACED == m_stereoMode
+ ? SHADER_METHOD_RENDER_STEREO_INTERLACED_RIGHT
+ : SHADER_METHOD_RENDER_STEREO_CHECKERBOARD_RIGHT;
+ SetAlphaBlendEnable(true);
+ CD3DTexture::DrawQuad(destRect, 0, 1, &m_pShaderResourceViewRight, NULL, method);
+ CD3DHelper::PSClearShaderResources(m_pContext);
+ }
+
+ FinishCommandList();
+
+ if (m_pSwapChain1)
{
- CLog::Log(LOGERROR, "m_pD3DDevice->BeginScene() failed. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
- // When XBMC caught an exception after BeginScene(), EndScene() may never been called
- // and thus all following BeginScene() will fail too.
- if(FAILED(hr = m_pD3DDevice->EndScene()))
- CLog::Log(LOGERROR, "m_pD3DDevice->EndScene() failed. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
+ // will use optimized present with dirty regions.
+ DXGI_PRESENT_PARAMETERS presentParams = {};
+ presentParams.DirtyRectsCount = 0;
+ presentParams.pDirtyRects = NULL;
+ presentParams.pScrollRect = NULL;
+ hr = m_pSwapChain1->Present1((m_bVSync ? 1 : 0), 0, &presentParams);
+ }
+ else
+ hr = m_pSwapChain->Present((m_bVSync ? 1 : 0), 0);
+
+ if (DXGI_ERROR_DEVICE_REMOVED == hr)
+ {
+ CLog::Log(LOGDEBUG, "%s - device removed", __FUNCTION__);
return false;
}
- IDirect3DSurface9 *pBackBuffer;
- if(m_pD3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer) != D3D_OK)
+ if (DXGI_ERROR_INVALID_CALL == hr)
+ {
+ m_bResizeRequred = true;
+ if (CreateWindowSizeDependentResources())
+ return true;
+ }
+
+ if (FAILED(hr))
+ {
+ CLog::Log(LOGDEBUG, "%s - Present failed. %s", __FUNCTION__, GetErrorDescription(hr).c_str());
return false;
+ }
- m_pD3DDevice->SetRenderTarget(0, pBackBuffer);
- pBackBuffer->Release();
+ return true;
+}
+
+bool CRenderSystemDX::BeginRender()
+{
+ if (!m_bRenderCreated)
+ return false;
+
+ HRESULT oldStatus = m_nDeviceStatus;
+ if (m_pSwapChain1)
+ {
+ DXGI_PRESENT_PARAMETERS presentParams = {};
+ presentParams.DirtyRectsCount = 0;
+ presentParams.pDirtyRects = NULL;
+ presentParams.pScrollRect = NULL;
+ m_nDeviceStatus = m_pSwapChain1->Present1(0, DXGI_PRESENT_TEST, &presentParams);
+ }
+ else
+ {
+ m_nDeviceStatus = m_pSwapChain->Present(0, DXGI_PRESENT_TEST);
+ }
+ // handling of return values.
+ switch (m_nDeviceStatus)
+ {
+ case DXGI_ERROR_DEVICE_REMOVED: // GPU has been physically removed from the system, or a driver upgrade occurred.
+ CLog::Log(LOGERROR, "DXGI_ERROR_DEVICE_REMOVED");
+ m_needNewDevice = true;
+ break;
+ case DXGI_ERROR_DEVICE_RESET: // This is an run-time issue that should be investigated and fixed.
+ CLog::Log(LOGERROR, "DXGI_ERROR_DEVICE_RESET");
+ m_nDeviceStatus = DXGI_ERROR_DEVICE_REMOVED;
+ m_needNewDevice = true;
+ 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;
+ break;
+ case DXGI_STATUS_OCCLUDED: // decide what we should do when windows content is not visible
+ // do not spam to log file
+ if (m_nDeviceStatus != oldStatus)
+ CLog::Log(LOGDEBUG, "DXGI_STATUS_OCCLUDED");
+ // Status OCCLUDED is not an error and not handled by FAILED macro,
+ // but if it occurs we should not render anything, so just return false
+ return false;
+ }
+
+ if (FAILED(m_nDeviceStatus))
+ {
+ if (DXGI_ERROR_DEVICE_REMOVED == m_nDeviceStatus)
+ {
+ OnDeviceLost();
+ }
+ return false;
+ }
+
+ m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, m_depthStencilView);
m_inScene = true;
+
return true;
}
if (!m_bRenderCreated)
return false;
-
+
if(m_nDeviceStatus != S_OK)
return false;
- HRESULT hr = m_pD3DDevice->EndScene();
- if(FAILED(hr))
- {
- CLog::Log(LOGERROR, "m_pD3DDevice->EndScene() failed. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
- return false;
- }
-
return true;
}
bool CRenderSystemDX::ClearBuffers(color_t color)
{
- if (!m_bRenderCreated)
+ if (!m_bRenderCreated || m_resizeInProgress)
return false;
- if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
- || m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA
- || m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE)
+ float fColor[4];
+ CD3DHelper::XMStoreColor(fColor, color);
+
+ // Unlike Direct3D 9, the full extent of the resource view is always cleared. Viewport and scissor settings are not applied.
+ if ( m_stereoMode != RENDER_STEREO_MODE_OFF
+ && m_stereoMode != RENDER_STEREO_MODE_MONO)
{
- // if stereo anaglyph, data was cleared when left view was rendererd
- if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
- return true;
- }
+ // if stereo anaglyph/tab/sbs, data was cleared when left view was rendererd
+ if (m_stereoView == RENDER_STEREO_VIEW_RIGHT)
+ {
+ // execute command's queue
+ if ( m_stereoMode != RENDER_STEREO_MODE_SPLIT_HORIZONTAL
+ && m_stereoMode != RENDER_STEREO_MODE_SPLIT_VERTICAL)
+ FinishCommandList();
- return SUCCEEDED(m_pD3DDevice->Clear(
- 0,
- NULL,
- D3DCLEAR_TARGET,
- color,
- 1.0,
- 0 ) );
+ // for interlaced/checkerboard/hw clear right view
+ if (m_pRenderTargetViewRight)
+ m_pContext->ClearRenderTargetView(m_pRenderTargetViewRight, fColor);
+ // for hw stereo clear depth view also
+ if (m_stereoMode == RENDER_STEREO_MODE_HARDWAREBASED)
+ m_pContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0, 0);
+
+ return true;
+ }
+ }
+
+ m_pContext->ClearRenderTargetView(m_pRenderTargetView, fColor);
+ m_pContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0, 0);
return true;
}
bool CRenderSystemDX::PresentRender(const CDirtyRegionList &dirty)
{
- if (!m_bRenderCreated)
+ if (!m_bRenderCreated || m_resizeInProgress)
return false;
bool result = PresentRenderImpl(dirty);
void CRenderSystemDX::SetVSync(bool enable)
{
- if (m_bVSync != enable)
- {
- bool inScene(m_inScene);
- if (m_inScene)
- EndRender();
- m_bVSync = enable;
- ResetRenderSystem(m_nBackBufferWidth, m_nBackBufferHeight, m_bFullScreenDevice, m_refreshRate);
- if (inScene)
- BeginRender();
- }
+ m_bVSync = enable;
}
void CRenderSystemDX::CaptureStateBlock()
{
if (!m_bRenderCreated)
return;
-
- SAFE_RELEASE(m_stateBlock);
- m_pD3DDevice->CreateStateBlock(D3DSBT_ALL, &m_stateBlock);
}
void CRenderSystemDX::ApplyStateBlock()
if (!m_bRenderCreated)
return;
- if (m_stateBlock)
- m_stateBlock->Apply();
+ m_pContext->RSSetState(m_ScissorsEnabled ? m_RSScissorEnable : m_RSScissorDisable);
+ m_pContext->OMSetDepthStencilState(m_depthStencilState, 0);
+ float factors[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ m_pContext->OMSetBlendState(m_BlendEnabled ? m_BlendEnableState : m_BlendDisableState, factors, 0xFFFFFFFF);
+
+ m_pGUIShader->ApplyStateBlock();
}
void CRenderSystemDX::SetCameraPosition(const CPoint &camera, int screenWidth, int screenHeight)
float w = m_viewPort.Width*0.5f;
float h = m_viewPort.Height*0.5f;
- CPoint offset = camera - CPoint(screenWidth*0.5f, screenHeight*0.5f);
+ XMFLOAT2 offset = XMFLOAT2(camera.x - screenWidth*0.5f, camera.y - screenHeight*0.5f);
- // world view. Until this is moved onto the GPU (via a vertex shader for instance), we set it to the identity
- // here.
- D3DXMATRIX mtxWorld;
- D3DXMatrixIdentity(&mtxWorld);
- m_pD3DDevice->SetTransform(D3DTS_WORLD, &mtxWorld);
+ // world view. Until this is moved onto the GPU (via a vertex shader for instance), we set it to the identity here.
+ m_pGUIShader->SetWorld(XMMatrixIdentity());
+ // Initialize the view matrix
// camera view. Multiply the Y coord by -1 then translate so that everything is relative to the camera
// position.
- D3DXMATRIX flipY, translate, mtxView;
- D3DXMatrixScaling(&flipY, 1.0f, -1.0f, 1.0f);
- D3DXMatrixTranslation(&translate, -(w + offset.x), -(h + offset.y), 2*h);
- D3DXMatrixMultiply(&mtxView, &translate, &flipY);
- m_pD3DDevice->SetTransform(D3DTS_VIEW, &mtxView);
+ XMMATRIX flipY, translate;
+ flipY = XMMatrixScaling(1.0, -1.0f, 1.0f);
+ translate = XMMatrixTranslation(-(w + offset.x), -(h + offset.y), 2 * h);
+ m_pGUIShader->SetView(XMMatrixMultiply(translate, flipY));
// projection onto screen space
- D3DXMATRIX mtxProjection;
- D3DXMatrixPerspectiveOffCenterLH(&mtxProjection, (-w - offset.x)*0.5f, (w - offset.x)*0.5f, (-h + offset.y)*0.5f, (h + offset.y)*0.5f, h, 100*h);
- m_pD3DDevice->SetTransform(D3DTS_PROJECTION, &mtxProjection);
-
- m_world = mtxWorld;
- m_view = mtxView;
- m_projection = mtxProjection;
+ 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));
}
void CRenderSystemDX::Project(float &x, float &y, float &z)
{
- D3DXVECTOR3 vScreenCoord;
- D3DXVECTOR3 vLocation(x, y, z);
-
- D3DXVec3Project(&vScreenCoord, &vLocation, &m_viewPort, &m_projection, &m_view, &m_world);
- x = vScreenCoord.x;
- y = vScreenCoord.y;
- z = 0;
+ m_pGUIShader->Project(x, y, z);
}
bool CRenderSystemDX::TestRender()
{
+ /*
static unsigned int lastTime = 0;
static float delta = 0;
m_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );
pVB->Release();
-
+ */
return true;
}
if (!m_bRenderCreated)
return;
- viewPort.x1 = (float)m_viewPort.X;
- viewPort.y1 = (float)m_viewPort.Y;
- viewPort.x2 = (float)m_viewPort.X + m_viewPort.Width;
- viewPort.y2 = (float)m_viewPort.Y + m_viewPort.Height;
+ viewPort.x1 = m_viewPort.TopLeftX;
+ viewPort.y1 = m_viewPort.TopLeftY;
+ viewPort.x2 = m_viewPort.TopLeftX + m_viewPort.Width;
+ viewPort.y2 = m_viewPort.TopLeftY + m_viewPort.Height;
}
void CRenderSystemDX::SetViewPort(CRect& viewPort)
if (!m_bRenderCreated)
return;
- m_viewPort.MinZ = 0.0f;
- m_viewPort.MaxZ = 1.0f;
- m_viewPort.X = (DWORD)viewPort.x1;
- m_viewPort.Y = (DWORD)viewPort.y1;
- m_viewPort.Width = (DWORD)(viewPort.x2 - viewPort.x1);
- m_viewPort.Height = (DWORD)(viewPort.y2 - viewPort.y1);
- m_pD3DDevice->SetViewport(&m_viewPort);
+ m_viewPort.MinDepth = 0.0f;
+ m_viewPort.MaxDepth = 1.0f;
+ m_viewPort.TopLeftX = viewPort.x1;
+ m_viewPort.TopLeftY = viewPort.y1;
+ m_viewPort.Width = viewPort.x2 - viewPort.x1;
+ m_viewPort.Height = viewPort.y2 - viewPort.y1;
+
+ m_pContext->RSSetViewports(1, &m_viewPort);
+ m_pGUIShader->SetViewPort(m_viewPort);
}
void CRenderSystemDX::RestoreViewPort()
if (!m_bRenderCreated)
return;
- m_pD3DDevice->SetViewport(&m_viewPort);
+ m_pContext->RSSetViewports(1, &m_viewPort);
+ m_pGUIShader->SetViewPort(m_viewPort);
+}
+
+bool CRenderSystemDX::ScissorsCanEffectClipping()
+{
+ return m_pGUIShader != NULL && m_pGUIShader->HardwareClipIsPossible();
+}
+
+CRect CRenderSystemDX::ClipRectToScissorRect(const CRect &rect)
+{
+ if (!m_bRenderCreated)
+ return CRect();
+
+ float xFactor = m_pGUIShader->GetClipXFactor();
+ float xOffset = m_pGUIShader->GetClipXOffset();
+ float yFactor = m_pGUIShader->GetClipYFactor();
+ float yOffset = m_pGUIShader->GetClipYOffset();
+
+ return CRect(rect.x1 * xFactor + xOffset,
+ rect.y1 * yFactor + yOffset,
+ rect.x2 * xFactor + xOffset,
+ rect.y2 * yFactor + yOffset);
}
void CRenderSystemDX::SetScissors(const CRect& rect)
if (!m_bRenderCreated)
return;
- RECT scissor;
+ D3D11_RECT scissor;
scissor.left = MathUtils::round_int(rect.x1);
scissor.top = MathUtils::round_int(rect.y1);
scissor.right = MathUtils::round_int(rect.x2);
scissor.bottom = MathUtils::round_int(rect.y2);
- m_pD3DDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
- m_pD3DDevice->SetScissorRect(&scissor);
+
+ m_pContext->RSSetState(m_RSScissorEnable);
+ m_ScissorsEnabled = true;
+ m_pContext->RSSetScissorRects(1, &scissor);
}
void CRenderSystemDX::ResetScissors()
if (!m_bRenderCreated)
return;
- RECT scissor;
+ D3D11_RECT scissor;
scissor.left = 0;
scissor.top = 0;
scissor.right = m_nBackBufferWidth;
scissor.bottom = m_nBackBufferHeight;
- m_pD3DDevice->SetScissorRect(&scissor);
- m_pD3DDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+
+ m_pContext->RSSetScissorRects(1, &scissor);
+ m_pContext->RSSetState(m_RSScissorDisable);
+ m_ScissorsEnabled = false;
}
void CRenderSystemDX::Register(ID3DResource *resource)
void CRenderSystemDX::Unregister(ID3DResource* resource)
{
CSingleLock lock(m_resourceSection);
- vector<ID3DResource*>::iterator i = find(m_resources.begin(), m_resources.end(), resource);
+ std::vector<ID3DResource*>::iterator i = find(m_resources.begin(), m_resources.end(), resource);
if (i != m_resources.end())
m_resources.erase(i);
}
std::string CRenderSystemDX::GetErrorDescription(HRESULT hr)
{
- return StringUtils::Format("%X - %s (%s)", hr, DXGetErrorString(hr), DXGetErrorDescription(hr));
+ WCHAR buff[1024];
+ DXGetErrorDescription(hr, buff, 1024);
+ std::wstring error(DXGetErrorString(hr));
+ std::wstring descr(buff);
+ return StringUtils::Format("%X - %ls (%ls)", hr, error.c_str(), descr.c_str());
}
void CRenderSystemDX::SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view)
{
CRenderSystemBase::SetStereoMode(mode, view);
- m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN);
+ if (!m_bRenderCreated)
+ return;
+
+ UINT writeMask = D3D11_COLOR_WRITE_ENABLE_ALL;
if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN)
{
if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
- m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED );
+ writeMask = D3D11_COLOR_WRITE_ENABLE_RED;
else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
- m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN );
+ writeMask = D3D11_COLOR_WRITE_ENABLE_BLUE | D3D11_COLOR_WRITE_ENABLE_GREEN;
}
if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA)
{
if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
- m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN );
+ writeMask = D3D11_COLOR_WRITE_ENABLE_GREEN;
else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
- m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_RED );
+ writeMask = D3D11_COLOR_WRITE_ENABLE_BLUE | D3D11_COLOR_WRITE_ENABLE_RED;
}
- if(m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE)
+ if (m_stereoMode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE)
{
- if(m_stereoView == RENDER_STEREO_VIEW_LEFT)
- m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN);
- else if(m_stereoView == RENDER_STEREO_VIEW_RIGHT)
- m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_BLUE);
+ if (m_stereoView == RENDER_STEREO_VIEW_LEFT)
+ writeMask = D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN;
+ else if (m_stereoView == RENDER_STEREO_VIEW_RIGHT)
+ writeMask = D3D11_COLOR_WRITE_ENABLE_BLUE;
+ }
+ if ( RENDER_STEREO_MODE_INTERLACED == m_stereoMode
+ || RENDER_STEREO_MODE_CHECKERBOARD == m_stereoMode
+ || RENDER_STEREO_MODE_HARDWAREBASED == m_stereoMode)
+ {
+ if (m_stereoView == RENDER_STEREO_VIEW_RIGHT)
+ {
+ // render right eye view to right render target
+ m_pContext->OMSetRenderTargets(1, &m_pRenderTargetViewRight, m_depthStencilView);
+ }
+ }
+
+ D3D11_BLEND_DESC desc;
+ m_BlendEnableState->GetDesc(&desc);
+ // update blend state
+ if (desc.RenderTarget[0].RenderTargetWriteMask != writeMask)
+ {
+ SAFE_RELEASE(m_BlendDisableState);
+ SAFE_RELEASE(m_BlendEnableState);
+
+ desc.RenderTarget[0].RenderTargetWriteMask = writeMask;
+ m_pD3DDev->CreateBlendState(&desc, &m_BlendEnableState);
+
+ desc.RenderTarget[0].BlendEnable = false;
+ m_pD3DDev->CreateBlendState(&desc, &m_BlendDisableState);
+
+ float blendFactors[] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ m_pContext->OMSetBlendState(m_BlendEnabled ? m_BlendEnableState : m_BlendDisableState, blendFactors, 0xFFFFFFFF);
}
}
bool CRenderSystemDX::SupportsStereo(RENDER_STEREO_MODE mode) const
{
- switch(mode)
+ bool isHWStereoSupport = false;
+ IDXGIFactory2* dxgiFactory2 = NULL;
+ if (SUCCEEDED(m_dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2))))
+ {
+ isHWStereoSupport = dxgiFactory2 && dxgiFactory2->IsWindowedStereoEnabled();
+ }
+ SAFE_RELEASE(dxgiFactory2);
+
+ switch (mode)
{
case RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN:
case RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA:
case RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE:
+ case RENDER_STEREO_MODE_INTERLACED:
+ case RENDER_STEREO_MODE_CHECKERBOARD:
return true;
+ case RENDER_STEREO_MODE_HARDWAREBASED:
+ return isHWStereoSupport;
default:
return CRenderSystemBase::SupportsStereo(mode);
}
void CRenderSystemDX::FlushGPU()
{
- IDirect3DQuery9* pEvent = NULL;
+ FinishCommandList();
+ m_pImdContext->Flush();
+}
+
+bool CRenderSystemDX::InitGUIShader()
+{
+ if (!m_pD3DDev)
+ return false;
- m_pD3DDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEvent);
- if (pEvent != NULL)
+ SAFE_DELETE(m_pGUIShader);
+ m_pGUIShader = new CGUIShaderDX();
+ if (!m_pGUIShader->Initialize())
{
- pEvent->Issue(D3DISSUE_END);
- while (S_FALSE == pEvent->GetData(NULL, 0, D3DGETDATA_FLUSH))
- Sleep(1);
+ CLog::Log(LOGERROR, __FUNCTION__ " - Failed to initialize GUI shader.");
+ return false;
}
+
+ m_pGUIShader->ApplyStateBlock();
+
+ return true;
+}
+
+void CRenderSystemDX::SetAlphaBlendEnable(bool enable)
+{
+ if (!m_bRenderCreated)
+ return;
+
+ float blendFactors[] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ m_pContext->OMSetBlendState(enable ? m_BlendEnableState : m_BlendDisableState, 0, 0xFFFFFFFF);
+ m_BlendEnabled = enable;
+}
+
+void CRenderSystemDX::FinishCommandList(bool bExecute /*= true*/)
+{
+ if (m_pImdContext == m_pContext)
+ return;
+
+ ID3D11CommandList* pCommandList = NULL;
+ if (FAILED(m_pContext->FinishCommandList(true, &pCommandList)))
+ {
+ CLog::Log(LOGERROR, "%s - Failed to finish command queue.", __FUNCTION__);
+ return;
+ }
+
+ if (bExecute)
+ m_pImdContext->ExecuteCommandList(pCommandList, false);
+
+ SAFE_RELEASE(pCommandList);
}
#endif