003-iOS離屏渲染產(chǎn)生的原因

離屏渲染產(chǎn)生的原因

在討論離屏渲染之前我們先要搞清楚正常的渲染流程是怎樣的

非離屏渲染流程:
非離屏渲染

我們可以看到在非離屏渲染的場(chǎng)景下医窿,需要渲染的數(shù)據(jù)是直接提交到GPU的幀緩沖區(qū)游岳,等待屏幕的垂直同步信號(hào)來(lái)完成頁(yè)面的顯示返干,但是在離屏渲染的場(chǎng)景下又是怎樣的呢?請(qǐng)看下圖


離屏渲染

我們可以看到在離屏渲染的場(chǎng)景下浦妄,要完成頁(yè)面的展示曾雕,中間多了一個(gè)過(guò)程,需要渲染的數(shù)據(jù)首先提交到了離屏緩沖區(qū)体谒,然后再提交到幀緩沖區(qū)的杯聚,為什么要增加一個(gè)OffsceenBuffer呢?這個(gè)OffsceenBuffer又有什么作用呢抒痒?

為什么要增加OffsceenBuffer幌绍?

如果觸發(fā)了離屏渲染,那么在顯示這個(gè)頁(yè)面的每一幀都會(huì)去做離屏渲染的處理故响,比如切圓角傀广,顯示陰影等,如果每一幀都要重新去處理彩届,那么對(duì)于CPU以及GPU都帶來(lái)很大的負(fù)擔(dān)伪冰。所以引入了離屏緩沖區(qū),將處理好的圖層直接丟到離屏緩沖區(qū)樟蠕,下次渲染的時(shí)候直接拿出來(lái)顯示到屏幕上

離屏緩存區(qū)也是有限制的

  • 時(shí)間限制:緩存的內(nèi)容超過(guò)100ms沒(méi)有被使用贮聂,內(nèi)容將會(huì)被丟棄
  • 空間限制:超過(guò)屏幕像素大小的2.5倍,將不能再存儲(chǔ)新的數(shù)據(jù)寨辩,離屏渲染會(huì)失效

這樣做雖然解決了多次處理數(shù)據(jù)的問(wèn)題吓懈,但是還是會(huì)帶來(lái)另外的性能問(wèn)題,由于離屏緩沖區(qū)和幀緩沖區(qū)屬于兩個(gè)不同的緩沖區(qū)靡狞,如果一個(gè)頁(yè)面觸發(fā)了多個(gè)離屏渲染耻警,那么GPU在顯示每一幀的時(shí)候都要在離屏緩沖區(qū)和幀緩沖區(qū)之間切換,在快速滾動(dòng)的場(chǎng)景下就會(huì)出現(xiàn)嚴(yán)重的掉幀甸怕。那么怎么解決這個(gè)問(wèn)題呢甘穿?其實(shí)答案就是要減少離屏渲染,那些場(chǎng)景會(huì)觸發(fā)離屏渲染呢梢杭?

觸發(fā)離屏渲染的場(chǎng)景

離屏渲染的檢測(cè)

在模擬器運(yùn)行時(shí)我們?cè)谶@里開(kāi)啟離屏渲染的檢測(cè):


離屏渲染檢測(cè)開(kāi)關(guān)

開(kāi)啟后温兼,如果有離屏渲染,則會(huì)顯示成黃色武契,如下圖:


離屏渲染
1. cornerRadius + masksToBounds

這兩個(gè)屬性我們都不陌生妨托,這是我們經(jīng)常使用的切圓角的方式,將cornerRadius > 0同時(shí)masksToBounds = YES時(shí)吝羞,就可能會(huì)觸發(fā)離屏渲染兰伤,注意,是可能钧排,我們來(lái)看下圖中的例子


例1

先不要著急敦腔,我們?cè)賮?lái)看另外一個(gè)例子:


例2

為什么同樣都是設(shè)置cornerRadius + masksToBounds,例1和例2的結(jié)果卻不相同呢恨溜?相信細(xì)心的同學(xué)已經(jīng)發(fā)現(xiàn)了符衔,例2多了一個(gè)綠色的view找前,例2中的圖層層級(jí)是這樣的:


例2圖層

所以我們能夠得出:

如果只有一個(gè)圖層,就算同時(shí)設(shè)置 cornerRadius + masksToBounds 也并不會(huì)觸發(fā)離屏渲染判族,只有多個(gè)圖層發(fā)生疊加的時(shí)候才會(huì)觸發(fā)離屏渲染

為什么多個(gè)圖層疊加會(huì)觸發(fā)離屏渲染呢 躺盛?

畫家算法: 當(dāng)GPU在渲染圖層的時(shí)候會(huì)根據(jù)圖層的遠(yuǎn)近去由遠(yuǎn)及近完成渲染,這里說(shuō)的遠(yuǎn)近就是疊加圖層時(shí)由內(nèi)到外形帮,當(dāng)一幀數(shù)據(jù)處理好后將被提交到幀緩沖區(qū)槽惫,但是如果當(dāng)前圖層是多個(gè)圖層疊加后的結(jié)果,那么將不能被直接提交到幀緩沖區(qū)(如果提交了辩撑,下一個(gè)垂直同步信號(hào)到來(lái)的時(shí)候會(huì)被直接顯示在界面上)界斜,需要存儲(chǔ)起來(lái),等待這個(gè)圖層的所有子圖層都被處理完通過(guò)疊加后合冀,再提交到幀緩沖區(qū)用于顯示

如果我們只設(shè)置cornerRadius各薇,會(huì)不會(huì)觸發(fā)離屏渲染呢?

cornerRadius
例3

這個(gè)就要從CALayer的結(jié)構(gòu)說(shuō)起了


CALayer結(jié)構(gòu)

CALayer大致分為三層

  1. backgroundColor : 背景顏色層
  2. content :內(nèi)容顯示層君躺,這一層主要用于顯示我們?cè)O(shè)置的內(nèi)容
  3. border :當(dāng)我們?cè)O(shè)置邊框的時(shí)候峭判,就是這一層在工作

cornerRadius只會(huì)設(shè)置backgroundColor和border的圓角,并不會(huì)對(duì)content設(shè)置圓角棕叫。除非同時(shí)設(shè)置了masksToBounds為YES(對(duì)應(yīng)view中的clipsToBounds),所以如果只設(shè)置cornerRadius朝抖,在圖層疊加時(shí)并不會(huì)觸發(fā)離屏渲染

2.mask

Mask 效果與混合圖層的效果非常相似,只是使用同一個(gè)遮罩圖像時(shí)谍珊,mask 與混合圖層的效果是相反的。Mask無(wú)法取消離屏渲染


例4

3. GroupOpacity

GroupOpacity

GroupOpacity 是指 CALayer 的allowsGroupOpacity屬性急侥,UIView 的alpha屬性等同于 CALayer opacity屬性砌滞。開(kāi)啟 GroupOpacity 后,子 layer 在視覺(jué)上的透明度的上限是其父 layer 的opacity坏怪。

從 iOS 7 以后默認(rèn)全局開(kāi)啟了這個(gè)功能贝润,這樣做是為了讓子視圖與其容器視圖保持同樣的透明度。

GroupOpacity 開(kāi)啟離屏渲染的條件是:layer.opacity != 1.0并且有子 layer 或者背景圖铝宵。

例5

4. shadow

陰影直接合成在視圖的下面打掘,視圖結(jié)構(gòu)里并沒(méi)有多出一個(gè)視圖。在沒(méi)有指定陰影路徑時(shí)鹏秋,陰影是沿著視圖的非透明部分?jǐn)U展的尊蚁,而且 CALayer 的三個(gè)視覺(jué)元素至少有一個(gè)存在時(shí)才會(huì)有陰影。
使用陰影必須保證 layer 的masksToBounds = false侣夷,因此陰影與系統(tǒng)圓角不兼容横朋。但是注意,只是在視覺(jué)上看不到百拓,對(duì)性能的影響依然琴锭。


例6

如果我們?cè)谠O(shè)置陰影時(shí)晰甚,給陰影指定了路徑,就不會(huì)觸發(fā)離屏渲染了
例如决帖,這樣設(shè)置陰影:

    self.view1.layer.shadowColor = [UIColor greenColor].CGColor;
    self.view1.layer.shadowOffset = CGSizeMake(5, 5);
    self.view1.layer.shadowOpacity = 0.5;
    self.view1.layer.shadowRadius = 3;
    UIBezierPath * path = [UIBezierPath bezierPathWithRect:self.view1.bounds];
    self.view1.layer.shadowPath = path.CGPath;
例7
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末厕九,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子地回,更是在濱河造成了極大的恐慌扁远,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件落君,死亡現(xiàn)場(chǎng)離奇詭異穿香,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)绎速,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門皮获,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人纹冤,你說(shuō)我怎么就攤上這事洒宝。” “怎么了萌京?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵雁歌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我知残,道長(zhǎng)靠瞎,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任求妹,我火速辦了婚禮乏盐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘制恍。我一直安慰自己父能,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布净神。 她就那樣靜靜地躺著何吝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鹃唯。 梳的紋絲不亂的頭發(fā)上爱榕,一...
    開(kāi)封第一講書(shū)人閱讀 51,231評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音坡慌,去河邊找鬼呆细。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的絮爷。 我是一名探鬼主播趴酣,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼坑夯!你這毒婦竟也來(lái)了岖寞?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤柜蜈,失蹤者是張志新(化名)和其女友劉穎仗谆,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體淑履,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡隶垮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秘噪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狸吞。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖指煎,靈堂內(nèi)的尸體忽然破棺而出蹋偏,到底是詐尸還是另有隱情,我是刑警寧澤至壤,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布威始,位于F島的核電站,受9級(jí)特大地震影響像街,放射性物質(zhì)發(fā)生泄漏黎棠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一镰绎、第九天 我趴在偏房一處隱蔽的房頂上張望脓斩。 院中可真熱鬧,春花似錦跟狱、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至叼丑,卻和暖如春关翎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鸠信。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工纵寝, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人星立。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓爽茴,卻偏偏與公主長(zhǎng)得像葬凳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子室奏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354