Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

读《webkit技术内幕》了解浏览器内核六——硬件加速机制 #39

Open
lizhongzhen11 opened this issue Sep 18, 2019 · 0 comments
Labels
浏览器 浏览器相关

Comments

@lizhongzhen11
Copy link
Owner

lizhongzhen11 commented Sep 18, 2019

前面了解到浏览器有软件渲染和GPU硬件加速渲染以及软件绘图的合成化渲染等方式,其中硬件加速渲染算是比较重要的,不过我只是了解了它的一些优缺点,至于浏览器到底如何实现硬件加速机制的,我还不知道,所以,本篇继续跟着书中讲解来了解下硬件加速机制

硬件加速机制其实就是指使用GPU的硬件能力来帮助渲染网页。

依然采用问题形式。

问题

前一篇提到过,在分层的网页结构中,GPU硬件加速渲染会提供相应的后端存储,而网页往往较为复杂,可能会分成很多层,会有很多 RenderLayer 对象,那么GPU是不是要给所有的RenderLayer 对象都进行后端存储?

那是理想情况,现实中不一定。

主要原因是实际中的硬件能力和资源有限。

考虑到资源节省等问题,硬件加速机制是如何去优化、去渲染网页呢?

主要是三件事:

  • WebKit决定将哪些 RenderLayer 对象组合在一起,形成一个有后端存储的新层,这一新层不久后会用于之后的 合成,作者将其称为 合成层。每个新层都有一个或多个后端存储,这里的后端存储可能是 GPU的内存。对于一个 RenderLayer 对象,如果它没有后端存储的新层,那么就使用它父亲所使用的的 合成层。
  • 将每个合成层包含的这些 RenderLayer 内容绘制在 合成层 的 后端存储 中,这里的绘制可以是软件绘制也可以是硬件绘制。
  • 合成器 将多个合成层合成起来,形成网页的最终可视化结果,实际就是一张图片。合成器 是一种能够将多个合成层按照这些层的前后顺序、合成层的 3D 变形等设置而合成一个图像结果的设施。

那么哪些 RenderLayer 对象可以组合成 合成层 呢?

具有以下等特征:

  • RenderLayer具有CSS 3D属性或者CSS透视效果
  • RenderLayer包含的RenderObject节点表示的是使用硬件加速的视频解码技术的 HTML5 video 元素
  • RenderLayer包含的RenderObject节点表示的是使用硬件加速的 Canvas 2D元素或者WebGL技术
  • RenderLayer使用了CSS透明效果的动画或者CSS变换的动画
  • RenderLayer使用了硬件加速的CSS Filters技术
  • RenderLayer使用了裁剪(Clip)或者反射(Reflection)属性,并且它的后代中包括一个合成层
  • RenderLayer有一个Z坐标比自己小的兄弟节点,且该节点是一个合成层

了解了以上的知识后,能说说硬件渲染的过程吗?

由于涉及到不少内部类和方法,考虑到项目一直在迭代,可能书上所讲的有所改变,所以这里提炼下大致过程,尽量不涉及具体类和方法名。

1.首先WebKit确定并计算合成层

  • 检查 RenderLayer 对象是否为合成层,是的话为其创建 后端存储对象RenderLayerBacking
  • 根据重新更新的合成层来更改合成层树,并修改后端存储对象的设置信息

2.其次,遍历和绘制每一个合成层,可能存在以下四种情况:

  • 第一种情况:HTMLDocument节点, 需要一个用于2D图形的 图形上下文对象,同软件渲染非常类似,但递归过程不同。每个 RenderLayer 对象被绘制到 祖先链中最近的合成层
  • 第二种情况:使用 CSS 3D变形的合成层。
  • 第三种情况:使用WebGL技术的 Canvas 元素所在的合成层,它的绘制由javascript操作完成,并且使用了 3D图形上下文
  • 第四种情况:类似使用了硬件加速的视频元素所在的合成层,该层的内容其实是由视频解码器来绘制,而后通过定时器或者其他通知机制来告诉WebKit该层内容发生改变.

3.最后渲染引擎将所有绘制完的合成层合成起来

前面介绍到webkit中会有3D和2D图形上下文,Chromium是不是也一样呢?内部调用栈是什么样的呢?

webkit中2D图形上下文对应Chromium的 Skia画布(canvas),具体调用栈可以看图了解下即可。

结合以前介绍的进程灯知识,GPU硬件加速渲染是在哪个进程上执行的?是Renderer进程吗?

对于使用多进程模型的Blink内核的浏览器来说,不是的,GPU硬件加速渲染的操作会交由 GPU进程 负责。

多进程模型下是如何实现跨进程的硬件加速渲染的?

这个很复杂,依靠Renderer进程的主要类和GPU进程的主要类它们彼此内部的实现。涉及到太多类,不展开,建议结合项目代码去看。

总结就是,GPU进程处理一些命令后,会向Renderer进程报告自己当前状态,Renderer进程通过检查状态信息和自己期望结果来确定是否满足自己的条件。

值得注意的是:GPU进程最终绘制的结果不再像 软件渲染那样通过共享内存传递给Browser进程,而是直接将页面内容绘制在浏览器的标签窗口。

本篇第一个问题下的回答就提到过合成器,Chromium的合成器是如何实现的呢?

在架构设计上,采用了 表示和实现分离原则
图例:

需要注意:Layer树工作的主线程,实际指的是渲染引擎工作的线程,不一定是Renderer进程的主线程。但是LayerImpl树工作的 实现部分的线程 既可以是主线程也可以是单独的线程。实现部分如果是一个单独的线程,那么可以称为 合成器线程,也叫线程化合成

Chromium合成器的组成部分是什么样的?

  • 事件处理部分。主要接收WebKit或者其他的用户事件,例如网页滚动、放大缩小等事件,这些事件会请求合成器重新绘制每一个合成层,然后合成器再合成这些层的绘制结果
  • 合成层的表示和实现。主要定义各种类型的合成层,包括它们的位置、滚动位置、颜色等属性
  • 合成层组成两种类型的树,以及它们之间的同步等机制
  • 合成调度器(Scheduler)主要调度来自用户的请求,它包括一个状态用于调度当前队列中需要执行的请求,目的当然是协调合成层的绘制和合成、树的同步等操作。调度器是在合成器线程中的,因而不能访问主线程中的资源
  • 合成器的输出结果。结果可以是一个GPU Surface或者一个CPU存储空间。
  • 各种后端存储等资源
  • 支持动画和3D变形这些功能所需要的基础设施

拓展介绍:绘制HTML元素和图片元素所生成的合成层,其后端存储会被瓦片化!

为什么会使用瓦片化的后端存储呢?

有以下三点好处:

  1. DOM树中的html元素所在的层可能会比较大,因为网页高度很大,如果只是使用一个后端存储的话,那么需要一个很大的对象,但是实际的GPU硬件可能只支持非常有限的纹理大小
  2. 在一个比较大的合成层中,可能只是其中一部分发生变化,根据之前的介绍,需要重新绘制整个层,这样必然产生额外的开销,使用瓦片化的后端存储,就只需要重绘一些存在更新的瓦片
  3. 当层发生滚动时,一些瓦片可能不再需要,然后WebKit需要一些新的瓦片来绘制新的区域,这些大小相同的后端存储很容易重复利用,简洁漂亮

了解完合成器知识后,能简要说说合成过程吗?

主要有四个步骤,都是由调度器调度:

  1. 创建输出结果的目标对象 Surface,也就是合成结果的存储空间
  2. 开始一个新的帧,包括计算滚动和缩放大小、动画计算、重新计算网页的布局、绘制每个合成层等
  3. 将Layer树中包含的这些变动同步到LayerImpl树中
  4. 合成LayerImpl树中各个层并交换前后帧缓冲区,完成一帧的绘制和显示动作

可以看看图了解下

前面介绍过2D绘图也可以进行硬件加速,如何做到的呢?

首先什么是2D绘图的硬件加速?

2D绘图本身是使用 2D的图形上下文,一般使用软件方式来绘制它们,也就是 光栅化

使用GPU来绘制2D图形的方法称为2D图形的硬件加速机制。

2D图形的硬件加速机制有两种应用场景:

  1. 2D图形上下文——网页基本元素绘制(HTML基本标签)
  2. canvas 2D

2D图形上下文是如何进行硬件加速的呢?

依靠 Skia图形库。当需要启动硬件加速时,只需要对 SkCanvas 对象进行的相应设置即可。

具体内部类和方法建议看书和代码。

Canvas 2D是如何进行硬件加速的呢?

比较复杂,涉及太多内部类,建议结合项目代码和书去看。
简单来说,在Chromium中,canvas 2D进行GPU硬件加速绘图时,会创建一个 SkDeferredCanvas 对象,该对象采用 延迟机制 来绘制2D图形。然后,该对象需要 SkGpuDevice 来将2D绘图操作转换为使用3D图形上下文来绘制。

WebGL是如何实现的?

同样设计太多内部类,建议看书。
粗略提下吧,Chromium中WebGL工作过程分成三个阶段:

  1. 对象的初始化
  2. 构建RenderLayer、WebLayer、CC::Layer等对象,在DOM树构建之后检查CSS样式变化时才会触发
  3. 3D绘图

读《webkit技术内幕》了解浏览器内核系列

  1. 读《webkit技术内幕》了解浏览器内核一
  2. 读《webkit技术内幕》了解浏览器内核二——内部架构
  3. 读《webkit技术内幕》了解浏览器内核三——资源与网络栈
  4. 读《webkit技术内幕》了解浏览器内核四——HTML、DOM以及CSS相关
  5. 读《webkit技术内幕》了解浏览器内核五——渲染基础
  6. 读《webkit技术内幕》了解浏览器内核六——硬件加速机制
  7. 读《webkit技术内幕》了解浏览器内核七——js引擎
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
浏览器 浏览器相关
Projects
None yet
Development

No branches or pull requests

1 participant