理解WebKit和Chromium: 硬件加速之RenderLayer树到合成树
转载请注明原文地址:http://blog.csdn.net/milado_nju
## 概述
在前面的章节中,笔者介绍了WebKit渲染引擎是如何有HTML网页构建DOM树、RenderObject树到RenderLayer树,以及它们之间的对应关系。这一渲染基础被软件渲染和硬件渲染共享,也就是说不管哪种类型的渲染机制,WebKit渲染引擎都会构建它们。不过对于软件渲染而言,到RenderLayer树就结束了,后面不会建立其它额外的树来对应于RenderLayer树。但是,对于硬件渲染来说,这是漫长阶段的一个部分,在RenderLayer树之后,WebKit渲染引擎为硬件渲染提供了更多的内部结构来支持这个机制。本文将在介绍WebKit中的内部结构之上,同时介绍Chromium又构建的新内部结构,用于该项目中引入的众多纷繁复杂的技术,例如线程化合成器,线程化绘图等等。
## WebKit基础设施
一个RenderLayer对象如果需要后端存储,它会创建一个RenderLayerBacking对象,该对象负责Renderlayer对象所需要的各种存储。正如前面所述,理想情况下,每个RenderLayer都可以创建自己的后端存储,事实上不是所有RenderLayer都有自己的RenderLayerBacking对象。如果一个RenderLayer对象被像样的创建后端存储,那么将该RenderLayer称为合成层(Compositing Layer)。
哪些RenderLayer可以是合成层呢?如果一个RenderLayer对象具有以下的特征之一,那么它就是合成层:
1. RenderLayer具有CSS 3D属性或者CSS透视效果。
2. RenderLayer包含的RenderObject节点表示的是使用硬件加速的视频解码技术的HTML5 ”video”元素。
3. RenderLayer包含的RenderObject节点表示的是使用硬件加速的Canvas2D元素或者WebGL技术。
4. RenderLayer使用了CSS透明效果的动画或者CSS变换的动画。
5. RenderLayer使用了硬件加速的CSSfilters技术。
6. RenderLayer使用了剪裁(clip)或者反射(reflection)属性,并且它的后代中包括了一个合成层。
7. RenderLayer有一个Z坐标比自己小的兄弟节点,该节点是一个合成层。
至于为什么这么做,不外乎两个原因,第一当然是合并一些RenderLayer层,这样减少内存的使用量,其二是在合并之后尽量减少合并带来的重绘性能和处理上的困难,其三同时对于那些使用单独层能够显著提升性能的RenderLayer对象,继续使用这些好处,例如使用WebGL技术的canvas元素。
每个合成层都有一个RenderLayerBacking,RenderLayerBacking负责管理RenderLayer所需要的所有后端存储,因为后端存储可能需要多个存储空间。在WebKit中,存储空间使用类GraphicsLayer来表示。
下图就是WebKit构建的从RenderLayer树到RenderLayBacking树,再到GraphicsLayer树,并给出这些硬件加速基础设施的对应关系。在RenderLayer树中的第四个节点没有创建RenderLayerBacking对象,因为不符合上面的创建条件,而对于每个RenderLayerBacking对象,它也至少需要一个GraphicsLayer对象,当然也可能需要多个,图中的RenderLayerBacking分别需要2个,1个或者4个GraphicsLayer对象,这些对象分别表示什么呢?
为什么一个RenderLayerBacking对象需要这么多层呢?原因有很多,例如是需要将滚动条独立开来称为一个层,需要前景层、背景层等,需要两个容器层来表示RenderLayer对应的Z坐标为正数的子女和Z坐标负数的子女,将可能需要滚动的内容建立新层,还有剪裁层和反射层,那么这些层次是如何组织并且它们的绘制顺序是如何呢?上图中的GraphicsLayer树状结构按照一定顺序,具体可以参考于Chromium工程师的文档”Compositing in Blink / WebCore: FromWebCore::RenderLayer to cc:Layer”,图中每个层就是一个GraphicsLayer对象,对于某个RenderLayerBacking对象来说,其中主层是肯定存在的,其它层则不一定存在,因为不是每个RenderLayer对象都需要用到它们。 这其中还有众多的其它层,这里不一一介绍了。
## Chromium基础设施
GraphicsLayer是对一个渲染后端存储的抽象,同众多其它WebKit所定义的抽象类一样,在WebKit移植中,它还需要具体的实现类来支持该类提供的功能。为了完成这一功能,Chromium提供了更为复杂的设施类,这一节主要介绍从GraphicsLayer类到合成器这一过程中所设计的众多内部结构。
下图中描述了从WebCore中同移植无关的GraphicsLayer到之后Chromium移植及Chromium浏览器所设计的Chromium合成器的LayerImpl类这一过程,读者可以看到,中间有好几层,原因在于抽象和合成机制的复杂性,以及性能等众多方面的考虑,从上到下主要类依次是:
GraphicsLayerChromium:GraphicsLayer的子类,实现了GraphicsLayer需要的一个功能,并且加入了Chromium的所需信息。
WebLayer:WebKit的Chromium移植的抽象接口类,它被GraphicsLayerChromium等调用,主要目的是将Chromium的实际后端存储类抽象出来,以便WebCore使用它们。
WebLayerImpl:WebLayer类的实现类,具体作用是将合成器的层能力暴露出来,跟Layer类一一对应。
Layer:合成器的层表示类,是Chromium合成器的接口类,用于表示合成器的合成层,它会形成一颗合成树。
LayerImpl:同Layer对象一一对应,是实际的实现类,包含有后端存储,可能更Layer树在不同的线程,具体在后面介绍。
由上面介绍可以看出,这个过程基本上就是各种类的映射,从GraphicsLayer类到LayerImpl类,目的是将WebKit的合成层映射到合成器中的合成层,合成器最终合成这些层。合成过程在合成器小节中介绍。
## Chromium合成器
合成器的作用就是合成多个合成层,所以它的输入是多个待合成的合成层,每个层都有一些属性(例如3D变形等)。它的输出就是一个后端存储,例如是一个GPU的纹理缓冲区。
Chromium合成器是一个独立并且复杂的模块,顾名思义,它的作用是合成网页划分后的合成层,但是,这里的合成器同网页没有必然的绑定关系,它既可以合成网页,也可合成用户界面,或者多个标签页。其实,按照笔者的理解,如果你的项目中需要合成器,可以尝试移植该合成器为自己所用,当然,该合成器有一些依赖关系需要解除,难度也很大,这些都是题外话。
在架构设计上,合成器采用将表示和实现分离开的原则,也就是前面介绍合成器Layer层(同GraphicsLayer类一一对应)同具体合成器所要合成的操作分离的原则,下图描述了这一思想。WebKit中对合成层的各种设置,最后都使用Layer树来表示,里面包含3D变形、剪裁等属性,但是将这些属性应用到后端存储并合成这一过程并不是在Layer树中进行,而是将这些功能委托LayerImpl树来完成,两者之间通过代理来同步。Layer树所有的信息都会复制到LayerImpl树中,代理的作用是协调和同步两者之间的这些操作。
上图中描述的Layer树工作在主线程,但是LayerImpl树在实现部分的线程,这里可以它理解为就是工作在主线程也可是是单独的一个线程,两者在Chromium中目前都被使用。实现部分作为单独一个线程是在Renderer进程中用来合成网页的时候,通常也称为合成器(compositor)线程,后者也称为线程化合成(threaded compositing)。在Chrome的Android版本,合成实现部分则是在主线程,目的是同浏览器界面的合成,称为线程内合成(in-thread compositing)。
在目前的Chromium合成器中,具体的工作非常复杂,例如还有线程化绘图(impl side painting),远远超出了文章"Chromium硬件加速合成"章节中介绍的合成器过程,希望以后可以在专门的章节中来介绍它们。
## 参考资料
By yongsheng@chromium.org
理解WebKit和Chromium: 硬件加速之RenderLayer树到合成树的更多相关文章
- 理解WebKit和Chromium(电子书)
前言 基础篇 WebKit, WebKit2, Chromium和Chrome介绍 WebKit和Blink WebKit和Chromium代码目录结构介绍 WebKit和Chromium功能模块 ...
- Chromium硬件加速渲染的UI合成过程分析
在Chromium中.Render端和WebGL端绘制出来的UI终于是通过Browser端显示在屏幕上的.换句话说.就是Browser端负责合成Render端和WebGL端的UI.这涉及到不同Open ...
- 理解WebKit和Chromium: Android 4.4 上的Chromium WebView
转载请注明原文地址:http://blog.csdn.net/milado_nju ## 概述 相信读者已经注意到了,在最新的Android 4.4 Kitkat版本中,原本基于Android Web ...
- 理解WebKit和Chromium: Chromium WebView和Chrome浏览器渲染机制
转载请注明原文地址:http://blog.csdn.net/milado_nju ## 数据对比 前面介绍过Chromium WebView的时候,说过有关ChromiumWebView同Chrom ...
- 理解WebKit和Chromium: 调试Android系统上的Chromium
转载请注明原文地址:http://blog.csdn.net/milado_nju 1. Android上的调试技术 在Android系统上,开发人员能够使用两种不同的语言来开发应用程序,一种是Jav ...
- 理解WebKit和Chromium: JavaScript引擎简介
转载请注明原文地址:http://blog.csdn.net/milado_nju 1. 什么是JavaScript引擎 什么是JavaScript引擎?简单来讲,就是能够提供执行JavaScript ...
- 【转】理解WebKit和Chromium: JavaScript引擎简介
转载请注明原文地址:http://blog.csdn.net/milado_nju1. 什么是JavaScript引擎什么是JavaScript引擎?简单来讲,就是能够提供执行JavaScript代码 ...
- 理解WebKit和Chromium: Chromium插件和扩展基础
转载请注明原文地址:http://blog.csdn.net/milado_nju ##概述 插件和扩展是一种扩充浏览器功能的技术,在之前我们介绍过NPAPI插件技术,在Chromium中,远远不只是 ...
- 理解WebKit和Chromium: 网页渲染的基本过程
转载请注明原文地址:http://blog.csdn.net/milado_nju ## 概述 前面介绍了一些渲染引擎的功能,包括网络,资源加载,DOM树,RenderObject树等等,但是,给人以 ...
随机推荐
- python的模块与包的导入
类似于C语言的包含头文件去引用其他文件的函数,python也有类似的机制,常用的引入方法有以下 import 模块名 #模块名就是py文件名 #使用这种方法以后调用函数的时候要使用模块名.函数名()这 ...
- page1
1.1 常用的客户端技术:HTML. CSS. 客户端脚本技术 1.2 常用的服务器端技术:CGI .ASP .PHP (一种开发动态网页技术).ASP.NET(是一种建立动态web应用程序的技术,是 ...
- Dubbo框架应用之(一)--服务体系
Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成,也是一个非常全面的SOA基础框架.其是阿里巴巴SO ...
- 初识Spark2.0之Spark SQL
内存计算平台spark在今年6月份的时候正式发布了spark2.0,相比上一版本的spark1.6版本,在内存优化,数据组织,流计算等方面都做出了较大的改变,同时更加注重基于DataFrame数据组织 ...
- Android简易实战教程--第四十七话《使用OKhttp回调方式获取网络信息》
在之前的小案例中写过一篇使用HttpUrlConnection获取网络数据的例子.在OKhttp盛行的时代,当然要学会怎么使用它,本篇就对其基本使用做一个介绍,然后再使用它的接口回调的方式获取相同的数 ...
- 【Unity Shader】Unity Chan的卡通材质
写在前面 时隔两个月我终于来更新博客了,之前一直在学东西,做一些项目,感觉没什么可以分享的就一直没写.本来之前打算写云彩渲染或是Compute Shader的,觉得时间比较长所以打算先写个简单的. 今 ...
- 关于在arm裸板编程时使用printf问题的解决方法
在ARM裸板驱动编程中,是不允许程序直接调用C库程序的.为什么呢?因为此时kernel还没有被加载,所以在封装在kernel层的C库的API是用不了的,那怎么办? 在开发过程中,printf的功能我不 ...
- Effective C++ ——实现
条款26:尽可能延后变量定义式的出现时间 当你定义一个变量的时候就要保证这个变量能够在程序中使用到,不要定义无意义的变量,这样就要求我们最好是在变量使用到的时候才做定义,因为如果一个变量定义了却不使用 ...
- 4.2、Android Studio压缩你的代码和资源
为了让你的APK文件尽可能的小,你需要在构建的时候开启压缩来移除无用的代码和资源. 代码压缩可在ProGuard中使用,可以检测和清除无用的类,变量,方法和属性,甚至包括你引用的库.ProGuard同 ...
- Servlet之cookie处理
Cookies 通常设置在 HTTP 头信息中(虽然JavaScript 也可以直接在浏览器上设置一个 Cookie).设置 Cookie 的 Servlet 会发送如下的头信息: HTTP/1.1 ...