375 lines
9.2 KiB
C++
375 lines
9.2 KiB
C++
//// DspPerf.CPP - Test and display performance
|
|
//
|
|
//
|
|
|
|
|
|
#include "precomp.hxx"
|
|
#include "global.h"
|
|
|
|
|
|
#if defined(i386)
|
|
|
|
|
|
double TimeDrawString(
|
|
Graphics *g,
|
|
RectF *textRect
|
|
)
|
|
{
|
|
StringFormat format(g_formatFlags);
|
|
format.SetAlignment(g_align);
|
|
format.SetLineAlignment(g_lineAlign);
|
|
format.SetHotkeyPrefix(g_hotkey);
|
|
|
|
REAL tab[3] = {textRect->Width/4,
|
|
textRect->Width*3/16,
|
|
textRect->Width*1/8};
|
|
|
|
format.SetTabStops(0.0, sizeof(tab)/sizeof(REAL), tab);
|
|
|
|
Color blackColor(0, 0, 0);
|
|
SolidBrush blackBrush(blackColor);
|
|
Pen blackPen(&blackBrush, 1.0);
|
|
|
|
Font font(&FontFamily(g_style[0].faceName), REAL(g_style[0].emSize), g_style[0].style, g_fontUnit);
|
|
|
|
|
|
// Once to load the cache
|
|
|
|
g->DrawString(g_wcBuf, g_iTextLen, &font, *textRect, &format, g_textBrush);
|
|
|
|
ShowCursor(FALSE);
|
|
g->Flush(FlushIntentionSync);
|
|
GdiFlush();
|
|
|
|
__int64 timeAtStart;
|
|
_asm {
|
|
_emit 0FH
|
|
_emit 31H
|
|
mov dword ptr timeAtStart+4,edx
|
|
mov dword ptr timeAtStart,eax
|
|
}
|
|
|
|
// Now paint again repeatedly and measure the time taken
|
|
|
|
for (INT i=0; i<g_PerfRepeat; i++)
|
|
{
|
|
g->DrawString(g_wcBuf, g_iTextLen, &font, *textRect, &format, g_textBrush);
|
|
}
|
|
|
|
g->Flush(FlushIntentionSync);
|
|
GdiFlush();
|
|
|
|
__int64 timeAtEnd;
|
|
_asm {
|
|
_emit 0FH
|
|
_emit 31H
|
|
mov dword ptr timeAtEnd+4,edx
|
|
mov dword ptr timeAtEnd,eax
|
|
}
|
|
|
|
ShowCursor(TRUE);
|
|
|
|
return (timeAtEnd - timeAtStart) / 1000000.0;
|
|
}
|
|
|
|
|
|
|
|
double TimeDrawText(
|
|
Graphics *g,
|
|
INT x,
|
|
INT y,
|
|
INT width,
|
|
INT height
|
|
)
|
|
{
|
|
g->Flush(FlushIntentionSync); // Th is may not be necessary.
|
|
HDC hdc = g->GetHDC();
|
|
|
|
HFONT hfont = CreateFontW(
|
|
-(INT)(g_style[0].emSize + 0.5),
|
|
0, // int nWidth, // average character width
|
|
0, // int nEscapement, // angle of escapement
|
|
0, // int nOrientation, // base-line orientation angle
|
|
g_style[0].style & FontStyleBold ? 700 : 400,
|
|
g_style[0].style & FontStyleItalic ? 1 : 0,
|
|
g_style[0].style & FontStyleUnderline ? 1 : 0,
|
|
g_style[0].style & FontStyleStrikeout ? 1 : 0,
|
|
0, // DWORD fdwCharSet, // character set identifier
|
|
0, // DWORD fdwOutputPrecision, // output precision
|
|
0, // DWORD fdwClipPrecision, // clipping precision
|
|
NONANTIALIASED_QUALITY, // DWORD fdwQuality, // output quality
|
|
0, // DWORD fdwPitchAndFamily, // pitch and family
|
|
g_style[0].faceName
|
|
);
|
|
HFONT hOldFont = (HFONT) SelectObject(hdc, hfont);
|
|
|
|
RECT textRECT;
|
|
textRECT.left = x;
|
|
textRECT.top = y;
|
|
textRECT.right = x + width;
|
|
textRECT.bottom = y + height;
|
|
|
|
SetBkMode(hdc, TRANSPARENT);
|
|
|
|
DrawTextW(
|
|
hdc,
|
|
g_wcBuf,
|
|
g_iTextLen,
|
|
&textRECT,
|
|
DT_EXPANDTABS | DT_WORDBREAK
|
|
);
|
|
|
|
ShowCursor(FALSE);
|
|
GdiFlush();
|
|
|
|
__int64 timeAtStart;
|
|
_asm {
|
|
_emit 0FH
|
|
_emit 31H
|
|
mov dword ptr timeAtStart+4,edx
|
|
mov dword ptr timeAtStart,eax
|
|
}
|
|
|
|
// Now paint again repeatedly and measure the time taken
|
|
|
|
for (INT i=0; i<g_PerfRepeat; i++)
|
|
{
|
|
DrawTextW(
|
|
hdc,
|
|
g_wcBuf,
|
|
g_iTextLen,
|
|
&textRECT,
|
|
DT_EXPANDTABS | DT_WORDBREAK
|
|
);
|
|
}
|
|
|
|
GdiFlush();
|
|
|
|
__int64 timeAtEnd;
|
|
_asm {
|
|
_emit 0FH
|
|
_emit 31H
|
|
mov dword ptr timeAtEnd+4,edx
|
|
mov dword ptr timeAtEnd,eax
|
|
}
|
|
|
|
ShowCursor(TRUE);
|
|
DeleteObject(SelectObject(hdc, hOldFont));
|
|
|
|
g->ReleaseHDC(hdc);
|
|
|
|
return (timeAtEnd - timeAtStart) / 1000000.0;
|
|
}
|
|
|
|
|
|
double TimeExtTextOut(
|
|
Graphics *g,
|
|
INT x,
|
|
INT y,
|
|
INT width,
|
|
INT height
|
|
)
|
|
{
|
|
HDC hdc = g->GetHDC();
|
|
|
|
HFONT hfont = CreateFontW(
|
|
-(INT)(g_style[0].emSize + 0.5),
|
|
0, // int nWidth, // average character width
|
|
0, // int nEscapement, // angle of escapement
|
|
0, // int nOrientation, // base-line orientation angle
|
|
g_style[0].style & FontStyleBold ? 700 : 400,
|
|
g_style[0].style & FontStyleItalic ? 1 : 0,
|
|
g_style[0].style & FontStyleUnderline ? 1 : 0,
|
|
g_style[0].style & FontStyleStrikeout ? 1 : 0,
|
|
0, // DWORD fdwCharSet, // character set identifier
|
|
0, // DWORD fdwOutputPrecision, // output precision
|
|
0, // DWORD fdwClipPrecision, // clipping precision
|
|
NONANTIALIASED_QUALITY, // DWORD fdwQuality, // output quality
|
|
0, // DWORD fdwPitchAndFamily, // pitch and family
|
|
g_style[0].faceName
|
|
);
|
|
HFONT hOldFont = (HFONT) SelectObject(hdc, hfont);
|
|
|
|
RECT textRECT;
|
|
textRECT.left = x;
|
|
textRECT.top = y;
|
|
textRECT.right = x + width;
|
|
textRECT.bottom = y + height;
|
|
|
|
SetBkMode(hdc, TRANSPARENT);
|
|
|
|
ExtTextOutW(
|
|
hdc,
|
|
textRECT.left,
|
|
textRECT.top,
|
|
ETO_IGNORELANGUAGE,
|
|
&textRECT,
|
|
g_wcBuf,
|
|
g_iTextLen,
|
|
NULL
|
|
);
|
|
|
|
ShowCursor(FALSE);
|
|
GdiFlush();
|
|
|
|
__int64 timeAtStart;
|
|
_asm {
|
|
_emit 0FH
|
|
_emit 31H
|
|
mov dword ptr timeAtStart+4,edx
|
|
mov dword ptr timeAtStart,eax
|
|
}
|
|
|
|
// Now paint again repeatedly and measure the time taken
|
|
|
|
for (INT i=0; i<g_PerfRepeat; i++)
|
|
{
|
|
ExtTextOutW(
|
|
hdc,
|
|
textRECT.left,
|
|
textRECT.top,
|
|
ETO_IGNORELANGUAGE,
|
|
&textRECT,
|
|
g_wcBuf,
|
|
g_iTextLen,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
GdiFlush();
|
|
|
|
__int64 timeAtEnd;
|
|
_asm {
|
|
_emit 0FH
|
|
_emit 31H
|
|
mov dword ptr timeAtEnd+4,edx
|
|
mov dword ptr timeAtEnd,eax
|
|
}
|
|
|
|
ShowCursor(TRUE);
|
|
DeleteObject(SelectObject(hdc, hOldFont));
|
|
|
|
g->ReleaseHDC(hdc);
|
|
|
|
return (timeAtEnd - timeAtStart) / 1000000.0;
|
|
}
|
|
|
|
#endif // defined(i386)
|
|
|
|
|
|
void PaintPerformance(
|
|
HDC hdc,
|
|
int *piY,
|
|
RECT *prc,
|
|
int iLineHeight) {
|
|
|
|
int icpLineStart; // First character of line
|
|
int icpLineEnd; // End of line (end of buffer or index of CR character)
|
|
HFONT hFont;
|
|
HFONT hOldFont;
|
|
LOGFONT lf;
|
|
|
|
|
|
// Establish available width and height in device coordinates
|
|
|
|
int plainTextWidth = prc->right - prc->left;
|
|
int plainTextHeight = prc->bottom - *piY;
|
|
|
|
|
|
// Paint some simple text, and then repaint it several times measuring the
|
|
// time taken.
|
|
|
|
Graphics g(hdc);
|
|
Matrix matrix;
|
|
|
|
|
|
g.ResetTransform();
|
|
g.SetPageUnit(UnitPixel);
|
|
g.TranslateTransform(REAL(prc->left), REAL(*piY));
|
|
g.SetSmoothingMode(g_SmoothingMode);
|
|
|
|
g.SetTextContrast(g_GammaValue);
|
|
g.SetTextRenderingHint(g_TextMode);
|
|
|
|
// Clear the background
|
|
|
|
RectF rEntire(0, 0, REAL(plainTextWidth), REAL(plainTextHeight));
|
|
SolidBrush whiteBrush(Color(0xff, 0xff, 0xff));
|
|
g.FillRectangle(g_textBackBrush, rEntire);
|
|
|
|
|
|
// Apply selected world transform, adjusted a little from the top left
|
|
// of the available area.
|
|
|
|
g.SetTransform(&g_WorldTransform);
|
|
g.TranslateTransform(
|
|
REAL(prc->left + plainTextWidth/20),
|
|
REAL(*piY + plainTextHeight/20),
|
|
MatrixOrderAppend);
|
|
|
|
|
|
#if defined(i386)
|
|
|
|
|
|
double drawString = TimeDrawString(
|
|
&g,
|
|
&RectF(
|
|
0.0,
|
|
0.0,
|
|
REAL(plainTextWidth*18.0/20.0),
|
|
REAL(plainTextHeight*5.0/20.0)
|
|
)
|
|
);
|
|
|
|
double drawText = TimeDrawText(
|
|
&g,
|
|
prc->left + plainTextWidth/20,
|
|
*piY + 6*plainTextHeight/20,
|
|
(18 * plainTextWidth)/20,
|
|
(5 * plainTextHeight)/20
|
|
);
|
|
|
|
double extTextOut = TimeExtTextOut(
|
|
&g,
|
|
prc->left + plainTextWidth/20,
|
|
*piY + 12*plainTextHeight/20,
|
|
(18 * plainTextWidth)/20,
|
|
(2 * plainTextHeight)/20
|
|
);
|
|
|
|
// Display the time taken
|
|
|
|
RectF statisticsRect(
|
|
0.0,
|
|
REAL(plainTextHeight*15.0/20.0),
|
|
REAL(plainTextWidth*18.0/20.0),
|
|
REAL(plainTextHeight*5.0/20.0)
|
|
);
|
|
|
|
Font font(&FontFamily(L"Verdana"), 12, 0, UnitPoint);
|
|
|
|
char drawStringFormatted[20]; _gcvt(drawString, 10, drawStringFormatted);
|
|
char drawTextFormatted[20]; _gcvt(drawText, 10, drawTextFormatted);
|
|
char extTextOutFormatted[20]; _gcvt(extTextOut, 10, extTextOutFormatted);
|
|
|
|
WCHAR str[200];
|
|
wsprintfW(str, L"Time taken to display %d times: DrawString %S, DrawText %S, ExtTextOut %S megaticks\n",
|
|
g_PerfRepeat,
|
|
drawStringFormatted,
|
|
drawTextFormatted,
|
|
extTextOutFormatted
|
|
);
|
|
g.DrawString(str, -1, &font, statisticsRect, NULL, g_textBrush);
|
|
|
|
|
|
|
|
#else
|
|
|
|
Font font(&FontFamily(L"Verdana"), 12, 0, UnitPoint);
|
|
g.DrawString(L"Perf test available only on i386 Intel architecture", -1, &font, PointF(0.0,0.0), NULL, g_textBrush);
|
|
|
|
#endif
|
|
|
|
*piY += plainTextHeight;
|
|
}
|