天天看點

關于Android圖形系統的一些事實真相

現在網上滿天飛的各類關于Android圖像渲染的水文實在讓我不爽,下面給大家一些關于Android硬體渲染的事實真相,硬體加速并非大家想的那麼完美,而我們也一直在改進!

1. Android 一直在使用硬體加速。實際上從1.0版本之後,所有的視窗元素的合成與顯示都是通過硬體完成的。

2.這意味着許多你所看見的動畫都是被加速過的:按鈕的顯示、通知欄下拉的陰影、不同Activity之間的切換動畫、彈出視窗以及提示框的顯示和隐藏等等等等。

3.Android以前使用軟體方式(與硬體加速相對應)來控制各個視窗元素的渲染,例如下圖的UI,其中包括四個視窗元件:狀态條、桌面、桌面上的的啟動器、以及菜單。如果其中一個元素更改了自身的内容,例如高亮一個菜單條目,對于3.0之前的版本,系統使用軟體方式來繪制新的内容,然而并非所有的元素都需要被重新繪制,同時各個視窗元素的拼接也是通過硬體方式完成的。類似的,任何視窗的移動:例如菜單的上下運動是完全通過硬體方式渲染的。

4. 現在我們來關注視窗元素的内部渲染,實際上為了達到每秒60幀的FPS,你并不一定需要硬體加速。幀速取決于要顯示的像素的數量以及CPU的速度。比如說,二兒子完全可以以60FPS的速度在它800*480分辨率的螢幕上完成任何普通的原生UI動畫,例如清單的滾動等,完全沒有問題。而最初的Droid系列卻很難達到這樣的速度。

5.在Android3.0中可以實作視窗的”完全”的硬體加速繪制。而在Android 4.0中也沒有引入更多的功能。 從3.0開始,如果在你的應用中設定了一個标志允許硬體加速,那麼此時所有的視窗的繪制都會交給GPU來完成。在Android 4.0中最主要的改變就是:在面向Android4.0或更高版本的應用中,硬體加速是被預設開啟的,再也不需要在配置檔案中設定 android:handwareAccelerated=”true”.(而我們不允許之前的應用預設打開硬體加速,是因為光靠硬體加速,無法很好的完成某些特殊的繪制操作;同時在應用需要其中一部分UI更新的時候,會影響其的一些表現。對于目前現有的很多應用,強制開啟硬體加速,會明顯的中斷應用的運作)

6.硬體加速并不如大家所認為的那樣完美。例如在基于PVR驅動的裝置上(比如二兒子跟三兒子),光是在程序中開啟OpenGL就得占用8M的RAM。對比一般程序的2M的開銷實在是巨大。RAM是有限的,一大部分被拿去繪制,那麼其他正在運作的程序就會因為缺少記憶體而出問題,比如降低應用間切換的速度。

7.由于OpenGL的額外開銷,我們最好不要過多的使用其進行繪制。比如我們現在在做的一些工作,就是為了讓Android 4.0能在不使用硬體加速的情況下流暢的在二兒子上使用:這樣我們就不需要在系統程序中浪費8MB的記憶體用,也不需要在手機程序中浪費額外的8M記憶體,或者是在系統UI程序中的8MB記憶體 等等等等。相信我,你不會注意到——用OpenGL來繪制一些類似狀态欄或是華麗的動畫是完全沒有好處的。

8.硬體加速并非流暢UI的“解藥”。我們為了UI的流暢嘗試了很多不同的方法,比如說在1.6中引入的對前台/背景程序的排程政策,在2.3中的對輸入系統的重寫,”嚴厲模式”的使用,并發的垃圾回收機制,載入器等等。如果你想達到60fps的幀速,你隻有20毫秒的時間來處理每幀的内容。這時間實在不長,光是在UI程序中讀取存儲卡的操作産生的延時就會大于這個時限,尤其是在寫操作的時候。

9.舉些最近發現的一些影響UI流暢度的例子:我們注意到在二兒子上,使用4.0時清單的滾動就不如使用2.3時流暢。而導緻這個現象的原因則是計時器的輕微漂移:有些時候應用正在接收觸摸事件并在螢幕上繪制,而在上一個動作還沒完成的的時候,就接受到下一個事件并開始繪制,導緻它丢失了目前這幀。盡管發生這種現象的時候,幀速能達到穩定的60FPS.(當然,這個問題已經修正)

10.當人們比較Android跟IOS上浏覽器的滾動流暢度的時候,他們所看見的差别并非開沒開啟硬體加速所導緻。 最初的時候,Android使用了一種完全不同的渲染政策,并做了一些折中:網頁被轉換成一個”顯示清單“,持續的在螢幕上進行繪制,而非使用塊(Tiles)的形式。它有一個優點:就是在滾動或是縮放的時候不會發生有的塊還沒被渲染出來的現象(譯者注:早期的IOS上這種現象非常明顯,快速滾動到底部時要等一會網頁才會一塊一塊的繪制出來)。 而這個方法的不給力之處就在于頁面複雜的時候,幀速就明顯低了。例如Android3.0,浏覽器中現在開始使用塊的方式進行渲染,于是它可以在滾動或是放大的時候保持一個穩定的幀速,自然也會出現新的塊沒有被立即渲染出來的情況。 而每個塊都是以軟體方式繪制的,我相信在IOS中也是這樣的。(在3.0之前的版本中,沒有開啟硬體加速,基于塊的政策也可以使用。而且如我之前提到的,二兒子可以很容易的達到60FPS)

11.硬體加速不能如大家所想奇迹般的讓繪制的問題統統消失。GPU的性能就是一個很重要的限制。最近一個很有趣的例子:基于英偉達的Tegra2的平闆可以很容易的以60FPS的速度通路2.5次1280*800分辨率的螢幕中的任何一個像素。現在考慮到在Android 3.0中切換到所有應用清單的情形:你需要繪制背景(1x 所有的像素)、接着是快捷方式和桌面小工具(假設内容不多,花費0.5x),接着是所有應用的黑色背景(1x),接着是所有應用的ICON(0.5x)。顯然,我們已經超過了原先的預算了,而此時我們還沒完成各個獨立視窗元素的拼接并做最後的顯示。想要取得60FPS的動畫,Android 3.0以及後續版本使用了一系列的小技巧。 其中主要的一個就是: 它将所有的視窗元素平鋪在一個層中,而不是挨個拷貝到CPU的緩存中。但即使是這樣,我們已然超出預算,幸好我們使用另一個技巧:因為Android中的背景是一個獨立的視窗元素,我們可以将它設定的比螢幕更大來放置整幅位圖,現在,使用者開始滑動,背景跟着運動,此時并不需要任何特殊的繪制,僅僅是移動視窗即可,而由于這個視窗是在一個平鋪層上,我們甚至不需要用GPU來将這個視窗元素組織到螢幕中輸出。

12.随着螢幕分辨率的不斷升高,能否達到60FPS跟GPU的速度尤其是記憶體總線帶寬息息相關。事實上,如果你想要提升硬體的效力,特别注意要提升記憶體總線的帶寬。很多時候CPU(特别是帶有完美的NEON指令集的CPU)會比記憶體總線塊的多。

UPDATE:下面居然有這麼多讨論,但是我木有能力解釋清楚相關的所有問題了。不過我會盡力在這裡提供一些我認為比較有趣的觀點。

有些人認為蓋世兔已經有了一個非常流暢的UI并指出他們已經超越三兒子并做了很多改進。事實上,大家忽略了很多裝置的差異,蓋世兔的螢幕是480*800而三兒子是720*1280。如果二兒子在它480*800的螢幕上都能達到60FPS,擁有更NB的CPU的蓋世兔必須得同樣流暢嘛。

而兩者之間最大的差别就是三兒子需要同時繪制2.4倍于蓋世兔的像素。這相當于在單核上提升到2.4倍的速度。(需要指出 在UI渲染的時候,多核是沒有意義的,因為渲染必須要在一個程序中完成,無法并行)

這就是為什麼硬體加速非常重要:随着像素的提升,GPU通常能更好的處理圖像的運算。事實上,這是我們在Android中引入硬體加速的最大動力。在720*1280的螢幕上,現有的ARM CPU達到60FPS很吃力,但是通過GPU渲染就不同了。同樣,在與蓋世兔的比較中,同時打開沒有硬體加速的應用,在三兒子中無法達到蓋世兔同樣的60FPS,是因為它得渲染2.4倍于蓋世兔的像素。

在最後,還得提及GPU的另外一個優勢:許多繪制的效果變得更加容易。比如你要以軟體形式繪制一個位圖,你除了設定一個位移,不能做任何事。僅僅是縮小就得花上相當多的時間進行渲染。而在GPU中,此類轉換則相當容易。這就是為神馬新的預設主題Holo使用硬體加速繪制背景。而在沒有開啟硬體加速的應用中,此類背景會自動去掉~

(說明:後面的很多評論認為我寫這個隻是為Android不如IOS卡亂找借口或是不體貼使用者等等,我在這裡需要澄清一下:我之是以寫這篇文章,僅僅是為 了糾正網上傳播的關于Android的各種錯誤認知。我并非是為了解釋什麼,隻不過是想給那些關注Android卻又被網上各種錯誤認知困擾的童鞋提供參 考)

繼續閱讀