今天有一位同窗,在羣裏問了這一個問題: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