Windows用EnumDisplaySettings获取当前生效刷新率(dmDisplayFrequency),需正确设备名和清零DEVMODE;macOS用CGDisplayCopyDisplayMode+CGDisplayModeGetFloatValue读取单显示器模式值;X11需xrandr或RandR扩展解析当前CRTC模式;SDL_GetDesktopDisplayMode不可靠,跨平台应优先选用原生API或Qt的QScreen::refreshRate()。

Windows平台用 EnumDisplaySettings 获取当前显示器刷新率
Windows下最直接的方式是调用GDI API的 EnumDisplaySettings,它能读取当前活动显示设备的显卡驱动上报的刷新率(即 dmDisplayFrequency 字段)。注意:这不是“理论最大值”,而是当前生效的设置值。
常见错误是传入错误的设备名 —— 必须用 ENUM_CURRENT_SETTINGS 或先调用 EnumDisplayDevices 获取真实设备名(如 "\\.\DISPLAY1"),硬编码 "DISPLAY1" 会失败。
- 调用前确保
DEVMODE结构体清零,并设置dmSize = sizeof(DEVMODE),否则返回FALSE - 刷新率单位是 Hz,
dmDisplayFrequency为 0 表示驱动未提供该值(常见于虚拟机或某些核显) - 多显示器场景下,需对每个
DISPLAY<i>n</i>设备分别枚举,不能默认只查主屏
macOS上通过 CGDisplayModeRef 读取 kCGDisplayRefreshRate
macOS不暴露全局“系统刷新率”概念,每个显示器有独立模式,需用 Core Graphics 框架获取当前激活模式的刷新率。关键函数是 CGDisplayCopyDisplayMode + CGDisplayModeGetFloatValue。
容易忽略的是:必须传入真实的 display ID(如 CGMainDisplayID() 或从 CGGetActiveDisplayList 获取),传 0 会崩溃;且 kCGDisplayRefreshRate 在部分外接显示器或缩放模式下可能返回 0.0 或 60.0(即使实际是 120Hz)。
立即学习“C++免费学习笔记(深入)”;
- 返回值类型是
CFNumberRef,需用CGDisplayModeGetFloatValue转换,直接 cast 会出错 - Retina 显示器启用“缩放”时,系统可能报告逻辑刷新率而非物理面板值(例如 MacBook Pro 16" 120Hz 屏在默认缩放下仍报 60.0)
- 需要链接
-framework CoreGraphics,否则链接失败
Linux X11环境下解析 xrandr 输出或使用 RandR 扩展
X11 没有统一API返回“当前刷新率”,可靠方式是调用 xrandr --verbose 解析 stdout,或用 Xlib 的 RandR 扩展(XRRGetScreenResources + XRRGetOutputInfo + XRRGetCrtcInfo)查当前 CRTC 的 mode。
直接读 /sys/class/graphics/fb0/videomode 或 /proc/fb 不可靠 —— 它们反映 framebuffer 层配置,和实际 GPU 输出刷新率常不一致(尤其启用了 compositor 或多显卡时)。
-
xrandr解析需匹配 “*” 标记的当前模式行,再提取括号内数值(如1920x1080 60.00*+) - RandR 方式需注意:mode id 是整数,要从
XRRGetScreenResources返回的 modes 数组中索引,不能直接用crtc->mode值 - Wayland 环境下
xrandr可能不可用,需走 wl_output 接口(但 C++ 绑定复杂,通常建议用xdpyinfo或桌面环境 D-Bus 接口)
跨平台封装时为什么不能只依赖 SDL_GetDesktopDisplayMode
SDL_GetDesktopDisplayMode 看似方便,但它返回的是“桌面默认模式”,不是当前实际刷新率 —— 尤其在 Windows 上,若用户手动设置了 144Hz 但桌面模式仍是 60Hz,它就返回 60;macOS 上它甚至可能返回 0(SDL 2.26+ 已修复部分情况,但仍有 fallback 行为)。
真正需要精确帧同步(如游戏引擎 vsync 控制、视频播放器时基校准)时,必须走原生 API。SDL 更适合快速原型,而非生产级刷新率感知。
- SDL 本身对多显示器支持弱:
SDL_GetDesktopDisplayMode(0)总是主屏,无法指定输出设备 - Linux Wayland 下 SDL 可能回退到 DRM/KMS 直接读取,但需要 root 权限且不兼容所有驱动
- 如果项目已用 Qt,
QScreen::refreshRate()是更稳的选择(Qt 5.10+ 支持 macOS/Linux Wayland/X11)
刷新率不是静态配置项,它是运行时状态,且不同平台语义差异大 —— Windows 报驱动设置值,macOS 报当前模式物理值,X11 则取决于 compositor 是否接管了 scanout。拿不准时,优先测真机,别信文档里的“典型值”。


















