HostDisplay: Add GetHostRefreshRate() function

Only implemented in Windows for now.
This commit is contained in:
Connor McLaughlin 2021-01-11 03:50:10 +10:00
parent 5769830b72
commit bb572741ae
4 changed files with 66 additions and 0 deletions

View File

@ -15,6 +15,11 @@
#include <vector>
Log_SetChannel(HostDisplay);
#ifdef _WIN32
#include "common/windows_headers.h"
#include <dwmapi.h>
#endif
HostDisplayTexture::~HostDisplayTexture() = default;
HostDisplay::~HostDisplay() = default;
@ -85,6 +90,43 @@ bool HostDisplay::SetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32
return true;
}
bool HostDisplay::GetHostRefreshRate(float* refresh_rate)
{
#ifdef _WIN32
static HMODULE dwm_module = nullptr;
static HRESULT(STDAPICALLTYPE * get_timing_info)(HWND hwnd, DWM_TIMING_INFO * pTimingInfo) = nullptr;
static bool load_tried = false;
if (!load_tried)
{
load_tried = true;
dwm_module = LoadLibrary("dwmapi.dll");
if (dwm_module)
{
std::atexit([]() {
FreeLibrary(dwm_module);
dwm_module = nullptr;
});
get_timing_info =
reinterpret_cast<decltype(get_timing_info)>(GetProcAddress(dwm_module, "DwmGetCompositionTimingInfo"));
}
}
DWM_TIMING_INFO ti = {};
ti.cbSize = sizeof(ti);
HRESULT hr = get_timing_info(nullptr, &ti);
if (SUCCEEDED(hr))
{
if (ti.rateRefresh.uiNumerator == 0 || ti.rateRefresh.uiDenominator == 0)
return false;
*refresh_rate = static_cast<float>(ti.rateRefresh.uiNumerator) / static_cast<float>(ti.rateRefresh.uiDenominator);
return true;
}
#endif
return false;
}
void HostDisplay::SetSoftwareCursor(std::unique_ptr<HostDisplayTexture> texture, float scale /*= 1.0f*/)
{
m_cursor_texture = std::move(texture);

View File

@ -163,6 +163,7 @@ public:
static u32 GetDisplayPixelFormatSize(HostDisplayPixelFormat format);
virtual bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const = 0;
virtual bool BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer,
@ -170,6 +171,8 @@ public:
virtual void EndSetDisplayPixels() = 0;
virtual bool SetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, const void* buffer, u32 pitch);
virtual bool GetHostRefreshRate(float* refresh_rate);
void SetDisplayLinearFiltering(bool enabled) { m_display_linear_filtering = enabled; }
void SetDisplayTopMargin(s32 height) { m_display_top_margin = height; }
void SetDisplayIntegerScaling(bool enabled) { m_display_integer_scaling = enabled; }

View File

@ -226,6 +226,25 @@ void D3D11HostDisplay::EndSetDisplayPixels()
m_context->Unmap(m_display_pixels_texture.GetD3DTexture(), 0);
}
bool D3D11HostDisplay::GetHostRefreshRate(float* refresh_rate)
{
if (m_swap_chain && IsFullscreen())
{
DXGI_SWAP_CHAIN_DESC desc;
if (SUCCEEDED(m_swap_chain->GetDesc(&desc)) && desc.BufferDesc.RefreshRate.Numerator > 0 &&
desc.BufferDesc.RefreshRate.Denominator > 0)
{
Log_InfoPrintf("using fs rr: %u %u", desc.BufferDesc.RefreshRate.Numerator,
desc.BufferDesc.RefreshRate.Denominator);
*refresh_rate = static_cast<float>(desc.BufferDesc.RefreshRate.Numerator) /
static_cast<float>(desc.BufferDesc.RefreshRate.Denominator);
return true;
}
}
return HostDisplay::GetHostRefreshRate(refresh_rate);
}
void D3D11HostDisplay::SetVSync(bool enabled)
{
m_vsync = enabled;

View File

@ -61,6 +61,8 @@ public:
u32* out_pitch) override;
void EndSetDisplayPixels() override;
bool GetHostRefreshRate(float* refresh_rate) override;
virtual void SetVSync(bool enabled) override;
virtual bool Render() override;