如何检测显示器是否支持可变刷新率(GSync、FreeSync)
编程检测显示器是否支持可变刷新率(VFR)的直接方法
你提到的关闭Vsync循环翻页统计帧率的方法确实可行,但存在画面撕裂、依赖运行时帧率的问题。更高效准确的方式是直接调用对应平台的系统API,查询显示器的硬件能力标识,以下分平台说明:
Windows平台
使用DXGI API可以直接检测是否支持可变刷新率:
- 通过
IDXGIOutput2接口的GetDisplayModeList1获取所有显示模式,检查模式的DXGI_MODE_DESC1.Flags是否包含DXGI_MODE_FLAG_VARIABLE_REFRESH_RATE标识。 - 示例代码片段:
#include <dxgi.h> #pragma comment(lib, "dxgi.lib") bool IsVariableRefreshRateSupported() { IDXGIFactory* factory = nullptr; if (CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory) != S_OK) { return false; } IDXGIAdapter* adapter = nullptr; for (UINT i = 0; factory->EnumAdapters(i, &adapter) != DXGI_ERROR_NOT_FOUND; i++) { IDXGIOutput* output = nullptr; for (UINT j = 0; adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND; j++) { IDXGIOutput2* output2 = nullptr; if (output->QueryInterface(__uuidof(IDXGIOutput2), (void**)&output2) == S_OK) { UINT modeCount = 0; output2->GetDisplayModeList1(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED | DXGI_ENUM_MODES_SCALING, &modeCount, nullptr); std::vector<DXGI_MODE_DESC1> modes(modeCount); output2->GetDisplayModeList1(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED | DXGI_ENUM_MODES_SCALING, &modeCount, modes.data()); for (const auto& mode : modes) { if (mode.Flags & DXGI_MODE_FLAG_VARIABLE_REFRESH_RATE) { // 释放资源 output2->Release(); output->Release(); adapter->Release(); factory->Release(); return true; } } output2->Release(); } output->Release(); } adapter->Release(); } factory->Release(); return false; }
Linux平台
可通过XRandR或DRM两种方式检测:
- XRandR方式:使用libXrandr库查询显示模式属性,或调用命令行工具解析输出。命令行示例(编程时可调用并解析):
xrandr --props | grep -A 5 "VariableRefresh"
若输出包含VariableRefresh: yes,则说明支持可变刷新率。
- DRM方式:通过DRM API获取CRTC属性,检查是否存在
DRM_MODE_PROP_VARIABLE_REFRESH_RATE属性。
macOS平台
借助Quartz Display Services框架直接查询:
- 通过
CGDisplayModeGetIOFlags检查当前显示模式的标识是否包含kDisplayModeIOFlagVariableRefreshRate。 - 示例代码片段:
#import <CoreGraphics/CoreGraphics.h> BOOL IsVariableRefreshRateSupported() { CGDirectDisplayID mainDisplay = CGMainDisplayID(); CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(mainDisplay); if (!currentMode) return NO; IOOptionFlags modeFlags = CGDisplayModeGetIOFlags(currentMode); BOOL isSupported = (modeFlags & kDisplayModeIOFlagVariableRefreshRate) != 0; CFRelease(currentMode); return isSupported; }
这些方法直接读取系统提供的硬件能力信息,无需运行帧率测试,结果更准确且不会产生画面撕裂等副作用。
内容的提问来源于stack exchange,提问作者Dwedit
相关产品推荐
相关产品推荐

