本篇文章主要介紹 Android 開(kāi)發(fā)中的部分知識(shí)點(diǎn),通過(guò)閱讀本篇文章,您將收獲以下內(nèi)容:
一、Vsync 概述二、Android 圖形數(shù)據(jù)流向三、Systrace 中的圖像數(shù)據(jù)流四、Vsync Offset五、HW_Vsync
Vsync 信號(hào)可以由硬件產(chǎn)生,也可以用軟件模擬,不過(guò)現(xiàn)在基本上都是硬件產(chǎn)生,負(fù)責(zé)產(chǎn)生硬件 Vsync 的是 HWC,HWC 可生成 VSYNC 事件并通過(guò)回調(diào)將事件發(fā)送到 SurfaceFlinger , DispSync 將 Vsync 生成由 Choreographer 和 SurfaceFlinger 使用的 VSYNC_APP 和 VSYNC_SF 信號(hào)
在 Android 基于 Choreographer 的渲染機(jī)制詳解 這篇文章里面,我們有提到 :Choreographer 的引入,主要是配合 Vsync,給上層 App 的渲染提供一個(gè)穩(wěn)定的 Message 處理的時(shí)機(jī),也就是 Vsync 到來(lái)的時(shí)候 ,系統(tǒng)通過(guò)對(duì) Vsync 信號(hào)周期的調(diào)整,來(lái)控制每一幀繪制操作的時(shí)機(jī). 目前大部分手機(jī)都是 60Hz 的刷新率,也就是 16.6ms 刷新一次,系統(tǒng)為了配合屏幕的刷新頻率,將 Vsync 的周期也設(shè)置為 16.6 ms,每個(gè) 16.6 ms,Vsync 信號(hào)喚醒 Choreographer 來(lái)做 App 的繪制操作 ,這就是引入 Choreographer 的主要作用
渲染層(App)與 Vsync 打交道的是 Choreographer,而合成層與 Vsync 打交道的,則是 SurfaceFlinger。SurfaceFlinger 也會(huì)在 Vsync 到來(lái)的時(shí)候,將所有已經(jīng)準(zhǔn)備好的 Surface 進(jìn)行合成操作
下圖顯示在 Systrace 中,SurfaceFlinger 進(jìn)程中的 VSYNC_APP 和 VSYNC_SF 的情況
首先我們要大概了解 Android 中的圖形數(shù)據(jù)流的方向,從下面這張圖,結(jié)合 Android 的圖像流,我們大概把從 App 繪制到屏幕顯示,分為下面幾個(gè)階段:
image
下面這張圖也是官方的一張圖,結(jié)合上面的階段,從左到右看,可以看到一幀的數(shù)據(jù)是如何在各個(gè)進(jìn)程之間流動(dòng)的
了解了 Android 中的圖形數(shù)據(jù)流的方向,我們就可以把上面這個(gè)比較抽象的數(shù)據(jù)流圖,在 Systrace 上進(jìn)行映射展示
上圖中主要包含 SurfaceFlinger、App 和 hwc 三個(gè)進(jìn)程,下面就來(lái)結(jié)合圖中的標(biāo)號(hào),來(lái)進(jìn)一步說(shuō)明數(shù)據(jù)的流向
文章最開(kāi)始有提到,Vsync 信號(hào)可以由硬件產(chǎn)生,也可以用軟件模擬,不過(guò)現(xiàn)在基本上都是硬件產(chǎn)生,負(fù)責(zé)產(chǎn)生硬件 Vsync 的是 HWC,HWC 可生成 VSYNC 事件并通過(guò)回調(diào)將事件發(fā)送到 SurfaceFlinge , DispSync 將 Vsync 生成由 Choreographer 和 SurfaceFlinger 使用的 VSYNC_APP 和 VSYNC_SF 信號(hào).
disp_sync_arch
其中 app 和 sf 相對(duì) hw_vsync_0 都有一個(gè)偏移,即 phase-app 和 phase-sf,如下圖
image
Vsync Offset 我們指的是 VSYNC_APP 和 VSYNC_SF 之間有一個(gè) Offset,即上圖中 phase-sf - phase-app 的值,這個(gè) Offset 是廠商可以配置的。如果 Offset 不為 0,那么意味著 App 和 SurfaceFlinger 主進(jìn)程不是同時(shí)收到 Vsync 信號(hào),而是間隔 Offset (通常在 0 - 16.6ms 之間)
目前大部分廠商都沒(méi)有配置這個(gè) Offset,所以 App 和 SurfaceFlinger 是同時(shí)收到 Vsync 信號(hào)的.
可以通過(guò) Dumpsys SurfaceFlinger 來(lái)查看對(duì)應(yīng)的值
Offset 為 0:(sf phase - app phase = 0)
Sync configuration: [using: EGL_ANDROID_native_fence_sync EGL_KHR_wait_sync]DispSync configuration: app phase 1000000 ns, sf phase 1000000 ns early app phase 1000000 ns, early sf phase 1000000 ns early app gl phase 1000000 ns, early sf gl phase 1000000 ns present offset 0 ns refresh 16666666 ns
Offset 不為 0 (SF phase - app phase = 4 ms)
Sync configuration: [using: EGL_ANDROID_native_fence_sync EGL_KHR_wait_sync]VSYNC configuration: app phase: 2000000 ns SF phase: 6000000 ns early app phase: 2000000 ns early SF phase: 6000000 nsGL early app phase: 2000000 ns GL early SF phase: 6000000 ns present offset: 0 ns VSYNC period: 16666666 ns
下面以 Systrace 為例,來(lái)看 Offset 在 Systrace 中的表現(xiàn)
首先說(shuō) Offset 為 0 的情況, 此時(shí) App 和 SurfaceFlinger 是同時(shí)收到 Vsync 信號(hào) , 其對(duì)應(yīng)的 Systrace 圖如下:
這個(gè)圖上面也有講解,這里就不再詳細(xì)說(shuō)明,大家只需要看到,App 渲染好的 Buffer,要等到下一個(gè) Vsync-SF 來(lái)的時(shí)候才會(huì)被 SurfaceFlinger 拿去做合成,這個(gè)時(shí)間大概在 16.6 ms。這時(shí)候大家可能會(huì)想,如果 App 的 Buffer 渲染結(jié)束,Swap 到 BufferQueue 中 ,就觸發(fā) SurfaceFlinger 去做合成,那豈不是省了一些時(shí)間(0-16.6ms )?
答案是可行的,這也就引入了 Offset 機(jī)制,在這種情況下,App 先收到 Vsync 信號(hào),進(jìn)行一幀的渲染工作,然后過(guò)了 Offset 時(shí)間后,SurfaceFlinger 才收到 Vsync 信號(hào)開(kāi)始合成,這時(shí)候如果 App 的 Buffer 已經(jīng) Ready 了,那么 SurfaceFlinger 這一次合成就可以包含 App 這一幀,用戶也會(huì)早一點(diǎn)看到。
下圖中,就是一個(gè) Offset 為 4ms 的案例,App 收到 Vsync 4 ms 之后,SurfaceFlinger 才收到 Vsync 信號(hào)
image
Offset 的一個(gè)比較難以確定的點(diǎn)就在與 Offset 的時(shí)間該如何設(shè)置,這也是眾多廠商默認(rèn)都不進(jìn)行配置 Offset 的一個(gè)原因,其優(yōu)缺點(diǎn)是動(dòng)態(tài)的,與機(jī)型的性能和使用場(chǎng)景有很大的關(guān)系
這里需要說(shuō)明的是,不是每次申請(qǐng) Vsync 都會(huì)由硬件產(chǎn)生 Vsync,只有此次請(qǐng)求 vsync 的時(shí)間距離上次合成時(shí)間大于 500ms,才會(huì)通知 hwc,請(qǐng)求 HW_VSYNC
以桌面滑動(dòng)為例,看 SurfaceFlinger 的進(jìn)程 Trace 可以看到 HW_VSYNC 的狀態(tài)
后續(xù) App 申請(qǐng) Vsync 時(shí)候,會(huì)有兩種情況,一種是有 HW_VSYNC 的情況,一種是沒(méi)有有 HW_VSYNC 的情況
HW_VSYNC 主要是利用最近的硬件 VSYNC 來(lái)做預(yù)測(cè),最少要 3 個(gè),最多是 32 個(gè),實(shí)際上要用幾個(gè)則不一定, DispSync 拿到 6 個(gè) VSYNC 后就會(huì)計(jì)算出 SW_VSYNC,只要收到的 Present Fence 沒(méi)有超過(guò)誤差,硬件 VSYNC 就會(huì)關(guān)掉,不然會(huì)繼續(xù)接收硬件 VSYNC 計(jì)算 SW_VSYNC 的值,直到誤差小于 threshold.關(guān)于這一塊的計(jì)算具體過(guò)程,可以參考這篇文章: S W-VS YN C 的生成與傳遞 ,關(guān)于這一塊的流程大家也可以參考這篇文章,里面有更細(xì)節(jié)的內(nèi)容,這里摘錄了他的結(jié)論
SurfaceFlinger 通過(guò)實(shí)現(xiàn)了 HWC2::ComposerCallback 接口,當(dāng) HW-VSYNC 到來(lái)的時(shí)候,SurfaceFlinger 將會(huì)收到回調(diào)并且發(fā)給 DispSync。DispSync 將會(huì)把這些 HW-VSYNC 的時(shí)間戳記錄下來(lái),當(dāng)累計(jì)了足夠的 HW-VSYNC 以后(目前是大于等于 6 個(gè)),就開(kāi)始計(jì)算 SW-VSYNC 的偏移 mPeriod。計(jì)算出來(lái)的 mPeriod 將會(huì)用于 DispSyncThread 用來(lái)模擬 HW-VSYNC 的周期性起來(lái)并且通知對(duì) VSYNC 感興趣的 Listener,這些 Listener 包括 SurfaceFlinger 和所有需要渲染畫(huà)面的 app。這些 Listener 通過(guò) EventThread 以 Connection 的抽象形式注冊(cè)到 EventThread。DispSyncThread 與 EventThread 通過(guò) DispSyncSource 作為中間人進(jìn)行連接。EventThread 在收到 SW-VSYNC 以后將會(huì)把通知所有感興趣的 Connection,然后 SurfaceFlinger 開(kāi)始合成,app 開(kāi)始畫(huà)幀。在收到足夠多的 HW-VSYNC 并且在誤差允許的范圍內(nèi),將會(huì)關(guān)閉通過(guò) EventControlThread 關(guān)閉 HW-VSYNC。
推薦閱讀:蘋(píng)果x好還是xr好
查看心情排行你看到此篇文章的感受是: