轉載請注明出處:http://www.cnblogs.com/fangkm/p/3960327.html
硬件渲染依賴計算機的GPU,GPU種類繁多,兼容這么多種類的硬件,穩定性是個大問題,雖然Chromium內部維護了一個GPU黑名單列表,限定了哪些渲染特性不能在哪些GPU上渲染,但還不足以解決使用GPU過程中的穩定性問題。在Chromium的多進程架構中,不穩定不可控的因素一般都會采取獨立進程的渲染方式, 從而保證主進程的穩定性,比如Render進程、插件進程,GPU的使用也一樣,采取獨立進程的方式運行。
主進程在啟動的時候,會調用GpuDataManagerImpl的Initialize初始化方法,在Initialize方法中,會加載預置的GPU黑名單列表,列表信息位於” src\gpu\config\software_rendering_list_json.cc”文件中,由JSON格式來描述,程序中通過kSoftwareRenderingListJson變量來訪問。通過分析GPU的黑名單列表,可以獲得當前GPU在當前的系統下不知道的渲染特性,當初始化渲染環境時,會從GpuDataManagerImpl維護的禁用渲染特性中查詢是否被禁用,從而決定采取硬件渲染還是軟件渲染。另外,在GPU進程崩潰超過三次時,會在GpuDataManagerImpl里禁用當前GPU的所有渲染支持,也就是將所有的渲染特性加入到當前的GPU黑名單列表,之后的渲染流程都走軟件渲染的邏輯。相關邏輯請參見GpuProcessHost的析構方法。
下面探尋一下GPU進程的啟動流程:
和創建Render進程類似,主進程首先創建一個創建一個命名管道的Server端(參見ChildProcessHostImpl的CreateChannel方法),然后啟動GPU進程,將創建好的管道名當命令行參數傳遞過去(參見GpuProcessHost的LaunchGpuProcess方法),GPU子進程啟動后,會從命令行參數中取出管道名,然后創建相應的管道Client端(參見ChildThread的Init方法),然后就完成管道的連接處理。
與GPU子進程建立連接后,主進程給GPU進程發送GpuMsg_Initialize消息,GPU進程收到這個消息后,會回復一個GpuHostMsg_Initialized消息,附上采集到的GPU信息,這個時候GPU會創建好GpuChannelManager對象,管理即將到來的專供GPU渲染的IPC連接列表。主進程在初始化硬件渲染上下文的時候(參見WebGraphicsContext3DCommandBufferImpl的Initialize方法,一般在主線程),會向GPU子進程發送GpuMsg_EstablishChannel消息(在IO線程發送),然后Wait住主線程,GPU進程在收到該消息后,會創建一個專供渲染用的管道Server端(參見GpuChannelManager的OnEstablishChannel處理),創建完成后會給主進程回復一個GpuHostMsg_ChannelEstablished消息,將剛創建好的渲染管道名稱傳遞過去,主進程接收到回復消息后(在IO線程接受處理),將之前Wait的信號授信,主線程繼續處理,從而完成硬件渲染通信管道的初始化過程。
Render進程也需要使用GPU進行硬件渲染,Render進程GPU管道的創建流程委托給主進程,當Render進程初始化3D繪制環境時,會給主進程發送GpuHostMsg_EstablishGpuChannel同步消息,然后等待答復消息的返回。主進程收到GpuHostMsg_EstablishGpuChannel消息后的處理過程,就是上面講到的主進程啟動GPU進程的流程,不同的是,當GPU進程返回創建好的IPC管道名后,會將該名稱通過GpuHostMsg_EstablishGpuChannel答復消息返回給Render進程,由Render進程創建相應的IPC管道客戶端。