《WebKit 技术内幕》之八(1):硬件加速机制

《WebKit 技术内幕》之八(1):硬件加速机制

1 硬件加速基础

1.1 概念

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

        对于GPU绘图而言,通常不像软件渲染那样只是计算其中更新的区域,一旦有更新请求,如果没有分层,引擎可能需要重新绘制所有的区域,因为计算更新部分对GPU来说可能耗费更多的时间。当网页分层之后,部分区域的更新可能只在网页的一层或者几层,而不需要将整个网页都重新绘制。通过重新绘制网页的一个或者几个层,并将它们和其他之前绘制完的层合成起来,既能使用GPU的能力,又能够减少重绘的开销。

        之前,笔者总是将RenderLayer对象和最终显示出来的图形层次一一对应起来,也就是每个RenderLayer对象都有一个后端存储与其对应,这样有很多好处,那就是当每一层更新的时候,WebKit只需要更新RenderLayer对象包含的节点即可。所以当某一层有任何更新时候,WebKit重绘该层的所有内容(当然对于Tiledlayer不是这样的情况)。这是理想情况,在现实中不一定会这样,主要原因是实际中的硬件能力和资源有限。为了节省GPU的内存资源,硬件加速机制在RenderLayer树建立之后需要做三件事情来完成网页的渲染。

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

        在WebKit中,只有把编译的C代码宏(macro)“ACCELERATED_COMPOSITING”打开之后,硬件加速机制才会被开启,有关硬件加速的基础设施才会被编译进去。

1.2 WebKit硬件加速设施

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

        每个合成层都有一个RenderLayerBacking ,RenderLayerBacking负责管理RenderLayer所需要的所有后端存储,因为后端存储可能需要多个存储空间。在WebKit中,存储空间使用GraphicsLayer类来表示,下图描述了这些主要类和它们的关系。

                               图WebKit的硬件加速基础类

        上图的上半部分是WebKit项目中WebCore部分的四个基础类,RenderLayer和RenderLayerBacking已经做过一些介绍了,GraphicsLayer表示RenderLayer中前景层、背景层所需要的一个后端存储。每个GraphicsLayer都使用一个GraphicsLayerClient对象,该对象能够收到GraphicsLayer的一些状态更新信息,并且包含一个绘制该GraphicsLayer对象的方法,RenderLayerBacking继承于该类。GraphicsLayer是WebKit中的基础类,主要定义一套标准接口,在WebKit不同的移植中,它们有不同的子类及其实现,图8-1的下半部分是两个不同移植的具体实现类。

        哪些RenderLayer对象可以是合成层呢?如果一个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坐标比自己小的兄弟节点,且该节点是一个合成层。

        至于为什么这么做,有以下三个原因:首先当然是合并一些RenderLayer层,这样可以减少内存的使用量;其二是在合并之后,尽量减少合并带来的重绘性能和处理上的困难;其三对于那些使用单独层能够显著提升性能的RenderLayer对象,可以继续使用这些好处,例如使用WebGL技术的canvas元素。

        下图描述了RenderLayer树、RenderLayerBacking对象和GraphicsLayer树这些硬件加速基础设施的对应关系。RenderLayer树中的第四个节点没有创建RenderLayerBacking对象,因为不符合上面的创建条件,而对于每个RenderLayerBacking对象,它也至少需要一个GraphicsLayer对象,当然也可能需要多个,图中的RenderLayerBacking对象分别需要2个、1个和4个GraphicsLayer对象,这些对象分别表示什么呢?图8-3描述了一个RenderLayerBacking对象可能包括的众多GraphicsLayer对象层,它们表示不同的含义。

                          图RenderLayer树、RenderLayerBacking对象和GraphicsLayer树

                                图RenderLayerBacking包含的各种GraphicsLayer对象层

        为什么一个RenderLayerBacking对象需要这么多层呢?原因有很多,例如WebKit需要将滚动条独立开来称为一个层,需要两个容器层来表示RenderLayer对应的Z坐标为正数的子女和Z坐标为负数的子女,需要滚动的内容建立新层,还可能需要剪裁层和反射层。那么这些层是如何被组织并且它们被绘制的顺序是如何呢?上图中的树状结构描述了所有层的绘制顺序,按照先根顺序遍历的结果即是绘制顺序,图中每个层就是一个GraphicsLayer对象。对于某个RenderLayerBacking对象来说,其主层是肯定存在的,其他层则不一定存在,因为不是每个RenderLayer对象都需要用到它们。

                                图RenderLayerBacking中包含的GraphicsLayer对象

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

                                                图RenderLayerCompositor类

1.3 硬件渲染过程

介绍完硬件加速机制所使用的内部设施之后,同前面介绍的软件渲染机制一样,下面详细分析硬件渲染机制过程。渲染的一般过程,在本章最开始的时候已经描述过,这里主要介绍WebKit是如何具体实现这一过程的。

示例代码8-1给出了一个网页,该网页中使用了很多HTML5新功能,它必须使用硬件加速机制才能够渲染,因为这其中的CSS 3D变形、WebGL和Video等都是HTML5引入的新特性,这些新特性必须依赖GPU硬件加速才能达到比较好的效果。

示例代码8-1需要硬件加速机制的HTML5网页

    <html><style>div{-webkit-transform:rotateY(10deg);}</style><body><p>test text</p><div>css 3d transform</div><canvas id="webgl"width="80"height="80"></canvas><video width="400"height="300"controls="controls"><source src="test.ogg"type="video/ogg"></video><script type="text/javascript">var canvas=document.getElementById("webgl");var gl=canvas.getContext("experimental-webgl");gl.clearColor(0.0, 1.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT);</script></body></html>

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

                                        图WebKit决定合成层并构建合成层树

        除了上图之外,当RenderLayer对象被创建时,网页还有一些其他情况也可能需要创建RenderLayerBacking对象。具体的过程是由RenderLayerModelObject::styleDidChanged()函数调用RenderLayer::styleChanged()函数来触发,然后WebKit调用RenderLayerCompositor::updateLayerCompositingState()函数为RenderLayerModelObject对象所在的RenderLayer层来创建后端存储对象。

        下图主要描述的是WebKit为示例代码8-1建立的合成层和合成层相应的RenderLayerBacking对象。根据前面的解释,WebKit为网页中的5个DOM节点创建RenderLayer对象,分别为HTMLDocument对象、HTMLHtmlElement对象、HTMLDivElement对象、HTMLCanvas对象和HTMLVideo对象。但是,图中只有4个RenderLayerBacking对象,这是因为HTMLHtmlElment对象对应的RenderLayer没有自己的RenderLayerBacking对象,原因是该RenderLayer对象不满足之前所描述的规则。

                            图示例代码的RenderLayer树和RenderLayerBacking对象

        其次,WebKit需要遍历和绘制每一个合成层,也就是每个合成层可能有一个或者多个RenderLayer对象,这可能包含至少四种情形,第一种情形是HTMLDocument节点,WebKit绘制该节点所在的合成层需要遍历两个RenderLayer对象所包含的子树,与其他绘制的内容的调用过程非常相似,该合成层也需要一个用于2D图形的图形上下文对象,该对象的内部实现由各个移植来决定,具体的2D绘图在后面介绍。该层的调用过程如图8-8所示,该过程同软件渲染非常类似,只是递归过程稍微不同。

                                图绘制HTMLDocument对应的RenderLayer层

        在软件渲染过程中,paintLayer函数被递归调用,也就是从RenderLayer根节点开始,直到所有的RenderLayer对象都被遍历为止。在硬件加速机制中,情况有所不同,这是因为引入了合成层的概念,每个RenderLayer对象被绘制到祖先链中最近的合成层。示例代码是WebKit中RenderLayer::paintLayer()函数的条件判断部分的代码,用来检查是否在父节点所在的后端存储中绘制当前节点。如果它不是合成层,那么就继续绘制该层;如果它是的话,那么就直接返回。在之后的逻辑中,WebKit会重新为每一个合成层调用绘制操作,每个合成层的图形上下文都不一样,这点不像软件渲染过程。

        示例代码WebKit的RenderLayer::paintLayer()函数的条件判断

    RenderLayer::paintLayer(){if (isComposited()){if (context->updatingControlTints()||(paintingInfo.paintBehavior&PaintBehaviorFlattenCompositingLayers)){paintFlags|=PaintLayerTemporaryClipRects;}else if (!backing()->paintsIntoWindow()&&!backing()->paintsIntoCompositedAncestor()&&!shouldDoSoftwarePaint(this, paintFlags&PaintLayerPaintingReflection)){//If this RenderLayer should paint into its backing, thatwill be done via RenderLayerBacking::paintIntoLayer().return;}}else if (viewportConstrainedNotCompositedReason()==NotCompositedForBoundsOutOfView){return;}}

        第二种情形是使用CSS 3D变形的合成层,这在本章8.3.3节中介绍。第三种情形是使用WebGL技术的Canvas元素所在的合成层,它的绘制是由JavaScript操作来完成的,并且使用了3D的图形上下文,后面会在8.3.1节中介绍。第四种情形是类似使用了硬件加速的视频元素所在的合成层,该层的内容其实是由视频解码器来绘制,而后通过定时器或者其他通知机制来告诉WebKit该层内容已经发生变化,需要重新合成,这在后面的章节中介绍。

        最后一个步骤是渲染引擎将所有绘制完的合成层合成起来,这个是由WebKit的移植来完成的,在本章的8.2.3小节中将做详细的介绍。

1.4 3D图形上下文

        WebKit中的3D图形上下文主要是提供一组抽象接口,这组接口能够提供类似OpenGLES(使用GPU硬件能力的3D图形应用编程接口)的功能,其主要目的当然也是使用OpenGL绘制3D图形的能力。这一层抽象能够将WebKit各个移植的不同部分隐藏起来,WebCore只是使用统一的抽象接口。在WebKit中,3D图形上下文的主要用途是WebGL,当然启用硬件加速的Canvas2D等HTML5技术也会使用3D图形技术,不过情况有些不同。

        下图给出了WebKit的GraphicsContext3D类,该类是一个抽象类,其包含的接口所处理的对象就是OpenGL中所提供的能力,例如针对纹理、着色器、纹理贴图、顶点等GL操作,不过这里是一个C++类的封装而已。

                                图WebKit的3D图形上下文相关类

        上图中的GraphicsContext3DPrivate就是一个跟WebKit的各个移植相关的类,虽然在各个移植中都是使用该名称,但是每个移植的定义非常不同,它主要是针对移植的不同来实现的。PlatformGraphicsContext3D类是WebCore用于创建Surface等对象的参数,所以其名字是一致的,但是每个移植的定义实际上不一样。

        GraphicsContext3D中的接口有三种类型,第一类是所有移植共享实现的接口,例如texImage2DResourceSafe;第二类是一些移植能够共享实现的接口,例如texImage2D,它们可以直接调用OpenGL或者OpenGL ES的应用编程接口;第三类则是跟每个移植具体相关,例如platformGraphicsContext3D。

        这些跟移植相关的类都是需要每个移植去实现的,否则这一机制不能工作,下面的部分就是Chromium移植如何实现这些部分并包含哪些不同之处。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/639677.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

腾讯云tsf平台-部署微服务项目

腾讯云tsf平台-部署微服务项目 一、腾讯云tsf平台简介二、部署准备0&#xff08;数据库、中间件等部署&#xff09;三、部署准备1&#xff08;创建集群和命名空间&#xff09;1、准备部署资源--集群2、使用容器部署微服务步骤 1&#xff1a;创建容器集群步骤 2&#xff1a;创建…

canvas绘制六芒星

查看专栏目录 canvas实例应用100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

计算机网络——运输层(2)暨小程送书

计算机网络——运输层&#xff08;2&#xff09;暨小程送书 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 运输层&#xff08;2&#xff09;TCP/IP对比TCP&#xff08;传输控制协议&#xff09;&#xff1a;IP&#xff08;互联网协议&#xff09;&#xff1a;总结 拥塞…

一.初识Linux 1-3操作系统概述Linux初识虚拟机介绍

目录 一.初识Linux 1.操作系统概述 计算机组成 硬件&#xff1a; 软件&#xff1a; 操作系统&#xff1a; 操作系统工作流程 操作系统作用 常见的操作系统 PC端&#xff1a; 移动端&#xff1a;&#xff08;掌上操作系统&#xff09; 一.初识Linux 2.Linux初识 linu…

【微信小程序独立开发 5】后端搭建联调

前言&#xff1a;上节我们完成了个人信息页的编写&#xff0c;本节完成将个人信息发给后端&#xff0c;并由后端存储 创建Spring Boot项目 配置maven仓库 使用自己下载的maven版本 添加pom文件 <dependencies><dependency><groupId>org.springframework.boo…

【服务器】Xshell与Xftp软件的使用指南

目录 【Xshell软件】 1.1 Xshell软件的功能 1.2 Xshell软件的使用 【Xftp软件】 2.1 Xftp软件的功能 2.2 Xftp软件的使用 可替代产品【FinalShell】 3.1 FinalShell软件的使用 3.2 FinalShell连接服务器失败解决方法 可替代产品【FileZilla】

Java网络编程——UDP通信原理

一、TCP和UDP概述 传输层通常以TCP和UDP协议来控制端点与端点的通信 TCPUDP协议名称传输控制协议用户数据包协议是否连接面向连接的协议。数据必须要建立连接无连接的协议&#xff0c;每个数据报中都给出完整的地址信息&#xff0c;因此不需要事先建立发送方和接受方的连接是…

Java面试题50道

文章目录 1.谈谈你对Spring的理解2.Spring的常用注解有哪些3.Spring中的bean线程安全吗4.Spring中的设计模式有哪些5.Spring事务传播行为有几种6.Spring是怎么解决循环依赖的7.SpringBoot自动配置原理8.SpringBoot配置文件类型以及加载顺序9.SpringCloud的常用组件有哪些10.说一…

toad 库中 iv 计算逻辑

merge 函数默认为决策树合并 决策树叶子结点默认值DEFAULT_BINS 10&#xff0c;可通过 n_bins 人为设置叶子结点数

Eureka整合seata分布式事务

文章目录 一、分布式事务存在的问题二、分布式事务理论三、认识SeataSeata分布式事务解决方案1、XA模式2、AT模式3、SAGA模式4.SAGA模式优缺点&#xff1a;5.四种模式对比 四、微服务整合Seata AT案例Seata配置微服务整合2.1、父工程项目创建引入依赖 2.2、Eureka集群搭建2.3、…

19万9的小米SU7已经彻底被否了

文 | AUTO芯球 作者 | 李诞 雷总 您是真不听劝啊 还要准备和米粉“干一架”啊 我和大家一样啊 这下好了 19万9的小米SU7已经彻底被否了 说实话 我心理真不是滋味 毕竟大家都说了&#xff0c; 9.9是雷爹&#xff0c;9万9是雷帝&#xff0c;15w是雷神 19万是雷总&#x…

Java开发工具:IntelliJ IDEA 2023 for Mac中文激活

IntelliJ IDEA 2023是一款由JetBrains开发的强大的集成开发环境&#xff08;IDE&#xff09;软件&#xff0c;适用于多个编程语言。它旨在提高开发人员的生产力和代码质量。 软件下载&#xff1a;Java开发工具&#xff1a;IntelliJ IDEA 2023 for Mac中文激活 IntelliJ IDEA 20…

[Java面试]JavaSE知识回顾

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;本文主要梳理Java面试中JavaSE中会涉及到的知识点 &#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以关注一下&#x…

设计螺栓长度的基本原理和细节考虑——SunTorque智能扭矩系统

螺栓长度通常是指从螺栓头部到底部的整体长度。在选择或设计螺栓长度时&#xff0c;需要考虑多个因素&#xff0c;如被连接件的材料、厚度、螺栓间距以及预紧力等。设计螺栓长度应注意哪些原则和细节&#xff0c;SunTorque智能扭矩系统和大家一起来了解。设计螺栓长度的基本原则…

每日一题——LeetCode1304.和为零的N个不同整数

方法一 个人方法 n为偶数&#xff0c;只要同时放入一个数的正数和负数&#xff0c;那么和总为0&#xff0c;n是奇数就放入一个0&#xff0c;剩下的当偶数看待 var sumZero function(n) {let res[]if(n%2!0){res.push(0)n--}nn/2for(let i1;i<n;i){res.push(i)res.push(-i…

Sci Transl Med | 自体中和抗体在早期抗逆转录病毒治疗中增加

今天给同学们分享一篇实验文章“Autologous neutralizing antibodies increase with early antiretroviral therapy and shape HIV rebound after treatment interruption”&#xff0c;这篇文章发表在Sci Transl Med期刊上&#xff0c;影响因子为17.1。 结果解读&#xff1a; …

vue3自定义按钮点击变颜色实现(多选功能)

实现效果图&#xff1a; 默认选中第一个按钮&#xff0c;未选中按钮为粉色&#xff0c;点击时颜色变为红色 利用动态类名&#xff0c;当定义isChange数值和下标index相同时&#xff0c;赋予act类名&#xff0c;实现变色效果 <template><div class"page"&…

Elastic Search 8.12:让 Lucene 更快,让开发人员更快

作者&#xff1a;来自 Elastic Serena Chou, Aditya Tripathi Elastic Search 8.12 包含新的创新&#xff0c;可供开发人员直观地利用人工智能和机器学习模型&#xff0c;通过闪电般的快速性能和增强的相关性来提升搜索体验。 此版本的 Elastic 基于 Apache Lucene 9.9&#xf…

re:从0开始的HTML学习之路 2. HTML的标准结构说明

1. <DOCTYPE html> 文档声明&#xff0c;用于告诉浏览器&#xff0c;当前HTML文档采用的是什么版本。 必须写在当前HTML文档的首行&#xff08;可执行代码的首行&#xff09; HTML4的此标签与HTML5不同。 2. <html lang“en”> 根标签&#xff0c;整个HTML文档中…

如何本地部署虚VideoReTalking

环境&#xff1a; Win10专业版 VideoReTalking 问题描述&#xff1a; 如何本地部署虚VideoReTalking 解决方案&#xff1a; VideoReTalking是一个强大的开源AI对嘴型工具&#xff0c;它是我目前使用过的AI对嘴型工具中效果最好的一个&#xff01;它是由西安电子科技大学、…