转载请注明原文地址: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硬件加速合成"章节中介绍的合成器过程,希望以后可以在专门的章节中来介绍它们。

## 参考资料

1. https://docs.google.com/presentation/d/1dDE5u76ZBIKmsqkWi2apx3BqV8HOcNf4xxBdyNywZR8/edit?pli=1#slide=id.g9ade3ed5_017

By yongsheng@chromium.org

理解WebKit和Chromium: 硬件加速之RenderLayer树到合成树的更多相关文章

  1. 理解WebKit和Chromium(电子书)

    前言   基础篇 WebKit, WebKit2, Chromium和Chrome介绍 WebKit和Blink WebKit和Chromium代码目录结构介绍 WebKit和Chromium功能模块 ...

  2. Chromium硬件加速渲染的UI合成过程分析

    在Chromium中.Render端和WebGL端绘制出来的UI终于是通过Browser端显示在屏幕上的.换句话说.就是Browser端负责合成Render端和WebGL端的UI.这涉及到不同Open ...

  3. 理解WebKit和Chromium: Android 4.4 上的Chromium WebView

    转载请注明原文地址:http://blog.csdn.net/milado_nju ## 概述 相信读者已经注意到了,在最新的Android 4.4 Kitkat版本中,原本基于Android Web ...

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

    转载请注明原文地址:http://blog.csdn.net/milado_nju ## 数据对比 前面介绍过Chromium WebView的时候,说过有关ChromiumWebView同Chrom ...

  5. 理解WebKit和Chromium: 调试Android系统上的Chromium

    转载请注明原文地址:http://blog.csdn.net/milado_nju 1. Android上的调试技术 在Android系统上,开发人员能够使用两种不同的语言来开发应用程序,一种是Jav ...

  6. 理解WebKit和Chromium: JavaScript引擎简介

    转载请注明原文地址:http://blog.csdn.net/milado_nju 1. 什么是JavaScript引擎 什么是JavaScript引擎?简单来讲,就是能够提供执行JavaScript ...

  7. 【转】理解WebKit和Chromium: JavaScript引擎简介

    转载请注明原文地址:http://blog.csdn.net/milado_nju1. 什么是JavaScript引擎什么是JavaScript引擎?简单来讲,就是能够提供执行JavaScript代码 ...

  8. 理解WebKit和Chromium: Chromium插件和扩展基础

    转载请注明原文地址:http://blog.csdn.net/milado_nju ##概述 插件和扩展是一种扩充浏览器功能的技术,在之前我们介绍过NPAPI插件技术,在Chromium中,远远不只是 ...

  9. 理解WebKit和Chromium: 网页渲染的基本过程

    转载请注明原文地址:http://blog.csdn.net/milado_nju ## 概述 前面介绍了一些渲染引擎的功能,包括网络,资源加载,DOM树,RenderObject树等等,但是,给人以 ...

随机推荐

  1. Docker常见仓库Ubuntu

    Ubuntu 基本信息 Ubuntu 是流行的 Linux 发行版,其自带软件版本往往较新一些. 该仓库提供了 Ubuntu从12.04 ~ 14.10 各个版本的镜像. 使用方法 默认会启动一个最小 ...

  2. lucene创建索引

    创建索引. 1.lucene下载. 下载地址:http://archive.apache.org/dist/lucene/java/. lucene不同版本之间有不小的差别,这里下载的是lucene ...

  3. Connection Reset By Peer 解析

    linux网络编程 Connection reset by peer错误服务器向客户端发送了数据,客户端没有接收就关闭了,服务器read就会发生Connection reset by peer错误.我 ...

  4. android MultiDex multidex原理下超出方法数的限制问题(三)

    android MultiDex 原理下超出方法数的限制问题(三)    插件化?自动化?multiDex?是不是觉得已经懵逼了?请先看这篇文章的内容,在下篇文章中将会详解具体的过程- 随着应用不断迭 ...

  5. Android常用的编译命令

    1.make -jX X表示数字,这个命令将编译Android系统并生成镜像,XX表示可以使用到的CPU核数,这在配置好的电脑上特别有用,公司的16核ubuntu服务器执行make -j16只要不到2 ...

  6. Python 描述符 data 和 non-data 两种类型

    仅包含__get__的,是non-data descriptor, 如果实例__dict__包含同名变量, 则实例优先; 如果还包含__set__, 则是data descriptor, 优先于实例_ ...

  7. shell命令执行hive脚本(hive交互,hive的shell编程)

    Hive执行方式 Hive的hql命令执行方式有三种: 1.CLI 方式直接执行 2.作为字符串通过shell调用hive –e执行(-S开启静默,去掉"OK","Tim ...

  8. 从Cell类型转变成数据型

    我们有一个如下的cell数据 cdata = {'1' '11' '111' '1111' '11111'}; 现在要把他转变成double型的数组,很自然会想到的方法是cell2mat,可悲的是会遇 ...

  9. mysql 远程连接配置

    近期买了阿里云服务器,服务器 安装了mysql,需要远程操作mysql数据库,但是远程不配置的话,连接不上去的.需要配置 .具体的配置如下: 先看看my.cnf是否绑定了本机,如果绑定了地址就解绑吧. ...

  10. [Mysql]Innodb 独立表空间和共享表空间

    innodb有2中表空间方式: 共享表空间 和 独立表空间 查询数据的设置: show variables like '%per_table'; 默认是共享表空间,独立表空间在配置文件中添加 inno ...