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

这篇具有很好参考价值的文章主要介绍了《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 技术内幕》学习之八(1):硬件加速机制,webkit学习,C/C++,系统内核,webkit,C/C++,内核开发,浏览器

                               图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对象层,它们表示不同的含义。

《WebKit 技术内幕》学习之八(1):硬件加速机制,webkit学习,C/C++,系统内核,webkit,C/C++,内核开发,浏览器                          图RenderLayer树、RenderLayerBacking对象和GraphicsLayer树

《WebKit 技术内幕》学习之八(1):硬件加速机制,webkit学习,C/C++,系统内核,webkit,C/C++,内核开发,浏览器

                                图RenderLayerBacking包含的各种GraphicsLayer对象层

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

《WebKit 技术内幕》学习之八(1):硬件加速机制,webkit学习,C/C++,系统内核,webkit,C/C++,内核开发,浏览器

                                图RenderLayerBacking中包含的GraphicsLayer对象

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

《WebKit 技术内幕》学习之八(1):硬件加速机制,webkit学习,C/C++,系统内核,webkit,C/C++,内核开发,浏览器

                                                图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 技术内幕》学习之八(1):硬件加速机制,webkit学习,C/C++,系统内核,webkit,C/C++,内核开发,浏览器

                                        图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对象不满足之前所描述的规则。

《WebKit 技术内幕》学习之八(1):硬件加速机制,webkit学习,C/C++,系统内核,webkit,C/C++,内核开发,浏览器                            图示例代码的RenderLayer树和RenderLayerBacking对象

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

《WebKit 技术内幕》学习之八(1):硬件加速机制,webkit学习,C/C++,系统内核,webkit,C/C++,内核开发,浏览器

                                图绘制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, that
    will 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 技术内幕》学习之八(1):硬件加速机制,webkit学习,C/C++,系统内核,webkit,C/C++,内核开发,浏览器

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

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

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

        这些跟移植相关的类都是需要每个移植去实现的,否则这一机制不能工作,下面的部分就是Chromium移植如何实现这些部分并包含哪些不同之处。文章来源地址https://www.toymoban.com/news/detail-816518.html

到了这里,关于《WebKit 技术内幕》学习之八(1):硬件加速机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《WebKit 技术内幕》学习之十二(2):安全机制

    2.1 原理         一般而言,对于网络上的网页中的JavaScript代码和插件是不受信的(除非是经过认证的网站),特别是一些故意设计侵入浏览器运行的主机代码更是非常危险,通过一些手段或者浏览器中的漏洞,这些代码可能获取了主机的管理权限,这对主机系统来说是非

    2024年01月25日
    浏览(43)
  • 《WebKit 技术内幕》学习之七(1): 渲染基础

    《WebKit 技术内幕》之七(1): 渲染基础         WebKit的布局计算使用 RenderObject 树并保存计算结果到 RenderObject 树。 RenderObject 树同其他树(如 RenderLayer 树等),构成了 WebKit 渲染的为要基础设施。 1.1 RenderObject基础类         为了解释说明渲染原理,首先使用一个网

    2024年01月23日
    浏览(40)
  • 《WebKit 技术内幕》学习之七(4): 渲染基础

    4.1 软件渲染过程         在很多情况下,也就是没有那些需要硬件加速内容的时候(包括但不限于CSS3 3D变形、CSS3 03D变换、WebGL和视频),WebKit可以使用软件渲染技术来完成页面的绘制工作(除非读者强行打开硬件加速机制),目前用户浏览的很多门户网站、论坛网站、

    2024年01月25日
    浏览(41)
  • ​《WebKit 技术内幕》学习之九(3): JavaScript引擎

    3.1 原理         JavaScriptCore引擎是WebKit中的默认JavaScript引擎,也是苹果在开源WebKit项目之后,开源的另外一个重要的项目。同其他很多引擎一样,在刚开始的时候它的主要部分是一个基于抽象语法树的解释器,这使得它的性能实在太差。         从2008年开始,JavaSc

    2024年01月23日
    浏览(47)
  • 《WebKit 技术内幕》学习之九(1): JavaScript引擎

    1 概述 1.1 JavaScript语言         说起JavaScript语言,又要讲一个典型的从弱小到壮大的奋斗史。起初,它只是一个非常不起眼的语言,用来处理非常小众的问题。所以,从设计之初,它的目标就是解决一些脚本语言的问题,因为设计的能力有限,性能不需要重点考虑。因为

    2024年01月25日
    浏览(48)
  • 《WebKit 技术内幕》学习之十一(2):多媒体

    2.1 HTML5视频         在HTML5规范定义中,Web开发者可以使用“video”元素来播放视频资源。视频中有个重要的问题就是视频编码格式,对此,目前标准中包含了三种编码格式,它们分别是Ogg、MPEG4和WebM。其中Ogg是由Xiph.org组织开发的一个开放标准,不需要任何授权费用,它

    2024年01月23日
    浏览(37)
  • 《WebKit 技术内幕》学习之十一(3):多媒体

    3.1 音频元素         说完视频之后,接下来就是HTML5中对音频的支持情况。音频支持不仅指对声音的播放,还包括对音频的编辑和合成,以及对乐器数字接口(MIDI)等的支持,下面逐次介绍并分析它们。 3.1.1 HTML5 Audio元素         说到音频,最简单当然也是最直接想

    2024年01月25日
    浏览(36)
  • 《WebKit 技术内幕》学习之十一(1):多媒体

            说到浏览器对多媒体的支持,不得不提的就是Flash插件和HTML5之争。Flash对Web的发展起了非常重要的作用,它能够支持视频、音频、动画等多媒体功能,虽然现在大家都在讨论Web前端领域是否应该丢弃Flash插件转而支持HTML5。在本章中,笔者将回顾Web前端中的多媒体

    2024年01月25日
    浏览(39)
  • 《WebKit 技术内幕》学习之四(3): 资源加载和网络栈

    3. 网络栈 3.1 WebKit的网络设施         WebKit的资源加载其实是交由各个移植来实现的,所以WebCore其实并没有什么特别的基础设施,每个移植的网络实现是非常不一样的。         从WebKit的代码结构中可以看出,网络部分代码的确比较少的,它们都在目录“WebKit/Source/WebCore/

    2024年02月20日
    浏览(41)
  • 《WebKit 技术内幕》学习之十(4): 插件与JavaScript扩展

    4.1 原理         Chromium的扩展(Extension)机制 (1) 原先是Chromium推出的一项技术,该机制能够扩展浏览器的能力,例如笔者使用的一个扩展实例名为“switchy proxy”,它可以帮助用户方便的切换Chromium浏览器代理,但是也仅此而已。本质上,它其实就是浏览器能力的简单扩

    2024年01月25日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包