一、按照渲染的时间顺序
流水线可分为如下几个子阶段:构建 DOM 树、样式计算、布局阶段、分层、图层绘制、栅格化、合成。
重点关注以下三点内容:
开始每个子阶段都有其输入的内容;
然后每个子阶段有其处理过程;
最终每个子阶段会生成输出内容。\
1、构建 DOM 树
输入:HTMLshu
过程:根据词法表将html转换成dom树,如果构建dom树的节点是css,图片,视频、音频,则异步下载。如果是js则停止dom树的构建,下载js并加载js后继续构建dom树
输出: DOM 树,但是 DOM 节点的样式我们依然不知道
2、样式计算(Recalculate Style)
输入:
通过 link 引用的外部 CSS 文件
<style>标记内的 CSS
元素的 style 属性内嵌的 CSS
过程:
1、浏览器会把获取到的 CSS 文本全部转换为 styleSheets 结构中的数据
2、属性值标准化 (比如2em转换成32PX,bold转换成700,red转换成rgb(255,0,0))
3、计算出 DOM 树中每个节点的具体样式,与CSS 的继承规则和层叠规则有关。
输出: 输出的内容是每个 DOM 节点的样式,并被保存在 ComputedStyle 的结构内。
3、布局阶段
输入:dom与computedStyle
过程:遍历dom树,将可见节点添加到布局树中,布局树构建完成后计算布局树节点的坐标位置。
输出:布局树
4、分层
输入:布局树
过程:根据布局树上元素节点的层叠上下文,需要裁剪的地方将多个元素节点或者单个元素节点合并生成一个图层,最后整合这些图层生成layer树。
输出:图层树(layer树)
层叠上下文 :定位属性的元素、定义透明属性的元素、使用 CSS 滤镜的元素、使用opacity的元素
裁剪的地方:文字溢出,如果出现滚动条,滚动条也会被提升为单独的层。
5、图层绘制
输入:图层树
过程:把一个图层的绘制拆分成很多小的绘制指令,然后再把这些指令按照顺序组成一个待绘制列表。
输出:绘制列表(paint)
6、栅格化(raster)操作
输入:绘制列表
过程:渲染进程包含了主线程与合成线程,主线程将绘制列表交给合成线程,合成线程按照视口(viewPort)区域的图层,将图层分割成图块,然后将这些图块栅格化生成位图指令。此时将位图指令交给GPU进程生成位图并将位图保存在GPU的内存中
输出:图块都被栅格化后,合成线程会生成一个绘制图块的命令——“DrawQuad”。
图块:是指图层被分割成几个图块。
栅格化:是指将图块转换为位图指令。
位图:是指用户看到的图像。
7、合成和显示
输入: 绘制图块的命令——“DrawQuad”
过程:浏览器进程中有一个叫 viz 的组件,接收 DrawQuad 命令后,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。
输出:页面内容。
8、总结:
渲染进程将 HTML 内容转换为能够读懂的DOM 树结构。
渲染引擎将 CSS 样式表转化为浏览器可以理解的styleSheets,计算出 DOM 节点的样式。
创建布局树,并计算元素的布局信息。
对布局树进行分层,并生成分层树。
为每个图层生成绘制列表,并将其提交到合成线程。
合成线程将图层分成图块,并在光栅化线程池中将图块转换成位图。
合成线程发送绘制图块命令DrawQuad给浏览器进程。
浏览器进程根据 DrawQuad 消息生成页面,并显示到显示器上。
二、相关概念
1. 更新了元素的几何属性(重排)
2. 更新元素的绘制属性(重绘)
3. 直接合成阶段
更改一个既不要布局也不要绘制的属性,渲染引擎将跳过布局和绘制,只执行后续的合成操作,这个过程叫做合成。例如transform