《WebKit 技术内幕》之七(3): 渲染基础

3 渲染方式

3.1 绘图上下文(GraphicsContext)

        上面介绍了WebKit的内部表示结构,RenderObject对象知道如何绘制自己,但是,问题是RenderObject对象用什么来绘制内容呢?在WebKit中,绘图操作被定义了一个抽象层,这就是绘图上下文,所有绘图的操作都是在该上下文中来进行的。绘图上下文可以分成两种类型,第一种是用来绘制2D图形的上下文,称之为2D绘图上下文(GraphicsContext);第二种是绘制3D图形的上下文,称之为3D绘图上下文(GraphicsContext3D)。这两种上下文都是抽象基类,也就是说它们只提供接口,因为WebKit需要支持不同的移植。而这两个抽象基类的具体绘制则由不同的移植提供不同的实现,每个移植使用的实际绘图类非常不一样,依赖的图形率也不一样,图7-7描述了抽象类和WebKit的移植实现类的关系。

                                        图绘图上下文类和移植相关的绘图上下文类

        PlatfromGraphicsContext类和PlatformGraphicsContext3D类是两个表示上下文的类,其实它们的类定义取决于各个移植。在WebKit的Safari移植中,这两个类其实是CGContext和CGLContextObj;而在Chromium移植中,它们则是PlatformContextSkia和GrContext。同之前描述的基类和子类的关系不一样,这些不是父子类关系,而是WebKit直接通过C语言的typedef来将每个不同移植的类重命名成PlatfromGraphicsContext和PlatformGraphicsContext3D。

        2D绘图上下文的具体作用就是提供基本绘图单元的绘制接口以及设置绘图的样式。绘图接口包括画点、画线、画图片、画多边形、画文字等,绘图样式包括颜色、线宽、字号大小、渐变等。RenderObject对象知道自己需要画什么样的点,什么样的图片,所以RenderObject对象调用绘图上下文的这些基本操作就是绘制实际的显示结果,图7-8描述了RenderObject类和GraphicsContext类的关系。

                             图 描述了RenderObject和绘图上下文之间的关系。

           关于3D绘图上下文的介绍,我们将在第8章中介绍,它的主要用处是支持CSS3D、WebGL等。

          在现有的网页中,由于HTML5标准引入了很多新的技术,所以同一网页中可能会既需要使用2D绘图上下文,也需要使用3D绘图上下文。对于2D绘图上下文来说,其平台相关的实现既可以使用CPU来完成2D相关的操作,也可以使用3D图形接口(如OpenGL)来完成2D相关的操作。而对于3D绘图上下文来说,因为性能的问题,WebKit的移值通常都是使用3D图形接口(如OpenGL或者Direct3D等技术)来实现。

3.2 渲染方式

        在完成构建DOM树之后,WebKit所要做的事情就是构建渲染的内部表示并使用图形库将这些模型绘制出来。提到网页的渲染方式,目前主要有两种方式,第一种是软件渲染,第二种是硬件加速渲染。其实这种描述并不精确,因为还有一种混合模式。要理解这一概念,笔者还得接着本章介绍的RenderLayer树来继续深入挖掘。

        每个RenderLayer对象可以被想象成图像中的一个层,各个层一同构成了一个图像。在渲染的过程中,浏览器也可以作同样的理解。每个层对应网页中的一个或者一些可视元素,这些元素都绘制内容到该层上,在本书中,一律把这一过程称为绘图操作。如果绘图操作使用CPU来完成,那么称之为软件绘图。如果绘图操作由GPU来完成,称之为GPU硬件加速绘图。理想情况下,每个层都有个绘制的存储区域,这个存储区域用来保存绘图的结果。最后,需要将这些层的内容合并到同一个图像之中,本书中称之为合成(Compositing),使用了合成技术的渲染称之为合成化渲染。

        所以在RenderObject树和RenderLayer树之后,WebKit的机制操作将内部模型转换成可视的结果分为两个阶段:每层的内容进行绘图工作及之后将这些绘图的结果合成为一个图像。对于软件渲染机制,WebKit需要使用CPU来绘制每层的内容,按照上面的介绍,读者可能觉得需要合成这些层,其实软件渲染机制是没有合成阶段的,为什么?原因很简单,没有必要。在软件渲染中,通常渲染的结果就是一个位图(Bitmap),绘制每一层的时候都使用该位图,区别在于绘制的位置可能不一样,当然每一层都按照从后到前的顺序。当然,你也可以为每层分配一个位图,问题是,一个位图就已经能够解决所有问题。下图是网页的三种渲染方式。

                                        图网页的三种渲染方式

        从上图可以看到,软件渲染中网页使用的一个位图,实际上就是一块CPU使用的内存空间。图7-9中的第二种和第三种方式,都是使用了合成化的渲染技术,也就是使用GPU硬件来加速合成这些网页层,合成的工作都是由GPU来做,这里称为硬件加速合成(Accelerated Compositing)。但是,对于每个层,这两种方式有不同的选择。其中某些层,第二种方式使用CPU来绘图,另外一些层使用GPU来绘图。对于使用CPU来绘图的层,该层的结果首先当然保存在CPU内存中,之后被传输到GPU的内存中,这主要是为了后面的合成工作。第三种渲染方式使用GPU来绘制所有合成层。第二种方式和第三种方式其实都属于硬件加速渲染方式。前面的这些描述,是把RenderLayer对象和实际的存储空间对应,现实中不是这样的,这只是理想的情况。

       到这里,读者可能感到奇怪为什么会有三种渲染方式,这是因为三种方式各有各的优缺点和适用场景,在介绍它们的特点之前,先了解一些渲染方面的基本知识。

        首先,对于常见的2D绘图操作,使用GPU来绘图不一定比使用CPU绘图在性能上有优势,例如绘制文字、点、线等,原因是CPU的使用缓存机制有效减少了重复绘制的开销而且不需要GPU并行性。其次,GPU的内存资源相对CPU的内存资源来说比较紧张,而且网页的分层使得GPU的内存使用相对比较多。鉴于此,就目前的情况来看,三者都存在是有其合理性的,下面分析一下它们的特点。

  • 软件渲染是目前很常见的技术,也是浏览器最早使用的渲染方式这一技术比较节省内存,特别是更宝贵的GPU内存,但是软件渲染只能处理2D方面的操作。简单的网页没有复杂绘图或者多媒体方面的需求,软件渲染方式就比较合适来渲染该类型的网页。问题是,一旦遇上了HTML5的很多新技术,软件渲染显然无能为力,一是因为能力不足,典型的例子是CSS3D、WebGL等;二是因为性能不好,例如视频、Canvas 2D等。所以,软件渲染技术被使用得越来越少,特别是在移动领域。软件渲染同硬件加速渲染另外一个很不同的地方就是对更新区域的处理。当网页中有一个更新小型区域的请求(如动画)时,软件渲染可能只需要计算一个极小的区域,而硬件渲染可能需要重新绘制其中的一层或者多层,然后再合成这些层。硬件渲染的代价可能会大得多。
  • 对于硬件加速的合成化渲染方式来说,每个层的绘制和所有层的合成均使用GPU硬件来完成,这对需要使用3D绘图的操作来说特别适合。这种方式下,在RenderLayer树之后,WebKit和Chromium还需要建立更多的内部表示,例如GraphicsLayer树、合成器中的层(如Chromium的CCLayer)等,目的是支持硬件加速机制,这显然会消耗更多的内存资源。但是,一方面,硬件加速机制能够支持现在所有的HTML5定义的2D或者3D绘图标准;另一方面,关于更新区域的讨论,如果需要更新某个层的一个区域,因为软件渲染没有为每一层提供后端存储,因而它需要将和这个区域有重叠部分的所有层次的相关区域依次从后向前重新绘制一遍,而硬件加速渲染只需要重新绘制更新发生的层次。因而在某些情况下,软件渲染的代价更大。当然,这取决于网页的结构和渲染策略,这些都是需要重点关注和讨论的。
  • 软件绘图的合成化渲染方式结合了前面两种方式的优点,这是因为很多网页可能既包含基本的HTML元素,也包含一些HTML5新功能,使用CPU绘图方式来绘制某些层,使用GPU来绘制其他一些层。原因当然是前面所述的基于性能和内存方面综合考虑的结果。

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

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

相关文章

算法第二十一天-丑数

丑数 题目要求 解题思路 首先判断数字是不是为0或者负数&#xff0c;两者均不可能成为丑数&#xff1b; 之后对n进行不断整除&#xff0c;直到无法除尽为止。 简单判断最后的数是不是1即可。 代码 class Solution:def isUgly(self, n: int) -> bool:if n<0:return Fa…

React的合成事件

合成事件&#xff1a;通过事件委托&#xff0c;利用事件传播机制&#xff0c;当事件传播到document时&#xff0c;再进行分发到对应的组件&#xff0c;从而触发对应所绑定的事件&#xff0c;然后事件开始在组件树DOM中走捕获冒泡流程。 原生事件 —— > React事件 —— >…

力扣每日一练(24-1-20)

大脑里的第一想法是排列组合&#xff0c;直接给出超级准确的最优解。 但不适用&#xff0c;hhh 只要连续的n个元素大于或者等于target就可以了 题目比自己想象的要好解决 解法是使用滑动窗口算法。这个算法的基本思想是维护一个窗口&#xff0c;使得窗口内的元素总和大于等于目…

MySQL---单表查询综合练习

创建emp表 CREATE TABLE emp( empno INT(4) NOT NULL COMMENT 员工编号, ename VARCHAR(10) COMMENT 员工名字, job VARCHAR(10) COMMENT 职位, mgr INT(4) COMMENT 上司, hiredate DATE COMMENT 入职时间, sal INT(7) COMMENT 基本工资, comm INT(7) COMMENT 补贴, deptno INT…

PostgreSQL命令大全

文章目录 连接与退出数据库操作表操作外键约束视图操作存储过程与函数权限管理事务管理查询优化与分析数据类型转换分区表操作复制与备份恢复 PostgreSQL是一个功能强大的开源关系型数据库管理系统&#xff0c;以下是一些基本且常用的命令按功能分类&#xff1a; 连接与退出 连…

Es bulk批量导入数据(1w+以上)

最近在学习es的理论知识以及实际操作&#xff0c;随时更新~ 概要&#xff1a;首先你得有1w条数据的json&#xff0c;然后用java读取json文件导入 一. 创建Json数据 首先我生成1.5w条数据&#xff0c;是为了实践分页查询&#xff0c;用from-size和scroll翻页去实践 生成四个字段…

Servlet系列:生命周期(init、 service、destroy)详解

Servlet的生命周期是由Web容器&#xff08;如Tomcat&#xff09;管理的&#xff0c;包括以下三个阶段&#xff1a; 加载和实例化&#xff1a;当Web应用程序启动时&#xff0c;Web容器会加载和实例化Servlet。加载和实例化过程可以在应用程序启动时自动完成&#xff0c;也可以通…

Nginx快速入门

1.Ngix介绍 1.1 介绍 Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器&#xff0c;同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔赛索耶夫为俄罗斯访问量第二的Rambler.ru站点&#xff08;俄文&#xff1a;Рамблер&#xff09;开发的&#xff0c;第一个公…

2.RHCSA启动配置

rht-clearcourse 0 #重置练习环境 rht-setcourse rh134 #切换CSA练习环境 cat /etc/rht #查看当前环境 virt-manager #打开KVM控制台 rht-vmctl start classroom #必做&#xff0c;start all不会包含classroom&#xff0c;需…

数据结构之树和二叉树定义

数据结构之树和二叉树定义 1、树的定义2、树的基本概念3、二叉树的定义 数据结构是程序设计的重要基础&#xff0c;它所讨论的内容和技术对从事软件项目的开发有重要作用。学习数据结构要达到的目标是学会从问题出发&#xff0c;分析和研究计算机加工的数据的特性&#xff0c;以…

【计算机网络】【Python】【练习题】【新加坡南洋理工大学】【Computer Control Network】

一、题目描述 该题目描述一个网络中数据包交换&#xff08;Packet Switching&#xff09;的例子。题目如下&#xff1a; 二、问题解答&#xff08;使用Python&#xff09; Q1&#xff1a;如何求出0.0004这个值&#xff1f; &#xff08;1&#xff09;、公式推导过程&#xf…

LeetCode 热题 100 | 双指针(下)

目录 42. 接雨水 1 方法一&#xff1a;我的方法 2 方法二&#xff1a;动态规划 3 方法三&#xff1a;双指针 菜鸟做题第一周&#xff0c;语言是 C 42. 接雨水 1 方法一&#xff1a;我的方法 Warning&#xff1a;这是我的智障做法&#xff0c;请勿模仿 我只能说它教会…

深度解析Python关键字:掌握核心语法的基石(新版本35+4)

目录 关键字 keyword 关键字列表 kwlist softkwlist 关键字分类 数据类型 True、False None 运算类型 and、or、not in is 模块导入 import 辅助关键字 from、as 上下文管理 with 占位语句 pass 流程控制 if、elif、else for while break、continue…

20240117在本地机器识别OCR法语电影的字幕效果PK

20240117在本地机器识别OCR法语电影的字幕效果PK 2024/1/17 11:18 1959 - Jirai Cracher Sur Vos Tombes [Gast, Vian].avi https://www.pianbar.net//drama/52892.html 1959[我唾弃你的坟墓]Jirai cracher sur vos tombes[BT下载/迅雷下载] magnet:?xturn:btih:7c9c99d9d048…

系统配置dns主从服务器

一、准备两台主机&#xff0c;区分主从 二、完全区域传送 1、主DNS服务器配置 #安装相关的包 [rootoula1 ~]# yum install bind -y#关闭防火墙 [rootoula1 ~]# systemctl stop firewalld [rootoula1 ~]# setenforce 0#修改配置主文件 [rootoula1 ~]# vim /etc/named.conf opt…

如何快速打开github

作为一个资深码农&#xff0c;怎么能不熟悉全球最大的同性交友社区——github呢&#xff0c;但头疼的是github有时能打开&#xff0c;有时打不开&#xff0c;这是怎么回事&#xff1f; 其实问题出在github.com解析DNS上&#xff0c;并不是需要FQ。下面提供一个方法&#xff0c;…

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用相机日志跟踪功能(C#)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用相机日志跟踪功能&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机NEOAPI SDK和短曝光功能的技术背景Baumer工业相机通过NEOAPI SDK使用相机日志跟踪功能1.引用合适的类文件2.通过NEOAPI SDK使用相机日志跟踪功能3.通…

C#,入门教程(30)——扎好程序的笼子,错误处理 try catch

上一篇&#xff1a; C#&#xff0c;入门教程(29)——修饰词静态&#xff08;static&#xff09;的用法详解https://blog.csdn.net/beijinghorn/article/details/124683349 程序员语录&#xff1a;凡程序必有错&#xff0c;凡有错未必改&#xff01; 程序出错的原因千千万&…

Centos 8 安装 Elasticsearch

简介&#xff1a;CentOS 8是一个基于Red Hat Enterprise Linux&#xff08;RHEL&#xff09;源代码构建的开源操作系统。它是一款稳定、可靠、安全的服务器操作系统&#xff0c;适合用于企业级应用和服务的部署。CentOS 8采用了最新的Linux内核和软件包管理系统&#xff0c;提供…

ThinkPad T14/T15/P14s/P15s gen2电脑原厂Win10系统镜像 恢复笔记本出厂时预装自带OEM系统

lenovo联想原装出厂Windows10系统&#xff0c;适用型号&#xff1a; ThinkPad T14 Gen 2&#xff0c;ThinPad T15 Gen 2&#xff0c;ThinkPad P14s Gen 2&#xff0c;ThinkPad P15s Gen 2 &#xff08;20W1,20W5,20VY,20W7,20W0,20W4,20VX,20W6&#xff09; 链接&#xff1…