mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Added stats overlay
This commit is contained in:
parent
ab443a1ac2
commit
07d77d09dc
@ -1,6 +1,41 @@
|
||||
#include <Common/Time.h>
|
||||
#include <D3dDdi/ScopedCriticalSection.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Overlay/StatsWindow.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
unsigned g_depth = 0;
|
||||
Overlay::StatsWindow* g_statsWindow = nullptr;
|
||||
}
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
Compat::CriticalSection ScopedCriticalSection::s_cs;
|
||||
|
||||
ScopedCriticalSection::ScopedCriticalSection()
|
||||
: Compat::ScopedCriticalSection(s_cs)
|
||||
{
|
||||
if (0 == g_depth)
|
||||
{
|
||||
g_statsWindow = Gdi::GuiThread::getStatsWindow();
|
||||
if (g_statsWindow)
|
||||
{
|
||||
g_statsWindow->m_ddiUsage.start();
|
||||
}
|
||||
}
|
||||
++g_depth;
|
||||
}
|
||||
|
||||
ScopedCriticalSection::~ScopedCriticalSection()
|
||||
{
|
||||
--g_depth;
|
||||
if (0 == g_depth)
|
||||
{
|
||||
if (g_statsWindow)
|
||||
{
|
||||
g_statsWindow->m_ddiUsage.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,8 @@ namespace D3dDdi
|
||||
class ScopedCriticalSection : public Compat::ScopedCriticalSection
|
||||
{
|
||||
public:
|
||||
ScopedCriticalSection() : Compat::ScopedCriticalSection(s_cs) {}
|
||||
ScopedCriticalSection();
|
||||
~ScopedCriticalSection();
|
||||
|
||||
private:
|
||||
static Compat::CriticalSection s_cs;
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <Gdi/Window.h>
|
||||
#include <Gdi/WinProc.h>
|
||||
#include <Overlay/ConfigWindow.h>
|
||||
#include <Overlay/StatsWindow.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
|
||||
namespace
|
||||
@ -319,6 +320,13 @@ namespace
|
||||
|
||||
Gdi::GuiThread::execute([]()
|
||||
{
|
||||
auto statsWindow = Gdi::GuiThread::getStatsWindow();
|
||||
if (statsWindow)
|
||||
{
|
||||
statsWindow->m_present.add();
|
||||
statsWindow->update();
|
||||
}
|
||||
|
||||
auto configWindow = Gdi::GuiThread::getConfigWindow();
|
||||
if (configWindow)
|
||||
{
|
||||
@ -531,6 +539,11 @@ namespace DDraw
|
||||
}
|
||||
else
|
||||
{
|
||||
auto statsWindow = Gdi::GuiThread::getStatsWindow();
|
||||
if (statsWindow && statsWindow->isVisible())
|
||||
{
|
||||
statsWindow->updateStats();
|
||||
}
|
||||
updateNow(PrimarySurface::getPrimary());
|
||||
}
|
||||
g_flipEndVsyncCount = D3dDdi::KernelModeThunks::getVsyncCounter() + flipInterval;
|
||||
@ -557,6 +570,12 @@ namespace DDraw
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto statsWindow = Gdi::GuiThread::getStatsWindow();
|
||||
if (statsWindow && statsWindow->isVisible())
|
||||
{
|
||||
statsWindow->updateStats();
|
||||
}
|
||||
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_presentCs);
|
||||
if (!g_isUpdateReady)
|
||||
|
@ -10,8 +10,10 @@
|
||||
#include <DDraw/Surfaces/PrimarySurfaceImpl.h>
|
||||
#include <Dll/Dll.h>
|
||||
#include <Gdi/Gdi.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/Region.h>
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
#include <Overlay/StatsWindow.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -97,6 +99,11 @@ namespace DDraw
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
bltToGdi(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
|
||||
auto statsWindow = Gdi::GuiThread::getStatsWindow();
|
||||
if (statsWindow)
|
||||
{
|
||||
statsWindow->m_blit.add();
|
||||
}
|
||||
RealPrimarySurface::scheduleUpdate();
|
||||
PrimarySurface::waitForIdle();
|
||||
}
|
||||
@ -116,6 +123,11 @@ namespace DDraw
|
||||
HRESULT result = SurfaceImpl::BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
auto statsWindow = Gdi::GuiThread::getStatsWindow();
|
||||
if (statsWindow)
|
||||
{
|
||||
statsWindow->m_blit.add();
|
||||
}
|
||||
RealPrimarySurface::scheduleUpdate();
|
||||
PrimarySurface::waitForIdle();
|
||||
}
|
||||
@ -158,6 +170,12 @@ namespace DDraw
|
||||
return result;
|
||||
}
|
||||
|
||||
auto statsWindow = Gdi::GuiThread::getStatsWindow();
|
||||
if (statsWindow)
|
||||
{
|
||||
statsWindow->m_flip.add();
|
||||
}
|
||||
|
||||
PrimarySurface::updateFrontResource();
|
||||
result = RealPrimarySurface::flip(surfaceTargetOverride, dwFlags);
|
||||
if (SUCCEEDED(result) && Config::Settings::FpsLimiter::FLIPEND == Config::fpsLimiter.get())
|
||||
@ -233,6 +251,11 @@ namespace DDraw
|
||||
HRESULT result = SurfaceImpl::ReleaseDC(This, hDC);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
auto statsWindow = Gdi::GuiThread::getStatsWindow();
|
||||
if (statsWindow)
|
||||
{
|
||||
statsWindow->m_lock.add();
|
||||
}
|
||||
RealPrimarySurface::scheduleUpdate();
|
||||
}
|
||||
return result;
|
||||
@ -277,6 +300,11 @@ namespace DDraw
|
||||
HRESULT result = SurfaceImpl::Unlock(This, lpRect);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
auto statsWindow = Gdi::GuiThread::getStatsWindow();
|
||||
if (statsWindow)
|
||||
{
|
||||
statsWindow->m_lock.add();
|
||||
}
|
||||
RealPrimarySurface::scheduleUpdate();
|
||||
}
|
||||
return result;
|
||||
|
@ -291,6 +291,14 @@
|
||||
<ClInclude Include="Overlay\LabelControl.h" />
|
||||
<ClInclude Include="Overlay\ScrollBarControl.h" />
|
||||
<ClInclude Include="Overlay\SettingControl.h" />
|
||||
<ClInclude Include="Overlay\StatsControl.h" />
|
||||
<ClInclude Include="Overlay\StatsEventCount.h" />
|
||||
<ClInclude Include="Overlay\StatsEventGroup.h" />
|
||||
<ClInclude Include="Overlay\StatsEventTime.h" />
|
||||
<ClInclude Include="Overlay\StatsQueue.h" />
|
||||
<ClInclude Include="Overlay\StatsEventRate.h" />
|
||||
<ClInclude Include="Overlay\StatsTimer.h" />
|
||||
<ClInclude Include="Overlay\StatsWindow.h" />
|
||||
<ClInclude Include="Overlay\Window.h" />
|
||||
<ClInclude Include="Win32\DisplayMode.h" />
|
||||
<ClInclude Include="Win32\Log.h" />
|
||||
@ -406,6 +414,14 @@
|
||||
<ClCompile Include="Overlay\LabelControl.cpp" />
|
||||
<ClCompile Include="Overlay\ScrollBarControl.cpp" />
|
||||
<ClCompile Include="Overlay\SettingControl.cpp" />
|
||||
<ClCompile Include="Overlay\StatsControl.cpp" />
|
||||
<ClCompile Include="Overlay\StatsEventCount.cpp" />
|
||||
<ClCompile Include="Overlay\StatsEventGroup.cpp" />
|
||||
<ClCompile Include="Overlay\StatsEventTime.cpp" />
|
||||
<ClCompile Include="Overlay\StatsQueue.cpp" />
|
||||
<ClCompile Include="Overlay\StatsEventRate.cpp" />
|
||||
<ClCompile Include="Overlay\StatsTimer.cpp" />
|
||||
<ClCompile Include="Overlay\StatsWindow.cpp" />
|
||||
<ClCompile Include="Overlay\Window.cpp" />
|
||||
<ClCompile Include="Win32\DisplayMode.cpp" />
|
||||
<ClCompile Include="Win32\Log.cpp" />
|
||||
|
@ -603,6 +603,30 @@
|
||||
<ClInclude Include="Config\Settings\ResolutionScaleFilter.h">
|
||||
<Filter>Header Files\Config\Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Overlay\StatsWindow.h">
|
||||
<Filter>Header Files\Overlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Overlay\StatsControl.h">
|
||||
<Filter>Header Files\Overlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Overlay\StatsQueue.h">
|
||||
<Filter>Header Files\Overlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Overlay\StatsTimer.h">
|
||||
<Filter>Header Files\Overlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Overlay\StatsEventRate.h">
|
||||
<Filter>Header Files\Overlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Overlay\StatsEventTime.h">
|
||||
<Filter>Header Files\Overlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Overlay\StatsEventCount.h">
|
||||
<Filter>Header Files\Overlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Overlay\StatsEventGroup.h">
|
||||
<Filter>Header Files\Overlay</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
@ -944,6 +968,30 @@
|
||||
<ClCompile Include="DDraw\Surfaces\PalettizedTextureImpl.cpp">
|
||||
<Filter>Source Files\DDraw\Surfaces</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Overlay\StatsWindow.cpp">
|
||||
<Filter>Source Files\Overlay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Overlay\StatsControl.cpp">
|
||||
<Filter>Source Files\Overlay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Overlay\StatsQueue.cpp">
|
||||
<Filter>Source Files\Overlay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Overlay\StatsTimer.cpp">
|
||||
<Filter>Source Files\Overlay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Overlay\StatsEventRate.cpp">
|
||||
<Filter>Source Files\Overlay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Overlay\StatsEventTime.cpp">
|
||||
<Filter>Source Files\Overlay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Overlay\StatsEventCount.cpp">
|
||||
<Filter>Source Files\Overlay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Overlay\StatsEventGroup.cpp">
|
||||
<Filter>Source Files\Overlay</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="DDrawCompat.rc">
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <Gdi/Region.h>
|
||||
#include <Gdi/WinProc.h>
|
||||
#include <Overlay/ConfigWindow.h>
|
||||
#include <Overlay/StatsWindow.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
|
||||
namespace
|
||||
@ -20,6 +21,7 @@ namespace
|
||||
|
||||
unsigned g_threadId = 0;
|
||||
Overlay::ConfigWindow* g_configWindow = nullptr;
|
||||
Overlay::StatsWindow* g_statsWindow = nullptr;
|
||||
HWND g_messageWindow = nullptr;
|
||||
bool g_isReady = false;
|
||||
|
||||
@ -78,6 +80,9 @@ namespace
|
||||
return 0;
|
||||
}
|
||||
|
||||
Overlay::StatsWindow statsWindow;
|
||||
g_statsWindow = &statsWindow;
|
||||
|
||||
Overlay::ConfigWindow configWindow;
|
||||
g_configWindow = &configWindow;
|
||||
|
||||
@ -160,6 +165,11 @@ namespace Gdi
|
||||
return g_configWindow;
|
||||
}
|
||||
|
||||
Overlay::StatsWindow* getStatsWindow()
|
||||
{
|
||||
return g_statsWindow;
|
||||
}
|
||||
|
||||
bool isGuiThreadWindow(HWND hwnd)
|
||||
{
|
||||
return GetWindowThreadProcessId(hwnd, nullptr) == g_threadId;
|
||||
|
@ -9,6 +9,7 @@
|
||||
namespace Overlay
|
||||
{
|
||||
class ConfigWindow;
|
||||
class StatsWindow;
|
||||
}
|
||||
|
||||
namespace Gdi
|
||||
@ -22,6 +23,7 @@ namespace Gdi
|
||||
void setWindowRgn(HWND hwnd, Gdi::Region rgn);
|
||||
|
||||
Overlay::ConfigWindow* getConfigWindow();
|
||||
Overlay::StatsWindow* getStatsWindow();
|
||||
|
||||
template <typename Func>
|
||||
void execute(const Func& func) { executeFunc(std::cref(func)); }
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <Gdi/Window.h>
|
||||
#include <Gdi/WinProc.h>
|
||||
#include <Overlay/ConfigWindow.h>
|
||||
#include <Overlay/StatsWindow.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
|
||||
namespace
|
||||
@ -141,18 +142,39 @@ namespace
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_ACTIVATEAPP:
|
||||
if (!wParam)
|
||||
{
|
||||
Gdi::GuiThread::execute([&]()
|
||||
Gdi::GuiThread::execute([&]()
|
||||
{
|
||||
static bool hidden = false;
|
||||
static bool configVisible = false;
|
||||
static bool statsVisible = false;
|
||||
|
||||
auto configWindow = Gdi::GuiThread::getConfigWindow();
|
||||
auto statsWindow = Gdi::GuiThread::getStatsWindow();
|
||||
if (!wParam && !hidden)
|
||||
{
|
||||
configVisible = configWindow ? configWindow->isVisible() : false;
|
||||
statsVisible = statsWindow ? statsWindow->isVisible() : false;
|
||||
hidden = true;
|
||||
}
|
||||
|
||||
if (configWindow)
|
||||
{
|
||||
configWindow->setVisible(wParam ? configVisible : false);
|
||||
}
|
||||
if (statsWindow)
|
||||
{
|
||||
statsWindow->setVisible(wParam ? statsVisible : false);
|
||||
}
|
||||
|
||||
if (wParam)
|
||||
{
|
||||
hidden = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto configWindow = Gdi::GuiThread::getConfigWindow();
|
||||
if (configWindow)
|
||||
{
|
||||
configWindow->setVisible(false);
|
||||
}
|
||||
CALL_ORIG_FUNC(ClipCursor)(nullptr);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case WM_CTLCOLORSCROLLBAR:
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <Gdi/Window.h>
|
||||
#include <Input/Input.h>
|
||||
#include <Overlay/ConfigWindow.h>
|
||||
#include <Overlay/StatsWindow.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -395,6 +396,15 @@ namespace Gdi
|
||||
}
|
||||
|
||||
RECT wr = {};
|
||||
auto statsWindow = GuiThread::getStatsWindow();
|
||||
if (statsWindow && statsWindow->isVisible())
|
||||
{
|
||||
GetWindowRect(statsWindow->getWindow(), &wr);
|
||||
auto visibleRegion(getWindowRegion(statsWindow->getWindow()));
|
||||
visibleRegion.offset(wr.left, wr.top);
|
||||
layeredWindows.push_back({ statsWindow->getWindow(), wr, visibleRegion });
|
||||
}
|
||||
|
||||
auto configWindow = GuiThread::getConfigWindow();
|
||||
if (configWindow && configWindow->isVisible())
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
namespace Overlay
|
||||
{
|
||||
ComboBoxDropDown::ComboBoxDropDown(ComboBoxControl& parent, const std::vector<std::string>& values)
|
||||
: Window(&static_cast<Window&>(parent.getRoot()), calculateRect(parent, values.size()))
|
||||
: Window(&static_cast<Window&>(parent.getRoot()), calculateRect(parent, values.size()), WS_BORDER)
|
||||
, m_parent(parent)
|
||||
{
|
||||
for (int i = 0; i < static_cast<int>(values.size()); ++i)
|
||||
@ -83,5 +83,6 @@ namespace Overlay
|
||||
{
|
||||
m_highlightedChild = nullptr;
|
||||
Window::setVisible(visible);
|
||||
Input::setCapture(visible ? this : m_parentWindow);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include <Common/Hook.h>
|
||||
#include <Common/Log.h>
|
||||
#include <Config/Config.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
@ -17,7 +16,7 @@ namespace
|
||||
namespace Overlay
|
||||
{
|
||||
ConfigWindow::ConfigWindow()
|
||||
: Window(nullptr, { 0, 0, SettingControl::TOTAL_WIDTH, 430 }, Config::configHotKey.get())
|
||||
: Window(nullptr, { 0, 0, SettingControl::TOTAL_WIDTH, 430 }, WS_BORDER, Config::configHotKey.get())
|
||||
, m_buttonCount(0)
|
||||
, m_focus(nullptr)
|
||||
{
|
||||
@ -186,6 +185,7 @@ namespace Overlay
|
||||
if (isVisible != Window::isVisible())
|
||||
{
|
||||
Window::setVisible(isVisible);
|
||||
Input::setCapture(isVisible ? this : nullptr);
|
||||
setFocus(nullptr);
|
||||
}
|
||||
}
|
||||
|
@ -33,4 +33,13 @@ namespace Overlay
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void LabelControl::setLabel(const std::string label)
|
||||
{
|
||||
if (m_label != label)
|
||||
{
|
||||
m_label = label;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace Overlay
|
||||
virtual void onLButtonDown(POINT pos) override;
|
||||
|
||||
const std::string& getLabel() const { return m_label; }
|
||||
void setLabel(const std::string label) { m_label = label; }
|
||||
void setLabel(const std::string label);
|
||||
void setColor(COLORREF color);
|
||||
|
||||
private:
|
||||
|
30
DDrawCompat/Overlay/StatsControl.cpp
Normal file
30
DDrawCompat/Overlay/StatsControl.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include <Overlay/StatsWindow.h>
|
||||
#include <Overlay/StatsControl.h>
|
||||
|
||||
namespace Overlay
|
||||
{
|
||||
StatsControl::StatsControl(StatsWindow& parent, const RECT& rect, const std::string& caption, UpdateFunc updateFunc, DWORD style)
|
||||
: Control(&parent, rect, style)
|
||||
, m_captionLabel(*this, { rect.left, rect.top,
|
||||
rect.left + NAME_LABEL_WIDTH, rect.bottom }, caption, 0, WS_DISABLED | WS_VISIBLE)
|
||||
, m_curLabel(*this, { m_captionLabel.getRect().right, rect.top,
|
||||
m_captionLabel.getRect().right + VALUE_LABEL_WIDTH, rect.bottom}, std::string(), DT_RIGHT)
|
||||
, m_avgLabel(*this, { m_curLabel.getRect().right, rect.top,
|
||||
m_curLabel.getRect().right + VALUE_LABEL_WIDTH, rect.bottom }, std::string(), DT_RIGHT)
|
||||
, m_minLabel(*this, { m_avgLabel.getRect().right, rect.top,
|
||||
m_avgLabel.getRect().right + VALUE_LABEL_WIDTH, rect.bottom }, std::string(), DT_RIGHT)
|
||||
, m_maxLabel(*this, { m_minLabel.getRect().right, rect.top,
|
||||
m_minLabel.getRect().right + VALUE_LABEL_WIDTH, rect.bottom }, std::string(), DT_RIGHT)
|
||||
, m_updateFunc(updateFunc)
|
||||
{
|
||||
}
|
||||
|
||||
void StatsControl::update(StatsQueue::TickCount tickCount)
|
||||
{
|
||||
auto stats = m_updateFunc(tickCount);
|
||||
m_curLabel.setLabel(stats[0]);
|
||||
m_avgLabel.setLabel(stats[1]);
|
||||
m_minLabel.setLabel(stats[2]);
|
||||
m_maxLabel.setLabel(stats[3]);
|
||||
}
|
||||
}
|
33
DDrawCompat/Overlay/StatsControl.h
Normal file
33
DDrawCompat/Overlay/StatsControl.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
|
||||
#include <Overlay/LabelControl.h>
|
||||
#include <Overlay/StatsQueue.h>
|
||||
|
||||
namespace Overlay
|
||||
{
|
||||
class StatsWindow;
|
||||
|
||||
class StatsControl : public Control
|
||||
{
|
||||
public:
|
||||
static const int NAME_LABEL_WIDTH = 70;
|
||||
static const int VALUE_LABEL_WIDTH = 40;
|
||||
|
||||
typedef std::function<std::array<std::string, 4>(StatsQueue::TickCount)> UpdateFunc;
|
||||
|
||||
StatsControl(StatsWindow& parent, const RECT& rect, const std::string& caption, UpdateFunc updateFunc, DWORD style);
|
||||
|
||||
void update(StatsQueue::TickCount tickCount);
|
||||
|
||||
private:
|
||||
LabelControl m_captionLabel;
|
||||
LabelControl m_curLabel;
|
||||
LabelControl m_avgLabel;
|
||||
LabelControl m_minLabel;
|
||||
LabelControl m_maxLabel;
|
||||
UpdateFunc m_updateFunc;
|
||||
};
|
||||
}
|
37
DDrawCompat/Overlay/StatsEventCount.cpp
Normal file
37
DDrawCompat/Overlay/StatsEventCount.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <Overlay/StatsEventCount.h>
|
||||
|
||||
StatsEventCount::StatsEventCount()
|
||||
: m_sampleCounts(TICKS_PER_SEC)
|
||||
, m_sampleCount(0)
|
||||
, m_totalSampleCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
void StatsEventCount::add(TickCount tickCount)
|
||||
{
|
||||
setTickCount(tickCount);
|
||||
m_sampleCount++;
|
||||
}
|
||||
|
||||
void StatsEventCount::finalize(SampleCount& sampleCount, Stat& sum, Stat& min, Stat& max)
|
||||
{
|
||||
const uint32_t index = getCurrentTickCount() % TICKS_PER_SEC;
|
||||
m_totalSampleCount += m_sampleCount;
|
||||
m_totalSampleCount -= m_sampleCounts[index];
|
||||
m_sampleCounts[index] = m_sampleCount;
|
||||
m_sampleCount = 0;
|
||||
|
||||
sum = m_totalSampleCount;
|
||||
min = m_totalSampleCount;
|
||||
max = m_totalSampleCount;
|
||||
sampleCount = 1;
|
||||
}
|
||||
|
||||
void StatsEventCount::resetTickCount()
|
||||
{
|
||||
std::fill(m_sampleCounts.begin(), m_sampleCounts.end(), 0);
|
||||
m_sampleCount = 0;
|
||||
m_totalSampleCount = 0;
|
||||
}
|
19
DDrawCompat/Overlay/StatsEventCount.h
Normal file
19
DDrawCompat/Overlay/StatsEventCount.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <Overlay/StatsQueue.h>
|
||||
|
||||
class StatsEventCount : public StatsQueue
|
||||
{
|
||||
public:
|
||||
StatsEventCount();
|
||||
|
||||
void add(TickCount tickCount);
|
||||
|
||||
private:
|
||||
virtual void finalize(SampleCount& sampleCount, Stat& sum, Stat& min, Stat& max) override;
|
||||
virtual void resetTickCount() override;
|
||||
|
||||
std::vector<SampleCount> m_sampleCounts;
|
||||
SampleCount m_sampleCount;
|
||||
SampleCount m_totalSampleCount;
|
||||
};
|
15
DDrawCompat/Overlay/StatsEventGroup.cpp
Normal file
15
DDrawCompat/Overlay/StatsEventGroup.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include <Overlay/StatsEventGroup.h>
|
||||
|
||||
StatsEventGroup::StatsEventGroup()
|
||||
: m_rate(m_time)
|
||||
{
|
||||
}
|
||||
|
||||
void StatsEventGroup::add()
|
||||
{
|
||||
auto qpcNow = Time::queryPerformanceCounter();
|
||||
auto tickCount = StatsQueue::getTickCount(qpcNow);
|
||||
|
||||
m_count.add(tickCount);
|
||||
m_time.add(tickCount, qpcNow);
|
||||
}
|
17
DDrawCompat/Overlay/StatsEventGroup.h
Normal file
17
DDrawCompat/Overlay/StatsEventGroup.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <Overlay/StatsEventCount.h>
|
||||
#include <Overlay/StatsEventRate.h>
|
||||
#include <Overlay/StatsEventTime.h>
|
||||
|
||||
class StatsEventGroup
|
||||
{
|
||||
public:
|
||||
StatsEventGroup();
|
||||
|
||||
void add();
|
||||
|
||||
StatsEventCount m_count;
|
||||
StatsEventTime m_time;
|
||||
StatsEventRate m_rate;
|
||||
};
|
22
DDrawCompat/Overlay/StatsEventRate.cpp
Normal file
22
DDrawCompat/Overlay/StatsEventRate.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <Overlay/StatsEventRate.h>
|
||||
#include <Overlay/StatsEventTime.h>
|
||||
|
||||
StatsEventRate::StatsEventRate(StatsEventTime& parent)
|
||||
: m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
StatsQueue::Stats StatsEventRate::getRawStats(TickCount tickCount)
|
||||
{
|
||||
auto stats = m_parent.getRawStats(tickCount);
|
||||
std::swap(stats.min, stats.max);
|
||||
return stats;
|
||||
}
|
||||
|
||||
double StatsEventRate::convert(double stat)
|
||||
{
|
||||
return Time::g_qpcFrequency / stat;
|
||||
}
|
17
DDrawCompat/Overlay/StatsEventRate.h
Normal file
17
DDrawCompat/Overlay/StatsEventRate.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <Overlay/StatsQueue.h>
|
||||
|
||||
class StatsEventTime;
|
||||
|
||||
class StatsEventRate : public StatsQueue
|
||||
{
|
||||
public:
|
||||
StatsEventRate(StatsEventTime& parent);
|
||||
|
||||
private:
|
||||
virtual double convert(double stat) override;
|
||||
virtual Stats getRawStats(TickCount tickCount) override;
|
||||
|
||||
StatsEventTime& m_parent;
|
||||
};
|
22
DDrawCompat/Overlay/StatsEventTime.cpp
Normal file
22
DDrawCompat/Overlay/StatsEventTime.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <Overlay/StatsEventTime.h>
|
||||
|
||||
StatsEventTime::StatsEventTime()
|
||||
: m_qpcLast(0)
|
||||
{
|
||||
}
|
||||
|
||||
void StatsEventTime::add(TickCount tickCount, long long qpcNow)
|
||||
{
|
||||
if (0 != m_qpcLast && qpcNow - m_qpcLast < HISTORY_TIME * Time::g_qpcFrequency)
|
||||
{
|
||||
addSample(tickCount, qpcNow - m_qpcLast);
|
||||
}
|
||||
m_qpcLast = qpcNow;
|
||||
}
|
||||
|
||||
double StatsEventTime::convert(double stat)
|
||||
{
|
||||
return 1000 * stat / Time::g_qpcFrequency;
|
||||
}
|
18
DDrawCompat/Overlay/StatsEventTime.h
Normal file
18
DDrawCompat/Overlay/StatsEventTime.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <Overlay/StatsQueue.h>
|
||||
|
||||
class StatsEventTime : public StatsQueue
|
||||
{
|
||||
public:
|
||||
StatsEventTime();
|
||||
|
||||
void add(TickCount tickCount, long long qpcNow);
|
||||
|
||||
private:
|
||||
friend class StatsEventRate;
|
||||
|
||||
virtual double convert(double stat) override;
|
||||
|
||||
long long m_qpcLast;
|
||||
};
|
138
DDrawCompat/Overlay/StatsQueue.cpp
Normal file
138
DDrawCompat/Overlay/StatsQueue.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
#include <Overlay/StatsQueue.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
bool greaterEqual(StatsQueue::Stat a, StatsQueue::Stat b)
|
||||
{
|
||||
return a >= b;
|
||||
}
|
||||
|
||||
bool lessEqual(StatsQueue::Stat a, StatsQueue::Stat b)
|
||||
{
|
||||
return a <= b;
|
||||
}
|
||||
}
|
||||
|
||||
StatsQueue::StatsQueue()
|
||||
: m_sums(HISTORY_SIZE)
|
||||
, m_sampleCounts(HISTORY_SIZE)
|
||||
, m_currentTickCount(0)
|
||||
, m_sampleCount(0)
|
||||
, m_sum(0)
|
||||
, m_min(0)
|
||||
, m_max(0)
|
||||
, m_totalSampleCount(0)
|
||||
, m_totalSum(0)
|
||||
{
|
||||
}
|
||||
|
||||
void StatsQueue::addSample(TickCount tickCount, Stat stat)
|
||||
{
|
||||
setTickCount(tickCount);
|
||||
|
||||
if (0 == m_sampleCount)
|
||||
{
|
||||
m_min = stat;
|
||||
m_max = stat;
|
||||
}
|
||||
else if (stat < m_min)
|
||||
{
|
||||
m_min = stat;
|
||||
}
|
||||
else if (stat > m_max)
|
||||
{
|
||||
m_max = stat;
|
||||
}
|
||||
|
||||
++m_sampleCount;
|
||||
m_sum += stat;
|
||||
}
|
||||
|
||||
double StatsQueue::getAvg(Stat sum, SampleCount sampleCount) const
|
||||
{
|
||||
return 0 == sampleCount ? NAN : (static_cast<double>(sum) / sampleCount);
|
||||
}
|
||||
|
||||
StatsQueue::Stats StatsQueue::getRawStats(TickCount tickCount)
|
||||
{
|
||||
setTickCount(tickCount);
|
||||
Stats stats = {};
|
||||
const uint32_t index = (m_currentTickCount - 1) % HISTORY_SIZE;
|
||||
stats.cur = getAvg(m_sums[index], m_sampleCounts[index]);
|
||||
stats.avg = getAvg(m_totalSum, m_totalSampleCount);
|
||||
stats.min = m_minQueue.empty() ? NAN : m_minQueue.front().stat;
|
||||
stats.max = m_maxQueue.empty() ? NAN : m_maxQueue.front().stat;
|
||||
return stats;
|
||||
}
|
||||
|
||||
StatsQueue::SampleCount StatsQueue::getSampleCount(TickCount tickCount) const
|
||||
{
|
||||
return m_sampleCounts[tickCount % HISTORY_SIZE];
|
||||
}
|
||||
|
||||
StatsQueue::Stats StatsQueue::getStats(TickCount tickCount)
|
||||
{
|
||||
Stats stats = getRawStats(tickCount);
|
||||
stats.cur = convert(stats.cur);
|
||||
stats.avg = convert(stats.avg);
|
||||
stats.min = convert(stats.min);
|
||||
stats.max = convert(stats.max);
|
||||
return stats;
|
||||
}
|
||||
|
||||
void StatsQueue::push()
|
||||
{
|
||||
finalize(m_sampleCount, m_sum, m_min, m_max);
|
||||
|
||||
uint32_t index = m_currentTickCount % HISTORY_SIZE;
|
||||
m_totalSampleCount -= m_sampleCounts[index];
|
||||
m_totalSampleCount += m_sampleCount;
|
||||
m_totalSum -= m_sums[index];
|
||||
m_totalSum += m_sum;
|
||||
m_sampleCounts[index] = m_sampleCount;
|
||||
m_sums[index] = m_sum;
|
||||
|
||||
pushToMinMaxQueue(m_minQueue, m_min, lessEqual);
|
||||
pushToMinMaxQueue(m_maxQueue, m_max, greaterEqual);
|
||||
|
||||
m_sampleCount = 0;
|
||||
m_sum = 0;
|
||||
m_min = 0;
|
||||
m_max = 0;
|
||||
++m_currentTickCount;
|
||||
}
|
||||
|
||||
void StatsQueue::pushToMinMaxQueue(std::deque<TimestampedStat>& queue, Stat stat, bool compare(Stat, Stat))
|
||||
{
|
||||
if (0 != m_sampleCount)
|
||||
{
|
||||
while (!queue.empty() && compare(stat, queue.back().stat))
|
||||
{
|
||||
queue.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
while (!queue.empty() && m_currentTickCount - queue.front().tickCount >= HISTORY_SIZE)
|
||||
{
|
||||
queue.pop_front();
|
||||
}
|
||||
|
||||
if (0 != m_sampleCount)
|
||||
{
|
||||
queue.push_back({ m_currentTickCount, stat });
|
||||
}
|
||||
}
|
||||
|
||||
void StatsQueue::setTickCount(TickCount tickCount)
|
||||
{
|
||||
if (tickCount - m_currentTickCount > HISTORY_SIZE)
|
||||
{
|
||||
m_currentTickCount = tickCount - HISTORY_SIZE;
|
||||
resetTickCount();
|
||||
}
|
||||
|
||||
while (m_currentTickCount < tickCount)
|
||||
{
|
||||
push();
|
||||
}
|
||||
}
|
76
DDrawCompat/Overlay/StatsQueue.h
Normal file
76
DDrawCompat/Overlay/StatsQueue.h
Normal file
@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
#include <Common/Time.h>
|
||||
|
||||
class StatsQueue
|
||||
{
|
||||
public:
|
||||
static const uint32_t TICKS_PER_SEC = 5;
|
||||
static const uint32_t HISTORY_TIME = 3;
|
||||
static const uint32_t HISTORY_SIZE = HISTORY_TIME * TICKS_PER_SEC;
|
||||
|
||||
typedef uint32_t SampleCount;
|
||||
typedef uint64_t Stat;
|
||||
typedef uint64_t TickCount;
|
||||
|
||||
struct Stats
|
||||
{
|
||||
double cur;
|
||||
double avg;
|
||||
double min;
|
||||
double max;
|
||||
};
|
||||
|
||||
StatsQueue();
|
||||
|
||||
void addSample(TickCount tickCount, Stat stat);
|
||||
Stats getStats(TickCount tickCount);
|
||||
|
||||
TickCount getCurrentTickCount() const { return m_currentTickCount; }
|
||||
|
||||
static long long getQpc(TickCount tickCount)
|
||||
{
|
||||
return tickCount * Time::g_qpcFrequency / TICKS_PER_SEC;
|
||||
}
|
||||
|
||||
static TickCount getTickCount(long long qpc = Time::queryPerformanceCounter())
|
||||
{
|
||||
return qpc * TICKS_PER_SEC / Time::g_qpcFrequency;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Stats getRawStats(TickCount tickCount);
|
||||
SampleCount getSampleCount(TickCount tickCount) const;
|
||||
void setTickCount(TickCount tickCount);
|
||||
|
||||
private:
|
||||
struct TimestampedStat
|
||||
{
|
||||
TickCount tickCount;
|
||||
Stat stat;
|
||||
};
|
||||
|
||||
virtual double convert(double stat) { return stat; }
|
||||
virtual void finalize(SampleCount& /*sampleCount*/, Stat& /*sum*/, Stat& /*min*/, Stat& /*max*/) {}
|
||||
virtual void resetTickCount() {}
|
||||
|
||||
double getAvg(Stat sum, SampleCount sampleCount) const;
|
||||
|
||||
void push();
|
||||
void pushToMinMaxQueue(std::deque<TimestampedStat>& queue, Stat stat, bool compare(Stat, Stat));
|
||||
|
||||
std::vector<Stat> m_sums;
|
||||
std::vector<SampleCount> m_sampleCounts;
|
||||
std::deque<TimestampedStat> m_minQueue;
|
||||
std::deque<TimestampedStat> m_maxQueue;
|
||||
TickCount m_currentTickCount;
|
||||
SampleCount m_sampleCount;
|
||||
Stat m_sum;
|
||||
Stat m_min;
|
||||
Stat m_max;
|
||||
SampleCount m_totalSampleCount;
|
||||
Stat m_totalSum;
|
||||
};
|
52
DDrawCompat/Overlay/StatsTimer.cpp
Normal file
52
DDrawCompat/Overlay/StatsTimer.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include <Overlay/StatsTimer.h>
|
||||
|
||||
StatsTimer::StatsTimer()
|
||||
: m_qpcStart(0)
|
||||
, m_qpcSum(0)
|
||||
{
|
||||
}
|
||||
|
||||
double StatsTimer::convert(double stat)
|
||||
{
|
||||
return 100 * stat * StatsQueue::TICKS_PER_SEC / Time::g_qpcFrequency;
|
||||
}
|
||||
|
||||
void StatsTimer::finalize(SampleCount& sampleCount, Stat& sum, Stat& min, Stat& max)
|
||||
{
|
||||
if (0 != m_qpcStart)
|
||||
{
|
||||
auto qpcTickEnd = getQpc(getCurrentTickCount() + 1);
|
||||
m_qpcSum += qpcTickEnd - m_qpcStart;
|
||||
m_qpcStart = qpcTickEnd;
|
||||
}
|
||||
|
||||
sampleCount = 1;
|
||||
sum = m_qpcSum;
|
||||
min = m_qpcSum;
|
||||
max = m_qpcSum;
|
||||
m_qpcSum = 0;
|
||||
}
|
||||
|
||||
void StatsTimer::resetTickCount()
|
||||
{
|
||||
if (0 != m_qpcStart)
|
||||
{
|
||||
m_qpcStart = getQpc(getCurrentTickCount());
|
||||
}
|
||||
m_qpcSum = 0;
|
||||
}
|
||||
|
||||
void StatsTimer::start()
|
||||
{
|
||||
auto qpcStart = Time::queryPerformanceCounter();
|
||||
setTickCount(getTickCount(qpcStart));
|
||||
m_qpcStart = qpcStart;
|
||||
}
|
||||
|
||||
void StatsTimer::stop()
|
||||
{
|
||||
auto qpcEnd = Time::queryPerformanceCounter();
|
||||
setTickCount(getTickCount(qpcEnd));
|
||||
m_qpcSum += qpcEnd - m_qpcStart;
|
||||
m_qpcStart = 0;
|
||||
}
|
20
DDrawCompat/Overlay/StatsTimer.h
Normal file
20
DDrawCompat/Overlay/StatsTimer.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <Overlay/StatsQueue.h>
|
||||
|
||||
class StatsTimer : public StatsQueue
|
||||
{
|
||||
public:
|
||||
StatsTimer();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
private:
|
||||
virtual double convert(double stat) override;
|
||||
virtual void finalize(SampleCount& sampleCount, Stat& sum, Stat& min, Stat& max) override;
|
||||
virtual void resetTickCount() override;
|
||||
|
||||
long long m_qpcStart;
|
||||
long long m_qpcSum;
|
||||
};
|
122
DDrawCompat/Overlay/StatsWindow.cpp
Normal file
122
DDrawCompat/Overlay/StatsWindow.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
#include <array>
|
||||
#include <functional>
|
||||
|
||||
#include <Common/Time.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Input/Input.h>
|
||||
#include <Overlay/ConfigWindow.h>
|
||||
#include <Overlay/StatsWindow.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
class UpdateStats
|
||||
{
|
||||
public:
|
||||
UpdateStats(StatsQueue& statsQueue)
|
||||
: m_statsQueue(statsQueue)
|
||||
{
|
||||
}
|
||||
|
||||
std::array<std::string, 4> operator()(StatsQueue::TickCount tickCount) const
|
||||
{
|
||||
auto stats = m_statsQueue.getStats(tickCount);
|
||||
return { toString(stats.cur), toString(stats.avg), toString(stats.min), toString(stats.max) };
|
||||
}
|
||||
|
||||
private:
|
||||
std::string toString(double stat) const
|
||||
{
|
||||
if (std::isnan(stat))
|
||||
{
|
||||
return "-";
|
||||
}
|
||||
|
||||
const char unitLetter[] = { 0, 'k', 'm', 'b' };
|
||||
std::size_t unitIndex = 0;
|
||||
while (stat >= 1000 && unitIndex + 1 < sizeof(unitLetter))
|
||||
{
|
||||
++unitIndex;
|
||||
stat /= 1000;
|
||||
}
|
||||
|
||||
char buf[20] = {};
|
||||
if (0 == unitIndex)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "%.0f", stat);
|
||||
return buf;
|
||||
}
|
||||
|
||||
auto len = snprintf(buf, sizeof(buf), "%.2f", stat);
|
||||
const auto decimalPoint = strchr(buf, '.');
|
||||
const auto intLen = decimalPoint ? decimalPoint - buf : len;
|
||||
if (len > 4)
|
||||
{
|
||||
len = intLen >= 3 ? intLen : 4;
|
||||
}
|
||||
buf[len] = unitLetter[unitIndex];
|
||||
buf[len + 1] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
StatsQueue& m_statsQueue;
|
||||
};
|
||||
}
|
||||
|
||||
namespace Overlay
|
||||
{
|
||||
StatsWindow::StatsWindow()
|
||||
: Window(nullptr, { 0, 0, StatsControl::NAME_LABEL_WIDTH + 4 * StatsControl::VALUE_LABEL_WIDTH, 105 + BORDER },
|
||||
0, Input::parseHotKey("shift+f12"))
|
||||
{
|
||||
addControl("", [](StatsQueue::TickCount) { return std::array<std::string, 4>{ "cur", "avg", "min", "max" }; },
|
||||
WS_VISIBLE | WS_DISABLED).update(0);
|
||||
addControl("Present rate", UpdateStats(m_present.m_rate));
|
||||
addControl("Flip rate", UpdateStats(m_flip.m_rate));
|
||||
addControl("Blit count", UpdateStats(m_blit.m_count));
|
||||
addControl("Lock count", UpdateStats(m_lock.m_count));
|
||||
addControl("DDI usage", UpdateStats(m_ddiUsage));
|
||||
addControl("GDI objects", UpdateStats(m_gdiObjects));
|
||||
}
|
||||
|
||||
StatsControl& StatsWindow::addControl(const std::string& name, StatsControl::UpdateFunc updateFunc, DWORD style)
|
||||
{
|
||||
const int index = m_statsControls.size();
|
||||
const int rowHeight = 15;
|
||||
|
||||
RECT rect = { 0, index * rowHeight + BORDER / 2, m_rect.right, (index + 1) * rowHeight + BORDER / 2 };
|
||||
return m_statsControls.emplace_back(*this, rect, name, updateFunc, style);
|
||||
}
|
||||
|
||||
RECT StatsWindow::calculateRect(const RECT& monitorRect) const
|
||||
{
|
||||
RECT r = { 0, 0, m_rect.right - m_rect.left, m_rect.bottom - m_rect.top };
|
||||
OffsetRect(&r, monitorRect.left + monitorRect.right - r.right, monitorRect.top);
|
||||
return r;
|
||||
}
|
||||
|
||||
HWND StatsWindow::getTopmost() const
|
||||
{
|
||||
auto configWindow = Gdi::GuiThread::getConfigWindow();
|
||||
return (configWindow && configWindow->isVisible()) ? configWindow->getWindow() : Window::getTopmost();
|
||||
}
|
||||
|
||||
void StatsWindow::updateStats()
|
||||
{
|
||||
static auto prevTickCount = StatsQueue::getTickCount() - 1;
|
||||
m_tickCount = StatsQueue::getTickCount();
|
||||
if (m_tickCount == prevTickCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_gdiObjects.addSample(m_tickCount, GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS));
|
||||
for (auto& statsControl : m_statsControls)
|
||||
{
|
||||
if (statsControl.isEnabled())
|
||||
{
|
||||
statsControl.update(m_tickCount);
|
||||
}
|
||||
}
|
||||
prevTickCount = m_tickCount;
|
||||
}
|
||||
}
|
38
DDrawCompat/Overlay/StatsWindow.h
Normal file
38
DDrawCompat/Overlay/StatsWindow.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <Overlay/StatsControl.h>
|
||||
#include <Overlay/StatsEventGroup.h>
|
||||
#include <Overlay/StatsQueue.h>
|
||||
#include <Overlay/StatsTimer.h>
|
||||
#include <Overlay/Window.h>
|
||||
|
||||
namespace Overlay
|
||||
{
|
||||
class StatsWindow : public Window
|
||||
{
|
||||
public:
|
||||
StatsWindow();
|
||||
|
||||
void updateStats();
|
||||
|
||||
StatsEventGroup m_present;
|
||||
StatsEventGroup m_flip;
|
||||
StatsEventGroup m_blit;
|
||||
StatsEventGroup m_lock;
|
||||
StatsTimer m_ddiUsage;
|
||||
StatsQueue m_gdiObjects;
|
||||
|
||||
private:
|
||||
StatsControl& addControl(const std::string& name, StatsControl::UpdateFunc updateFunc, DWORD style = WS_VISIBLE);
|
||||
|
||||
virtual RECT calculateRect(const RECT& monitorRect) const override;
|
||||
virtual HWND getTopmost() const override;
|
||||
|
||||
std::list<StatsControl> m_statsControls;
|
||||
uint64_t m_tickCount;
|
||||
};
|
||||
}
|
@ -45,8 +45,8 @@ namespace
|
||||
|
||||
namespace Overlay
|
||||
{
|
||||
Window::Window(Window* parentWindow, const RECT& rect, const Input::HotKey& hotKey)
|
||||
: Control(nullptr, rect, WS_BORDER)
|
||||
Window::Window(Window* parentWindow, const RECT& rect, DWORD style, const Input::HotKey& hotKey)
|
||||
: Control(nullptr, rect, style)
|
||||
, m_hwnd(Gdi::PresentationWindow::create(parentWindow ? parentWindow->m_hwnd : nullptr))
|
||||
, m_parentWindow(parentWindow)
|
||||
, m_transparency(25)
|
||||
@ -99,6 +99,11 @@ namespace Overlay
|
||||
{
|
||||
}
|
||||
|
||||
HWND Window::getTopmost() const
|
||||
{
|
||||
return DDraw::RealPrimarySurface::getTopmost();
|
||||
}
|
||||
|
||||
void Window::invalidate()
|
||||
{
|
||||
m_invalid = true;
|
||||
@ -122,7 +127,6 @@ namespace Overlay
|
||||
if (m_style & WS_VISIBLE)
|
||||
{
|
||||
updatePos();
|
||||
Input::setCapture(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -132,8 +136,8 @@ namespace Overlay
|
||||
capture->setVisible(false);
|
||||
}
|
||||
ShowWindow(m_hwnd, SW_HIDE);
|
||||
Input::setCapture(m_parentWindow);
|
||||
}
|
||||
DDraw::RealPrimarySurface::scheduleUpdate();
|
||||
}
|
||||
|
||||
LRESULT CALLBACK Window::staticWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
@ -213,7 +217,7 @@ namespace Overlay
|
||||
m_rect = calculateRect({ monitorRect.left / m_scaleFactor, monitorRect.top / m_scaleFactor,
|
||||
monitorRect.right / m_scaleFactor, monitorRect.bottom / m_scaleFactor });
|
||||
|
||||
CALL_ORIG_FUNC(SetWindowPos)(m_hwnd, DDraw::RealPrimarySurface::getTopmost(),
|
||||
CALL_ORIG_FUNC(SetWindowPos)(m_hwnd, getTopmost(),
|
||||
m_rect.left * m_scaleFactor, m_rect.top * m_scaleFactor,
|
||||
(m_rect.right - m_rect.left) * m_scaleFactor, (m_rect.bottom - m_rect.top) * m_scaleFactor,
|
||||
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
|
||||
|
@ -13,7 +13,7 @@ namespace Overlay
|
||||
class Window : public Control
|
||||
{
|
||||
public:
|
||||
Window(Window* parentWindow, const RECT& rect, const Input::HotKey& hotKey = {});
|
||||
Window(Window* parentWindow, const RECT& rect, DWORD style, const Input::HotKey& hotKey = {});
|
||||
virtual ~Window() override;
|
||||
|
||||
virtual RECT calculateRect(const RECT& monitorRect) const = 0;
|
||||
@ -30,6 +30,8 @@ namespace Overlay
|
||||
Window* m_parentWindow;
|
||||
int m_transparency;
|
||||
|
||||
virtual HWND getTopmost() const;
|
||||
|
||||
void updatePos();
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user