Windows平台最可靠方式是调用EnumDisplaySettings传ENUM_CURRENT_SETTINGS获取dmDisplayFrequency,需初始化DEVMODE并校验返回值;Linux用xrandr --verbose解析含*标记的刷新率;macOS需遍历CGDisplayCopyAllDisplayModes找当前模式再调CGDisplayModeGetRefreshRate。

Windows平台用EnumDisplaySettings查当前刷新率最可靠
直接调用EnumDisplaySettings获取主显示器当前模式的dmDisplayFrequency,这是Windows API中唯一能拿到实际生效刷新率的途径。它不依赖显卡驱动报告的“支持列表”,而是返回系统当前真正使用的值。
常见错误是误用EnumDisplayDevices或DXGI枚举所有模式——那些只是显卡声称支持的候选值,不一定正在启用;而V-Sync是否开启、实际帧率是否被锁死,也得看应用层是否启用了同步机制(如wglSwapIntervalEXT或vkQueuePresent的VkPresentModeKHR)。
- 必须传入
ENUM_CURRENT_SETTINGS(即-1),而不是0或具体模式索引,否则可能返回默认/未激活模式的频率 -
DEVMODE结构体需初始化为0,并设置dmSize = sizeof(DEVMODE),否则调用失败且不报错 - 多显示器场景下,需先用
EnumDisplayDevices获取设备名,再对每个设备调用EnumDisplaySettings
Linux上靠xrandr命令+解析输出拿刷新率
在X11环境下,xrandr --verbose输出包含当前激活输出的详细时序参数,其中Monitor name后紧跟的60.00*+这类标记里的数字就是实时刷新率(*表示当前激活,+表示首选)。C++中可用popen捕获并解析该输出。
注意:Wayland会屏蔽xrandr的部分能力,此时需走libdrm + ioctl读取drmModeGetConnector和drmModeGetEncoder,但仅限于内核DRM层可见的原生模式——桌面环境可能做了缩放或合成,最终显示帧率仍可能不同。
立即学习“C++免费学习笔记(深入)”;
-
xrandr输出中同一输出可能有多个“current”行,应取第一个匹配connected且含*的那行 - 不要只依赖
xrandr -q,它不带时序细节;必须用--verbose才能看到60.00*格式的刷新率标记 - 解析时建议用正则匹配
(\d+\.\d+)\s*\*而非简单空格分割,避免字段位移导致错位
macOS需用CGDisplayCopyAllDisplayModes配合CGDisplayModeGetRefreshRate
macOS没有全局“当前刷新率”API,必须先获取当前显示器的所有可用模式,再遍历找出CGDisplayModeIsCurrent为TRUE的那个,再调用CGDisplayModeGetRefreshRate。返回值为CGFloat,典型值如60.0、120.0(ProMotion屏)。
关键陷阱在于:macOS可能动态切换刷新率(如ProMotion在滚动时升频、静止时降频),而CGDisplayModeIsCurrent只反映当前配置项,不反映瞬时硬件状态。若需真实V-Sync周期,必须结合CADisplayLink回调测得的实际帧间隔。
- 必须用
CGDisplayCopyAllDisplayModes,CGDisplayCopyDisplayMode只返回一个模式,无法判断是否为当前 - 返回的
CFArrayRef需手动CFRelease,否则内存泄漏 -
CGDisplayModeGetRefreshRate对非整数刷新率(如47.95Hz)返回近似值,精度有限
V-Sync开关状态不能靠查询,只能靠控制路径反推
操作系统和GPU驱动不提供“V-Sync是否开启”的直接查询接口。你只能根据当前使用的图形API及上下文判断:
- OpenGL:检查
wglGetSwapIntervalEXT()返回值(Windows)或glXGetSwapIntervalSGI()(X11),值为1表示开启,0为关闭 - Vulkan:查看
vkGetPhysicalDeviceSurfaceCapabilitiesKHR中supportedPresentModes是否含VK_PRESENT_MODE_FIFO_KHR(V-Sync等效模式),但实际是否启用取决于vkQueuePresentKHR提交时选择的presentMode - DirectX:无直接查询方式,需回溯
IDXGISwapChain::Present调用时的syncInterval参数
真正影响帧率上限的是这些控制点,而非显示器标称参数。比如即使显示器支持144Hz,若OpenGL上下文设了wglSwapIntervalEXT(1)且垂直空白期未被抢占,实际帧率就被锁在60Hz——这和“显示器刷新率”是两件事。


















