今天有一位同窗,在群里问了这一个问题:requestAnimationFrame
的执行机制如何php
这个问题固然不陌生。requestAnimationFrame
在浏览器每一帧开始绘制以前会执行。借助 requestAnimationFrame
高效的执行效率,咱们可使用requestAnimationFrame
进行动画操做、FPS 的计算、甚至能够经过算每一帧所须要的真实时间,来增长帧数。 html
在MDN中,还有这样一句话:在多数遵循W3C建议的浏览器中,回调函数执行次数一般与浏览器屏幕刷新次数相匹配。因而yck同窗此时问了一句:我屏幕刷新率特别快怎么办?html5
这句话使人深思。在现在高刷显示器盛行的年代,我依然在使用60hz的MacBook。虽然MDN写着匹配,但这个也不必定对。带着这个疑问,我开始了探索之旅。linux
做为一个半数码党,对于如今数码产品显示器的刷新率种类仍是懂一点的。有120hz,144hz等等。我抱着试试看的心态,去搜了144hz下 requestAnimationFrame
的情况浏览器
果真不出所料。我经过搜索,找到了一篇问答帖:这位网友讲,它使用了165hz
的显示器,但经过requestAnimationFrame
计算出来的FPS
依然只有30-60fps
。markdown
那就证实了,的确在一部分用户下,刷新率和 requestAnimationFrame
存在不一样步问题。但是在回答区,有一部分用户也反馈,他们屏幕刷新率和 requestAnimationFrame
是同步的。这样也印证了大几率是一个Bug。ide
因而我去Chromium Bugs
网站内去查找,找到了这样的一个Issue。内容也在写,使用了144hz
刷新率的显示器,但FPS上限依然只有60。函数
因而我抛弃掉一部分争论,直接找修复的代码和备注。继续向下翻,找到了chromium
官方人员关于只有60fps
的解释:oop
On Linux Nvidia we use GLX_SGI_video_sync to time vsyncs. Unfortunatelyit's difficult to calculate an accurate refresh rate with it because itsvideo sync counter is wrong. Before, we hardcoded 60 FPS. Now insteadwe use xrandr to get the refresh rate of the primary monitor.动画
其大意是,因为在Linux
下的Nvdia
驱动,在使用GLX_SGI_video_sync
进行计算vsyncs
(垂直同步)的时间时,因为计数器错误,因而官方直接将60FPS
进行硬编码。如今,他们换成了使用xrandr
进行获取刷新率计算。
xrandr 是一款Linux官方的 RandR (Resize and Rotate)。它能够设置屏幕显示的大小、方向、镜像等。wiki.archlinux.org/index.php/X…
既然是Bug
,那咱们就看下Chromium
究竟是怎么修复的
找到回答中具体的commit
记录,而后连接到Chromium Gerrit
平台。来到了这个CR详情
来到 gl_surface_glx.cc这个文件。glx
是Chromium
中硬件加速相关的代码
能够看到,其中的一个float变量叫 refresh_rate
,这个就是最后计算刷新率的值。而后使用 (1 / refresh_rate)
,计算出刷新一次所控制的秒。若是是60hz
,则 1000ms / 60次 = 16.66ms
1次。
这里咱们继续跟 refresh_rate
的计算方法 => GetRefreshRateFromXRRModeInfo
。找到 x11_display_util.cc 文件能够看到逻辑
这里能够看到,其计算逻辑是 Pixel Clock / (Horizontal Total * Vertical Total)
。那么这三个数值表明什么意思呢?
Pixel Clock
时钟频率,是显示器每秒钟绘制的像素数。Horizontal Total
每一帧绘制的水平像素数量Vertical Total
每一帧绘制的垂直像素数量即时钟每秒处理的像素数量 / (水平像素数量) * (行像素数量)
。
从Chromium Gerrit
平台提交的代码注释中能够看到,多显示器支持实际上是存在问题的。这里能够参考另一个Bug。这位同窗使用了144hz + 60hz
的显示器,但输出依然是60fps
目前官方人员只提出了解决方案,但没有看到任何commit
有产出。因此这仍是个Bug