[譯]關于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分辨率的屏幕中的任何一個像素?,F在考慮到在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
(說明:后面的很多評論認為我寫這個只是為Android不如IOS卡亂找借口或是不體貼用戶等等,我在這里需要澄清一下:我之所以寫這篇文章,僅僅是為 了糾正網上傳播的關于Android的各種錯誤認知。我并非是為了解釋什么,只不過是想給那些關注Android卻又被網上各種錯誤認知困擾的童鞋提供參 考)
- 目前還沒評論,等你發揮!