6月阅读周·WebKit技术内幕 | 硬件加速机制

举报
叶一一 发表于 2024/06/25 09:26:41 2024/06/25
【摘要】 背景去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。没有计划的阅读,收效甚微。新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。这个“玩法”虽然常见且板正,但是有效,已经坚持阅读五个月。已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScri...

背景

去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。

没有计划的阅读,收效甚微。

新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。

这个“玩法”虽然常见且板正,但是有效,已经坚持阅读五个月。

已读完书籍《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》

当前阅读周书籍《WebKit技术内幕》

硬件加速机制

硬件加速基础

概念

这里说的硬件加速技术是指使用GPU的硬件能力来帮助渲染网页,因为GPU的作用主要是用来绘制3D图形并且性能特别好,这是它的专长所在,它同软件渲染有很多不同的地方,既有自己的优点,当然也有些不足之处。

为了节省GPU的内存资源,硬件加速机制在RenderLayer树建立之后需要做三件事情来完成网页的渲染。

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

WebKit硬件加速设施

一个RenderLayer对象如果需要后端存储,它会创建一个RenderLayerBacking对象,该对象负责Renderlayer对象所需要的各种存储。正如前面所述,理想情况下,每个RenderLayer都可以创建自己的后端存储,但事实上不是所有RenderLayer都有自己的RenderLayerBacking对象。如果一个RenderLayer对象被WebKit依照一定的规则创建了后端存储,那么该RenderLayer被称为合成层。

每个合成层都有一个RenderLayerBacking,RenderLayerBacking负责管理RenderLayer所需要的所有后端存储,因为后端存储可能需要多个存储空间。在WebKit中,存储空间使用GraphicsLayer类来表示。

管理这些合成层等工作的是RenderLayerCompositor类,这个类可以说是个“大管家”。它不仅计算和决定哪些RenderLayer对象是合成层,而且为合成层创建GraphicsLayer对象。每个RenderView对象包含一个RenderLayerCompositor,这些对象仅在硬件加速机制下才会被创建。RenderLayerCompositor类本身也类似于一个RenderLayerBacking类,也就是说它也包含一些GraphicsLayer对象,这些对象对应的是整个网页所需要的后端存储。

硬件渲染过程

WebKit如何决定哪些层是合成层并为它们分配后端存储的过程。主要包含两个部分,都是RenderLayerCompositor类的函数,一是检查RenderLayer对象是否为合成层,如果是的话,为它们创建后端存储对象RenderLayerBacking;二是根据重新更新的合成层来更改合成层树,并修改后端存储对象的一个设置信息。

WebKit为网页中的5个DOM节点创建RenderLayer对象,分别为HTMLDocument对象、HTMLHtmlElement对象、HTMLDivElement对象、HTMLCanvas对象和HTMLVideo对象。但是,图中只有4个RenderLayerBacking对象,这是因为HTMLHtmlElment对象对应的RenderLayer没有自己的RenderLayerBacking对象,原因是该RenderLayer对象不满足之前所描述的规则。

随着HTML5中不断加入图形和多媒体方面的功能,例如Canvas2D、WebGL、CSS 3D和视频等。

其次,WebKit需要遍历和绘制每一个合成层,也就是每个合成层可能有一个或者多个RenderLayer对象。

在软件渲染过程中,paintLayer函数被递归调用,也就是从RenderLayer根节点开始,直到所有的RenderLayer对象都被遍历为止。

Chromium的硬件加速机制

GraphicsLayer的支持

GraphicsLayer对象是对一个渲染后端存储中某一层的抽象,同众多其他WebKit所定义的抽象类一样,在WebKit移植中,它还需要具体的实现类来支持该类所要提供的功能。为了完成这一功能,Chromium提供了更为复杂的设施类。

框架

在Chromium中,有个比较特别的设计,就是所有使用GPU硬件加速(也就是调用OpenGL编程接口)的操作都是由一个进程(称为GPU进程)负责来完成的,这其中包括使用GPU硬件来进行绘图和合成。Chromium是多进程架构,每个网页的Renderer进程都是将之前介绍的3D绘图和合成操作通过IPC传递给GPU进程,由它来统一调度并执行。在Chrome的Android版本中,GPU进程并不存在,Chrome是将GPU的所有工作放在Browser进程中的一个线程来完成,这得益于结构设计的灵活性。但是本质上,GPU进程和GPU线程并无太大区别。

命令缓冲区

命令缓冲区(Command Buffer)主要用于GPU进程(以后称为GPU服务端)和GPU的调用者进程(且称GPU客户端进程,如Renderer进程、Pepper插件进程)传递GL操作命令。从接口上来讲,这一设计只提供一些基本的接口来管理缓冲区,它并没有对缓冲区的具体方式和命令的类型进行任何限制,不过目前Chromium只有GLES一种实现方式。

现有的实现是基于共享内存的方式来完成的,因而命令是基于GLES编码成特定的格式存储在共享内存中。共享内存方式采用了环形缓冲区(RingBuffer)的方式来管理,这表示内存可以循环使用,旧的命令会被新的命令所覆盖。

总结

本篇进入WebKit高级技术部分,这部分介绍更为复杂和新颖的技术,包括硬件加速机制、JavaScript引擎内部原理、插件和扩展机制、多媒体技术、安全机制、移动技术、调试技术和Web平台。

随着HTML5中不断加入图形和多媒体方面的功能,例如Canvas2D、WebGL、CSS 3D和视频等,这对渲染引擎使用图形库的性能提出了很高的要求。在WebKit渲染基础之上,本章着重描述WebKit为了支持硬件加速机制而引入了哪些内部结构,以及Chromium如何在这些设施上实现了特殊的硬件加速机制,这些机制的引入极大地提升了WebKit引擎的渲染性能。


作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏️ | 留言📝

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。