理解WebKit和Chromium: Chromium WebView和Chrome浏览器渲染机制

转载请注明原文地址: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线程对用户事件等的响应。

相关文章
相关标签/搜索