一、基本概念
GPU屏幕渲染有兩種方式
- On-Screen Rendering 當(dāng)前屏幕渲染,是指渲染操作是在當(dāng)前用于顯示屏幕緩沖區(qū)中進(jìn)行的宠纯。
- Off-Screen Rendering 離屏渲染,指的是GPU在當(dāng)前屏幕緩沖區(qū)以外新開辟一個(gè)緩沖區(qū)進(jìn)行渲染操作。
- 另一種特殊的離屏渲染:CPU渲染
如果我們重寫了drawRect方法掠廓,并且使用任何Core Graphics的技術(shù)進(jìn)行了繪制操作,就涉及到了CPU渲染甩恼。整個(gè)渲染過程由CPU在App內(nèi)同步地完成蟀瞧,渲染得到的bitmap最后再交由GPU用于顯示。
相比于當(dāng)前屏幕渲染条摸,離屏渲染的代價(jià)比較高悦污,主要體現(xiàn)在兩個(gè)方面:
- 創(chuàng)建新緩沖區(qū)
想要離屏渲染,就必須創(chuàng)建一個(gè)新的緩沖區(qū)钉蒲; - 上下文切換
離屏渲染的整個(gè)過程切端,需要多次切換上下文環(huán)境:先是從當(dāng)前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結(jié)束以后子巾,將離屏緩沖區(qū)的渲染結(jié)果顯示到屏幕上帆赢。而上下文環(huán)境的切換是要付出很大代價(jià)的。
二线梗、離屏渲染的觸發(fā)方式
設(shè)置以下屬性都會(huì)觸發(fā)離屏繪制:
- shouldRasterize(光柵化)
- masks(遮罩)
- shadows(陰影)
- edge antialiasing(抗鋸齒)
- group opacity(不透明)
#######舉個(gè)例子
設(shè)置圓角:
view.layer.cornerRadius = 5
這行代碼做了什么椰于?文檔中cornerRadius屬性的說明:
Setting the radius to a value greater than 0.0 causes the layer to begin drawing rounded corners on its background. By default, the corner radius does not apply to the image in the layer’s contents property; it applies only to the background color and border of the layer. However, setting the masksToBounds property to YES causes the content to be clipped to the rounded corners.
很明了,只對(duì)前景框和背景色起作用仪搔,再看 CALayer 的結(jié)構(gòu)瘾婿,如果contents有內(nèi)容或者內(nèi)容的背景不是透明的話,還需要把這部分弄個(gè)角出來烤咧,不然合成的結(jié)果還是沒有圓角偏陪,所以才要修改masksToBounds為true(在 UIView 上對(duì)應(yīng)的屬性是clipsToBounds,在 IB 里對(duì)應(yīng)的設(shè)置是「Clip Subiews」選項(xiàng))煮嫌。前些日子很熱鬧的圓角優(yōu)化文章中的2篇指出是修改masksToBounds為true而非修改cornerRadius才是觸發(fā)離屏渲染的原因笛谦,但如果以「Color Offscreen-Renderd Yellow」的特征為標(biāo)準(zhǔn)的話,這兩個(gè)屬性單獨(dú)作用時(shí)都不是引發(fā)離屏渲染的原因昌阿,他倆合體(masksToBounds = true, cornerRadius>0)才是饥脑。
另外對(duì)于設(shè)置陰影效果(shadow)恳邀,可以通過設(shè)置路徑來減少離屏渲染帶來的消耗:
let imageViewLayer = avatorView.layer
imageViewLayer.shadowColor = UIColor.blackColor().CGColor
imageViewLayer.shadowOpacity = 1.0 //此參數(shù)默認(rèn)為0,即陰影不顯示
imageViewLayer.shadowRadius = 2.0 //給陰影加上圓角灶轰,對(duì)性能無明顯影響
imageViewLayer.shadowOffset = CGSize(width: 5, height: 5)
//設(shè)定路徑:與視圖的邊界相同
let path = UIBezierPath(rect: cell.imageView.bounds)
imageViewLayer.shadowPath = path.CGPath//路徑默認(rèn)為 nil
三谣沸、如何選擇
- 任何時(shí)候優(yōu)先考慮避免觸發(fā)離屏渲染;
- 離屏渲染 VS CPU渲染笋颤;
由于GPU的浮點(diǎn)運(yùn)算能力比CPU強(qiáng)乳附,CPU渲染的效率可能不如離屏渲染;但如果僅僅是實(shí)現(xiàn)一個(gè)簡(jiǎn)單的效果伴澄,直接使用CPU渲染的效率又可能比離屏渲染好赋除,畢竟離屏渲染要涉及到緩沖區(qū)創(chuàng)建和上下文切換等耗時(shí)操作。
總之秉版,具體的選擇應(yīng)該由性能測(cè)試結(jié)果來決定贤重。