一帧发生了什么

浏览器渲染图

  1. Vsync 接收到Vsync信号
  2. Input event handlers之前Compositor Thread接收到的用户UI交互输入在这一刻会被传入给主线程,触发相关event的回调
  3. requestAnimationFrame : 图中的红线的意思是你可能会在JS里Force Layout,也就是我们说的访问了scrollWidth、clientHeight、ComputedStyle等触发了强制重排,导致Recalc Styles和Layout前移到代码执行过程当中。
  4. parse HTML : 如果有DOM变动,那么会有解析DOM的这一过程。
  5. Recalculate Styles: 如果你在JS执行过程中修改了样式或者改动了DOM,那么便会执行这一步,重新计算指定元素及其子元素的样式。
  6. Layout: 重排reflow。如果有涉及元素位置信息的DOM改动或者样式改动,那么浏览器会重新计算所有元素的位置、尺寸信息
  7. update layer tree : 更新Render Layer的层叠排序关系
  8. Paint : 其实Paint有两步,第一步是记录要执行哪些绘画调用,第二步才是执行这些绘画调用。第一步只是把所需要进行的操作记录序列化进一个叫做SkPicture的数据结构里
  9. Composite : 主线程里的这一步会计算出每个Graphics Layers的合成时所需要的data,包括位移(Translation)、缩放(Scale)、旋转(Rotation)、Alpha 混合等操作的参数,并把这些内容传给Compositor Thread
  10. Raster Scheduled and Rasterize: 第8步生成的SkPicture records在这个阶段被执行。
  11. commit:
    1. 如果是Software Rasterization,所有tile的光栅化完成后Compositor Thread会commit通知GPU Thread,于是所有的tile的位图都会作为纹理都会被GPU Thread上传到GPU里
    2. 如果是使用GPU 的Hardware Rasterization,那么此时纹理都已经在GPU中。接下来,GPU Thread会调用平台对应的3D API(windows下是D3D,其他平台都是GL),把所有纹理绘制到最终的一个位图里,从而完成纹理的合并。
      同时,非常关键的一点:在纹理的合并时,借助于3D API的相关合成参数,可以在合并前对纹理transformations(也就是之前提到的位移、旋转、缩放、alpha通道改变等等操作),先变形再合并。合并完成之后就可以将内容呈现到屏幕上了。

      浏览器中的进程

Renderer Process

浏览器一个标签页的周边容器

  1. Compositor Thread
    负责接收浏览器传来的垂直同步信号,也负责接收从OS传来的用户交互, 比如滚动、输入、点击、鼠标移动等等,从而唤起 Main Thread 执行相关操作

  2. Main Thread
    某段 JS的执行, Recalculate Style, Update Layer tree, Paint, Composite layers 等等

  3. Compositor Tile Worker
    专门处理 til的Rasterization(光栅化)

GPU process

为浏览器所有的标签页和周边进程提供服务的单个进程

参考文档

https://github.com/hushicai/hushicai.github.io/issues/5
https://juejin.cn/post/6844903506059477000
http://dev.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome