考古挖掘:高刷显示器下的 requestAnimationFrame

原由

今天有一位同窗,在群里问了这一个问题:requestAnimationFrame 的执行机制如何php

image.png

这个问题固然不陌生。requestAnimationFrame 在浏览器每一帧开始绘制以前会执行。借助 requestAnimationFrame 高效的执行效率,咱们可使用requestAnimationFrame 进行动画操做、FPS 的计算、甚至能够经过算每一帧所须要的真实时间,来增长帧数。 image.pnghtml

MDN中,还有这样一句话:在多数遵循W3C建议的浏览器中,回调函数执行次数一般与浏览器屏幕刷新次数相匹配。因而yck同窗此时问了一句:我屏幕刷新率特别快怎么办?html5

image.png

这句话使人深思。在现在高刷显示器盛行的年代,我依然在使用60hz的MacBook。虽然MDN写着匹配,但这个也不必定对。带着这个疑问,我开始了探索之旅。linux

做为一个半数码党,对于如今数码产品显示器的刷新率种类仍是懂一点的。有120hz,144hz等等。我抱着试试看的心态,去搜了144hz下 requestAnimationFrame 的情况浏览器

现状

果真不出所料。我经过搜索,找到了一篇问答帖:这位网友讲,它使用了165hz的显示器,但经过requestAnimationFrame 计算出来的FPS依然只有30-60fpsmarkdown

image.png

那就证实了,的确在一部分用户下,刷新率和 requestAnimationFrame 存在不一样步问题。但是在回答区,有一部分用户也反馈,他们屏幕刷新率和 requestAnimationFrame 是同步的。这样也印证了大几率是一个Bug。ide

真的是 Bug

因而我去Chromium Bugs网站内去查找,找到了这样的一个Issue。内容也在写,使用了144hz刷新率的显示器,但FPS上限依然只有60。函数

image.png

因而我抛弃掉一部分争论,直接找修复的代码和备注。继续向下翻,找到了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这个文件。glxChromium中硬件加速相关的代码

image.png

能够看到,其中的一个float变量叫 refresh_rate,这个就是最后计算刷新率的值。而后使用 (1 / refresh_rate),计算出刷新一次所控制的秒。若是是60hz,则 1000ms / 60次 = 16.66ms 1次。

这里咱们继续跟 refresh_rate 的计算方法 => GetRefreshRateFromXRRModeInfo。找到 x11_display_util.cc 文件能够看到逻辑

image.png

这里能够看到,其计算逻辑是 Pixel Clock / (Horizontal Total * Vertical Total)。那么这三个数值表明什么意思呢?

  • Pixel Clock 时钟频率,是显示器每秒钟绘制的像素数。
  • Horizontal Total 每一帧绘制的水平像素数量
  • Vertical Total 每一帧绘制的垂直像素数量

时钟每秒处理的像素数量 / (水平像素数量) * (行像素数量)

关于多显示器

Chromium Gerrit平台提交的代码注释中能够看到,多显示器支持实际上是存在问题的。这里能够参考另一个Bug。这位同窗使用了144hz + 60hz的显示器,但输出依然是60fps

image.png

目前官方人员只提出了解决方案,但没有看到任何commit有产出。因此这仍是个Bug

其余参考

相关文章
相关标签/搜索