mirror of
https://github.com/libretro/RetroArch
synced 2025-02-25 12:41:18 +00:00
Revert "(360) Cleanups fonts.cpp"
This reverts commit 0c5c3c4299d7115610bd0f6de119238dc28f7372.
This commit is contained in:
parent
8e4d2f6feb
commit
8f7ca9130a
236
360/fonts.cpp
236
360/fonts.cpp
@ -62,6 +62,7 @@ HRESULT xdk360_console_init( LPCSTR strFontFileName, unsigned long colBackColor,
|
||||
video_console.m_Lines = NULL;
|
||||
video_console.m_nScrollOffset = 0;
|
||||
|
||||
// Calculate the safe area
|
||||
unsigned int uiSafeAreaPct = vid->video_mode.fIsHiDef ? SAFE_AREA_PCT_HDTV
|
||||
: SAFE_AREA_PCT_4x3;
|
||||
|
||||
@ -71,6 +72,7 @@ HRESULT xdk360_console_init( LPCSTR strFontFileName, unsigned long colBackColor,
|
||||
video_console.m_cxSafeAreaOffset = ( vid->d3dpp.BackBufferWidth - video_console.m_cxSafeArea ) / 2;
|
||||
video_console.m_cySafeAreaOffset = ( vid->d3dpp.BackBufferHeight - video_console.m_cySafeArea ) / 2;
|
||||
|
||||
// Create the font
|
||||
HRESULT hr = xdk360_video_font_init(&m_Font, strFontFileName );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
@ -78,9 +80,11 @@ HRESULT xdk360_console_init( LPCSTR strFontFileName, unsigned long colBackColor,
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Save the colors
|
||||
video_console.m_colBackColor = colBackColor;
|
||||
video_console.m_colTextColor = colTextColor;
|
||||
|
||||
// Calculate the number of lines on the screen
|
||||
float fCharWidth, fCharHeight;
|
||||
xdk360_video_font_get_text_width(&m_Font, L"i", &fCharWidth, &fCharHeight, FALSE);
|
||||
|
||||
@ -91,9 +95,11 @@ HRESULT xdk360_console_init( LPCSTR strFontFileName, unsigned long colBackColor,
|
||||
|
||||
video_console.m_fLineHeight = fCharHeight;
|
||||
|
||||
// Allocate memory to hold the lines
|
||||
video_console.m_Buffer = new wchar_t[ video_console.m_cScreenHeightVirtual * ( video_console.m_cScreenWidth + 1 ) ];
|
||||
video_console.m_Lines = new wchar_t *[ video_console.m_cScreenHeightVirtual ];
|
||||
|
||||
// Set the line pointers as indexes into the buffer
|
||||
for( unsigned int i = 0; i < video_console.m_cScreenHeightVirtual; i++ )
|
||||
video_console.m_Lines[ i ] = video_console.m_Buffer + ( video_console.m_cScreenWidth + 1 ) * i;
|
||||
|
||||
@ -107,6 +113,7 @@ HRESULT xdk360_console_init( LPCSTR strFontFileName, unsigned long colBackColor,
|
||||
|
||||
void xdk360_console_deinit()
|
||||
{
|
||||
// Delete the memory we've allocated
|
||||
if(video_console.m_Lines)
|
||||
{
|
||||
delete[] video_console.m_Lines;
|
||||
@ -119,11 +126,13 @@ void xdk360_console_deinit()
|
||||
video_console.m_Buffer = NULL;
|
||||
}
|
||||
|
||||
// Destroy the font
|
||||
xdk360_video_font_deinit(&m_Font);
|
||||
}
|
||||
|
||||
void xdk360_console_add( wchar_t wch )
|
||||
{
|
||||
// If this is a newline, just increment lines and move on
|
||||
if( wch == L'\n' )
|
||||
{
|
||||
video_console.m_nCurLine = ( video_console.m_nCurLine + 1 )
|
||||
@ -134,12 +143,13 @@ void xdk360_console_add( wchar_t wch )
|
||||
return;
|
||||
}
|
||||
|
||||
int bIncrementLine = FALSE;
|
||||
int bIncrementLine = FALSE; // Whether to wrap to the next line
|
||||
|
||||
if( video_console.m_cCurLineLength == video_console.m_cScreenWidth )
|
||||
bIncrementLine = TRUE;
|
||||
else
|
||||
{
|
||||
// Try to append the character to the line
|
||||
video_console.m_Lines[ video_console.m_nCurLine ][ video_console.m_cCurLineLength ] = wch;
|
||||
|
||||
float fTextWidth, fTextHeight;
|
||||
@ -149,11 +159,13 @@ void xdk360_console_add( wchar_t wch )
|
||||
|
||||
if( fTextHeight > video_console.m_cxSafeArea )
|
||||
{
|
||||
// The line is too long, we need to wrap the character to the next line
|
||||
video_console.m_Lines[video_console.m_nCurLine][ video_console.m_cCurLineLength ] = L'\0';
|
||||
bIncrementLine = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// If we need to skip to the next line, do so
|
||||
if( bIncrementLine )
|
||||
{
|
||||
video_console.m_nCurLine = ( video_console.m_nCurLine + 1 )
|
||||
@ -179,21 +191,24 @@ void xdk360_console_format(_In_z_ _Printf_format_string_ LPCSTR strFormat, ... )
|
||||
va_list pArgList;
|
||||
va_start( pArgList, strFormat );
|
||||
|
||||
// Count the required length of the string
|
||||
unsigned long dwStrLen = _vscprintf( strFormat, pArgList ) + 1;
|
||||
// +1 = null terminator
|
||||
char * strMessage = ( char * )_malloca( dwStrLen );
|
||||
vsprintf_s( strMessage, dwStrLen, strFormat, pArgList );
|
||||
|
||||
// Output the string to the console
|
||||
unsigned long uStringLength = strlen( strMessage );
|
||||
for( unsigned long i = 0; i < uStringLength; i++ )
|
||||
{
|
||||
wchar_t wch;
|
||||
int ret = MultiByteToWideChar(
|
||||
CP_ACP,
|
||||
0,
|
||||
&strMessage[i],
|
||||
1,
|
||||
&wch,
|
||||
1 );
|
||||
CP_ACP, // ANSI code page
|
||||
0, // No flags
|
||||
&strMessage[i], // Character to convert
|
||||
1, // Convert one byte
|
||||
&wch, // Target wide character buffer
|
||||
1 ); // One wide character
|
||||
xdk360_console_add( wch );
|
||||
}
|
||||
|
||||
@ -212,10 +227,12 @@ void xdk360_console_format_w(_In_z_ _Printf_format_string_ LPCWSTR wstrFormat, .
|
||||
va_list pArgList;
|
||||
va_start( pArgList, wstrFormat );
|
||||
|
||||
unsigned long dwStrLen = _vscwprintf( wstrFormat, pArgList ) + 1;
|
||||
// Count the required length of the string
|
||||
unsigned long dwStrLen = _vscwprintf( wstrFormat, pArgList ) + 1; // +1 = null terminator
|
||||
wchar_t * strMessage = ( wchar_t * )_malloca( dwStrLen * sizeof( wchar_t ) );
|
||||
vswprintf_s( strMessage, dwStrLen, wstrFormat, pArgList );
|
||||
|
||||
// Output the string to the console
|
||||
unsigned long uStringLength = wcslen( strMessage );
|
||||
for( unsigned long i = 0; i < uStringLength; i++ )
|
||||
xdk360_console_add( strMessage[i] );
|
||||
@ -226,19 +243,24 @@ void xdk360_console_format_w(_In_z_ _Printf_format_string_ LPCWSTR wstrFormat, .
|
||||
}
|
||||
|
||||
#define CALCFONTFILEHEADERSIZE(x) ( sizeof(unsigned long) + (sizeof(float)* 4) + sizeof(unsigned short) + (sizeof(wchar_t)*(x)) )
|
||||
#define FONTFILEVERSION 5
|
||||
|
||||
typedef struct FontFileHeaderImage_t {
|
||||
float m_fFontHeight;
|
||||
float m_fFontTopPadding;
|
||||
float m_fFontBottomPadding;
|
||||
float m_fFontYAdvance;
|
||||
unsigned short m_cMaxGlyph;
|
||||
wchar_t m_TranslatorTable[1];
|
||||
unsigned long m_dwFileVersion; // Version of the font file (Must match FONTFILEVERSION)
|
||||
float m_fFontHeight; // Height of the font strike in pixels
|
||||
float m_fFontTopPadding; // Padding above the strike zone
|
||||
float m_fFontBottomPadding; // Padding below the strike zone
|
||||
float m_fFontYAdvance; // Number of pixels to move the cursor for a line feed
|
||||
unsigned short m_cMaxGlyph; // Number of font characters (Should be an odd number to maintain DWORD Alignment)
|
||||
wchar_t m_TranslatorTable[1]; // ASCII to Glyph lookup table, NOTE: It's m_cMaxGlyph+1 in size.
|
||||
} FontFileHeaderImage_t;
|
||||
|
||||
// Font strike array. Immediately follows the FontFileHeaderImage_t
|
||||
// structure image
|
||||
|
||||
typedef struct FontFileStrikesImage_t {
|
||||
unsigned long m_dwNumGlyphs;
|
||||
GLYPH_ATTR m_Glyphs[1];
|
||||
unsigned long m_dwNumGlyphs; // Size of font strike array (First entry is the unknown glyph)
|
||||
GLYPH_ATTR m_Glyphs[1]; // Array of font strike uv's etc... NOTE: It's m_dwNumGlyphs in size
|
||||
} FontFileStrikesImage_t;
|
||||
|
||||
static PackedResource m_xprResource;
|
||||
@ -274,21 +296,37 @@ static const char g_strFontShader[] =
|
||||
"}\n";
|
||||
|
||||
typedef struct Font_Locals_t {
|
||||
D3DVertexDeclaration* m_pFontVertexDecl;
|
||||
D3DVertexShader* m_pFontVertexShader;
|
||||
D3DPixelShader* m_pFontPixelShader;
|
||||
D3DVertexDeclaration* m_pFontVertexDecl; // Shared vertex buffer
|
||||
D3DVertexShader* m_pFontVertexShader; // Created vertex shader
|
||||
D3DPixelShader* m_pFontPixelShader; // Created pixel shader
|
||||
} Font_Locals_t;
|
||||
|
||||
static Font_Locals_t s_FontLocals;
|
||||
// All elements are defaulted to NULL
|
||||
static Font_Locals_t s_FontLocals; // Global static instance
|
||||
|
||||
static HRESULT xdk360_video_font_create_shaders (xdk360_video_font_t * font)
|
||||
{
|
||||
//
|
||||
// There are only two states the globals could be in,
|
||||
// Initialized, in which the ref count is increased,
|
||||
// Uninialized, in which the vertex/pixel shaders need to be
|
||||
// started up and a vertex array created.
|
||||
///
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
if (!s_FontLocals.m_pFontVertexDecl)
|
||||
{
|
||||
// Use the do {} while(0); trick for a fake goto
|
||||
// It simplies tear down on error conditions.
|
||||
do
|
||||
{
|
||||
|
||||
// Step #1, create my vertex array with 16 bytes per entry
|
||||
// Floats for the position,
|
||||
// shorts for the uvs
|
||||
// 32 bit packed ARGB 8:8:8:8 for color
|
||||
|
||||
static const D3DVERTEXELEMENT9 decl[] =
|
||||
{
|
||||
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
|
||||
@ -297,6 +335,7 @@ static HRESULT xdk360_video_font_create_shaders (xdk360_video_font_t * font)
|
||||
D3DDECL_END()
|
||||
};
|
||||
|
||||
// Cache this global into a register
|
||||
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
|
||||
D3DDevice *pd3dDevice = vid->d3d_render_device;
|
||||
|
||||
@ -304,6 +343,7 @@ static HRESULT xdk360_video_font_create_shaders (xdk360_video_font_t * font)
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Step #2, create my vertex shader
|
||||
ID3DXBuffer* pShaderCode;
|
||||
|
||||
hr = D3DXCompileShader( g_strFontShader, sizeof(g_strFontShader)-1 ,
|
||||
@ -312,35 +352,42 @@ static HRESULT xdk360_video_font_create_shaders (xdk360_video_font_t * font)
|
||||
{
|
||||
hr = pd3dDevice->CreateVertexShader( ( unsigned long * )pShaderCode->GetBufferPointer(),
|
||||
&s_FontLocals.m_pFontVertexShader );
|
||||
// Release the compiled shader
|
||||
pShaderCode->Release();
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
// Step #3, create my pixel shader
|
||||
hr = D3DXCompileShader( g_strFontShader, sizeof(g_strFontShader)-1 ,
|
||||
NULL, NULL, "main_fragment", "ps.2.0", 0,&pShaderCode, NULL, NULL );
|
||||
if ( SUCCEEDED(hr))
|
||||
{
|
||||
hr = pd3dDevice->CreatePixelShader( ( DWORD* )pShaderCode->GetBufferPointer(),
|
||||
&s_FontLocals.m_pFontPixelShader );
|
||||
// Release the compiled shader
|
||||
pShaderCode->Release();
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = S_OK;
|
||||
break;
|
||||
break; // Skip the teardown code
|
||||
}
|
||||
}
|
||||
|
||||
// If the code got to here, a fatal error has occured
|
||||
// and a clean shutdown needs to be performed.
|
||||
D3DResource_Release((D3DResource *)s_FontLocals.m_pFontVertexShader);
|
||||
}
|
||||
|
||||
// Ensure the pointer is NULL
|
||||
s_FontLocals.m_pFontVertexShader = NULL;
|
||||
}
|
||||
|
||||
D3DResource_Release((D3DResource *)s_FontLocals.m_pFontVertexDecl);
|
||||
}
|
||||
// Ensure this pointer is NULL
|
||||
s_FontLocals.m_pFontVertexDecl = NULL;
|
||||
}while(0);
|
||||
}while(0); // Exit point for the break command.
|
||||
return hr;
|
||||
}
|
||||
else
|
||||
@ -350,7 +397,7 @@ static HRESULT xdk360_video_font_create_shaders (xdk360_video_font_t * font)
|
||||
D3DResource_AddRef((D3DResource *)s_FontLocals.m_pFontPixelShader);
|
||||
hr = S_OK;
|
||||
}
|
||||
return hr;
|
||||
return hr; // Return the error code if any
|
||||
}
|
||||
|
||||
void xdk360_video_font_set_size(xdk360_video_font_t * font, float x, float y)
|
||||
@ -372,28 +419,45 @@ HRESULT xdk360_video_font_init(xdk360_video_font_t * font, const char * strFontF
|
||||
font->m_TranslatorTable = NULL;
|
||||
font->m_dwNestedBeginCount = 0L;
|
||||
|
||||
// Create the font
|
||||
if( FAILED( m_xprResource.Create( strFontFileName ) ) )
|
||||
return E_FAIL;
|
||||
|
||||
D3DTexture * pFontTexture = m_xprResource.GetTexture( "FontTexture" );
|
||||
const void * pFontData = m_xprResource.GetData( "FontData");
|
||||
|
||||
// Save a copy of the texture
|
||||
font->m_pFontTexture = pFontTexture;
|
||||
|
||||
// Check version of file (to make sure it matches up with the FontMaker tool)
|
||||
const unsigned char * pData = static_cast<const unsigned char *>(pFontData);
|
||||
unsigned long dwFileVersion = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_dwFileVersion;
|
||||
|
||||
font->m_fFontHeight = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontHeight;
|
||||
font->m_fFontTopPadding = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontTopPadding;
|
||||
font->m_fFontBottomPadding = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontBottomPadding;
|
||||
font->m_fFontYAdvance = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontYAdvance;
|
||||
font->m_cMaxGlyph = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_cMaxGlyph;
|
||||
font->m_TranslatorTable = const_cast<FontFileHeaderImage_t*>(reinterpret_cast<const FontFileHeaderImage_t *>(pData))->m_TranslatorTable;
|
||||
if( dwFileVersion == FONTFILEVERSION )
|
||||
{
|
||||
font->m_fFontHeight = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontHeight;
|
||||
font->m_fFontTopPadding = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontTopPadding;
|
||||
font->m_fFontBottomPadding = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontBottomPadding;
|
||||
font->m_fFontYAdvance = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontYAdvance;
|
||||
|
||||
pData += CALCFONTFILEHEADERSIZE( font->m_cMaxGlyph + 1 );
|
||||
// Point to the translator string which immediately follows the 4 floats
|
||||
font->m_cMaxGlyph = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_cMaxGlyph;
|
||||
|
||||
font->m_dwNumGlyphs = reinterpret_cast<const FontFileStrikesImage_t *>(pData)->m_dwNumGlyphs;
|
||||
font->m_Glyphs = reinterpret_cast<const FontFileStrikesImage_t *>(pData)->m_Glyphs;
|
||||
font->m_TranslatorTable = const_cast<FontFileHeaderImage_t*>(reinterpret_cast<const FontFileHeaderImage_t *>(pData))->m_TranslatorTable;
|
||||
|
||||
pData += CALCFONTFILEHEADERSIZE( font->m_cMaxGlyph + 1 );
|
||||
|
||||
// Read the glyph attributes from the file
|
||||
font->m_dwNumGlyphs = reinterpret_cast<const FontFileStrikesImage_t *>(pData)->m_dwNumGlyphs;
|
||||
font->m_Glyphs = reinterpret_cast<const FontFileStrikesImage_t *>(pData)->m_Glyphs; // Pointer
|
||||
}
|
||||
else
|
||||
{
|
||||
RARCH_ERR( "Incorrect version number on font file.\n" );
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Create the vertex and pixel shaders for rendering the font
|
||||
if( FAILED( xdk360_video_font_create_shaders(font) ) )
|
||||
{
|
||||
RARCH_ERR( "Could not create font shaders.\n" );
|
||||
@ -403,6 +467,7 @@ HRESULT xdk360_video_font_init(xdk360_video_font_t * font, const char * strFontF
|
||||
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
|
||||
D3DDevice *pd3dDevice = vid->d3d_render_device;
|
||||
|
||||
// Initialize the window
|
||||
D3DDISPLAYMODE DisplayMode;
|
||||
pd3dDevice->GetDisplayMode( 0, &DisplayMode );
|
||||
font->m_rcWindow.x1 = 0;
|
||||
@ -410,6 +475,7 @@ HRESULT xdk360_video_font_init(xdk360_video_font_t * font, const char * strFontF
|
||||
font->m_rcWindow.x2 = DisplayMode.Width;
|
||||
font->m_rcWindow.y2 = DisplayMode.Height;
|
||||
|
||||
// Determine whether we should save/restore state
|
||||
font->m_bSaveState = TRUE;
|
||||
|
||||
return S_OK;
|
||||
@ -424,6 +490,10 @@ void xdk360_video_font_deinit(xdk360_video_font_t * font)
|
||||
font->m_TranslatorTable = NULL;
|
||||
font->m_dwNestedBeginCount = 0L;
|
||||
|
||||
// Safely release shaders
|
||||
// NOTE: They are released in reverse order of creation
|
||||
// to make sure any interdependencies are dealt with
|
||||
|
||||
if( ( s_FontLocals.m_pFontPixelShader != NULL ) && ( s_FontLocals.m_pFontPixelShader->Release() == 0 ) )
|
||||
s_FontLocals.m_pFontPixelShader = NULL;
|
||||
if( ( s_FontLocals.m_pFontVertexShader != NULL ) && ( s_FontLocals.m_pFontVertexShader->Release() == 0 ) )
|
||||
@ -443,53 +513,67 @@ void xdk360_video_font_set_cursor_position(xdk360_video_font_t *font, float fCur
|
||||
|
||||
void xdk360_video_font_get_text_width(xdk360_video_font_t * font, const wchar_t * strText, float * pWidth, float * pHeight, int bFirstLineOnly)
|
||||
{
|
||||
// Set default text extent in output parameters
|
||||
int iWidth = 0;
|
||||
float fHeight = 0.0f;
|
||||
|
||||
if( strText )
|
||||
{
|
||||
// Initialize counters that keep track of text extent
|
||||
int ix = 0;
|
||||
float fy = font->m_fFontHeight;
|
||||
float fy = font->m_fFontHeight; // One character high to start
|
||||
if( fy > fHeight )
|
||||
fHeight = fy;
|
||||
|
||||
// Loop through each character and update text extent
|
||||
unsigned long letter;
|
||||
while( (letter = *strText) != 0 )
|
||||
{
|
||||
++strText;
|
||||
|
||||
// Handle newline character
|
||||
if( letter == L'\n' )
|
||||
{
|
||||
if( bFirstLineOnly )
|
||||
break;
|
||||
ix = 0;
|
||||
fy += font->m_fFontYAdvance;
|
||||
// since the height has changed, test against the height extent
|
||||
if( fy > fHeight )
|
||||
fHeight = fy;
|
||||
}
|
||||
|
||||
// Handle carriage return characters by ignoring them. This helps when
|
||||
// displaying text from a file.
|
||||
if( letter == L'\r' )
|
||||
continue;
|
||||
|
||||
// Translate unprintable characters
|
||||
const GLYPH_ATTR* pGlyph;
|
||||
|
||||
if( letter > font->m_cMaxGlyph )
|
||||
letter = 0;
|
||||
letter = 0; // Out of bounds?
|
||||
else
|
||||
letter = font->m_TranslatorTable[letter];
|
||||
letter = font->m_TranslatorTable[letter]; // Remap ASCII to glyph
|
||||
|
||||
pGlyph = &font->m_Glyphs[letter];
|
||||
pGlyph = &font->m_Glyphs[letter]; // Get the requested glyph
|
||||
|
||||
// Get text extent for this character's glyph
|
||||
ix += pGlyph->wOffset;
|
||||
ix += pGlyph->wAdvance;
|
||||
|
||||
// Since the x widened, test against the x extent
|
||||
|
||||
if( ix > iWidth )
|
||||
iWidth = ix;
|
||||
}
|
||||
}
|
||||
|
||||
float fWidth = static_cast<float>(iWidth);
|
||||
// Convert the width to a float here, load/hit/store. :(
|
||||
float fWidth = static_cast<float>(iWidth); // Delay the use if fWidth to reduce LHS pain
|
||||
// Apply the scale factor to the result
|
||||
fHeight *= font->m_fYScaleFactor;
|
||||
// Store the final results
|
||||
*pHeight = fHeight;
|
||||
|
||||
fWidth *= font->m_fXScaleFactor;
|
||||
@ -498,14 +582,21 @@ void xdk360_video_font_get_text_width(xdk360_video_font_t * font, const wchar_t
|
||||
|
||||
void xdk360_video_font_begin (xdk360_video_font_t * font)
|
||||
{
|
||||
// Set state on the first call
|
||||
if( font->m_dwNestedBeginCount == 0 )
|
||||
{
|
||||
// Cache the global pointer into a register
|
||||
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
|
||||
D3DDevice *pD3dDevice = vid->d3d_render_device;
|
||||
|
||||
// Save state
|
||||
if( font->m_bSaveState )
|
||||
{
|
||||
pD3dDevice->GetRenderState( D3DRS_ALPHABLENDENABLE, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHABLENDENABLE ] );
|
||||
// Note, we are not saving the texture, vertex, or pixel shader,
|
||||
// since it's not worth the performance. We're more interested
|
||||
// in saving state that would cause hard to find problems.
|
||||
pD3dDevice->GetRenderState( D3DRS_ALPHABLENDENABLE,
|
||||
&font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHABLENDENABLE ] );
|
||||
pD3dDevice->GetRenderState( D3DRS_SRCBLEND, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_SRCBLEND ] );
|
||||
pD3dDevice->GetRenderState( D3DRS_DESTBLEND, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_DESTBLEND ] );
|
||||
pD3dDevice->GetRenderState( D3DRS_BLENDOP, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_BLENDOP ] );
|
||||
@ -521,12 +612,16 @@ void xdk360_video_font_begin (xdk360_video_font_t * font)
|
||||
font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSV ] = D3DDevice_GetSamplerState_AddressV( pD3dDevice, 0);
|
||||
}
|
||||
|
||||
// Set the texture scaling factor as a vertex shader constant
|
||||
D3DSURFACE_DESC TextureDesc;
|
||||
D3DTexture_GetLevelDesc(font->m_pFontTexture, 0, &TextureDesc);
|
||||
D3DTexture_GetLevelDesc(font->m_pFontTexture, 0, &TextureDesc); // Get the description
|
||||
|
||||
// Set render state
|
||||
D3DDevice_SetTexture_Inline(pD3dDevice, 0, font->m_pFontTexture);
|
||||
|
||||
// Read the TextureDesc here to ensure no load/hit/store from GetLevelDesc()
|
||||
float vTexScale[4];
|
||||
vTexScale[0] = 1.0f / TextureDesc.Width;
|
||||
vTexScale[0] = 1.0f / TextureDesc.Width; // LHS due to int->float conversion
|
||||
vTexScale[1] = 1.0f / TextureDesc.Height;
|
||||
vTexScale[2] = 0.0f;
|
||||
vTexScale[3] = 0.0f;
|
||||
@ -550,9 +645,12 @@ void xdk360_video_font_begin (xdk360_video_font_t * font)
|
||||
D3DDevice_SetVertexShader(pD3dDevice, s_FontLocals.m_pFontVertexShader );
|
||||
D3DDevice_SetPixelShader(pD3dDevice, s_FontLocals.m_pFontPixelShader );
|
||||
|
||||
// Set the texture scaling factor as a vertex shader constant
|
||||
// Call here to avoid load hit store from writing to vTexScale above
|
||||
pD3dDevice->SetVertexShaderConstantF( 2, vTexScale, 1 );
|
||||
}
|
||||
|
||||
// Keep track of the nested begin/end calls.
|
||||
font->m_dwNestedBeginCount++;
|
||||
}
|
||||
|
||||
@ -561,8 +659,10 @@ void xdk360_video_font_end(xdk360_video_font_t * font)
|
||||
if( --font->m_dwNestedBeginCount > 0 )
|
||||
return;
|
||||
|
||||
// Restore state
|
||||
if( font->m_bSaveState )
|
||||
{
|
||||
// Cache the global pointer into a register
|
||||
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
|
||||
D3DDevice *pD3dDevice = vid->d3d_render_device;
|
||||
|
||||
@ -596,16 +696,22 @@ void xdk360_video_font_draw_text(xdk360_video_font_t * font, float fOriginX, flo
|
||||
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
|
||||
D3DDevice *pd3dDevice = vid->d3d_render_device;
|
||||
|
||||
// Set the color as a vertex shader constant
|
||||
float vColor[4];
|
||||
vColor[0] = ( ( dwColor & 0x00ff0000 ) >> 16L ) / 255.0F;
|
||||
vColor[1] = ( ( dwColor & 0x0000ff00 ) >> 8L ) / 255.0F;
|
||||
vColor[2] = ( ( dwColor & 0x000000ff ) >> 0L ) / 255.0F;
|
||||
vColor[3] = ( ( dwColor & 0xff000000 ) >> 24L ) / 255.0F;
|
||||
|
||||
// Set up stuff to prepare for drawing text
|
||||
xdk360_video_font_begin(font);
|
||||
|
||||
// Perform the actual storing of the color constant here to prevent
|
||||
// a load-hit-store by inserting work between the store and the use of
|
||||
// the vColor array.
|
||||
pd3dDevice->SetVertexShaderConstantF( 1, vColor, 1 );
|
||||
|
||||
// Set the starting screen position
|
||||
if((fOriginX < 0.0f))
|
||||
fOriginX += font->m_rcWindow.x2;
|
||||
if( fOriginY < 0.0f )
|
||||
@ -613,8 +719,11 @@ void xdk360_video_font_draw_text(xdk360_video_font_t * font, float fOriginX, flo
|
||||
|
||||
font->m_fCursorX = floorf( fOriginX );
|
||||
font->m_fCursorY = floorf( fOriginY );
|
||||
|
||||
// Adjust for padding
|
||||
fOriginY -= font->m_fFontTopPadding;
|
||||
|
||||
// Add window offsets
|
||||
float Winx = 0.0f;
|
||||
float Winy = 0.0f;
|
||||
fOriginX += Winx;
|
||||
@ -622,21 +731,32 @@ void xdk360_video_font_draw_text(xdk360_video_font_t * font, float fOriginX, flo
|
||||
font->m_fCursorX += Winx;
|
||||
font->m_fCursorY += Winy;
|
||||
|
||||
// Begin drawing the vertices
|
||||
|
||||
// Declared as volatile to force writing in ascending
|
||||
// address order. It prevents out of sequence writing in write combined
|
||||
// memory.
|
||||
|
||||
volatile float * pVertex;
|
||||
|
||||
unsigned long dwNumChars = wcslen(strText);
|
||||
HRESULT hr = pd3dDevice->BeginVertices( D3DPT_QUADLIST, 4 * dwNumChars, sizeof( XMFLOAT4 ) ,
|
||||
( VOID** )&pVertex );
|
||||
|
||||
// The ring buffer may run out of space when tiling, doing z-prepasses,
|
||||
// or using BeginCommandBuffer. If so, make the buffer larger.
|
||||
if( FAILED( hr ) )
|
||||
RARCH_ERR( "Ring buffer out of memory.\n" );
|
||||
|
||||
// Draw four vertices for each glyph
|
||||
while( *strText )
|
||||
{
|
||||
wchar_t letter;
|
||||
|
||||
// Get the current letter in the string
|
||||
letter = *strText++;
|
||||
|
||||
// Handle the newline character
|
||||
if( letter == L'\n' )
|
||||
{
|
||||
font->m_fCursorX = fOriginX;
|
||||
@ -644,6 +764,7 @@ void xdk360_video_font_draw_text(xdk360_video_font_t * font, float fOriginX, flo
|
||||
continue;
|
||||
}
|
||||
|
||||
// Translate unprintable characters
|
||||
const GLYPH_ATTR * pGlyph = &font->m_Glyphs[ ( letter <= font->m_cMaxGlyph ) ? font->m_TranslatorTable[letter] : 0 ];
|
||||
|
||||
float fOffset = font->m_fXScaleFactor * (float)pGlyph->wOffset;
|
||||
@ -651,6 +772,7 @@ void xdk360_video_font_draw_text(xdk360_video_font_t * font, float fOriginX, flo
|
||||
float fWidth = font->m_fXScaleFactor * (float)pGlyph->wWidth;
|
||||
float fHeight = font->m_fYScaleFactor * font->m_fFontHeight;
|
||||
|
||||
// Setup the screen coordinates
|
||||
font->m_fCursorX += fOffset;
|
||||
float X4 = font->m_fCursorX;
|
||||
float X1 = X4;
|
||||
@ -663,39 +785,58 @@ void xdk360_video_font_draw_text(xdk360_video_font_t * font, float fOriginX, flo
|
||||
|
||||
font->m_fCursorX += fAdvance;
|
||||
|
||||
unsigned long dwChannelSelector = pGlyph->wMask;
|
||||
// Select the RGBA channel that the compressed glyph is stored in
|
||||
// Takes a 4 bit per pixel ARGB value and expand it to an 8 bit per pixel ARGB value
|
||||
|
||||
unsigned long dwChannelSelector = pGlyph->wMask; // Convert to 32 bit
|
||||
// Perform the conversion without branching
|
||||
|
||||
// Splat the 4 bit per pixels from 0x1234 to 0x01020304
|
||||
dwChannelSelector = ((dwChannelSelector&0xF000)<<(24-12))|((dwChannelSelector&0xF00)<<(16-8))|
|
||||
((dwChannelSelector&0xF0)<<(8-4))|(dwChannelSelector&0xF);
|
||||
|
||||
// Perform a vectorized multiply to make 0x01020304 into 0x11223344
|
||||
dwChannelSelector *= 0x11;
|
||||
|
||||
unsigned long tu1 = pGlyph->tu1;
|
||||
// Add the vertices to draw this glyph
|
||||
|
||||
unsigned long tu1 = pGlyph->tu1; // Convert shorts to 32 bit longs for in register merging
|
||||
unsigned long tv1 = pGlyph->tv1;
|
||||
unsigned long tu2 = pGlyph->tu2;
|
||||
unsigned long tv2 = pGlyph->tv2;
|
||||
|
||||
// NOTE: The vertexs are 2 floats for the screen coordinates,
|
||||
// followed by two USHORTS for the u/vs of the character,
|
||||
// terminated with the ARGB 32 bit color.
|
||||
// This makes for 16 bytes per vertex data (Easier to read)
|
||||
// Second NOTE: The uvs are merged and written using a DWORD due
|
||||
// to the write combining hardware being only able to handle 32,
|
||||
// 64 and 128 writes. Never store to write combined memory with
|
||||
// 8 or 16 bit instructions. You've been warned.
|
||||
|
||||
pVertex[0] = X1;
|
||||
pVertex[1] = Y1;
|
||||
reinterpret_cast<volatile unsigned long *>(pVertex)[2] = (tu1<<16)|tv1;
|
||||
reinterpret_cast<volatile unsigned long *>(pVertex)[2] = (tu1<<16)|tv1; // Merged using big endian rules
|
||||
reinterpret_cast<volatile unsigned long *>(pVertex)[3] = dwChannelSelector;
|
||||
pVertex[4] = X2;
|
||||
pVertex[5] = Y2;
|
||||
reinterpret_cast<volatile unsigned long *>(pVertex)[6] = (tu2<<16)|tv1;
|
||||
reinterpret_cast<volatile unsigned long *>(pVertex)[6] = (tu2<<16)|tv1; // Merged using big endian rules
|
||||
reinterpret_cast<volatile unsigned long *>(pVertex)[7] = dwChannelSelector;
|
||||
pVertex[8] = X3;
|
||||
pVertex[9] = Y3;
|
||||
reinterpret_cast<volatile unsigned long *>(pVertex)[10] = (tu2<<16)|tv2;
|
||||
reinterpret_cast<volatile unsigned long *>(pVertex)[10] = (tu2<<16)|tv2; // Merged using big endian rules
|
||||
reinterpret_cast<volatile unsigned long *>(pVertex)[11] = dwChannelSelector;
|
||||
pVertex[12] = X4;
|
||||
pVertex[13] = Y4;
|
||||
reinterpret_cast<volatile unsigned long *>(pVertex)[14] = (tu1<<16)|tv2;
|
||||
reinterpret_cast<volatile unsigned long *>(pVertex)[14] = (tu1<<16)|tv2; // Merged using big endian rules
|
||||
reinterpret_cast<volatile unsigned long *>(pVertex)[15] = dwChannelSelector;
|
||||
pVertex+=16;
|
||||
|
||||
dwNumChars--;
|
||||
}
|
||||
|
||||
// Since we allocated vertex data space based on the string length, we now need to
|
||||
// add some dummy verts for any skipped characters (like newlines, etc.)
|
||||
while( dwNumChars )
|
||||
{
|
||||
pVertex[0] = 0;
|
||||
@ -718,10 +859,13 @@ void xdk360_video_font_draw_text(xdk360_video_font_t * font, float fOriginX, flo
|
||||
dwNumChars--;
|
||||
}
|
||||
|
||||
// Stop drawing vertices
|
||||
D3DDevice_EndVertices(pd3dDevice);
|
||||
|
||||
// Undo window offsets
|
||||
font->m_fCursorX -= Winx;
|
||||
font->m_fCursorY -= Winy;
|
||||
|
||||
// Call End() to complete the begin/end pair for drawing text
|
||||
xdk360_video_font_end(font);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user