Chromium Graphics: 再談Chromium WebView硬體渲染模式的演化,chromiumwebview

來源:互聯網
上載者:User

Chromium Graphics: 再談Chromium WebView硬體渲染模式的演化,chromiumwebview

原創文章,轉載請以連結形式註明原始出處為http://blog.csdn.net/hongbomin/article/details/40896313

摘要:從Android KitKat系統第一個採用Chromium核心的WebView開始,Android WebView一直在持續演化中,自Chromium M38開始,WebView在硬體渲染模式方面發生了較大的變化,最明顯的變化莫過於WebGL的支援以及ubercompositor的使用,同時為了吻合Android L的渲染模型變化,DrawGL函數是在Android系統的渲染線程中執行的。

Android 4.4系統WebView的硬體渲染

對於Chromium WebView來說,首先它是單進程模型的,至少在使用CommandBuffer時可以省去不必要的跨進程IPC開銷,儘管IPC開銷並沒有想象中那麼大(根據效能評測,大概佔了不超過5%的開銷)。更為重要的是,WebView必須是Android視窗中一個普通的View,與視窗其他View共用同一個Android Surface繪製表面,因此,

  • WebView在UI線程上響應onDraw事件,啟動頁面渲染的流水線工作,將新的幀內容通過onDraw繪製到Canvas上;
  • WebView使用同步合成器(SynchronousCompositor)來合成頁面內容,“同步”指的是運行在UI線程上,合成操作是由UI線程的onDraw事件觸發的,而不是VSYNC觸發的。從線程化合成器的角度看,UI線程實際上也是Compositing線程;
  • WebView提供了一個硬體加速版本的回呼函數DrawGL(即AwContents::DrawGL),將Chromium的渲染流水線工作串到AndroidView的渲染路徑上。在使用硬體加速的情況下,WebView.onDraw接受的參數Canvas是一個對Android SDK不可見的android.view.HardwareCanvas對象,HardwareCanvas允許用戶端提供自己的GL回呼函數,Android  View系統在重放(playback)顯示列表繪製View層次時會調用這個回呼函數。(註:在AndroidFramework內部實現中,當開始繪製HardwareCanvas時,當前GL上下文會綁定HardwareCanvas的framebuffer對象,所以GL回呼函數中所有的GL命令實際上在操作HardwareCanvas的framebuffer對象)。

Android 4.4系統中,在繪製View層次時,顯示列表的更新記錄以及重放都發生在UI線程上,相應地,WebView.onDraw事件的處理中,頁面的層合成,以及通過DrawGL函數將合成的內容繪製到HardwareCanvas,都是在UI線程執行的。當WebView收到invalidate訊息後,ViewRoot會遍曆整個View樹決定向哪些View派送onDraw事件,WebView響應onDraw事件時,會直接請求HardwareCanvas執行DrawGL回呼函數,DrawGL再請求同步合成器以硬體加速方式合成新的一幀內容,並將這個新的內容通過GL命令繪製到HardwareCanvas上。這裡沒有特別提到Blink線程,原因是Blink線程相對來說還是比較獨立的,在Blink線程啟動後,會逐步執行DOM解析和排版,JS代碼的執行,以及渲染層的狀態資訊計算等工作,這些工作運行完畢之後,如果Compositor內部狀態機器發現頁面還需要繼續更新內容,執行動畫,Blink線程會通知UI線程(即Compositing線程)將WebView置為失效(invalidate)狀態,繼而觸發onDraw事件,再把上述過程走一遍。具體過程可參考如示:


必要的解釋:

  • Blink線程啟用了Impl-Side-Painting方式,在繪製頁面內容時,先將繪製命令錄製到一個SkPicture中,稍後再在Raster線程中重放這些繪製命令,從而儘可能的降低Blink線程的負載;
  • Raster線程是通過zero-copy技術直接將rasterization繪製到GPU記憶體中,從而減少了一次CPU到GPU的資料拷貝開銷;
  • 整個渲染過程中只有一個Compositor,在UI線程將已更新的Web頁面內容執行合成操作,寫到HardwareCanvas後端的FBO中,然後由Android SurfaceFlinger將最後的UI呈現在螢幕上
  • 步驟1,2,6和步驟3,4,5是可以同時進行的,步驟3,4,5總是在準備下一幀內容

這裡還需要特別說明的是,Android 4.4系統中WebView是沒有單獨的GPU線程執行GL命令的,所有的一切都發生在UI線程上,導致很難再提供WebGL的支援了,就算是花些力氣支援了WebGL,估計也是吃力不討好,因為效能是個大問題,在UI線程上執行WebGL很可能導致UI根本不會有響應。

Android L系統WebView的改進

Chromium WebView的演化速度還是相當的快。從最新發行的Android L開發人員預覽版來看,在頁面渲染的流水線和執行緒模式都有不少改進,如所示:


ubercompositor的使用

簡單的來說,ubercompositor是一個大一統的合成器,不管Chromium系統中存在幾個合成器,但最終的合成總是由一個稱為Parent Compositor完成,其他的Compositor唯一要做的事情是將自己管理的GPU資源打包為CompositorFrame發送給Parent Compositor,由Parent Compositor根據CompositorFrame包含的RenderPass列表和中繼資料等,執行合成操作將最後的內容寫到Native視窗上,當Parent Compositor完成合成操作,它會通知Child compositor可以執行資源的清理工作了,如所示:


為了吻合Android L引入的渲染線程(註:為了和Android系統的渲染線程作區分,Chromium的渲染線程稱為Blink線程),將Chromium渲染流程無縫整合到Android L系統中,WebView新的架構中引入了兩級合成器

  • Child Compositor:頁面內容的合成器,就是前面提到的同步合成器,運行在UI線程上,是一個線程化的合成器,其中Blink線程負責產生渲染層的狀態資訊,而UI線程負責合成渲染層。每收到onDraw事件後,WebView會使用ChildCompositor合成新的一幀,並將內容打包到CompositorFrame結構體中,稍後Android渲染線程會訪問這個結構體。ChildCompositor由android_webview::BrowserViewRenderer建立;
  • Parent Compositor:類似於Chrome on Android中Browser進程端的合成器,是一個單線程版本的合成器,其作用是在Android系統的渲染線程,注意不是UI線程,通過DrawGL回呼函數將已經由ChildCompositor合成好的CompositorFrame繪製到HardwareCanvas上。ParentCompositor由android_webview::HardwareRender建立;

與Android 4.4系統不同的是,在Android L系統上WebView處理onDraw事件邏輯上可以分解為兩個步驟:

  • 第一步,在UI線程上調用Child Compositor合成操作產生新的CompositorFrame,再向Android系統請求執行DrawGL回呼函數,但此時DrawGL並不會立即執行。UI線程負責為發生invalidate操作的View產生顯示列表,再將這個顯示列表同步給渲染線程上的ThreadedRenderer渲染器;
  • 第二步,Android View系統在渲染線程上將顯示列表提交給GPU驅動,繪製View層次的內容,在繪製顯示列表的過程中,DrawGL函數將會被調用,在渲染線程上請求Parent Compositor將合成的頁面內容繪製到HardwareCanvas上。

註:關於DrawGL回呼函數是如何指派到Android渲染線程上執行的,由於AndroidL的原始碼尚未完全公開,還不能100%確定上述描述是否完全正確。從已有掌握的資訊分析來看,UI線程會向HardwareCanvas發起DrawGL調用請求,此時可能不會立即執行DrawGL,而是作為drawOp先儲存在HardwareCanvas中,當渲染線程開始重放HardwareCanvas顯示列表時,再調用DrawGL。

上述兩個步驟與Android L採用的渲染執行緒模式完全吻合,這也是要引入兩級合成器的原因。AwContents::DrawGL是將Chromium圖形系統整合到Android中的一個極其關鍵的方法,它是Android L渲染線程進入Chromium圖形系統的唯一入口,DrawGL是在Android L在渲染線程為HardwareCanvas對象重放顯示列表被調用的,而另一方面,Chromium只能被動地由渲染線程調用DrawGL操作,唯一能夠擷取的資訊是當前HardwareCanvas後端的FBO對象,然後所有的內容都繪製到這個Canvas上,其他資訊諸如訊息佇列,非同步執行任務的能力,都難以擷取,這就導致Chromium會在DrawGL中,只能一次性地將任務隊列中所有的任務,例如等待SyncPoint,重新整理CommandBuffer等,全部執行完畢,這也就是為什麼下面提到的WebGL要在一個專門的GPU線程中執行的原因。

此外,WebView這個新型的渲染模型與Android4.4系統是不相容的,也就是從AndroidL編譯出來的libwebviewchromium.so是不能夠在Android 4.4系統啟動並執行。

WebGL和硬體加速Canvas 2D的支援

以WebGL為例,WebView為渲染WebGL還建立 了專門的GPU線程,WebGL程式中所有的GL命令都發生在這個線程上。渲染WebGL的egl上下文就是這個線程上建立的,然而,這個egl上下文是一個獨立的上下文,不與WebView進程內任何其他上下文共用資源,即與AndroidView系統的上下文不在同一個share group。關於Chromium中上下文和share group相關技術細節,可參閱ChromiumGraphics: 3D上下文及其虛擬化一文。Android View系統的上下文指的是調用DrawGL繪製HardwareCanvas時的上下文,因此,要將WebGL的內容繪製到HardwareCanvas上,需要解決將WebGL上下文和AndroidView系統上下文之間的texture共用和同步問題。首先,這兩個上下文都屬於同一進程,因此可以利用EGLImage進行跨線程的texture共用,再次,Chromium圖形棧提供的信箱texture(mailbox texture)機制有助於解決texture共用。Mailbox texture機製為每個產生的texture產生一個64位元組的唯一名字,並建立名字到texture id的全域對應表,所以不管在哪個上下文建立的texture,都可以通過mailbox的名字檢索到對應的texture id,mailbox機制的好處就是在一個支援多內容相關的環境提供了textureid的全域別名系統,換句話說,有了這個別名系統,所有上下文看起來都屬於“同一個share group”。

那麼,渲染WebGL是如何使用EGLImage和mailbox texture機制實現資源共用的呢?

Chromium中WebGL的內容是通過離屏的framebuffer對象渲染到texture中的,在GPU線程的WebGL上下文建立這個texture時將其綁定一個唯一的mailbox名字,還會調用eglCreateImageKHR為這個texture id建立一個可以被其他上下文共用的EGLImage,當AndroidView系統的渲染線程在另一個上下文中執行DrawGL函數,通過mailbox名字可確定GPU線程中的EGLImage,將其綁定到該內容相關的一個texture便可以直接使用WebGL內容相關的texture了,至此解決了texture共用問題。這裡還有一個問題需要交代一下,在多個上下文中共用texture時,必須處理好生產者和消費者之間的同步問題,即執行DrawGL函數繪製新的一幀時,要確保WebGL內容相關的所有GL命令都已經執行完畢。Chromium同樣提供了一套同步點(syncpoint)機制,來保證多個上下文(Chromium裡也稱CommandBuffer)之間GL命令的執行次序,在上下文A中插入一個同步點,然後在上下文B中等待這個同步點,可以保證上下文B中的GL命令必須等待上下文同步點A之前所有的GL命令全部執行完畢之後,才能開始執行。

所以,當WebGL將新的一幀內容產生完畢後,會插入一個同步點,而DrawGL時AndroidView系統上下文會等待這個同步點,只有當前WebGL所有GL命令都提交給GPU驅動之後,才開始使用WebGL的內容,從而保證了WebGL內容和DrawGL的同步。關於同步點機制的細節,請參閱ChromiumGraphics: GPU用戶端之間同步機制的原理和實現分析一文。

AndroidWebViewShell也支援硬體渲染模式

WebView Shell構建在核心類AwContents之上,AwContents在功能基本上可以等同於android.webkit.WebView類。Chromium M30的程式碼程式庫中只能編譯出僅支援軟體渲染模式的WebViewShell,從Chromium M38開始,WebView Shell也支援硬體加速渲染了,主要改進的地方是,使用GLSurfaceView作為最後的渲染目的地,如上所述,DrawGL回呼函數可以在非UI線程上調用,而GLSurfaceView正好也內建性地支援在單獨的線程中被渲染。

小結

最後,來總結一下Android L系統WebView的幾個重要特點:第一,使用的in-process模式的命令列緩衝區,與Chromium瀏覽器不同的是,它沒有IPC開銷;第二,Parent合成器的DrawGL函數是Android Render線程進入Chromium系統的唯一入口,它在Android Render線程中被調用;第三,WebGL和硬體加速的Canvas 2D運行在單獨的GPU線程中,並使用EGLImage實現GPU線程和Android Render線程之間的GPU資源共用;第四,UI線程仍然有許多事情要做,包括Child合成器”合成“頁面內容打包成CompositorFrame結構體,處理使用者輸入事件等;第五,UI線程和Android Render線程需要一定的機制去同步兩者對CompositorFrame結構體的訪問;第六,WebView Shell已經可以支援硬體加速模式了
原創文章,轉載請註明來自http://blog.csdn.net/hongbomin/article/details/40896313,謝謝!


Chromium怎顯示網頁(how Chromium displays web pages)

應用程式層次概念圖
layers 每個盒子代表一個概念中的應用程式層。通常情況下應該有可能通過替換任意一層及其上層組建來產生一個新的瀏覽器。因此,沒有任何層應該與其更高層次有依賴關係。 WebKit的:Safari,Chromium和其他所有基於WebKit的瀏覽器都使用Webkit作為渲染引擎。WebKit Port是WebKit的一部分,處理與具體平台相關的操作,如資源載入和圖形。 Glue: 將WebKit類型轉換成Chromium類型 。這就是我們的“WebKit嵌入層”。這是瀏覽器Chromium和test_shell(允許我們測試WebKit)的基礎。 Renderer/Render Host: 這是Chromium的“多進程嵌入層。”由它代理傳遞跨進程的訊息和命令。你可以想象,其他的多進程瀏覽器也可以使用這一層,它對其他的瀏覽器服務沒有依賴。 Tab contents: Chrome的特有層,來表示標籤顯示的內容。它與應用服務綁定, 例如密碼管理器和history系統。本層不應該假設它嵌入在Chromium瀏覽器視窗中(還有其他Chromium組件如”HTML對話方塊“使用本層)。 瀏覽器:展現瀏覽器視窗,它嵌入了多個TabContentses。 WebKit 我們使用 WebKit這個開源項目來展示網頁。此代碼主要是由Apple編寫的並存放在/third_party/WebKit目錄中。WebKit主要包括兩部分:“WebCore”負責核心布局功能,“JavaScriptCore”用來執行JavaScript。我們只將JavaScriptCore用於測試目的,通常我們使用高效能的V8 JavaScript引擎取代它。我們實際不使用蘋果稱之為“WebKit”的軟體層(譯註:就是WebKit/Source/WebKit目錄下的內容,Webkit/Source目錄下同樣有WebCore和JavaScriptCore目錄),這個軟體層用在如Safari這樣的應用程式中,用來銜接WebCore和OS X。為了方便,我們通常將從Apple擷取的代碼稱作“WebKit”。(譯註,其實只使用了WebCore) The WebKit Port 在最底層,我們有我們的WebKit“Port”。這是我們實現的平台相關的代碼,它用來銜接平台和WebCore。這些檔案位於WebKit目錄中,通常在Chromium目錄中或者以Chromium為尾碼名。實際上Port的大部分代碼不是和作業系統相關的:你可以把它看成是WebCore的Chromium Port(譯註:用來銜接WebKit和Chromium的)。有些部分,如字型渲染,必須針對每個作業系統平台分別處理。 網路流量是由我們的多進程資源載入系統處理的,而不是由渲染進程直接叫用作業系統完成。 圖形使用為Android開發的Skia圖形庫。這是一個跨平台的圖形庫,原生的處理除了文字以外的所有圖形、映像。Skia位於/third_party/skia。圖形操作的主要進入點是 / WebKit/port/platform/graphics/GraphicsContextSkia.cpp。它使用了同目錄及/base/gfx目錄中的許多其他檔案 。 WebKit glue Chromium使用了和WebKit代碼不同的類型,編碼方式和代碼結構。WebKit“glue”提供一個更方便的嵌入WebKit的API......餘下全文>>
 
libwebviewchromiumso可以刪

刪了之後, 就無法從chromium瀏覽器中, 查看你的網路攝影機了.
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.