下一场录像控制器会遵照HSync信号逐行读取帧缓冲区的数额,当前屏幕渲染不需额外创制新的缓存

举手投足应用优化及最后根本要看FPS(页面流畅程度)性能、内存占用等方面。离屏渲染也是外常谈的一个题目,本文侧重点在泛导致离屏渲染之素跟缓解方案。

屏幕显示图像的规律:

这就是说为何离屏渲染会挑起性能问题?

OpenGL中,GPU屏幕渲染有有限栽方法: On-Screen Rendering (当前屏幕渲染)
Off-Screen Rendering (离屏渲染)
,当前屏幕渲染不需卓殊创设新的缓存,也无欲被新的上下文,相对于离屏渲染性能更好。然而给时屏幕渲染的受制因素限制(唯有自身上下文、屏幕缓存有限等),当前屏幕渲染有些情况下之渲染解决不了的,就动用及离屏渲染。离屏渲染之方方面面过程用切换上下文环境,先由
当前屏幕切换至离屏,等终结后,又如以上下文环境切换回来.这吗是怎会吃性能的原由了。

离屏渲染引发因一向
cornerRadius(设置圆角)、shadows(阴影)、masks(遮罩)、edge
antialiasing(抗锯齿)、group
opacity(不透明)、shouldRasterize(光栅化)

等,至于检测离屏渲染的工具 Instruments的Core Animation
就非多说了。本文紧要介绍 装圆角阴影 的方案。

高中物理应该学了呈现器是怎体现图像的:需要显示的图像经过CRT电子枪为极快的进度一行一行的扫视,扫描出来就突显了平轴画面,随后电子枪又会回去起先地方循环扫描,形成了大家看来底图纸或摄像。

安装圆角

健康做法:

   //只需要设置layer层的两个属性
   //设置圆角
   imageView.layer.cornerRadius = imageView.frame.size.width / 2;
   //将多余的部分切掉
   imageView.layer.masksToBounds = YES;

此间提供个别种制止离屏渲染的方案

  • 1.视图上加加一个子layer到最好上层,用于覆盖该视图及其子视图,设置layer的图纸为刚可以遮盖成所待圆角样子,并且图片颜色刚好是欠视图父视图的背景颜色就是达成想要之功能。
    初稿地址
    ,该作者写的酷好,封装了一个UIView的分类,3个API,分别是
    设置一个季竞赛圆角,设置一个点名地方的圆角,设置一个带来边框的圆角

    github地址

/**
 设置一个四角圆角

 @param radius 圆角半径
 @param color  圆角背景色
 */
- (void)xw_roundedCornerWithRadius:(CGFloat)radius cornerColor:(UIColor *)color;

/**
 设置一个普通圆角

 @param radius  圆角半径
 @param color   圆角背景色
 @param corners 圆角位置
 */
- (void)xw_roundedCornerWithRadius:(CGFloat)radius cornerColor:(UIColor *)color corners:(UIRectCorner)corners;

/**
 设置一个带边框的圆角

 @param cornerRadii 圆角半径cornerRadii
 @param color       圆角背景色
 @param corners     圆角位置
 @param borderColor 边框颜色
 @param borderWidth 边框线宽
 */
- (void)xw_roundedCornerWithCornerRadii:(CGSize)cornerRadii cornerColor:(UIColor *)color corners:(UIRectCorner)corners borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth;

下载下来是分类直接拖入工程即便好运用了,调用很有益于,可是以的时段会发觉,这三独API都需要传一个参数
cornerColor (父视图的背景象),所以呢促成了之职能的局限,即
要该父视图的颜料不是纯色,此时该法即使无适用了,同样
苟父视图的颜色会变化,这实现起来的代码也非那么优雅,如下图,有接触尴尬,这里引出了亚栽方案。

边角颜色与背景象不符

  • 2.经修改layer.mask,首先通过贝塞尔曲线创造基于矢量的途径
    ,传递给CAShapeLayer举行渲染。路径闭环,再将绘制有之Shape赋值给layer.mask,在Mask范围之外的Layer将非给展现从而达到圆角效果。代码实现大简短,如下:

    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(130, 330, 100, 100)];
    [btn setBackgroundColor:[UIColor colorWithRed:(226.0 / 255.0) green:(113.0 / 255.0) blue:(19.0 / 255.0) alpha:1]];
    [backgroundImageView addSubview:btn];
    //绘制曲线路径
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:btn.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:btn.bounds.size];
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
    //设置大小
    maskLayer.frame = btn.bounds;
    //设置图形样子
    maskLayer.path = maskPath.CGPath;
    btn.layer.mask = maskLayer;

效果图:

个体觉得第二种植方案还简明又效果扩张性更强些

为了给显示器的示跟录像控制器同步,当电子枪新扫描一行的时光,准备扫描的时发送一个水准并信号(HSync信号),彰显器的刷新频率尽管是HSync信号产生的频率。然后CPU总结好frame等属性,将计好之情提交GPU去渲染,GPU渲染好后虽会放入帧缓冲区。然后视频控制器会按照HSync信号逐行读取帧缓冲区的数量,经过可能的数模转换传递给显示器,就亮出了。这里只是简作描述,专业描述请自行查询。

设置阴影

正常做法:

//阴影的颜色
self.imageView.layer.shadowColor= [UIColorblackColor].CGColor;
//阴影的透明度
self.imageView.layer.shadowOpacity=0.8f;
//阴影的圆角
self.imageView.layer.shadowRadius=4;
//阴影偏移量
self.imageView.layer.shadowOffset=CGSizeMake(0,0);

优化方案:
避免对shadowOffset直接修改,通过调用setShadowPath来提供一个CGPath给视图的Layer,向Core
Animation提供渲染之View的形状Shape,就会面减离屏渲染总结

[self.imageView.layer setShadowPath:[[UIBezierPath 
    bezierPathWithRect:myView.bounds] CGPath]];

加:当用阴影的视图形状暴发变化时,即shadowPath并无相会从CALayer的bounds属性举行转变,所以在layer的bounds爆发变化之后用手动更新shadowPath才可以于这个适配新的bounds。切切实实推荐看即首著作

关于界面流畅而想如果深层探索可看 YYKit作者 写的篇章iOS
保持界面流畅的艺

。该篇于屏幕呈现图像的规律,到立异的方案都暴发详尽介绍。

谢谢各位,欢迎指教!

GPU屏幕渲染有半点种模式:

(1)On-Screen Rendering (当前屏幕渲染) 

仰的凡GPU的渲染操作是以眼前用来体现的屏幕缓冲区举行。

(2)Off-Screen Rendering (离屏渲染)

看重的是以GPU在时屏幕缓冲区以外开辟一个缓冲区举办渲染操作。

近来屏幕渲染不需异常成立新的缓存,也无欲被新的上下文,相对于离屏渲染性能更好。不过于时屏幕渲染的局限因素限制(唯有我上下文、屏幕缓存有限等),当前屏幕渲染有些情形下的渲染解决不了的,就以及离屏渲染。

对照叫即屏幕渲染,离屏渲染之代价是那么些高之,首要呈现在点滴单地点:

(1)创设新缓冲区

比方牵挂举办离屏渲染,首先要创制一个初的缓冲区。

(2)上下文切换

离屏渲染的任何过程,需要数切换上下文环境:先是起目前屏幕(On-Screen)切换来离屏(Off-Screen),等到离屏渲染了之后,将离屏缓冲区的渲染结果展现到屏幕上发得拿上下文环境从离屏切换至当下屏幕。而上下文环境的切换是假若付出好要命代价的。

出于直同步的建制,即便当一个 HSync 时间内,CPU 或者 GPU
没有做到内容交给,则这无异幅就碰面吃抛,等待下一样次机遇又突显,而此时突显屏会保留在此之前的情不换。这就是界面卡顿的由。

既离屏渲染这么吃性能,为何来就套机制为?

有些效果被认为无法一贯表现于屏幕,而需在此外地点做额外的拍卖预合成。图层属性之混合体没有预合成以前未可以直接当屏幕被绘制,所以尽管得屏幕外渲染。屏幕外渲染并无代表软件绘图,可是它们意味着图层必须于吃显示从前在一个屏幕外直达下文中叫渲染(不论CPU仍然GPU)。

脚的气象或者操作会吸引离屏渲染:

为图层设置遮罩(layer.mask)

– 将图层的layer.masksToBounds / view.clipsToBounds属性设置为true

– 将图层layer.allowsGroupOpacity属性设置为YES和layer.opacity小于1.0

– 为图层设置阴影(layer.shadow *)。

– 为图层设置layer.shouldRasterize=true

– 具有layer.cornerRadius,layer.edgeAntialiasingMask,layer.allowsEdgeAntialiasing的图层

– 文本(任何类型,包括UILabel,CATextLayer,Core Text等)。

– 使用CGContext在drawRect
:方法中绘制大部分状下会导致离屏渲染,甚至仅是一个拖欠的实现。

优化方案

官对离屏渲染发生性能问题呢拓展了优化:

iOS 9.0 往日UIimageView跟UIButton设置圆角都相会触发离屏渲染。

iOS 9.0
之后UIButton设置圆角会触发离屏渲染,而UIImageView里png图片设置圆角不会师触发离屏渲染了,如若设置任何阴影效果之类的尚是晤面触发离屏渲染的。

1、圆角优化

当APP开发被,圆角图形或日常出现的。如果一个界面被仅仅发少量圆角图片或对性没死好之影响,然则当圆角图片于多之上就是谋面APP性能有强烈的震慑。

我们安圆角一般通过如下格局:

imageView.layer.cornerRadius = CGFloat(10);

imageView.layer.masksToBounds = YES;

诸如此类处理的渲染机制是GPU在此时此刻屏幕缓冲区外新开发一个渲染缓冲区举办工作,也固然是离屏渲染,这会给大家带万分的属性损耗,假若那样的圆角操作上自然数量,会触发缓冲区的频繁合并及上下文的底反复切换,性能的代价会主地显示于用户体验上——掉帧。

优化方案1:使用贝塞尔曲线UIBezierPath及Core Graphics框架画出一个圆角

UIImageView *imageView = [[UIImageView alloc]
initWithFrame:CGRectMake(100,100,100,100)];

imageView.image = [UIImage imageNamed:@”myImg”];

//起先对imageView举行绘画

UIGraphicsBeginImageContextWithOptions(imageView.bounds.size,NO,1.0);

//使用贝塞尔曲线画来一个圆形图

[[UIBezierPath
bezierPathWithRoundedRect:imageView.boundscornerRadius:imageView.frame.size.width]addClip];

[imageView drawRect:imageView.bounds];

imageView.image=UIGraphicsGetImageFromCurrentImageContext();

//停止画图

UIGraphicsEndImageContext();

[self.view addSubview:imageView];

优化方案2:使用CAShapeLayer和UIBezierPath设置圆角

UIImageView *imageView = [[UIImageView
alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];

imageView.image = [UIImage imageNamed:@”myImg”];

UIBezierPath *maskPath = [UIBezierPath
bezierPathWithRoundedRect:imageView.bounds
byRoundingCorners:UIRectCornerAllCorners
cornerRadii:imageView.bounds.size];

CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];

//设置大小

maskLayer.frame = imageView.bounds;

//设置图形样子

maskLayer.path = maskPath.CGPath;

imageView.layer.mask = maskLayer;

[self.view addSubview:imageView];

于方案2亟需讲的是:

CAShapeLayer继承于CALayer,可以应用CALayer的享有属于性值;

CAShapeLayer需要贝塞尔曲线配合以才暴发义(也就是说才发出效用)

下CAShapeLayer(属于CoreAnimation)与贝塞尔曲线可以兑现不以view的drawRect(继承给CoreGraphics走的凡CPU,消耗的性于生)方法吃描绘出部分怀恋假设之图

CAShapeLayer动画渲染直接交给到手机的GPU当中,相较于view的drawRect方法以CPU渲染而言,其效能极高,能大大优化内存以意况。

总的看就是用CAShapeLayer的内存消耗掉,渲染速度快,提出接纳优化方案2。

2、shadow优化

于shadow,如若图层是个简单的几哪儿图形或者圆角图形,大家可以通过安装shadowPath来优化性能,能大幅提升性能。示例如下:

imageView.layer.shadowColor=[UIColorgrayColor].CGColor;

imageView.layer.shadowOpacity=1.0;

imageView.layer.shadowRadius=2.0;

UIBezierPath *path=[UIBezierPathbezierPathWithRect:imageView.frame];

imageView.layer.shadowPath=path.CGPath;

我们还可以够通过安装shouldRasterize属性值为YES来强制开启离屏渲染。其实就是是光栅化(Rasterization)。既然离屏渲染这么不好,为啥咱们还要强制开启也?当一个图像混合了差不五个图层,每一趟活动时,每一样轴都如重新合成这多少个图层,非凡吃性能。当大家打开光栅化后,会当首不行发一个员图缓存,当又使用时尽管汇合复用这些缓存。不过要图层暴发变更的时刻就会更发位图缓存。所以这一个功效相似不克用于UITableViewCell中,cell的复用反而下跌了性。最好用于图层较多的静态内容之图样。而且出的位图缓存的高低是发限定的,一般是2.5只屏幕尺寸。在100ms之内不使用此缓存,缓存也会受剔除。所以我们假若依照使用意况而肯定。

3、其他的片段优化提议

当大家用圆角效率时,可以用同样摆放中间透明图片蒙上失去

拔取ShadowPath指定layer阴影效果路径

行使异步举行layer渲染(非死不可开源的异步绘制框架AsyncDisplay基特(Kit))

安layer的opaque值为YES,裁减复杂图层合成

尽可能用非分包透明(alpha)通道的图资源

尽可能设置layer的大小值为整形值

一直为美工把图纸切成圆角举办体现,这是效用最高的同一栽方案

不少情况下用户上传图片举办显示,可以给服务端处理圆角

用代码手动生成圆角Image设置及即便出示的View上,利用UIBezierPath(CoreGraphics框架)画出来圆角图片

Core Animation工具检测离屏渲染

对此离屏渲染之检测,苹果为我们提供了一个测试工具Core
Animation。可以于Xcode->Open Develeper Tools->Instruments中找到

图片 1

Core Animation工具用来监测Core
Animation性能,提供可见的FPS值,并且提供几乎只选项来测量渲染性能。如下图:

图片 2

脚大家来表明每个选项之职能:

Color Blended
Layers:这些选项即使勾选,你能看出哪位layer是晶莹剔透的,GPU正于开混合总括。突显黄色的固然是晶莹的,红色就是勿透明底。

Color Hits 格林(Green) and Misses
Red:假如勾选这些选项,且当大家代码中有安shouldRasterize为YES,那么肉色表示没有复用离屏渲染之缓存,黄色则表示复用了缓存。我们当愿意可以复用。

Color Copied
Images:依据合法的传道,当图片的颜色格式GPU不辅助之上,Core
Animation会

拷贝一客数据让CPU举行转发。例如从网上下载了TIFF格式的图样,则用CPU举行转账,这么些区域会显成粉红色。还有同种情状会触发Core
Animation的copy方法,就是字节不针对合的时。如下图:

图片 3

Color Immediately:默认情况下Core
Animation工具为各飞秒10糟糕的频率更新图层调试颜色,尽管勾选这么些选项则移除10ms的推移。对某些情形用如此,然则暴发或影响正常帧数的测试。

Color Misaligned
Images:勾选此起,如果图片需要缩放则标记为绿色,倘若无像素对一头则标记为粉色。像从对伙同大家已以上头装有介绍。

Color Offscreen-Rendered
Yellow:用来检测离屏渲染之,假若突显紫色,表示有离屏渲染。当然还要做Color
Hits 格林(Green) and Misses Red来拘禁,是否复用了缓存。

Color OpenGL Fast Path
Blue:这一个选项对这些以OpenGL的图层才来由此,像是GLKView或者
CAEAGLLayer,假若未出示绿色则意味用了CPU渲染,绘制在了屏幕外,呈现黄色代表正常。

Flash Updated
Regions:当对图层重绘的时节回亮褐色,假设反复发则会影响性。可以就此长缓存来增进性。

相关文章