淺談離屏渲染

1.GPU屏幕渲染的兩種方式

-On-Screen Rendering 當(dāng)前屏幕渲染:指的是GPU的渲染操作是在當(dāng)前用于顯示的屏幕緩沖區(qū)中進(jìn)行湘纵。
-Off-Screen Rendering 離屏渲染: 指的是GPU在當(dāng)前屏幕緩沖區(qū)以外新開(kāi)辟一個(gè)緩沖區(qū)進(jìn)行渲染操作。

2.什么是離屏渲染

相信許多iOS開(kāi)發(fā)者及舍,都聽(tīng)說(shuō)過(guò)離屏渲染贤徒,大部分應(yīng)該是面試的時(shí)候被問(wèn)及芹壕。那么問(wèn)題來(lái)了,什么是離屏渲染接奈,原理又是什么哪
-什么是離屏渲染
先說(shuō)一下畫家算法
畫家算法踢涌,又稱深度排序法。


畫家算法由遠(yuǎn)及近.png

我們先看看它的算法:
(1)將畫布設(shè)成背景色序宦,
(2)然后頭腦簡(jiǎn)單的畫家首先繪制距離較遠(yuǎn)的場(chǎng)景,然后用繪制距離較近的場(chǎng)景覆蓋較遠(yuǎn)的部分睁壁。畫家算法首先將場(chǎng)景中的多邊形根據(jù)深度進(jìn)行排序,然后按照順序進(jìn)行描繪。這種方法通常會(huì)將不可見(jiàn)的部分覆蓋,這樣就可以解決可見(jiàn)性問(wèn)題互捌∨嗣鳎”

如上圖,要在屏幕上顯示圖3的ImageView疫剃,通常GPU的Render Server會(huì)遵循 “畫家算法” 按秩序先渲染圖1的那一層钉疫,然后渲染圖2的那一層硼讽,最后渲染圖3巢价,渲染好后的每一層都會(huì)存入幀緩存區(qū),然后按照次序繪制到屏幕固阁,當(dāng)繪制完一層壤躲,就會(huì)將該層從幀緩存區(qū)中移除(以節(jié)省空間)
但是有時(shí)候有些特殊情況,例如對(duì)多圖層的圖片進(jìn)行圓角顯示的時(shí)候备燃,一層一層渲染完成碉克,進(jìn)行圓角裁剪,當(dāng)前已經(jīng)渲染完成的圖片幀緩存區(qū)的數(shù)據(jù)渲染完成丟棄或者被覆蓋的時(shí)候 我們沒(méi)有辦法再去對(duì)圖層進(jìn)行裁剪并齐,因此需要?jiǎng)?chuàng)建一個(gè)離屏緩存區(qū)來(lái)存儲(chǔ)渲染完成的數(shù)據(jù)漏麦,等全部圖層渲染到離屏緩存區(qū)之后,我們?cè)偃〕鰜?lái)况褪,進(jìn)行裁剪操作撕贞,之后存在幀緩存區(qū),等待屏幕控制器讀取和操作测垛。

比如 UIImageView 要圓角. 然后還有背景.
此時(shí)它就先把你里面的背景色圖層渲染好,存到離屏緩存區(qū);
然后再把圖片渲染好, 存到離屏渲染緩存去.
最后在把這個(gè)2個(gè)存到離屏緩存區(qū)的圖層進(jìn)行圓角處理
然后再把結(jié)果放到幀緩存區(qū)
最后 顯示


流程.png

3.離屏渲染的利弊

離屏渲染其實(shí)是加大了系統(tǒng)的負(fù)擔(dān)捏膨,確實(shí)會(huì)造成性能上的損耗
1.離屏渲染需要開(kāi)辟額外的存儲(chǔ)控件,是當(dāng)前屏幕的2.5倍,超過(guò)無(wú)效
2.從離屏緩沖區(qū)拷貝數(shù)據(jù)到幀緩沖區(qū)号涯,上下文切換耗性能
有那么多弊端為什么還要用離屏渲染
多次出現(xiàn)在屏幕當(dāng)中目胡,可以提前渲染好,可以復(fù)用链快,減壓CPU/GPU
還有一些特殊情況誉己,不得不使用離屏渲染(使用額外的離屏緩沖區(qū)(offscreen butter)保存中間狀態(tài),最后疊加域蜗、處理后繪制在屏幕上巫延,這樣就不得不使用離屏渲染)

4.常見(jiàn)的幾種離屏渲染的情況

使用了 mask 的 layer (layer.mask)
需要進(jìn)行裁剪的 layer (layer.masksToBounds /view.clipsToBounds)
設(shè)置了組透明度為 YES,并且透明度不為 1 的layer (layer.allowsGroupOpacity/ layer.opacity)
添加了投影的 layer (layer.shadow*)
采用了光柵化的 layer (layer.shouldRasterize)
繪制了文字的 layer (UILabel, CATextLayer, Core Text 等)

-離屏渲染的另一個(gè)情況(光柵化)

When the value of this property is YES, the layer is rendered as a bitmap in its local coordinate space and then composited to the destination with any other content
如果shouldRasterize被設(shè)置成YES地消,在觸發(fā)離屏繪制的同時(shí)炉峰,會(huì)將光柵化后的內(nèi)容緩存起來(lái),如果對(duì)應(yīng)的layer及其sublayers沒(méi)有發(fā)生改變脉执,在下一幀的時(shí)候可以直接復(fù)用疼阔。這將在很大程度上提升渲染性能

5.layer.cornerRadius和clipsToBounds = YES一定會(huì)觸發(fā)離屏渲染嗎

開(kāi)始代碼測(cè)試前,我們先開(kāi)啟離屏渲染的檢測(cè)半夷,在模擬器打開(kāi)color offscreen-rendered,開(kāi)啟后會(huì)把那些需要離屏渲染的圖層高亮成黃色婆廊。


模擬器調(diào)試

上代碼

UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn1.frame = CGRectMake(kScreenWidth/2-50, 120, 100, 100);
    btn1.layer.cornerRadius = 50;
    [self.view addSubview:btn1];

    [btn1 setImage:[UIImage imageNamed:@"test.png"] forState:UIControlStateNormal];
    btn1.clipsToBounds = YES;
    
    UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn2.frame = CGRectMake(kScreenWidth/2-50, 260, 100, 100);
    btn2.layer.cornerRadius = 50;
    btn2.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:btn2];
    btn2.clipsToBounds = YES;
    
    UIImageView *image3 = [[UIImageView alloc]initWithFrame:CGRectMake(kScreenWidth/2-50, 400, 100, 100)];
    image3.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:image3];
    image3.image = [UIImage imageNamed:@"test.png"];
    image3.layer.cornerRadius = 50;
    image3.clipsToBounds = YES;
    
    UIImageView *image4 = [[UIImageView alloc]initWithFrame:CGRectMake(kScreenWidth/2-50, 540, 100, 100)];
    [self.view addSubview:image4];
    image4.layer.cornerRadius = 50;
    image4.clipsToBounds = YES;
    image4.image = [UIImage imageNamed:@"test.png"];

run一下看效果


模擬器iPhone11為例

我們創(chuàng)建了兩個(gè)button 兩個(gè)imageview 為什么1和3觸發(fā)了離屏渲染 2和4沒(méi)有觸發(fā)
分析一下
按鈕1和2 的區(qū)別就是一個(gè)是設(shè)置了背景圖片,一個(gè)設(shè)置的是顏色巫橄,可以看出淘邻,離屏渲染觸發(fā)的條件就是存在多組不同的layer需要渲染在一個(gè)視圖上,而GPU無(wú)法一次性全部渲染時(shí)湘换,需要保存離屏緩存區(qū)宾舅,等把這個(gè)2個(gè)存到離屏緩存區(qū)的圖層進(jìn)行圓角處理的時(shí)候才會(huì)觸發(fā)。
imageview3和4的去區(qū)別就是一個(gè)設(shè)置了背景色一個(gè)沒(méi)有彩倚,為啥3觸發(fā)了離屏渲染筹我,因?yàn)?里面包好了背景色,圖片帆离,圓角處理蔬蕊,渲染完背景色,再去渲染圖片哥谷,再去圓角裁剪的時(shí)候岸夯,可能背景色已經(jīng)被幀緩存區(qū)給移除了,所以需要觸發(fā)離屏渲染们妥,image4 直接渲染裁剪就可以顯示
可能有人會(huì)提問(wèn)了猜扮,為啥button1只設(shè)置了圖片但是觸發(fā)了離屏渲染,因?yàn)閁Ibutton有一個(gè)UIImageView屬性王悍,離屏渲染的觸發(fā)兩個(gè)條件破镰,重組和渲染,按鈕里面的imageview屬性先去渲染圖片 再去裁剪imageview 再去裁剪按鈕 ,button的bg是layer鲜漩,只有在重組源譬,重新渲染才會(huì)離屏渲染。
-所以總結(jié)了一下并不是layer.cornerRadius和clipsToBounds = YES一定會(huì)觸發(fā)離屏渲染嗎孕似,

6.iOS 常見(jiàn)的幾種圓角處理方式

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末踩娘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子喉祭,更是在濱河造成了極大的恐慌养渴,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泛烙,死亡現(xiàn)場(chǎng)離奇詭異理卑,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蔽氨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門藐唠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人鹉究,你說(shuō)我怎么就攤上這事宇立。” “怎么了自赔?”我有些...
    開(kāi)封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵妈嘹,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我绍妨,道長(zhǎng)润脸,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任痘绎,我火速辦了婚禮津函,結(jié)果婚禮上肖粮,老公的妹妹穿的比我還像新娘孤页。我一直安慰自己,他們只是感情好涩馆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布行施。 她就那樣靜靜地躺著,像睡著了一般魂那。 火紅的嫁衣襯著肌膚如雪蛾号。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天涯雅,我揣著相機(jī)與錄音鲜结,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛精刷,可吹牛的內(nèi)容都是我干的拗胜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼怒允,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼埂软!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起纫事,我...
    開(kāi)封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤勘畔,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后丽惶,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體炫七,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年钾唬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诉字。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡知纷,死狀恐怖壤圃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情琅轧,我是刑警寧澤伍绳,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站乍桂,受9級(jí)特大地震影響冲杀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜睹酌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一权谁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧憋沿,春花似錦旺芽、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至壶辜,卻和暖如春悯舟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背砸民。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工抵怎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留奋救,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓反惕,卻偏偏與公主長(zhǎng)得像菠镇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子承璃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355