请稍侯

iOS中触发离屏渲染的本质原因与场景

05 December 2020

iOS中触发离屏渲染的本质原因与场景

当前屏幕渲染(On-Screen Rendering):当前屏幕渲染,CPU、GPU 不停地将内容渲染完成放入frame buffer帧缓冲区中,显示屏幕从 frame buffer中获取内容显示。

离屏渲染(Off-Screen Rendering):离屏渲染,先创建离屏渲染帧缓冲区offscreen frame buffer,然后逐一将内容渲染放入其中,完成后对离屏渲染缓冲区做阴影叠加、裁剪等操作,最后将结果拷贝或切换到帧缓冲区frame buffer中,显示屏幕从 frame buffer中获取内容显示。

触发离屏渲染的原因

因为离屏渲染相对于当前屏幕渲染会多创建一个叫作离屏渲染帧缓冲区(offscreen frame buffer)的临时缓冲区,在这个临时缓冲区是主要用来存放一些全局操作过程当中的渲染结果。比如阴影叠加、裁剪、蒙版、模糊、光栅化、组透明、投影、圆角等操作会涉及到多个渲染结果的合并,所以需要临时缓冲区来暂存这些用来最终用来合并的中间渲染结果。

所以,触发离屏渲染本质上是因为涉及到多个渲染结果合并时,需要借助离屏渲染帧缓冲区来暂存渲染结果才触发的。如果说能避免需要多个图层的渲染结果合并操作,就能避免触发离屏渲染。

避免触发离屏渲染

  • 不要使用不必要的 mask,可以预处理图片为圆形,通过 Core Graphics手动绘制圆角;
  • 使用中间为圆形透明的白色背景视图覆盖。但这种方式不能解决背景色为图片或渐变色的情况;
  • 用 UIBezierPath 贝塞尔曲线绘制闭合带圆角的矩形,再将不带圆角的 layer 渲染成图片,添加到贝塞尔矩形中,另外,layer 的布局若生成改变,再重新绘制贝塞尔曲线即可。

常见触发离屏渲染的情况

  • layer 设置了使用了 mask 蒙版;
  • layer 设置了圆角裁剪(masksToBounds+cornerRadius),且包含 sub layer;
  • layer 设置了组不透明度allowsGroupOpacity,并且不透明度opacity小于1;
  • layer 设置了投影shadowXX;
  • layer 设置了光栅化shouldRasterize;
  • 使用了 blur 模糊效果UIVisualEffectView;

参考: iOS 屏幕渲染分析