Files
bullet3/Extras/CDTestFramework/AntTweakBar/src/TwDirect3D11.cpp
erwin.coumans 4442a826ed add commandline arguments to serialize demo for xml export and Bullet import file name
update AntTweakBar version in CDTestFramework
add btCompoundShape support in BulletXmlWorldImporter (this importer is still premature/work-in-progress)
2012-09-26 19:47:18 +00:00

1654 lines
58 KiB
C++

// ---------------------------------------------------------------------------
//
// @file TwDirect3D11.cpp
// @author Philippe Decaudin - http://www.antisphere.com
// @license This file is part of the AntTweakBar library.
// For conditions of distribution and use, see License.txt
//
// ---------------------------------------------------------------------------
#include "TwPrecomp.h"
#include "TwDirect3D11.h"
#include "TwMgr.h"
#include "TwColors.h"
#include "d3d10vs2003.h" // Workaround to include D3D10.h and D3D11.h with VS2003
#define D3D11_IGNORE_SDK_LAYERS // d3d11sdklayers.h may not exist
#include <d3d11.h>
using namespace std;
const char *g_ErrCantLoadD3D11 = "Cannot load Direct3D11 library dynamically";
const char *g_ErrCreateVS11 = "Direct3D11 vertex shader creation failed";
const char *g_ErrCreatePS11 = "Direct3D11 pixel shader creation failed";
const char *g_ErrCreateLayout11 = "Direct3D11 vertex layout creation failed";
const char *g_ErrCreateBuffer11 = "Direct3D11 vertex buffer creation failed";
const char *g_ErrCreateSampler11 = "Direct3D11 sampler state creation failed";
// ---------------------------------------------------------------------------
// Shaders : In order to avoid linkage with D3DX11 or D3DCompile libraries,
// vertex and pixel shaders are compiled offline in a pre-build step using
// the fxc.exe compiler (from the DirectX SDK Aug'09 or later)
#ifdef _WIN64
# ifdef _DEBUG
# include "debug64\TwDirect3D11_LineRectVS.h"
# include "debug64\TwDirect3D11_LineRectCstColorVS.h"
# include "debug64\TwDirect3D11_LineRectPS.h"
# include "debug64\TwDirect3D11_TextVS.h"
# include "debug64\TwDirect3D11_TextCstColorVS.h"
# include "debug64\TwDirect3D11_TextPS.h"
# else
# include "release64\TwDirect3D11_LineRectVS.h"
# include "release64\TwDirect3D11_LineRectCstColorVS.h"
# include "release64\TwDirect3D11_LineRectPS.h"
# include "release64\TwDirect3D11_TextVS.h"
# include "release64\TwDirect3D11_TextCstColorVS.h"
# include "release64\TwDirect3D11_TextPS.h"
# endif
#else
# ifdef _DEBUG
# include "debug32\TwDirect3D11_LineRectVS.h"
# include "debug32\TwDirect3D11_LineRectCstColorVS.h"
# include "debug32\TwDirect3D11_LineRectPS.h"
# include "debug32\TwDirect3D11_TextVS.h"
# include "debug32\TwDirect3D11_TextCstColorVS.h"
# include "debug32\TwDirect3D11_TextPS.h"
# else
# include "release32\TwDirect3D11_LineRectVS.h"
# include "release32\TwDirect3D11_LineRectCstColorVS.h"
# include "release32\TwDirect3D11_LineRectPS.h"
# include "release32\TwDirect3D11_TextVS.h"
# include "release32\TwDirect3D11_TextCstColorVS.h"
# include "release32\TwDirect3D11_TextPS.h"
# endif
#endif
// ---------------------------------------------------------------------------
const RECT FullRect = {0, 0, 16000, 16000};
static bool RectIsFull(const RECT& r) { return r.left==FullRect.left && r.right==FullRect.right && r.top==FullRect.top && r.bottom==FullRect.bottom; }
// ---------------------------------------------------------------------------
static void BindFont(ID3D11Device *_Dev, const CTexFont *_Font, ID3D11Texture2D **_Tex, ID3D11ShaderResourceView **_TexRV)
{
assert(_Font!=NULL);
*_Tex = NULL;
*_TexRV = NULL;
int w = _Font->m_TexWidth;
int h = _Font->m_TexHeight;
color32 *font32 = new color32[w*h];
color32 *p = font32;
for( int i=0; i<w*h; ++i, ++p )
*p = 0x00ffffff | (((color32)(_Font->m_TexBytes[i]))<<24);
D3D11_TEXTURE2D_DESC desc;
desc.Width = w;
desc.Height = h;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_IMMUTABLE;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA data;
data.pSysMem = font32;
data.SysMemPitch = w*sizeof(color32);
data.SysMemSlicePitch = 0;
if( SUCCEEDED(_Dev->CreateTexture2D(&desc, &data, _Tex)) )
_Dev->CreateShaderResourceView(*_Tex, NULL, _TexRV);
delete[] font32;
}
// ---------------------------------------------------------------------------
static void UnbindFont(ID3D11Device *_Dev, ID3D11Texture2D *_Tex, ID3D11ShaderResourceView *_TexRV)
{
(void)_Dev;
if( _TexRV )
{
ULONG rc = _TexRV->Release();
assert( rc==0 ); (void)rc;
}
if( _Tex )
{
ULONG rc = _Tex->Release();
assert( rc==0 ); (void)rc;
}
}
// ---------------------------------------------------------------------------
struct CState11
{
ID3D11ComputeShader * m_CSShader;
ID3D11ClassInstance ** m_CSClassInstances;
UINT m_CSNumClassInstances;
ID3D11DomainShader * m_DSShader;
ID3D11ClassInstance ** m_DSClassInstances;
UINT m_DSNumClassInstances;
ID3D11GeometryShader * m_GSShader;
ID3D11ClassInstance ** m_GSClassInstances;
UINT m_GSNumClassInstances;
ID3D11HullShader * m_HSShader;
ID3D11ClassInstance ** m_HSClassInstances;
UINT m_HSNumClassInstances;
ID3D11PixelShader * m_PSShader;
ID3D11ClassInstance ** m_PSClassInstances;
UINT m_PSNumClassInstances;
ID3D11Buffer * m_PSConstantBuffer; // backup the first constant buffer only
ID3D11SamplerState * m_PSSampler; // backup the first sampler only
ID3D11ShaderResourceView*m_PSShaderResourceView; // backup the first shader resource only
ID3D11VertexShader * m_VSShader;
ID3D11ClassInstance ** m_VSClassInstances;
UINT m_VSNumClassInstances;
ID3D11Buffer * m_VSConstantBuffer; // backup the first constant buffer only
ID3D11Buffer * m_IAIndexBuffer;
DXGI_FORMAT m_IAIndexBufferFormat;
UINT m_IAIndexBufferOffset;
ID3D11InputLayout * m_IAInputLayout;
D3D11_PRIMITIVE_TOPOLOGY m_IATopology;
ID3D11Buffer * m_IAVertexBuffer; // backup the first buffer only
UINT m_IAVertexBufferStride;
UINT m_IAVertexBufferOffset;
ID3D11BlendState * m_OMBlendState;
FLOAT m_OMBlendFactor[4];
UINT m_OMSampleMask;
ID3D11DepthStencilState*m_OMDepthStencilState;
UINT m_OMStencilRef;
UINT m_RSScissorNumRects;
D3D11_RECT m_RSScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
ID3D11RasterizerState * m_RSRasterizerState;
UINT m_RSNumViewports;
D3D11_VIEWPORT m_RSViewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
void Save();
void Restore();
void Release();
CState11(ID3D11Device *_Dev, ID3D11DeviceContext *_ImmCtx);
~CState11();
private:
ID3D11Device * m_D3DDev;
ID3D11DeviceContext * m_D3DDevImmContext;
};
CState11::CState11(ID3D11Device *_Dev, ID3D11DeviceContext *_ImmCtx)
{
ZeroMemory(this, sizeof(CState11));
m_D3DDev = _Dev;
m_D3DDevImmContext = _ImmCtx;
}
CState11::~CState11()
{
Release();
m_D3DDev = NULL;
m_D3DDevImmContext = NULL;
}
void CState11::Save()
{
// Release previous state if needed
Release();
// Save shaders.
// Not sure how xxGetShader works, D3D11 doc is evasive... Attempt:
// First call GetShader with NULL ClassInstances to get the number of class instances.
// Second, if not zero allocate an array of class instances and call GetShader again
// with this array ptr to get the class instances and release the shader since its
// ref count has been incremented a second time.
m_CSShader = NULL;
m_CSClassInstances = NULL;
m_CSNumClassInstances = 0;
m_D3DDevImmContext->CSGetShader(&m_CSShader, NULL, &m_CSNumClassInstances);
if (m_CSNumClassInstances > 0)
{
m_CSClassInstances = new ID3D11ClassInstance*[m_CSNumClassInstances];
for (UINT i = 0; i < m_CSNumClassInstances; i++)
m_CSClassInstances[i] = NULL;
m_D3DDevImmContext->CSGetShader(&m_CSShader, m_CSClassInstances, &m_CSNumClassInstances);
if (m_CSShader != NULL)
m_CSShader->Release();
}
m_DSShader = NULL;
m_DSClassInstances = NULL;
m_DSNumClassInstances = 0;
m_D3DDevImmContext->DSGetShader(&m_DSShader, NULL, &m_DSNumClassInstances);
if (m_DSNumClassInstances > 0)
{
m_DSClassInstances = new ID3D11ClassInstance*[m_DSNumClassInstances];
for (UINT i = 0; i < m_DSNumClassInstances; i++)
m_DSClassInstances[i] = NULL;
m_D3DDevImmContext->DSGetShader(&m_DSShader, m_DSClassInstances, &m_DSNumClassInstances);
if (m_DSShader != NULL)
m_DSShader->Release();
}
m_GSShader = NULL;
m_GSClassInstances = NULL;
m_GSNumClassInstances = 0;
m_D3DDevImmContext->GSGetShader(&m_GSShader, NULL, &m_GSNumClassInstances);
if (m_GSNumClassInstances > 0)
{
m_GSClassInstances = new ID3D11ClassInstance*[m_GSNumClassInstances];
for (UINT i = 0; i < m_GSNumClassInstances; i++)
m_GSClassInstances[i] = NULL;
m_D3DDevImmContext->GSGetShader(&m_GSShader, m_GSClassInstances, &m_GSNumClassInstances);
if (m_GSShader != NULL)
m_GSShader->Release();
}
m_HSShader = NULL;
m_HSClassInstances = NULL;
m_HSNumClassInstances = 0;
m_D3DDevImmContext->HSGetShader(&m_HSShader, NULL, &m_HSNumClassInstances);
if (m_HSNumClassInstances > 0)
{
m_HSClassInstances = new ID3D11ClassInstance*[m_HSNumClassInstances];
for (UINT i = 0; i < m_HSNumClassInstances; i++)
m_HSClassInstances[i] = NULL;
m_D3DDevImmContext->HSGetShader(&m_HSShader, m_HSClassInstances, &m_HSNumClassInstances);
if (m_HSShader != NULL)
m_HSShader->Release();
}
m_PSShader = NULL;
m_PSClassInstances = NULL;
m_PSNumClassInstances = 0;
m_D3DDevImmContext->PSGetShader(&m_PSShader, NULL, &m_PSNumClassInstances);
if (m_PSNumClassInstances > 0)
{
m_PSClassInstances = new ID3D11ClassInstance*[m_PSNumClassInstances];
for (UINT i = 0; i < m_PSNumClassInstances; i++)
m_PSClassInstances[i] = NULL;
m_D3DDevImmContext->PSGetShader(&m_PSShader, m_PSClassInstances, &m_PSNumClassInstances);
if (m_PSShader != NULL)
m_PSShader->Release();
}
m_D3DDevImmContext->PSGetConstantBuffers(0, 1, &m_PSConstantBuffer);
m_D3DDevImmContext->PSGetSamplers(0, 1, &m_PSSampler);
m_D3DDevImmContext->PSGetShaderResources(0, 1, &m_PSShaderResourceView);
m_VSShader = NULL;
m_VSClassInstances = NULL;
m_VSNumClassInstances = 0;
m_D3DDevImmContext->VSGetShader(&m_VSShader, NULL, &m_VSNumClassInstances);
if (m_VSNumClassInstances > 0)
{
m_VSClassInstances = new ID3D11ClassInstance*[m_VSNumClassInstances];
for (UINT i = 0; i < m_VSNumClassInstances; i++)
m_VSClassInstances[i] = NULL;
m_D3DDevImmContext->VSGetShader(&m_VSShader, m_VSClassInstances, &m_VSNumClassInstances);
if (m_VSShader != NULL)
m_VSShader->Release();
}
m_D3DDevImmContext->VSGetConstantBuffers(0, 1, &m_VSConstantBuffer);
// Save Input-Assembler states
m_D3DDevImmContext->IAGetIndexBuffer(&m_IAIndexBuffer, &m_IAIndexBufferFormat, &m_IAIndexBufferOffset);
m_D3DDevImmContext->IAGetInputLayout(&m_IAInputLayout);
m_D3DDevImmContext->IAGetPrimitiveTopology(&m_IATopology);
m_D3DDevImmContext->IAGetVertexBuffers(0, 1, &m_IAVertexBuffer, &m_IAVertexBufferStride, &m_IAVertexBufferOffset);
// Save Ouput-Merger states
m_D3DDevImmContext->OMGetBlendState(&m_OMBlendState, m_OMBlendFactor, &m_OMSampleMask);
m_D3DDevImmContext->OMGetDepthStencilState(&m_OMDepthStencilState, &m_OMStencilRef);
// Save Rasterizer states
m_D3DDevImmContext->RSGetScissorRects(&m_RSScissorNumRects, NULL);
if (m_RSScissorNumRects > 0)
m_D3DDevImmContext->RSGetScissorRects(&m_RSScissorNumRects, m_RSScissorRects);
m_D3DDevImmContext->RSGetViewports(&m_RSNumViewports, NULL);
if (m_RSNumViewports > 0)
m_D3DDevImmContext->RSGetViewports(&m_RSNumViewports, m_RSViewports);
m_D3DDevImmContext->RSGetState(&m_RSRasterizerState);
}
void CState11::Restore()
{
// Restore shaders
m_D3DDevImmContext->CSSetShader(m_CSShader, m_CSClassInstances, m_CSNumClassInstances);
m_D3DDevImmContext->DSSetShader(m_DSShader, m_DSClassInstances, m_DSNumClassInstances);
m_D3DDevImmContext->GSSetShader(m_GSShader, m_GSClassInstances, m_GSNumClassInstances);
m_D3DDevImmContext->HSSetShader(m_HSShader, m_HSClassInstances, m_HSNumClassInstances);
m_D3DDevImmContext->PSSetShader(m_PSShader, m_PSClassInstances, m_PSNumClassInstances);
m_D3DDevImmContext->PSSetConstantBuffers(0, 1, &m_PSConstantBuffer);
m_D3DDevImmContext->PSSetSamplers(0, 1, &m_PSSampler);
m_D3DDevImmContext->PSSetShaderResources(0, 1, &m_PSShaderResourceView);
m_D3DDevImmContext->VSSetShader(m_VSShader, m_VSClassInstances, m_VSNumClassInstances);
m_D3DDevImmContext->VSSetConstantBuffers(0, 1, &m_VSConstantBuffer);
// Restore Input-Assembler
m_D3DDevImmContext->IASetIndexBuffer(m_IAIndexBuffer, m_IAIndexBufferFormat, m_IAIndexBufferOffset);
m_D3DDevImmContext->IASetInputLayout(m_IAInputLayout);
m_D3DDevImmContext->IASetPrimitiveTopology(m_IATopology);
m_D3DDevImmContext->IASetVertexBuffers(0, 1, &m_IAVertexBuffer, &m_IAVertexBufferStride, &m_IAVertexBufferOffset);
// Restore Ouput-Merger
m_D3DDevImmContext->OMSetBlendState(m_OMBlendState, m_OMBlendFactor, m_OMSampleMask);
m_D3DDevImmContext->OMSetDepthStencilState(m_OMDepthStencilState, m_OMStencilRef);
// Restore Rasterizer states
m_D3DDevImmContext->RSSetScissorRects(m_RSScissorNumRects, m_RSScissorRects);
m_D3DDevImmContext->RSSetViewports(m_RSNumViewports, m_RSViewports);
m_D3DDevImmContext->RSSetState(m_RSRasterizerState);
}
void CState11::Release()
{
// Release stored shaders
if (m_CSClassInstances != NULL)
{
for (UINT i = 0; i < m_CSNumClassInstances; i++)
if (m_CSClassInstances[i] != NULL)
m_CSClassInstances[i]->Release();
delete[] m_CSClassInstances;
m_CSClassInstances = NULL;
m_CSNumClassInstances = 0;
}
if (m_CSShader != NULL)
{
m_CSShader->Release();
m_CSShader = NULL;
}
if (m_DSClassInstances != NULL)
{
for (UINT i = 0; i < m_DSNumClassInstances; i++)
if (m_DSClassInstances[i] != NULL)
m_DSClassInstances[i]->Release();
delete[] m_DSClassInstances;
m_DSClassInstances = NULL;
m_DSNumClassInstances = 0;
}
if (m_DSShader != NULL)
{
m_DSShader->Release();
m_DSShader = NULL;
}
if (m_GSClassInstances != NULL)
{
for (UINT i = 0; i < m_GSNumClassInstances; i++)
if (m_GSClassInstances[i] != NULL)
m_GSClassInstances[i]->Release();
delete[] m_GSClassInstances;
m_GSClassInstances = NULL;
m_GSNumClassInstances = 0;
}
if (m_GSShader != NULL)
{
m_GSShader->Release();
m_GSShader = NULL;
}
if (m_HSClassInstances != NULL)
{
for (UINT i = 0; i < m_HSNumClassInstances; i++)
if (m_HSClassInstances[i] != NULL)
m_HSClassInstances[i]->Release();
delete[] m_HSClassInstances;
m_HSClassInstances = NULL;
m_HSNumClassInstances = 0;
}
if (m_HSShader != NULL)
{
m_HSShader->Release();
m_HSShader = NULL;
}
if (m_PSClassInstances != NULL)
{
for (UINT i = 0; i < m_PSNumClassInstances; i++)
if (m_PSClassInstances[i] != NULL)
m_PSClassInstances[i]->Release();
delete[] m_PSClassInstances;
m_PSClassInstances = NULL;
m_PSNumClassInstances = 0;
}
if (m_PSShader != NULL)
{
m_PSShader->Release();
m_PSShader = NULL;
}
if (m_PSConstantBuffer != NULL)
{
m_PSConstantBuffer->Release();
m_PSConstantBuffer = NULL;
}
if (m_PSSampler != NULL)
{
m_PSSampler->Release();
m_PSSampler = NULL;
}
if (m_PSShaderResourceView != NULL)
{
m_PSShaderResourceView->Release();
m_PSShaderResourceView = NULL;
}
if (m_VSClassInstances != NULL)
{
for (UINT i = 0; i < m_VSNumClassInstances; i++)
if (m_VSClassInstances[i] != NULL)
m_VSClassInstances[i]->Release();
delete[] m_VSClassInstances;
m_VSClassInstances = NULL;
m_VSNumClassInstances = 0;
}
if (m_VSShader != NULL)
{
m_VSShader->Release();
m_VSShader = NULL;
}
if (m_VSConstantBuffer != NULL)
{
m_VSConstantBuffer->Release();
m_VSConstantBuffer = NULL;
}
// Release Input-Assembler states
if (m_IAIndexBuffer != NULL)
{
m_IAIndexBuffer->Release();
m_IAIndexBuffer = NULL;
}
if (m_IAInputLayout != NULL)
{
m_IAInputLayout->Release();
m_IAInputLayout = 0;
}
if (m_IAVertexBuffer != NULL)
{
m_IAVertexBuffer->Release();
m_IAVertexBuffer = NULL;
}
// Release Output-Merger states
if (m_OMBlendState != NULL)
{
m_OMBlendState->Release();
m_OMBlendState = NULL;
}
if (m_OMDepthStencilState != NULL)
{
m_OMDepthStencilState->Release();
m_OMDepthStencilState = NULL;
}
// Release Rasterizer state
if (m_RSRasterizerState != 0)
{
m_RSRasterizerState->Release();
m_RSRasterizerState = NULL;
}
m_RSNumViewports = 0;
m_RSScissorNumRects = 0;
}
// ---------------------------------------------------------------------------
int CTwGraphDirect3D11::Init()
{
assert(g_TwMgr!=NULL);
assert(g_TwMgr->m_Device!=NULL);
m_D3DDev = static_cast<ID3D11Device *>(g_TwMgr->m_Device);
m_D3DDevInitialRefCount = m_D3DDev->AddRef() - 1;
m_D3DDev->GetImmediateContext(&m_D3DDevImmContext);
m_Drawing = false;
m_OffsetX = m_OffsetY = 0;
m_ViewportInit = new D3D11_VIEWPORT;
m_FontTex = NULL;
m_FontD3DTex = NULL;
m_FontD3DTexRV = NULL;
m_WndWidth = 0;
m_WndHeight = 0;
m_State = NULL;
m_DepthStencilState = NULL;
m_BlendState = NULL;
m_RasterState = NULL;
m_RasterStateAntialiased = NULL;
m_RasterStateMultisample = NULL;
m_RasterStateCullCW = NULL;
m_RasterStateCullCCW = NULL;
m_LineRectVS = NULL;
m_LineRectCstColorVS = NULL;
m_LineRectPS = NULL;
m_LineRectVertexLayout = NULL;
m_TextVS = NULL;
m_TextCstColorVS = NULL;
m_TextPS = NULL;
m_TextVertexLayout = NULL;
m_LineVertexBuffer = NULL;
m_RectVertexBuffer = NULL;
m_TrianglesVertexBuffer = NULL;
m_TrianglesVertexBufferCount = 0;
m_ConstantBuffer = NULL;
m_SamplerState = NULL;
// Allocate state object
m_State = new CState11(m_D3DDev, m_D3DDevImmContext);
// Disable client shaders
m_D3DDevImmContext->CSSetShader(NULL, NULL, 0);
m_D3DDevImmContext->DSSetShader(NULL, NULL, 0);
m_D3DDevImmContext->GSSetShader(NULL, NULL, 0);
m_D3DDevImmContext->HSSetShader(NULL, NULL, 0);
m_D3DDevImmContext->PSSetShader(NULL, NULL, 0);
m_D3DDevImmContext->VSSetShader(NULL, NULL, 0);
// Create shaders
HRESULT hr = m_D3DDev->CreateVertexShader(g_LineRectVS, sizeof(g_LineRectVS), NULL, &m_LineRectVS);
if( FAILED(hr) )
{
g_TwMgr->SetLastError(g_ErrCreateVS11);
Shut();
return 0;
}
hr = m_D3DDev->CreateVertexShader(g_LineRectCstColorVS, sizeof(g_LineRectCstColorVS), NULL, &m_LineRectCstColorVS);
if( FAILED(hr) )
{
g_TwMgr->SetLastError(g_ErrCreateVS11);
Shut();
return 0;
}
hr = m_D3DDev->CreatePixelShader(g_LineRectPS, sizeof(g_LineRectPS), NULL, &m_LineRectPS);
if( FAILED(hr) )
{
g_TwMgr->SetLastError(g_ErrCreatePS11);
Shut();
return 0;
}
hr = m_D3DDev->CreateVertexShader(g_TextVS, sizeof(g_TextVS), NULL, &m_TextVS);
if( FAILED(hr) )
{
g_TwMgr->SetLastError(g_ErrCreateVS11);
Shut();
return 0;
}
hr = m_D3DDev->CreateVertexShader(g_TextCstColorVS, sizeof(g_TextCstColorVS), NULL, &m_TextCstColorVS);
if( FAILED(hr) )
{
g_TwMgr->SetLastError(g_ErrCreateVS11);
Shut();
return 0;
}
hr = m_D3DDev->CreatePixelShader(g_TextPS, sizeof(g_TextPS), NULL, &m_TextPS);
if( FAILED(hr) )
{
g_TwMgr->SetLastError(g_ErrCreatePS11);
Shut();
return 0;
}
// Create input layout for lines & rect
D3D11_INPUT_ELEMENT_DESC lineRectLayout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(CLineRectVtx, m_Color), D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
hr = m_D3DDev->CreateInputLayout(lineRectLayout, sizeof(lineRectLayout)/sizeof(lineRectLayout[0]), g_LineRectVS, sizeof(g_LineRectVS), &m_LineRectVertexLayout);
if( FAILED(hr) )
{
g_TwMgr->SetLastError(g_ErrCreateLayout11);
Shut();
return 0;
}
// Create line vertex buffer
D3D11_BUFFER_DESC bd;
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = 2 * sizeof(CLineRectVtx);
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
bd.StructureByteStride = 0;
hr = m_D3DDev->CreateBuffer(&bd, NULL, &m_LineVertexBuffer);
if( FAILED(hr) )
{
g_TwMgr->SetLastError(g_ErrCreateBuffer11);
Shut();
return 0;
}
// Create rect vertex buffer
bd.ByteWidth = 4 * sizeof(CLineRectVtx);
hr = m_D3DDev->CreateBuffer(&bd, NULL, &m_RectVertexBuffer);
if( FAILED(hr) )
{
g_TwMgr->SetLastError(g_ErrCreateBuffer11);
Shut();
return 0;
}
// Create constant buffer
bd.ByteWidth = sizeof(CConstants);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
hr = m_D3DDev->CreateBuffer(&bd, NULL, &m_ConstantBuffer);
if( FAILED(hr) )
{
g_TwMgr->SetLastError(g_ErrCreateBuffer11);
Shut();
return 0;
}
// Create sampler
D3D11_SAMPLER_DESC sd;
sd.AddressU = sd.AddressV = sd.AddressW = D3D11_TEXTURE_ADDRESS_BORDER;
sd.BorderColor[0] = sd.BorderColor[1] = sd.BorderColor[2] = sd.BorderColor[3] = 0;
sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
sd.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
sd.MaxAnisotropy = 1;
sd.MaxLOD = sd.MinLOD = 0;
sd.MipLODBias = 0;
hr = m_D3DDev->CreateSamplerState(&sd, &m_SamplerState);
if( FAILED(hr) )
{
g_TwMgr->SetLastError(g_ErrCreateSampler11);
Shut();
return 0;
}
// Create input layout for text
D3D11_INPUT_ELEMENT_DESC textLayout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(CTextVtx, m_Color), D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(CTextVtx, m_UV), D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
hr = m_D3DDev->CreateInputLayout(textLayout, sizeof(textLayout)/sizeof(textLayout[0]), g_TextVS, sizeof(g_TextVS), &m_TextVertexLayout);
if( FAILED(hr) )
{
g_TwMgr->SetLastError(g_ErrCreateLayout11);
Shut();
return 0;
}
// Create depth stencil state object
D3D11_DEPTH_STENCILOP_DESC od;
od.StencilFunc = D3D11_COMPARISON_ALWAYS;
od.StencilFailOp = D3D11_STENCIL_OP_KEEP;
od.StencilPassOp = D3D11_STENCIL_OP_KEEP;
od.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
D3D11_DEPTH_STENCIL_DESC dsd;
dsd.DepthEnable = FALSE;
dsd.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
dsd.DepthFunc = D3D11_COMPARISON_ALWAYS;
dsd.StencilEnable = FALSE;
dsd.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
dsd.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
dsd.FrontFace = od;
dsd.BackFace = od;
m_D3DDev->CreateDepthStencilState(&dsd, &m_DepthStencilState);
// Create blend state object
D3D11_BLEND_DESC bsd;
bsd.AlphaToCoverageEnable = FALSE;
bsd.IndependentBlendEnable = FALSE;
for(int i=0; i<8; ++i)
{
bsd.RenderTarget[i].BlendEnable = TRUE;
bsd.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
bsd.RenderTarget[i].SrcBlend = D3D11_BLEND_SRC_ALPHA;
bsd.RenderTarget[i].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
bsd.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
bsd.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
bsd.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
bsd.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
}
m_D3DDev->CreateBlendState(&bsd, &m_BlendState);
// Create rasterizer state object
D3D11_RASTERIZER_DESC rd;
rd.FillMode = D3D11_FILL_SOLID;
rd.CullMode = D3D11_CULL_NONE;
rd.FrontCounterClockwise = true;
rd.DepthBias = false;
rd.DepthBiasClamp = 0;
rd.SlopeScaledDepthBias = 0;
rd.DepthClipEnable = false;
rd.ScissorEnable = true;
rd.MultisampleEnable = false; // do not allow msaa (fonts would be degraded)
rd.AntialiasedLineEnable = false;
m_D3DDev->CreateRasterizerState(&rd, &m_RasterState);
rd.AntialiasedLineEnable = true;
m_D3DDev->CreateRasterizerState(&rd, &m_RasterStateAntialiased);
rd.AntialiasedLineEnable = false;
// the three following raster states allow msaa
rd.MultisampleEnable = true;
m_D3DDev->CreateRasterizerState(&rd, &m_RasterStateMultisample);
rd.CullMode = D3D11_CULL_BACK;
m_D3DDev->CreateRasterizerState(&rd, &m_RasterStateCullCW);
rd.CullMode = D3D11_CULL_FRONT;
m_D3DDev->CreateRasterizerState(&rd, &m_RasterStateCullCCW);
return 1;
}
// ---------------------------------------------------------------------------
int CTwGraphDirect3D11::Shut()
{
assert(m_Drawing==false);
UnbindFont(m_D3DDev, m_FontD3DTex, m_FontD3DTexRV);
m_FontD3DTex = NULL;
m_FontD3DTexRV = NULL;
if( m_State )
{
delete m_State;
m_State = NULL;
}
if( m_ViewportInit )
{
delete m_ViewportInit;
m_ViewportInit = NULL;
}
if( m_DepthStencilState )
{
ULONG rc = m_DepthStencilState->Release();
//assert( rc==0 ); // no assert: the client can use a similar (then shared) state
(void)rc;
m_DepthStencilState = NULL;
}
if( m_BlendState )
{
ULONG rc = m_BlendState->Release();
//assert( rc==0 ); // no assert: the client can use a similar (then shared) state
(void)rc;
m_BlendState = NULL;
}
if( m_RasterState )
{
ULONG rc = m_RasterState->Release();
//assert( rc==0 ); // no assert: the client can use a similar (then shared) state
(void)rc;
m_RasterState = NULL;
}
if( m_RasterStateAntialiased )
{
ULONG rc = m_RasterStateAntialiased->Release();
//assert( rc==0 ); // no assert: the client can use a similar (then shared) state
(void)rc;
m_RasterStateAntialiased = NULL;
}
if( m_RasterStateMultisample )
{
ULONG rc = m_RasterStateMultisample->Release();
//assert( rc==0 ); // no assert: the client can use a similar (then shared) state
(void)rc;
m_RasterStateMultisample = NULL;
}
if( m_RasterStateCullCW )
{
ULONG rc = m_RasterStateCullCW->Release();
//assert( rc==0 ); // no assert: the client can use a similar (then shared) state
(void)rc;
m_RasterStateCullCW = NULL;
}
if( m_RasterStateCullCCW )
{
ULONG rc = m_RasterStateCullCCW->Release();
//assert( rc==0 ); // no assert: the client can use a similar (then shared) state
(void)rc;
m_RasterStateCullCCW = NULL;
}
if( m_SamplerState )
{
ULONG rc = m_SamplerState->Release();
//assert( rc==0 ); // no assert: the client can use a similar (then shared) state
(void)rc;
m_SamplerState = NULL;
}
if( m_LineRectVS )
{
ULONG rc = m_LineRectVS->Release();
assert( rc==0 ); (void)rc;
m_LineRectVS = NULL;
}
if( m_LineRectCstColorVS )
{
ULONG rc = m_LineRectCstColorVS->Release();
assert( rc==0 ); (void)rc;
m_LineRectCstColorVS = NULL;
}
if( m_LineRectPS )
{
ULONG rc = m_LineRectPS->Release();
assert( rc==0 ); (void)rc;
m_LineRectPS = NULL;
}
if( m_TextVS )
{
ULONG rc = m_TextVS->Release();
assert( rc==0 ); (void)rc;
m_TextVS = NULL;
}
if( m_TextCstColorVS )
{
ULONG rc = m_TextCstColorVS->Release();
assert( rc==0 ); (void)rc;
m_TextCstColorVS = NULL;
}
if( m_TextPS )
{
ULONG rc = m_TextPS->Release();
assert( rc==0 ); (void)rc;
m_TextPS = NULL;
}
if( m_LineVertexBuffer )
{
ULONG rc = m_LineVertexBuffer->Release();
assert( rc==0 ); (void)rc;
m_LineVertexBuffer = NULL;
}
if( m_RectVertexBuffer )
{
ULONG rc = m_RectVertexBuffer->Release();
assert( rc==0 ); (void)rc;
m_RectVertexBuffer = NULL;
}
if( m_TrianglesVertexBuffer )
{
ULONG rc = m_TrianglesVertexBuffer->Release();
assert( rc==0 ); (void)rc;
m_TrianglesVertexBuffer = NULL;
m_TrianglesVertexBufferCount = 0;
}
if( m_ConstantBuffer )
{
ULONG rc = m_ConstantBuffer->Release();
assert( rc==0 ); (void)rc;
m_ConstantBuffer = NULL;
}
if( m_LineRectVertexLayout )
{
ULONG rc = m_LineRectVertexLayout->Release();
assert( rc==0 ); (void)rc;
m_LineRectVertexLayout = NULL;
}
if( m_TextVertexLayout )
{
ULONG rc = m_TextVertexLayout->Release();
assert( rc==0 ); (void)rc;
m_TextVertexLayout = NULL;
}
if( m_D3DDevImmContext )
{
m_D3DDevImmContext->Release();
m_D3DDevImmContext = NULL;
}
if( m_D3DDev )
{
//unsigned int rc = m_D3DDev->Release();
//assert( m_D3DDevInitialRefCount==rc ); (void)rc;
m_D3DDev->Release();
m_D3DDev = NULL;
}
return 1;
}
// ---------------------------------------------------------------------------
void CTwGraphDirect3D11::BeginDraw(int _WndWidth, int _WndHeight)
{
assert(m_Drawing==false && _WndWidth>0 && _WndHeight>0);
m_Drawing = true;
m_WndWidth = _WndWidth;
m_WndHeight = _WndHeight;
m_OffsetX = m_OffsetY = 0;
// save client context state
m_State->Save();
// Setup the viewport
D3D11_VIEWPORT vp;
vp.Width = (FLOAT)_WndWidth;
vp.Height = (FLOAT)_WndHeight;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
m_D3DDevImmContext->RSSetViewports(1, &vp);
*static_cast<D3D11_VIEWPORT *>(m_ViewportInit) = vp;
m_ViewportAndScissorRects[0] = FullRect;
m_ViewportAndScissorRects[1] = FullRect;
m_D3DDevImmContext->RSSetScissorRects(1, m_ViewportAndScissorRects);
m_D3DDevImmContext->RSSetState(m_RasterState);
m_D3DDevImmContext->OMSetDepthStencilState(m_DepthStencilState, 0);
float blendFactors[4] = { 1, 1, 1, 1 };
m_D3DDevImmContext->OMSetBlendState(m_BlendState, blendFactors, 0xffffffff);
m_D3DDevImmContext->CSSetShader(NULL, NULL, 0);
m_D3DDevImmContext->DSSetShader(NULL, NULL, 0);
m_D3DDevImmContext->GSSetShader(NULL, NULL, 0);
m_D3DDevImmContext->HSSetShader(NULL, NULL, 0);
}
// ---------------------------------------------------------------------------
void CTwGraphDirect3D11::EndDraw()
{
m_D3DDevImmContext->RSSetState(NULL);
m_D3DDevImmContext->OMSetDepthStencilState(NULL, 0);
m_D3DDevImmContext->OMSetBlendState(NULL, NULL, 0xffffffff);
assert(m_Drawing==true);
m_Drawing = false;
// restore and release client context state
m_State->Restore();
m_State->Release();
}
// ---------------------------------------------------------------------------
bool CTwGraphDirect3D11::IsDrawing()
{
return m_Drawing;
}
// ---------------------------------------------------------------------------
void CTwGraphDirect3D11::Restore()
{
if( m_State )
m_State->Release();
UnbindFont(m_D3DDev, m_FontD3DTex, m_FontD3DTexRV);
m_FontD3DTexRV = NULL;
m_FontD3DTex = NULL;
m_FontTex = NULL;
}
// ---------------------------------------------------------------------------
static inline float ToNormScreenX(int x, int wndWidth)
{
return 2.0f*((float)x-0.5f)/wndWidth - 1.0f;
}
static inline float ToNormScreenY(int y, int wndHeight)
{
return 1.0f - 2.0f*((float)y-0.5f)/wndHeight;
}
static inline color32 ToR8G8B8A8(color32 col)
{
return (col & 0xff00ff00) | ((col>>16) & 0xff) | ((col<<16) & 0xff0000);
}
// ---------------------------------------------------------------------------
void CTwGraphDirect3D11::DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color0, color32 _Color1, bool _AntiAliased)
{
assert(m_Drawing==true);
float x0 = ToNormScreenX(_X0 + m_OffsetX, m_WndWidth);
float y0 = ToNormScreenY(_Y0 + m_OffsetY, m_WndHeight);
float x1 = ToNormScreenX(_X1 + m_OffsetX, m_WndWidth);
float y1 = ToNormScreenY(_Y1 + m_OffsetY, m_WndHeight);
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = m_D3DDevImmContext->Map(m_LineVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( SUCCEEDED(hr) )
{
CLineRectVtx *vertices = (CLineRectVtx *)mappedResource.pData;
// Fill vertex buffer
vertices[0].m_Pos[0] = x0;
vertices[0].m_Pos[1] = y0;
vertices[0].m_Pos[2] = 0;
vertices[0].m_Color = ToR8G8B8A8(_Color0);
vertices[1].m_Pos[0] = x1;
vertices[1].m_Pos[1] = y1;
vertices[1].m_Pos[2] = 0;
vertices[1].m_Color = ToR8G8B8A8(_Color1);
m_D3DDevImmContext->Unmap(m_LineVertexBuffer, 0);
if( _AntiAliased )
m_D3DDevImmContext->RSSetState(m_RasterStateAntialiased);
// Reset shader constants
hr = m_D3DDevImmContext->Map(m_ConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( SUCCEEDED(hr) )
{
CConstants *constants = (CConstants *)mappedResource.pData;
constants->m_Offset[0] = 0;
constants->m_Offset[1] = 0;
constants->m_Offset[2] = 0;
constants->m_Offset[3] = 0;
constants->m_CstColor[0] = 1;
constants->m_CstColor[1] = 1;
constants->m_CstColor[2] = 1;
constants->m_CstColor[3] = 1;
m_D3DDevImmContext->Unmap(m_ConstantBuffer, 0);
}
// Set the input layout
m_D3DDevImmContext->IASetInputLayout(m_LineRectVertexLayout);
// Set vertex buffer
UINT stride = sizeof(CLineRectVtx);
UINT offset = 0;
m_D3DDevImmContext->IASetVertexBuffers(0, 1, &m_LineVertexBuffer, &stride, &offset);
// Set primitive topology
m_D3DDevImmContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
// Render the line
m_D3DDevImmContext->VSSetConstantBuffers(0, 1, &m_ConstantBuffer);
m_D3DDevImmContext->VSSetShader(m_LineRectVS, NULL, 0);
m_D3DDevImmContext->PSSetShader(m_LineRectPS, NULL, 0);
m_D3DDevImmContext->Draw(2, 0);
if( _AntiAliased )
m_D3DDevImmContext->RSSetState(m_RasterState); // restore default raster state
}
}
// ---------------------------------------------------------------------------
void CTwGraphDirect3D11::DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color00, color32 _Color10, color32 _Color01, color32 _Color11)
{
assert(m_Drawing==true);
// border adjustment
if(_X0<_X1)
++_X1;
else if(_X0>_X1)
++_X0;
if(_Y0<_Y1)
++_Y1;
else if(_Y0>_Y1)
++_Y0;
float x0 = ToNormScreenX(_X0 + m_OffsetX, m_WndWidth);
float y0 = ToNormScreenY(_Y0 + m_OffsetY, m_WndHeight);
float x1 = ToNormScreenX(_X1 + m_OffsetX, m_WndWidth);
float y1 = ToNormScreenY(_Y1 + m_OffsetY, m_WndHeight);
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = m_D3DDevImmContext->Map(m_RectVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( SUCCEEDED(hr) )
{
CLineRectVtx *vertices = (CLineRectVtx *)mappedResource.pData;
// Fill vertex buffer
vertices[0].m_Pos[0] = x0;
vertices[0].m_Pos[1] = y0;
vertices[0].m_Pos[2] = 0;
vertices[0].m_Color = ToR8G8B8A8(_Color00);
vertices[1].m_Pos[0] = x1;
vertices[1].m_Pos[1] = y0;
vertices[1].m_Pos[2] = 0;
vertices[1].m_Color = ToR8G8B8A8(_Color10);
vertices[2].m_Pos[0] = x0;
vertices[2].m_Pos[1] = y1;
vertices[2].m_Pos[2] = 0;
vertices[2].m_Color = ToR8G8B8A8(_Color01);
vertices[3].m_Pos[0] = x1;
vertices[3].m_Pos[1] = y1;
vertices[3].m_Pos[2] = 0;
vertices[3].m_Color = ToR8G8B8A8(_Color11);
m_D3DDevImmContext->Unmap(m_RectVertexBuffer, 0);
// Reset shader constants
hr = m_D3DDevImmContext->Map(m_ConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( SUCCEEDED(hr) )
{
CConstants *constants = (CConstants *)mappedResource.pData;
constants->m_Offset[0] = 0;
constants->m_Offset[1] = 0;
constants->m_Offset[2] = 0;
constants->m_Offset[3] = 0;
constants->m_CstColor[0] = 1;
constants->m_CstColor[1] = 1;
constants->m_CstColor[2] = 1;
constants->m_CstColor[3] = 1;
m_D3DDevImmContext->Unmap(m_ConstantBuffer, 0);
}
// Set the input layout
m_D3DDevImmContext->IASetInputLayout(m_LineRectVertexLayout);
// Set vertex buffer
UINT stride = sizeof(CLineRectVtx);
UINT offset = 0;
m_D3DDevImmContext->IASetVertexBuffers(0, 1, &m_RectVertexBuffer, &stride, &offset);
// Set primitive topology
m_D3DDevImmContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// Render the rect
m_D3DDevImmContext->VSSetConstantBuffers(0, 1, &m_ConstantBuffer);
m_D3DDevImmContext->VSSetShader(m_LineRectVS, NULL, 0);
m_D3DDevImmContext->PSSetShader(m_LineRectPS, NULL, 0);
m_D3DDevImmContext->Draw(4, 0);
}
}
// ---------------------------------------------------------------------------
void *CTwGraphDirect3D11::NewTextObj()
{
CTextObj *textObj = new CTextObj;
memset(textObj, 0, sizeof(CTextObj));
return textObj;
}
// ---------------------------------------------------------------------------
void CTwGraphDirect3D11::DeleteTextObj(void *_TextObj)
{
assert(_TextObj!=NULL);
CTextObj *textObj = static_cast<CTextObj *>(_TextObj);
if( textObj->m_TextVertexBuffer )
textObj->m_TextVertexBuffer->Release();
if( textObj->m_BgVertexBuffer )
textObj->m_BgVertexBuffer->Release();
memset(textObj, 0, sizeof(CTextObj));
delete textObj;
}
// ---------------------------------------------------------------------------
void CTwGraphDirect3D11::BuildText(void *_TextObj, const std::string *_TextLines, color32 *_LineColors, color32 *_LineBgColors, int _NbLines, const CTexFont *_Font, int _Sep, int _BgWidth)
{
assert(m_Drawing==true);
assert(_TextObj!=NULL);
assert(_Font!=NULL);
if( _Font != m_FontTex )
{
UnbindFont(m_D3DDev, m_FontD3DTex, m_FontD3DTexRV);
BindFont(m_D3DDev, _Font, &m_FontD3DTex, &m_FontD3DTexRV);
m_FontTex = _Font;
}
int nbTextVerts = 0;
int line;
for( line=0; line<_NbLines; ++line )
nbTextVerts += 6 * (int)_TextLines[line].length();
int nbBgVerts = 0;
if( _BgWidth>0 )
nbBgVerts = _NbLines*6;
CTextObj *textObj = static_cast<CTextObj *>(_TextObj);
textObj->m_LineColors = (_LineColors!=NULL);
textObj->m_LineBgColors = (_LineBgColors!=NULL);
// (re)create text vertex buffer if needed, and map it
CTextVtx *textVerts = NULL;
if( nbTextVerts>0 )
{
if( textObj->m_TextVertexBuffer==NULL || textObj->m_TextVertexBufferSize<nbTextVerts )
{
if( textObj->m_TextVertexBuffer!=NULL )
{
ULONG rc = textObj->m_TextVertexBuffer->Release();
assert( rc==0 ); (void)rc;
textObj->m_TextVertexBuffer = NULL;
}
textObj->m_TextVertexBufferSize = nbTextVerts + 6*256; // add a reserve of 256 characters
D3D11_BUFFER_DESC bd;
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = textObj->m_TextVertexBufferSize * sizeof(CTextVtx);
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
bd.StructureByteStride = 0;
m_D3DDev->CreateBuffer(&bd, NULL, &textObj->m_TextVertexBuffer);
}
if( textObj->m_TextVertexBuffer!=NULL )
{
D3D11_MAPPED_SUBRESOURCE mappedResource;
m_D3DDevImmContext->Map(textObj->m_TextVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
textVerts = (CTextVtx *)mappedResource.pData;
}
}
// (re)create bg vertex buffer if needed, and map it
CLineRectVtx *bgVerts = NULL;
if( nbBgVerts>0 )
{
if( textObj->m_BgVertexBuffer==NULL || textObj->m_BgVertexBufferSize<nbBgVerts )
{
if( textObj->m_BgVertexBuffer!=NULL )
{
ULONG rc = textObj->m_BgVertexBuffer->Release();
assert( rc==0 ); (void)rc;
textObj->m_BgVertexBuffer = NULL;
}
textObj->m_BgVertexBufferSize = nbBgVerts + 6*32; // add a reserve of 32 rects
D3D11_BUFFER_DESC bd;
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = textObj->m_BgVertexBufferSize * sizeof(CLineRectVtx);
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
bd.StructureByteStride = 0;
m_D3DDev->CreateBuffer(&bd, NULL, &textObj->m_BgVertexBuffer);
}
if( textObj->m_BgVertexBuffer!=NULL )
{
D3D11_MAPPED_SUBRESOURCE mappedResource;
m_D3DDevImmContext->Map(textObj->m_BgVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
bgVerts = (CLineRectVtx *)mappedResource.pData;
}
}
int x, x1, y, y1, i, len;
float px, px1, py, py1;
unsigned char ch;
const unsigned char *text;
color32 lineColor = COLOR32_RED;
CTextVtx vtx;
vtx.m_Pos[2] = 0;
CLineRectVtx bgVtx;
bgVtx.m_Pos[2] = 0;
int textVtxIndex = 0;
int bgVtxIndex = 0;
for( line=0; line<_NbLines; ++line )
{
x = 0;
y = line * (_Font->m_CharHeight+_Sep);
y1 = y+_Font->m_CharHeight;
len = (int)_TextLines[line].length();
text = (const unsigned char *)(_TextLines[line].c_str());
if( _LineColors!=NULL )
lineColor = ToR8G8B8A8(_LineColors[line]);
if( textVerts!=NULL )
for( i=0; i<len; ++i )
{
ch = text[i];
x1 = x + _Font->m_CharWidth[ch];
px = ToNormScreenX(x, m_WndWidth);
py = ToNormScreenY(y, m_WndHeight);
px1 = ToNormScreenX(x1, m_WndWidth);
py1 = ToNormScreenY(y1, m_WndHeight);
vtx.m_Color = lineColor;
vtx.m_Pos[0] = px;
vtx.m_Pos[1] = py;
vtx.m_UV [0] = _Font->m_CharU0[ch];
vtx.m_UV [1] = _Font->m_CharV0[ch];
textVerts[textVtxIndex++] = vtx;
vtx.m_Pos[0] = px1;
vtx.m_Pos[1] = py;
vtx.m_UV [0] = _Font->m_CharU1[ch];
vtx.m_UV [1] = _Font->m_CharV0[ch];
textVerts[textVtxIndex++] = vtx;
vtx.m_Pos[0] = px;
vtx.m_Pos[1] = py1;
vtx.m_UV [0] = _Font->m_CharU0[ch];
vtx.m_UV [1] = _Font->m_CharV1[ch];
textVerts[textVtxIndex++] = vtx;
vtx.m_Pos[0] = px1;
vtx.m_Pos[1] = py;
vtx.m_UV [0] = _Font->m_CharU1[ch];
vtx.m_UV [1] = _Font->m_CharV0[ch];
textVerts[textVtxIndex++] = vtx;
vtx.m_Pos[0] = px1;
vtx.m_Pos[1] = py1;
vtx.m_UV [0] = _Font->m_CharU1[ch];
vtx.m_UV [1] = _Font->m_CharV1[ch];
textVerts[textVtxIndex++] = vtx;
vtx.m_Pos[0] = px;
vtx.m_Pos[1] = py1;
vtx.m_UV [0] = _Font->m_CharU0[ch];
vtx.m_UV [1] = _Font->m_CharV1[ch];
textVerts[textVtxIndex++] = vtx;
x = x1;
}
if( _BgWidth>0 && bgVerts!=NULL )
{
if( _LineBgColors!=NULL )
bgVtx.m_Color = ToR8G8B8A8(_LineBgColors[line]);
else
bgVtx.m_Color = ToR8G8B8A8(COLOR32_BLACK);
px = ToNormScreenX(-1, m_WndWidth);
py = ToNormScreenY(y, m_WndHeight);
px1 = ToNormScreenX(_BgWidth+1, m_WndWidth);
py1 = ToNormScreenY(y1, m_WndHeight);
bgVtx.m_Pos[0] = px;
bgVtx.m_Pos[1] = py;
bgVerts[bgVtxIndex++] = bgVtx;
bgVtx.m_Pos[0] = px1;
bgVtx.m_Pos[1] = py;
bgVerts[bgVtxIndex++] = bgVtx;
bgVtx.m_Pos[0] = px;
bgVtx.m_Pos[1] = py1;
bgVerts[bgVtxIndex++] = bgVtx;
bgVtx.m_Pos[0] = px1;
bgVtx.m_Pos[1] = py;
bgVerts[bgVtxIndex++] = bgVtx;
bgVtx.m_Pos[0] = px1;
bgVtx.m_Pos[1] = py1;
bgVerts[bgVtxIndex++] = bgVtx;
bgVtx.m_Pos[0] = px;
bgVtx.m_Pos[1] = py1;
bgVerts[bgVtxIndex++] = bgVtx;
}
}
assert( textVtxIndex==nbTextVerts );
assert( bgVtxIndex==nbBgVerts );
textObj->m_NbTextVerts = nbTextVerts;
textObj->m_NbBgVerts = nbBgVerts;
if( textVerts!=NULL )
m_D3DDevImmContext->Unmap(textObj->m_TextVertexBuffer, 0);
if( bgVerts!=NULL )
m_D3DDevImmContext->Unmap(textObj->m_BgVertexBuffer, 0);
}
// ---------------------------------------------------------------------------
void CTwGraphDirect3D11::DrawText(void *_TextObj, int _X, int _Y, color32 _Color, color32 _BgColor)
{
assert(m_Drawing==true);
assert(_TextObj!=NULL);
CTextObj *textObj = static_cast<CTextObj *>(_TextObj);
float dx = 2.0f*(float)(_X + m_OffsetX)/m_WndWidth;
float dy = -2.0f*(float)(_Y + m_OffsetY)/m_WndHeight;
// Draw background
if( textObj->m_NbBgVerts>=4 && textObj->m_BgVertexBuffer!=NULL )
{
// Set offset and constant color
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = m_D3DDevImmContext->Map(m_ConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( SUCCEEDED(hr) )
{
CConstants *constants = (CConstants *)mappedResource.pData;
constants->m_Offset[0] = dx;
constants->m_Offset[1] = dy;
constants->m_Offset[2] = 0;
constants->m_Offset[3] = 0;
Color32ToARGBf(_BgColor, constants->m_CstColor+3, constants->m_CstColor+0, constants->m_CstColor+1, constants->m_CstColor+2);
m_D3DDevImmContext->Unmap(m_ConstantBuffer, 0);
}
// Set the input layout
m_D3DDevImmContext->IASetInputLayout(m_LineRectVertexLayout);
// Set vertex buffer
UINT stride = sizeof(CLineRectVtx);
UINT offset = 0;
m_D3DDevImmContext->IASetVertexBuffers(0, 1, &textObj->m_BgVertexBuffer, &stride, &offset);
// Set primitive topology
m_D3DDevImmContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// Render the bg rectangles
m_D3DDevImmContext->VSSetConstantBuffers(0, 1, &m_ConstantBuffer);
if( _BgColor!=0 || !textObj->m_LineBgColors ) // use a constant bg color
m_D3DDevImmContext->VSSetShader(m_LineRectCstColorVS, NULL, 0);
else
m_D3DDevImmContext->VSSetShader(m_LineRectVS, NULL, 0);
m_D3DDevImmContext->PSSetSamplers(0, 1, &m_SamplerState);
m_D3DDevImmContext->PSSetShader(m_LineRectPS, NULL, 0);
m_D3DDevImmContext->Draw(textObj->m_NbBgVerts, 0);
}
// Draw text
if( textObj->m_NbTextVerts>=4 && textObj->m_TextVertexBuffer!=NULL )
{
// Set offset and constant color
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = m_D3DDevImmContext->Map(m_ConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( SUCCEEDED(hr) )
{
CConstants *constants = (CConstants *)mappedResource.pData;
constants->m_Offset[0] = dx;
constants->m_Offset[1] = dy;
constants->m_Offset[2] = 0;
constants->m_Offset[3] = 0;
Color32ToARGBf(_Color, constants->m_CstColor+3, constants->m_CstColor+0, constants->m_CstColor+1, constants->m_CstColor+2);
m_D3DDevImmContext->Unmap(m_ConstantBuffer, 0);
}
// Set the input layout
m_D3DDevImmContext->IASetInputLayout(m_TextVertexLayout);
// Set vertex buffer
UINT stride = sizeof(CTextVtx);
UINT offset = 0;
m_D3DDevImmContext->IASetVertexBuffers(0, 1, &textObj->m_TextVertexBuffer, &stride, &offset);
// Set primitive topology
m_D3DDevImmContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// Render the text
m_D3DDevImmContext->VSSetConstantBuffers(0, 1, &m_ConstantBuffer);
if( _Color!=0 || !textObj->m_LineColors ) // use a constant color
m_D3DDevImmContext->VSSetShader(m_TextCstColorVS, NULL, 0);
else
m_D3DDevImmContext->VSSetShader(m_TextVS, NULL, 0);
m_D3DDevImmContext->PSSetShaderResources(0, 1, &m_FontD3DTexRV);
m_D3DDevImmContext->PSSetSamplers(0, 1, &m_SamplerState);
m_D3DDevImmContext->PSSetShader(m_TextPS, NULL, 0);
m_D3DDevImmContext->Draw(textObj->m_NbTextVerts, 0);
}
}
// ---------------------------------------------------------------------------
void CTwGraphDirect3D11::ChangeViewport(int _X0, int _Y0, int _Width, int _Height, int _OffsetX, int _OffsetY)
{
if( _Width>0 && _Height>0 )
{
/* viewport changes screen coordinates, use scissor instead
D3D11_VIEWPORT vp;
vp.TopLeftX = _X0;
vp.TopLeftY = _Y0;
vp.Width = _Width;
vp.Height = _Height;
vp.MinDepth = 0;
vp.MaxDepth = 1;
m_D3DDev->RSSetViewports(1, &vp);
*/
m_ViewportAndScissorRects[0].left = _X0;
m_ViewportAndScissorRects[0].right = _X0 + _Width - 1;
m_ViewportAndScissorRects[0].top = _Y0;
m_ViewportAndScissorRects[0].bottom = _Y0 + _Height - 1;
if( RectIsFull(m_ViewportAndScissorRects[1]) )
m_D3DDevImmContext->RSSetScissorRects(1, m_ViewportAndScissorRects); // viewport clipping only
else
m_D3DDevImmContext->RSSetScissorRects(2, m_ViewportAndScissorRects);
m_OffsetX = _X0 + _OffsetX;
m_OffsetY = _Y0 + _OffsetY;
}
}
// ---------------------------------------------------------------------------
void CTwGraphDirect3D11::RestoreViewport()
{
//m_D3DDevImmContext->RSSetViewports(1, static_cast<D3D11_VIEWPORT *>(m_ViewportInit));
m_ViewportAndScissorRects[0] = FullRect;
m_D3DDevImmContext->RSSetScissorRects(1, m_ViewportAndScissorRects+1); // scissor only
m_OffsetX = m_OffsetY = 0;
}
// ---------------------------------------------------------------------------
void CTwGraphDirect3D11::SetScissor(int _X0, int _Y0, int _Width, int _Height)
{
if( _Width>0 && _Height>0 )
{
m_ViewportAndScissorRects[1].left = _X0 - 2;
m_ViewportAndScissorRects[1].right = _X0 + _Width - 3;
m_ViewportAndScissorRects[1].top = _Y0 - 1;
m_ViewportAndScissorRects[1].bottom = _Y0 + _Height - 1;
if( RectIsFull(m_ViewportAndScissorRects[0]) )
m_D3DDevImmContext->RSSetScissorRects(1, m_ViewportAndScissorRects+1); // no viewport clipping
else
m_D3DDevImmContext->RSSetScissorRects(2, m_ViewportAndScissorRects);
}
else
{
m_ViewportAndScissorRects[1] = FullRect;
m_D3DDevImmContext->RSSetScissorRects(1, m_ViewportAndScissorRects); // apply viewport clipping only
}
}
// ---------------------------------------------------------------------------
void CTwGraphDirect3D11::DrawTriangles(int _NumTriangles, int *_Vertices, color32 *_Colors, Cull _CullMode)
{
assert(m_Drawing==true);
if( _NumTriangles<=0 )
return;
if( m_TrianglesVertexBufferCount<3*_NumTriangles ) // force re-creation
{
if( m_TrianglesVertexBuffer!=NULL )
m_TrianglesVertexBuffer->Release();
m_TrianglesVertexBuffer = NULL;
m_TrianglesVertexBufferCount = 0;
}
// DrawTriangles uses LineRect layout and shaders
if( m_TrianglesVertexBuffer==NULL )
{
// Create triangles vertex buffer
D3D11_BUFFER_DESC bd;
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
bd.ByteWidth = 3*_NumTriangles * sizeof(CLineRectVtx);
bd.StructureByteStride = 0;
HRESULT hr = m_D3DDev->CreateBuffer(&bd, NULL, &m_TrianglesVertexBuffer);
if( SUCCEEDED(hr) )
m_TrianglesVertexBufferCount = 3*_NumTriangles;
else
{
m_TrianglesVertexBuffer = NULL;
m_TrianglesVertexBufferCount = 0;
return; // Problem: cannot create triangles VB
}
}
assert( m_TrianglesVertexBufferCount>=3*_NumTriangles );
assert( m_TrianglesVertexBuffer!=NULL );
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = m_D3DDevImmContext->Map(m_TrianglesVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( SUCCEEDED(hr) )
{
CLineRectVtx *vertices = (CLineRectVtx *)mappedResource.pData;
// Fill vertex buffer
for( int i=0; i<3*_NumTriangles; ++ i )
{
vertices[i].m_Pos[0] = ToNormScreenX(_Vertices[2*i+0] + m_OffsetX, m_WndWidth);
vertices[i].m_Pos[1] = ToNormScreenY(_Vertices[2*i+1] + m_OffsetY, m_WndHeight);
vertices[i].m_Pos[2] = 0;
vertices[i].m_Color = ToR8G8B8A8(_Colors[i]);
}
m_D3DDevImmContext->Unmap(m_TrianglesVertexBuffer, 0);
// Reset shader constants
hr = m_D3DDevImmContext->Map(m_ConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( SUCCEEDED(hr) )
{
CConstants *constants = (CConstants *)mappedResource.pData;
constants->m_Offset[0] = 0;
constants->m_Offset[1] = 0;
constants->m_Offset[2] = 0;
constants->m_Offset[3] = 0;
constants->m_CstColor[0] = 1;
constants->m_CstColor[1] = 1;
constants->m_CstColor[2] = 1;
constants->m_CstColor[3] = 1;
m_D3DDevImmContext->Unmap(m_ConstantBuffer, 0);
}
// Set the input layout
m_D3DDevImmContext->IASetInputLayout(m_LineRectVertexLayout);
// Set vertex buffer
UINT stride = sizeof(CLineRectVtx);
UINT offset = 0;
m_D3DDevImmContext->IASetVertexBuffers(0, 1, &m_TrianglesVertexBuffer, &stride, &offset);
// Set primitive topology
m_D3DDevImmContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
if( _CullMode==CULL_CW )
m_D3DDevImmContext->RSSetState(m_RasterStateCullCW);
else if( _CullMode==CULL_CCW )
m_D3DDevImmContext->RSSetState(m_RasterStateCullCCW);
else
m_D3DDevImmContext->RSSetState(m_RasterStateMultisample);
// Render the triangles
m_D3DDevImmContext->VSSetConstantBuffers(0, 1, &m_ConstantBuffer);
m_D3DDevImmContext->VSSetShader(m_LineRectVS, NULL, 0);
m_D3DDevImmContext->PSSetShader(m_LineRectPS, NULL, 0);
m_D3DDevImmContext->Draw(3*_NumTriangles, 0);
m_D3DDevImmContext->RSSetState(m_RasterState); // restore default raster state
}
}
// ---------------------------------------------------------------------------