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

var: http://bigline.cn/word/index.php/2011/12/android-2/

(說明:我之所以寫這篇文章,僅僅是爲了糾正網上傳播的關於Android的各種錯誤認知。我並非是爲了解釋什麼,只不過是想給那些關注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使用硬件加速繪製背景。而在沒有開啓硬件加速的應用中,此類背景會自動去掉~


原文地址:https://plus.google.com/105051985738280261832/posts/2FXDCz8x93s

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章