Make font rendering a lot prettier.
Fix constant buffers in EmuGfxState::ApplyState() to really have a size which is a multiple of 16 instead of 65536.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5755 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
NeoBrainX 2010-06-20 23:10:55 +00:00
parent 6a88241e64
commit a450fd45d8
4 changed files with 43 additions and 39 deletions

View File

@ -61,8 +61,9 @@ const char fontpixshader[] = {
"SamplerState linearSampler\n" "SamplerState linearSampler\n"
"{\n" "{\n"
" Filter = MIN_MAG_MIP_LINEAR;\n" " Filter = MIN_MAG_MIP_LINEAR;\n"
" AddressU = Wrap;\n" " AddressU = D3D11_TEXTURE_ADDRESS_BORDER;\n"
" AddressV = Wrap;\n" " AddressV = D3D11_TEXTURE_ADDRESS_BORDER;\n"
" BorderColor = float4(0.f, 0.f, 0.f, 0.f);\n"
"};\n" "};\n"
"struct PS_INPUT\n" "struct PS_INPUT\n"
"{\n" "{\n"
@ -120,12 +121,9 @@ int CD3DFont::Init()
SetMapMode(hDC, MM_TEXT); SetMapMode(hDC, MM_TEXT);
// create a GDI font // create a GDI font
int m_dwFontHeight = 24; HFONT hFont = CreateFont(24, 0, 0, 0, FW_NORMAL, FALSE,
int nHeight = -MulDiv(m_dwFontHeight, (int)GetDeviceCaps(hDC, LOGPIXELSY), 72);
int dwBold = FW_NORMAL;
HFONT hFont = CreateFont(nHeight, 0, 0, 0, dwBold, 0,
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
VARIABLE_PITCH, _T("Tahoma")); VARIABLE_PITCH, _T("Tahoma"));
if (NULL == hFont) return E_FAIL; if (NULL == hFont) return E_FAIL;
@ -137,6 +135,10 @@ int CD3DFont::Init()
SetBkColor (hDC, 0); SetBkColor (hDC, 0);
SetTextAlign(hDC, TA_TOP); SetTextAlign(hDC, TA_TOP);
TEXTMETRICW tm;
GetTextMetricsW(hDC, &tm);
m_LineHeight = tm.tmHeight;
// loop through all printable characters and output them to the bitmap // loop through all printable characters and output them to the bitmap
// meanwhile, keep track of the corresponding tex coords for each character. // meanwhile, keep track of the corresponding tex coords for each character.
int x = 0, y = 0; int x = 0, y = 0;
@ -149,14 +151,14 @@ int CD3DFont::Init()
if ((int)(x+size.cx+1) > m_dwTexWidth) if ((int)(x+size.cx+1) > m_dwTexWidth)
{ {
x = 0; x = 0;
y += size.cy + 1; y += m_LineHeight;
} }
ExtTextOutA(hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL); ExtTextOutA(hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL);
m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth; m_fTexCoords[c][0] = (float) x /m_dwTexWidth;
m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight; m_fTexCoords[c][1] = (float) y /m_dwTexHeight;
m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth; m_fTexCoords[c][2] = (float)(x+size.cx)/m_dwTexWidth;
m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight; m_fTexCoords[c][3] = (float)(y+size.cy)/m_dwTexHeight;
x += size.cx + 3; // 3 to work around annoying ij conflict (part of the j ends up with the i) x += size.cx + 3; // 3 to work around annoying ij conflict (part of the j ends up with the i)
} }
@ -187,7 +189,7 @@ int CD3DFont::Init()
for (x = 0; x < m_dwTexWidth; x++) for (x = 0; x < m_dwTexWidth; x++)
{ {
const u8 bAlpha = (pBitmapBits[m_dwTexWidth * y + x] & 0xff); const u8 bAlpha = (pBitmapBits[m_dwTexWidth * y + x] & 0xff);
pDst32[x] = ((bAlpha * 255 / 15) << 24) | 0xFFFFFF; *pDst32++ = (((bAlpha << 4) | bAlpha) << 24) | 0xFFFFFF;
} }
} }
@ -270,16 +272,20 @@ int CD3DFont::Shutdown()
return S_OK; return S_OK;
} }
int CD3DFont::DrawTextScaled(float x, float y, float scale, float spacing, u32 dwColor, const char* strText, bool center) int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dwColor, const char* strText, bool center)
{ {
if (!m_pVB) return 0; if (!m_pVB) return 0;
UINT stride = sizeof(FONT2DVERTEX); UINT stride = sizeof(FONT2DVERTEX);
UINT bufoffset = 0; UINT bufoffset = 0;
float scalex = 1 / (float)D3D::GetBackBufferWidth() * 2.f;
float scaley = 1 / (float)D3D::GetBackBufferHeight() * 2.f;
float sizeratio = size / (float)m_LineHeight;
// translate starting positions // translate starting positions
float sx = x / m_dwTexWidth - 1; float sx = x * scalex - 1.f;
float sy = 1 - y / m_dwTexHeight; float sy = 1.f - y * scaley;
char c; char c;
// fill vertex buffer // fill vertex buffer
@ -301,20 +307,15 @@ int CD3DFont::DrawTextScaled(float x, float y, float scale, float spacing, u32 d
while (c = *strText++) while (c = *strText++)
{ {
if (c == ('\n')) if (c == ('\n')) mx = 0;
mx = 0; if (c < (' ') ) continue;
if (c < (' '))
continue;
c -= 32; c -= 32;
mx += (m_fTexCoords[c][2]-m_fTexCoords[c][0])/(m_fTexCoords[0][3] - m_fTexCoords[0][1]) mx += (m_fTexCoords[c][2]-m_fTexCoords[c][0])/(m_fTexCoords[0][3] - m_fTexCoords[0][1]) + spacing;
+ spacing;
if (mx > maxx) maxx = mx; if (mx > maxx) maxx = mx;
} }
sx -= scale*maxx/(2*m_dwTexWidth); sx -= scalex*maxx*size;
strText = oldText; strText = oldText;
} }
// we now have a starting point
float fStartX = sx;
// set general pipeline state // set general pipeline state
D3D::stateman->PushBlendState(m_blendstate); D3D::stateman->PushBlendState(m_blendstate);
D3D::stateman->PushRasterizerState(m_raststate); D3D::stateman->PushRasterizerState(m_raststate);
@ -326,23 +327,25 @@ int CD3DFont::DrawTextScaled(float x, float y, float scale, float spacing, u32 d
D3D::context->IASetInputLayout(m_InputLayout); D3D::context->IASetInputLayout(m_InputLayout);
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
D3D::context->PSSetShaderResources(0, 1, &m_pTexture); D3D::context->PSSetShaderResources(0, 1, &m_pTexture);
float fStartX = sx;
while (c = *strText++) while (c = *strText++)
{ {
if (c == ('\n')) if (c == ('\n'))
{ {
sx = fStartX; sx = fStartX;
sy -= scale / m_dwTexHeight; sy -= scaley * size;
} }
if (c < (' ')) if (c < (' ')) continue;
continue;
c -= 32; c -= 32;
float tx1 = m_fTexCoords[c][0]; float tx1 = m_fTexCoords[c][0];
float ty1 = m_fTexCoords[c][1]; float ty1 = m_fTexCoords[c][1];
float tx2 = m_fTexCoords[c][2]; float tx2 = m_fTexCoords[c][2];
float ty2 = m_fTexCoords[c][3]; float ty2 = m_fTexCoords[c][3];
float w = (tx2-tx1)/2; float w = (float)(tx2-tx1) * m_dwTexWidth * scalex * sizeratio;
float h = (ty1-ty2)/2; float h = (float)(ty1-ty2) * m_dwTexHeight * scaley * sizeratio;
FONT2DVERTEX v[6]; FONT2DVERTEX v[6];
v[0] = InitFont2DVertex( sx, h+sy, dwColor, tx1, ty2); v[0] = InitFont2DVertex( sx, h+sy, dwColor, tx1, ty2);
@ -366,11 +369,11 @@ int CD3DFont::DrawTextScaled(float x, float y, float scale, float spacing, u32 d
dwNumTriangles = 0; dwNumTriangles = 0;
D3D11_MAPPED_SUBRESOURCE vbmap; D3D11_MAPPED_SUBRESOURCE vbmap;
HRESULT hr = context->Map(m_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vbmap); hr = context->Map(m_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vbmap);
if (FAILED(hr)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__, __LINE__); if (FAILED(hr)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__, __LINE__);
pVertices = (D3D::FONT2DVERTEX*)vbmap.pData; pVertices = (D3D::FONT2DVERTEX*)vbmap.pData;
} }
sx += w + spacing*scale/m_dwTexWidth; sx += w + spacing * scalex * size;
} }
// Unlock and render the vertex buffer // Unlock and render the vertex buffer

View File

@ -41,6 +41,7 @@ namespace D3D
ID3D11RasterizerState* m_raststate; ID3D11RasterizerState* m_raststate;
const int m_dwTexWidth; const int m_dwTexWidth;
const int m_dwTexHeight; const int m_dwTexHeight;
unsigned int m_LineHeight;
float m_fTexCoords[128-32][4]; float m_fTexCoords[128-32][4];
public: public:
@ -50,7 +51,7 @@ namespace D3D
int Init(); int Init();
int Shutdown(); int Shutdown();
int DrawTextScaled(float x, float y, int DrawTextScaled(float x, float y,
float scale, float size,
float spacing, u32 dwColor, float spacing, u32 dwColor,
const char* strText, bool center=true); const char* strText, bool center=true);
}; };

View File

@ -141,7 +141,7 @@ void EmuGfxState::ApplyState()
// TODO: improve interaction between EmuGfxState and global state management, so that we don't need to set the constant buffers every time // TODO: improve interaction between EmuGfxState and global state management, so that we don't need to set the constant buffers every time
if (!vscbuf) if (!vscbuf)
{ {
unsigned int size = ((sizeof(float)*952)&(~0xffff))+0x10000; // must be a multiple of 16 unsigned int size = ((sizeof(vsconstants))&(~0xf))+0x10; // must be a multiple of 16
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
hr = device->CreateBuffer(&cbdesc, NULL, &vscbuf); hr = device->CreateBuffer(&cbdesc, NULL, &vscbuf);
CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", size); CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", size);
@ -159,7 +159,7 @@ void EmuGfxState::ApplyState()
// pixel shader // pixel shader
if (!pscbuf) if (!pscbuf)
{ {
unsigned int size = ((sizeof(float)*116)&(~0xffff))+0x10000; // must be a multiple of 16 unsigned int size = ((sizeof(psconstants))&(~0xf))+0x10; // must be a multiple of 16
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
device->CreateBuffer(&cbdesc, NULL, &pscbuf); device->CreateBuffer(&cbdesc, NULL, &pscbuf);
CHECK(hr==S_OK, "Create pixel shader constant buffer (size=%u)", size); CHECK(hr==S_OK, "Create pixel shader constant buffer (size=%u)", size);

View File

@ -469,7 +469,7 @@ void Renderer::DrawDebugText()
void Renderer::RenderText(const char* text, int left, int top, u32 color) void Renderer::RenderText(const char* text, int left, int top, u32 color)
{ {
D3D::font.DrawTextScaled((float)left, (float)top, 15, 0.0f, color, text, false); D3D::font.DrawTextScaled((float)left, (float)top, 20.f, 0.0f, color, text, false);
} }
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
@ -930,7 +930,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
{ {
char fps[20]; char fps[20];
StringCchPrintfA(fps, 20, "FPS: %d\n", s_fps); StringCchPrintfA(fps, 20, "FPS: %d\n", s_fps);
D3D::font.DrawTextScaled(0,30,30,0.0f,0xFF00FFFF,fps,false); D3D::font.DrawTextScaled(0,30,20,0.0f,0xFF00FFFF,fps,false);
} }
Renderer::DrawDebugText(); Renderer::DrawDebugText();
@ -938,13 +938,13 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
{ {
char buf[32768]; char buf[32768];
Statistics::ToString(buf); Statistics::ToString(buf);
D3D::font.DrawTextScaled(0,30,30,0.0f,0xFF00FFFF,buf,false); D3D::font.DrawTextScaled(0,30,20,0.0f,0xFF00FFFF,buf,false);
} }
else if (g_ActiveConfig.bOverlayProjStats) else if (g_ActiveConfig.bOverlayProjStats)
{ {
char buf[32768]; char buf[32768];
Statistics::ToStringProj(buf); Statistics::ToStringProj(buf);
D3D::font.DrawTextScaled(0,30,30,0.0f,0xFF00FFFF,buf,false); D3D::font.DrawTextScaled(0,30,20,0.0f,0xFF00FFFF,buf,false);
} }
OSD::DrawMessages(); OSD::DrawMessages();