而在混合加速的渲染架构下,一些 RenderLayer 会拥有自己独立的缓存,它们被称为混合图层(Compositing Layer),WebKit 会为这些 RenderLayer 创建对应的 GraphicsLayer,不同的浏览器需要提供自己的 GrphicsLayer 实现用于管理缓存的分配,释放,更新等等。拥有 GrphicsLayer 的 RenderLayer 会被绘制到自己的缓存里面,而没有 GrphicsLayer 的 RenderLayer 它们会向上追溯有 GrphicsLayer 的父/祖先 RenderLayer,直到 Root RenderLayer 为止,然后绘制在有 GrphicsLayer 的父/祖先 RenderLayer 的缓存上,而 Root RenderLayer 总是会创建一个 GrphicsLayer 并拥有自己独立的缓存。最终,GraphicsLayer 又构成了一棵与 RenderLayer 并行的树,而 RenderLayer 与 GraphicsLayer 的关系有些类似于 RenderObject 与 RenderLayer 之间的关系。
混合加速渲染架构下的网页混合,也变得比以前复杂,不再是简单的将一个缓存拷贝到窗口缓存上,而是需要完成源自不同 Layer 的多个缓存的拷贝,再加上可能的2D/3D变换,再加上缓存之间的Alpha混合等操作,当然,对于支持硬件加速,使用 GPU 来完成混合的浏览器来说,速度还是很快的。
RenderLayer 生成 GraphicsLayer 的条件,来自 GPU Accelerated Compositing in Chrome
混合加速的渲染架构下,Layer 的内容变化,只需要更新所属的 GraphicsLayer 的缓存即可,而缓存的更新,也只需要绘制直接或者间接属于这个 GraphicsLayer 的 RenderLayer 而不是所有的 RenderLayer。特别是一些特定的 CSS 样式属性的变化,实际上并不引起内容的变化,只需要改变一些 GraphicsLayer 的混合参数,然后重新混合即可,而混合相对绘制而言是很快的,这些特定的 CSS 样式属性我们一般称之为是被加速的,不同的浏览器支持的状况不太一样,但基本上 CSS Transform & Opacity 在所有支持混合加速的浏览器上都是被加速的。被加速的CSS 样式属性的动画,就比较容易达到60帧/每秒的流畅效果了。
图片来自 Understanding Hardware Acceleration on Mobile Browsers,展现了经典的 CSS 动画 Demo – Falling Leaves 的图层混合的示意图,它所使用的 Transform 和 Opacity 动画在所有支持混合加速的浏览器上都是被加速的
不过并不是拥有独立缓存的 RenderLayer 越多越好,太多拥有独立缓存的 Layer 会带来一些严重的副作用 – 首先它大大增加了内存的开销,这点在移动设备上的影响更大,甚至导致浏览器在一些内存较少的移动设备上无法很好地支持图层混合加速;其次,它加大了混合的时间开销,导致混合性能的下降,而混合性能跟网页滚动/缩放操作的流畅度又息息相关,最终导致网页滚动/缩放的流畅度下降,让用户觉得操作不够流畅。
在 Chrome://flags 里面开启“合成渲染层边框”就可以看到哪些 Layer 是一个 Compositing Layer,也就是拥有自己的独立缓存。前端开发者可以用此帮助自己控制 Compositing Layer 的创建。总的的说, Compositing Layer 可以提升绘制性能,但是会降低混合性能,网页只有合理地使用 Compositing Layer,才能在绘制和混合之间取得一个良好的平衡,实现整体渲染性能的提升。
图片来自 Chrome,展现了经典的 CSS 动画 Demo – Falling Leaves 的合成渲染层边框
网页游戏渲染 - Canvas & WebGL图片来自 [UC 浏览器 9.7 Android版],基于2D Canvas 的游戏不江湖,在主流配置手机上可以达到60帧/每秒的流畅度
以前网页游戏一般都是使用 Flash 来实现,但是随着 Flash 从移动设备被淘汰,越来越多的网页游戏会改用 Canvas 和 WebGL 来开发,浏览器关于 Canvas 的基本绘制流程可以参考我以前的文章 Introduce My Work。虽然一般网页元素都是使用 CPU 来绘制,但是对于加速的2D Canvas 和 WebGL 来说,它们的绘制是直接使用 GPU 的,所以它们一般会拥有一个 GL FBO(FrameBufferObject)作为自己的缓存,Canvas/WebGL 的内容被绘制到这个 FBO 上面,而这个 FBO 所关联的纹理再在混合操作里面被拷贝到窗口缓存上。简单的来说,对于加速的2D Canvas 和 WebGL,它们的绘制和混合都是使用 GPU。
图片来自 [UC 浏览器 9.7 Android版],一个演示 WebGL 的网页 Demo
关于如何优化 Canvas 游戏的性能,请参考我以前的文章 – High Performance Canvas Game for Android(高性能Android Canvas游戏开发)。
参考索引How Browsers Work: Behind the scenes of modern web browsers
WebKit for Developers
GPU Accelerated Compositing in Chrome
Understanding Hardware Acceleration on Mobile Browsers
Web Page Rendering and Accelerated Compositing
我的2013 – 年终总结 + 浏览器渲染发展的一些思考
Introduce My Work
High Performance Canvas Game for Android(高性能Android Canvas游戏开发)
OpenGL Frame Buffer Object (FBO)
您可能感兴趣的文章