在本部分中,您将了解如何设置 RenderingNG 的组件部分,以及渲染流水线如何在这些部分中流动。
从最高级别开始,渲染任务如下:
- 将内容渲染到屏幕上的像素。
- 为内容从一种状态转换为另一种状态添加视觉效果动画。
- 响应输入进行滚动。
- 高效地将输入转送到正确的位置,以便开发者脚本和其他子系统做出响应。
要渲染的内容是每个浏览器标签页的帧树,以及浏览器界面。以及来自触摸屏、鼠标、键盘和其他硬件设备的一连串原始输入事件。
每个帧包含:
- DOM 状态
- CSS
- 画布
- 外部资源,例如图片、视频、字体和 SVG
框架是指 HTML 文档及其网址。 在浏览器标签页中加载的网页包含一个顶级框架、顶级文档中包含的每个 iFrame 的子框架,以及它们的递归 iFrame 后代。
视觉效果是指应用于位图的图形操作,例如滚动、转换、剪裁、滤镜、不透明度或混合。
架构组件
在 RenderingNG 中,这些任务会在逻辑上分布在多个阶段和代码组件中。这些组件最终会位于各种 CPU 进程、线程以及这些线程中的子组件中。每种方法都对实现所有 Web 内容的可靠性、可伸缩性能和可扩展性起着重要作用。
渲染管线结构
渲染会在流水线中进行,并在此过程中创建多个阶段和工件。每个阶段都代表在渲染过程中执行一项明确定义的任务的代码。工件是阶段的输入或输出数据结构。
各阶段如下:
- 动画:根据声明式时间轴,更改计算样式并随时间更改属性树。
- 样式:将 CSS 应用于 DOM,并创建计算样式。
- 布局:确定屏幕上 DOM 元素的大小和位置,并创建不可变 fragment 树。
- 预绘制:根据需要计算属性树,并使所有现有的显示列表和 GPU 纹理图块失效。
- 滚动:通过更改属性树来更新文档和可滚动 DOM 元素的滚动偏移量。
- 绘制:计算一个显示列表,用于描述如何从 DOM 光栅化 GPU 纹理图块。
- 提交:将属性树和显示列表复制到 compositor 线程。
- 分层:将显示列表拆分为复合层列表,以便独立进行光栅化和动画处理。
- 光栅化、解码和绘制工作流:分别将显示列表、编码图片和绘制工作流代码转换为 GPU 纹理图块。
- 激活:创建一个合成器帧,表示如何在屏幕上绘制和放置 GPU 图块以及任何视觉效果。
- 汇总:将所有可见合成器帧中的合成器帧合并到单个全局合成器帧中。
- 绘制:在 GPU 上执行汇总的 compositor 帧,以在屏幕上创建像素。
如果不需要,可以跳过渲染流水线的阶段。例如,视觉效果和滚动动画可以跳过布局、预绘制和绘制。 因此,动画和滚动在图表中分别用黄色和绿色圆点标记。如果可以为视觉效果跳过布局、预绘制和绘制,则可以完全在 compositor 线程上运行这些操作,并跳过主线程。
此处未直接描述浏览器界面渲染,但可以将其视为此流水线的简化版本(事实上,其实现会共用大量代码)。视频(也未直接描绘)通常使用独立代码进行渲染,该代码会将帧解码为 GPU 纹理图块,然后将这些图块插入合成器帧和绘制步骤。
进程和线程结构
CPU 进程
使用多个 CPU 进程可实现网站之间的性能和安全隔离,以及与浏览器状态的隔离,还可实现与 GPU 硬件的稳定性和安全隔离。