考古挖掘:高刷顯示器下的 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

其餘參考

相關文章
相關標籤/搜索