轉(zhuǎn)載請(qǐng)注明原文地址:http://blog.csdn.net/milado_nju/article/details/7292174
# Chromium硬件加速合成(hardware accelerated compositing)
## 概述
在介紹硬件加速合成之前,讓我們先大概了解一下基本的做法是如何渲染生成網(wǎng)頁內(nèi)容的。
一個(gè)網(wǎng)頁通常可以包含很多層,這個(gè)我們?cè)赪ebKit渲染基礎(chǔ)中講過,例如有透明效果的節(jié)點(diǎn), Canvas節(jié)點(diǎn)等,這些節(jié)點(diǎn)都可以是頁面中的一層,這些層的內(nèi)容最后組成一個(gè)可視化的網(wǎng)頁內(nèi)容,如下圖所示。
在沒有硬件加速的情況下,瀏覽器通常是依賴于CPU來渲染生成網(wǎng)頁的內(nèi)容,大致的做法是遍歷這些層,然后按照順序把這些層的內(nèi)容依次繪制在一個(gè)內(nèi)部存儲(chǔ)空間上(例如bitmap),最后把這個(gè)內(nèi)部表示顯示出來,這種做法就是軟件渲染(software rendering),我們會(huì)有專門針對(duì)它的介紹。
隨著GPU硬件能力的增強(qiáng),包括在很多小型設(shè)備上也是如此,瀏覽器可以借助于其處理圖形方面的性能來對(duì)渲染實(shí)現(xiàn)加速,本章要介紹的就是利用GPU來實(shí)現(xiàn)對(duì)頁面分層渲染并加速合成網(wǎng)頁的可視化結(jié)果。
前面我們已經(jīng)介紹了WebKit中對(duì)于渲染所做的一些基礎(chǔ)設(shè)施,包括Render樹和RenderLayer樹,對(duì)于每一個(gè)RenderLayer,我們可以為其單獨(dú)創(chuàng)建一塊內(nèi)部存儲(chǔ)(有些情況下可以為多個(gè)layer創(chuàng)建同一塊存儲(chǔ)),這些存儲(chǔ)會(huì)被用來保存該層中的內(nèi)容,瀏覽器最后會(huì)把這些所有的層通過GPU合成起來,形成最終網(wǎng)頁渲染的內(nèi)容,這就是硬件加速合成。
本節(jié)主要介紹WebKit中為硬件加速所做的另外一些基礎(chǔ)設(shè)施,接著是chromium中為硬件加速合成所做的支持,最后介紹chromium中最新的合成器:chromium compositor(cc)。
## WebKit 的支持
在建立DOM樹后,如前面所述, WebKit會(huì)創(chuàng)建相應(yīng)的Render樹和RenderLayer樹。如果啟用“加速合成(accelerated_compositing)”選項(xiàng),WebKit會(huì)做一些特別的處理。
它為每個(gè)RenderLayer創(chuàng)建一個(gè)RenderLayerBacking,這個(gè)類非常的有用,它是用來管理和控制RenderLayer的合成相關(guān)的事情,決定對(duì)該層是否做優(yōu)化,同時(shí)包含了很多GraphicsLayer的對(duì)象。GraphicsLayer類是一種抽象,用于表示有后端存儲(chǔ)(backing store)的渲染surface,同時(shí),也包括作用于之上的各種變換(transformation)和動(dòng)畫(animation)。 RenderLayerBacking類中包含的這些GraphicsLayer有內(nèi)容層,可能還有前景層(Foreground),剪切層(clipping)等。下圖中的WebKit部分是WebKit中為渲染和硬件加速所涉及的類,在此一一介紹。
RenderLayerCompositor: WebKit中渲染部分‘掌控大局’的類, 管理RenderLayer樹結(jié)構(gòu),它通過瀏覽器的設(shè)置來決定是否創(chuàng)建RenderLayer以及是否硬件加速合成,同時(shí)也決定是否為RenderLayer創(chuàng)建RenderLayerBacking
RenderLayerBacking:用來管理和控制相對(duì)應(yīng)的RenderLayer的合成行為,包含很多GraphicsLayer對(duì)象,這些對(duì)象用于表示層內(nèi)容,前景(foreground)內(nèi)容等等
GraphicsLayer: 用于表示有后端存儲(chǔ)(backingstore)的渲染surface及其相應(yīng)的變換等,該類是一個(gè)抽象類,不同平臺(tái)的移植有不同的實(shí)現(xiàn)
## Chromium的支持
WebKit提供了基礎(chǔ)設(shè)施, 但要實(shí)現(xiàn)硬件加速合成,各個(gè)移植還有很多事要做,chromium也是如此,見上圖中的Chromium部分。
大致地,可以把Chromium中的關(guān)于硬件加速合成部分分成兩塊,第一塊是對(duì)WebKit接口的具體實(shí)現(xiàn),第二塊是Chromium合成的管理和實(shí)現(xiàn)部分。
第一塊包括上圖中Chromium部分的兩個(gè)類GraphicsLayerChromium和LayerChromium:
GraphicsLayerChromium:繼承自GraphicsLayer,實(shí)現(xiàn)了GraphicsLayer的虛函數(shù)接口,提供了chromium自已的移植。
LayerChromium:Chromium中的PlatformLayer類,具體的就是chromium的實(shí)際的被合成層的基類,被GraphicsLayerChromium所創(chuàng)建。LayerChromium有多個(gè)子類,例如對(duì)WebGL和video支持的WebGLLayerChromium,VideoLayerChromium類
第二塊則是Chromium部分的CC開頭的類和LayerRenderChromium:
LayerRendererChromium:一個(gè)很重要的類,負(fù)責(zé)實(shí)現(xiàn)合成功能,利用GL來繪制被合成的各個(gè)CCLayerImpl層
CCLayerImpl:該類主要是負(fù)責(zé)一個(gè)層的繪制(drawing)工作,由LayerChromium創(chuàng)建,同樣構(gòu)成一個(gè)樹型結(jié)構(gòu),被CCLayerTreeHostImpl來管理。每個(gè)對(duì)象可以有自己的渲染surface對(duì)象,也可以使用其祖先的,這取決于具體的策略。
CCRenderSurface:渲染的surface類,被CCLayerImpl所創(chuàng)建和使用,有自己的存儲(chǔ)后端
CCLayerTreeHost: 一個(gè)CCLayerImpl樹的客戶端類,用于響應(yīng)Chromium的合成請(qǐng)求后,處理LayerChromium準(zhǔn)備工作,并把請(qǐng)求最后傳遞給CCProxy,由其轉(zhuǎn)發(fā)給具體的實(shí)現(xiàn)者,該類被主線程所調(diào)用
CCProxy:一個(gè)代理抽象類,用于將主線程的合成操作橋接到具體的合成器實(shí)現(xiàn),合成器的線程可能并非主線程。
CCSingleThreadProxy:CCProxy的子類,該類表明合成任務(wù)沒有在單獨(dú)的線程中執(zhí)行,該類將客戶端的請(qǐng)求發(fā)送到合成的具體類CCLayerTreeHostImpl,并響應(yīng)合成器調(diào)用客戶端的回調(diào)函數(shù)
CCThreadProxy:CCProxy的子類,將合成任務(wù)放在單獨(dú)的新線程中執(zhí)行, 目前沒有被使用
CCLayerTreeHostImpl:該類主要管理CCLayerImpl樹及相應(yīng)的狀態(tài),接受來自CCProxy的請(qǐng)求,將實(shí)際的合成任務(wù)交給LayerRendererChromium來處理
在早期的版本中,Chromium中對(duì)合成的支持主要就是LayerRenderChromium,該類負(fù)責(zé)處理所有關(guān)于合成方面的工作。后來, Chromium新引入了CC(chromium compositor)的設(shè)計(jì)。
## Chromium Compositor
為了把合成這一功能獨(dú)立出來,chromium設(shè)計(jì)了一套新的合成架構(gòu)chromium compositor(后面簡(jiǎn)稱CC)。
Chromium定義了自己的層(CCLayerImpl)和層的后端存儲(chǔ)方式(CCRenderSurface),所以它的合成任務(wù)是基于它們來完成。從架構(gòu)上來講,新的CC設(shè)計(jì)了一套更加靈活的機(jī)制來實(shí)現(xiàn)合成:合成的任務(wù)可以放在獨(dú)立的線程中來做,而不僅僅是當(dāng)前線程,該機(jī)制的好處是合成不會(huì)阻礙當(dāng)前線程的響應(yīng),比較靈活。
結(jié)合上面的類圖,我們來理解一下其內(nèi)部的機(jī)制。簡(jiǎn)單來講,可以把合成分成調(diào)用端和實(shí)現(xiàn)端。調(diào)用段由CCLayerTreeHost來提供相應(yīng)的接口,被render的主線程調(diào)用,當(dāng)需要合成時(shí),就會(huì)調(diào)用CCLayerTreeHost::composite來完成, 這里它可以被看成調(diào)用端。但是實(shí)際的實(shí)現(xiàn)者卻不是該類,而是CCLayerTreeHostImpl(和LayerRenderChromium),它們是實(shí)現(xiàn)端。它們這兩端如何連接起來呢?答案是CCProxy,它提供了一組抽象的接口,而它的子類(CCSingleThreadProxy和CCThreadProxy)來決定具體的實(shí)現(xiàn),它們可以讓合成在調(diào)用端的線程來完成,也可以創(chuàng)建一個(gè)獨(dú)立的線程來完成。目前,在Renderer進(jìn)程中的合成是在主線程中來完成的。
假以時(shí)日,我們有理由相信, chromium compositor應(yīng)該會(huì)被抽取出來,形成一個(gè)獨(dú)立的庫(2012-11-12更新:該部分已經(jīng)成為一個(gè)獨(dú)立的庫),這樣它會(huì)被同時(shí)用在網(wǎng)頁的合成和chromium主界面的合成,借助于靈活的架構(gòu),合成的工作也不會(huì)影響正常的主界面對(duì)用戶的響應(yīng)。
## GPU硬件加速合成過程
在了解這些基礎(chǔ)模塊類之后,下面讓我們來看看合成是如何來完成的。下圖給出的是一個(gè)完整的Renderer進(jìn)程的合成過程。
來解釋一下這個(gè)過程。Browser進(jìn)程或者頁面發(fā)起一個(gè)失效(Invalidate)的請(qǐng)求后,Renderer進(jìn)程會(huì)調(diào)度一個(gè)任務(wù)來更新相關(guān)區(qū)域。當(dāng)該任務(wù)被調(diào)度執(zhí)行時(shí),如果硬件加速合成被打開后,Renderer進(jìn)程便開始執(zhí)行對(duì)網(wǎng)頁的合成。
合成任務(wù)由CC來管理和執(zhí)行的。首先,調(diào)用CCSingleThreadProxy::commitIfNeeded,它主要做兩件事,第一件,CCLayerTreeHost::updateLayers為合成做更新LayerChromium的準(zhǔn)備工作,包括創(chuàng)建RenderSurface,設(shè)置繪制的區(qū)域,計(jì)算和設(shè)置需要更新的層。第二件,如果CCLayerImpl樹來沒有建立的話,那么就根據(jù)LayerChromium樹來建立它。
再次,就是來繪制并合成相關(guān)的層,CCLayerTreeHostImpl::drawLayers基于CCLayerImpl樹做繪制工作,把需要的繪制的所有層以此重新繪制并合成,該任務(wù)由LayerRenderChromium類負(fù)責(zé)處理完成(調(diào)用GPU Process來完成GL的繪制)。
最后,調(diào)用swapbuffers把命令發(fā)給GPU進(jìn)程用來交換前后端buffer,完成了頁面的顯示。
## 源文件目錄
third_party/WebKit/Source/WebCore/platform/graphics/chromium/
與硬件加速相關(guān)的chromium移植的相關(guān)類
third_party/WebKit/Source/WebCore/platform/graphics/chromium/cc
Chromium新的合成器CC,包含所有CC的基礎(chǔ)和管理類
cc/
最新的CC部分的相關(guān)代碼,已經(jīng)成為一個(gè)新的獨(dú)立的庫
## 參考文獻(xiàn)
1. http://www.chromium.org/developers/design-documents/aura/graphics-architecture
2. http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
3. http://www.chromium.org/developers/design-documents/rendering-architecture-diagrams
By yongsheng@chromium.org
聯(lián)系客服