在多數(shù)博客中提到的runloop 在即將休眠前的屏幕繪制和接收到VSync 信號后的屏幕繪制,它們之間是什么關(guān)系呢?
這個問題困擾了我很長時間,現(xiàn)在做一個簡單總結(jié)。
runloop 在即將休眠前的屏幕繪制:如果 CoreAnimation 有未提交內(nèi)容,則提交到 GPU 中去工作。也就是說,runloop 與屏幕繪制之間沒有直接的關(guān)系,只是從 CPU 提交到 GPU。
接收到 VSync 信號后的屏幕繪制:VSync 信號由硬件時鐘生成,每秒鐘發(fā)出 60 次。當 runloop 進入到 mach_msg_trap(睡眠)的狀態(tài)時,可以通過 mach_port 接收傳過來的時鐘信號通知(source1 事件),被喚醒。如果 CoreAnimation 有未提交內(nèi)容,則執(zhí)行提交操作、如果有 CADisplayLink 等用戶自定義回調(diào),則觸發(fā)回調(diào)。
FPS中的刷新屏幕:當兩次 Vsync 信號到達之間,如果幀緩沖區(qū)中的數(shù)據(jù)發(fā)生了改變,就會刷新這一幀。卡頓是由于 CPU 和 GPU 的過載導致幀緩沖區(qū)的數(shù)據(jù)沒有刷新。
關(guān)于YY大神提到的
App 的 Runloop 在啟動后會注冊對應的 CFRunLoopSource 通過 mach_port 接收傳過來的時鐘信號通知,隨后 Source 的回調(diào)會驅(qū)動整個 App 的動畫與顯示。
我不能贊同。因為我在 demo 中測試發(fā)現(xiàn),當屏幕靜止不動時,runloop 處于一個每一分鐘喚醒一次的狀態(tài),并沒有被 Vsync 信號喚醒。只有當在 runloop 中加入了 CADisplayLink 之后,才會在一秒鐘被喚醒 60 次,CADisplayLink 應該是 source1 的 mach_msg 觸發(fā)(補充 source1: 當 硬件事件發(fā)生的時候,mach_port 轉(zhuǎn)發(fā)給App進程,source1 接收后觸發(fā) source0 再觸發(fā)到 UIApplication 的事件隊列中的)。