轉載請註明原文地址:http://blog.csdn.net/milado_njucanvas
## 數據對比瀏覽器
前面介紹過Chromium WebView的時候,說過有關ChromiumWebView同Chrome瀏覽器有不少不一樣之處,下面以Chromium Content Shell來對比來描述Chromium WebView,這是由於Chrome瀏覽器的渲染機制等同Content Shell是相似的,不過Chrome瀏覽器上層代碼是源的,因此筆者使用本身編譯的Content Shell來分析。架構
在仔細介紹Chromium WebView以前,先看一組性能方面的數據,是有關於Chromium WebView和Chromium Content Shell的對比。雖然版本有些舊,而且如今的變化很快,可是這一版本依舊可以說明一些問題。函數
下面的性能數據是在Android4.4系統上測試基於Chromium30的WebView和ChromiumContent Shell。所使用的測試的兩個Benchmark一個是測試CSS3D性能,另一個是測試Canvas 2D性能。性能指標主要是包括FPS和內存兩個方面,以下圖所示。性能
性能方面,目前Content Shell較ChromiumWebView有不錯的表現,在CSS3D和Canvas 2D上都有出色的表現,其中FishIETank出現的特別大的差別主要是由於Chromium 30上硬件加速的Canvas2D技術尚未支持。在內存方面,Chromium WebView使用更少的內存,這個主要源於它的進程模型,它沒有使用多進程架構。測試
## Content Shell的渲染方式動畫
下面詳細描述Content Shell的渲染方式。圖中有多個線程,其中標註橙色的是在Browser進程中,標註另外顏色的是Renderer進程。在Renderer線程中,主要是渲染樹和合成樹,同時有個合成器線程,根據以前章節的描述,它負責合成網頁的各個層。在Android系統上,Chromium中的GPU工做變成一個線程,工做在Browser進程中,具體功能以前介紹過。spa
在Browser進程中,還有一個瀏覽器測的合成器線程,它的主要工做是將Renderer進程中合成結果和瀏覽器界面的一些內容合成起來,輸出到SurfaceView對象。由於Android上SurfaceView的特性,因此能夠爲它建立單獨的EGLContext,合成器線程能夠結果繪製到該SurfaceView對象中顯示出來。.net
在這一過程當中,Chromium並不須要UI線程的參與,全部的工做都是在其它線程來完成的,因此UI線程不會被阻塞。不過,由於Android系統上的動畫、變換等並能做用於SurfaceView對象,因此瀏覽器沒有關係,可是用來嵌入其它UI界面,可能不能知足開發者的需求。具體的過程以下圖所示。線程
這種狀況下,就須要可以嵌入用戶界面的一種機制,那就是Chromium WebView。
## Chromium WebView
Chromium WebView同以前的基於AndroidWebKit的所提供的功能相似,那就是它也可以提供一個View,並嵌入到其它UI界面中,跟其它沒有view沒有什麼不一樣,只不過是用來渲染網頁,下圖描述Chromium WebView如何將網頁內容繪製到用戶UI界面中。
由於Chromium WebView沒有多進程架構,因此圖中全部線程都工做在主進程中。首先看渲染線程,它也再也不工做在Renderer進程。同Content Shell相似,它也是包括渲染樹和合成樹。GPU線程也是相似的功能。不一樣之處在於同步的合成器,將網頁的合成器放在主線程中來工做,這裏主要的問題在於,須要繪製網頁內容到UI中的時候須要在UI線程。
在Android系統中,若是用戶界面設置的渲染方式硬件加速渲染方式,那麼Android會使用內部HwUI機制。該機制會爲每一個Activity的內部View(ViewRootImpl類)構建一個HardwareRenderer,該對象可以建立EGLSurface和EGLContext,並將繪圖動做轉變成OpenGLES的操做。當繪製界面內容的時候,會充值當前EGLContext爲本身建立的,逐次調用每一個View的繪圖操做。當繪製到WebView對象的時候,它會調用同步合成器將網頁的結果繪製到當前的FBO中。下圖是Android系統如何調用WebView的繪圖網頁內容的過程。
上圖中上面三個階段是Android繪圖系統中的調用,下面兩個是WebView的調用過程。在繪製界面的過程,會出現多個階段,每一個階段的操做可能還不同,因此讀者可以看到圖中Functor::operator函數出現state參數。
若是是軟件渲染模式,那麼問題變得更簡單一些。在Renderer線程中,只須要渲染樹,當調用WebView::onDraw(Canvas canvas)的時候,將網頁的內容直接繪製在該Canvas對象上。在新版本上,由於使用UberCompositor等機制,因此合成器也可以直接輸出到一個Bitmap對象上。
## PictureLayer層等處理
除了整體上的繪製機制存在明顯的不一樣以外,二者還存在對某些層的繪製方法不一致的地方。這裏的主要緣由在於Chromium WebView可以使用系統內部的函數,而做爲App的Content Shell缺不行。主要針對於那些常見的層,也就是基本文字圖片等層PictureLayer,以下圖所示。
左側是Content Shell所使用的機制,右側是Chromium WebView所使用的機制。由於跨進程的緣由,Chromium使用共享內存將SkPicture繪製的內容(CPU內存中保存)經過共享內存傳到Browser進程,並上傳到GPU的紋理對象。右側則是使用「gralloc」函數來分配」graphic buffer」,SkPicture直接將網頁的一層繪製到該緩衝區對象上。
相信隨着時間的推移,ChromiumWebView會愈來愈接近Content Shell,不過若是Android圖形系統不改變,那麼在某些方面Chromium WebView仍然不會遇上Content Shell的性能,特別是將網頁的結果合成部分必須在UI線程來進行,必然會阻礙UI線程對用戶事件等的響應。