Lmsgsendnilself

Uninhibited Soul, Free Craziness

maskToBounds离屏渲染的解决

| Comments

GPU渲染机制:

CPU计算好显示内容提交到GPU,GPU渲染完成后将渲染结果放入帧缓冲区,随后视频控制器会按照 VSync 信号逐行读取帧缓冲区的数据,经过可能的数模转换传递给显示器显示。

渲染类型:

当前屏幕渲染:GPU的渲染在当前用于显示的屏幕缓冲区中进行操作。 离屏渲染 :GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。

CPU渲染。这是一种特殊的离屏渲染,如果我们重写了drawRect方法,并且使用任何Core Graphics的技术进行了绘制操作,就涉及到了CPU渲染。整个渲染过程由CPU在App内 同步地 完成,渲染得到的bitmap最后再交由GPU用于显示。

离屏渲染的触发方式

设置以下属性时,都会触发离屏绘制:

shouldRasterize(光栅化) masks(遮罩) shadows(阴影) edge antialiasing(抗锯齿) group opacity(不透明) 复杂形状设置圆角等 渐变

概念相关参考:http://www.jianshu.com/p/6d24a4c29e18

  • 备注:CoreGraphics 通常是线程安全的,所以可以进行异步绘制,显示的时候再放回主线程。

解决离屏渲染

平时用的最多的场景是画圆角图片的时候容易出现离屏渲染。我的处理办法是: 对于UIView,使用UIGraphics画一个image,加到View底部来避免,

1
2
3
4
5
6
7
8
9
UIGraphicsBeginImageContextWithOptions(customSize, NO, [UIScreen mainScreen].scale);
CGContextRef context  = UIGraphicsGetCurrentContext();

CGContextMoveToPoint(context, startX,startY);  
CGContextAddArcToPoint(context, x1, y1, x2, y2, radius);  
CGContextDrawPath(context, kCGPathFillStroke);
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

对于UIImageview,则是裁剪其属性image的方式处理。

1
2
3
4
5
6
7
8
9
10
11
12
CGSize size = self.bounds.size;
CGFloat scale = [UIScreen mainScreen].scale;
CGSize cornerRadiiSize = CGSizeMake(cornerRadius, cornerRadius);

UIGraphicsBeginImageContextWithOptions(size, NO, scale);

UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds     byRoundingCorners:rectCornerType cornerRadii:cornerRadiiSize];
[cornerPath addClip];
[image drawInRect:self.bounds];
 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
 
UIGraphicsEndImageContext();

当然,有时候也许最傻最直接,但最省事的方法,就是上面直接多加一层uiview罩住… 微博头像便如此。

Comments