圖像顯示原理
顯示器顯示出來(lái)的圖像是經(jīng)過(guò)CRT電子槍一行一行的掃描,掃描出來(lái)就呈現(xiàn)了一幀畫(huà)面华匾,隨后電子槍又會(huì)回到初始位置循環(huán)掃描映琳。為了讓顯示器的顯示跟視頻控制器同步,當(dāng)電子槍新掃描一行的時(shí)候瘦真,會(huì)發(fā)送一個(gè)水平同步信號(hào)(HSync信號(hào))刊头。顯示器一般是固定刷新頻率的,這個(gè)刷新的頻率其實(shí)就是行同步信號(hào)產(chǎn)生的頻率诸尽。然后CPU計(jì)算好幀等屬性原杂,就將計(jì)算好的內(nèi)容提交給GPU去渲染,GPU渲染完成之后就會(huì)放入幀緩沖區(qū)您机,然后視頻控制器會(huì)按照行同步信號(hào)逐行讀取幀緩沖區(qū)的數(shù)據(jù)穿肄,經(jīng)過(guò)可能的數(shù)模轉(zhuǎn)換傳遞給顯示器。就顯示出來(lái)了际看。
iOS設(shè)備通常是60fps(每秒60幀)咸产,也就是說(shuō)兩幀相隔的時(shí)間是1/60秒,大概16.7ms仲闽。在這16.7ms中脑溢,為了顯示一幀,需要如下工作:
- CPU計(jì)算好各個(gè)視圖的位置赖欣,大小屑彻,對(duì)圖片進(jìn)行解碼等,繪制成紋理交給GPU
- GPU對(duì)收到的紋理進(jìn)行混合顶吮,頂點(diǎn)變換社牲,渲染到幀緩沖區(qū)
- 每16.7ms,一個(gè)時(shí)鐘信號(hào)到達(dá),幀緩沖區(qū)取出一幀悴了,顯示到屏幕搏恤。
基礎(chǔ)概念
渲染通常分為CPU和GPU渲染兩種违寿,而GPU渲染又分為在GPU緩沖區(qū)和非緩沖區(qū)兩種:
- CPU渲染(軟件渲染),CPU繪制成bitmap熟空,交給GPU
- GPU渲染(硬件渲染)
- 屏幕渲染(GPU緩沖區(qū)渲染)藤巢,指的是GPU的渲染操作是在當(dāng)前用于顯示的屏幕緩沖區(qū)進(jìn)行。
- 離屏渲染(非GPU緩沖區(qū)渲染)痛阻,指的是在GPU在當(dāng)前屏幕緩沖區(qū)以外開(kāi)辟一個(gè)緩沖區(qū)進(jìn)行渲染操作菌瘪。
離屏渲染的代價(jià)很高腮敌,想要進(jìn)行離屏渲染阱当,首選要?jiǎng)?chuàng)建一個(gè)新的緩沖區(qū),屏幕渲染會(huì)有一個(gè)上下文環(huán)境的一個(gè)概念糜工,離屏渲染的整個(gè)過(guò)程需要切換上下文環(huán)境弊添,先從當(dāng)前顯示幕切換到離屏,等結(jié)束后捌木,又要將上下文環(huán)境切換回來(lái)油坝。這也是為什么會(huì)消耗性能的原因了。
由于垂直同步的機(jī)制刨裆,如果在一個(gè)HSync時(shí)間內(nèi)澈圈,CPU或GPU沒(méi)有完成內(nèi)容提交,則那一幀就會(huì)被丟棄帆啃,等待下一次機(jī)會(huì)再顯示瞬女,而這時(shí)顯示屏?xí)A糁暗膬?nèi)容不變。也就是說(shuō)努潘,CPU或者GPU被大量占用的時(shí)候诽偷,都有可能在16.7ms中沒(méi)辦法完成一幀的繪制,導(dǎo)致時(shí)鐘信號(hào)到來(lái)的時(shí)候疯坤,取得還是上一幀的內(nèi)容报慕。這就是界面卡頓的原因。
為什么離屏渲染這么耗性能压怠,為什么有這套機(jī)制呢眠冈?
比如當(dāng)使用圓角,陰影菌瘫,遮罩的時(shí)候蜗顽,圖層屬性的混合體被指定為在未預(yù)合成之前(下一個(gè)HSync信號(hào)開(kāi)始前)不能直接在屏幕中繪制,所以就需要屏幕外渲染突梦。
離屏渲染也不是一定會(huì)引起性能問(wèn)題诫舅,而且是很少會(huì),比如drawRect這個(gè)方法宫患,只會(huì)在時(shí)圖進(jìn)行重新繪制的時(shí)候才會(huì)調(diào)用刊懈。也就是說(shuō),假如你的View并不會(huì)頻繁重繪,那么即使實(shí)現(xiàn)了drawRect虚汛,也沒(méi)什么關(guān)系匾浪。
哪些操作會(huì)觸發(fā)離屏渲染?
包括:
Layer具有Mask(遮罩)卷哩,比如圓角蛋辈、Shadow、漸變
group opacity(不透明)
edge antialiasing(邊緣抗鋸齒)
Layer的光柵化shouldRasterize為T(mén)rue
用CoreGraphics的CGContext繪制的
在drawRect中繪制的将谊,即使drawRect是空的
文本(UILabel冷溶,UITextfield,UITextView尊浓,CoreText逞频,UITextLayer等)
?栋齿?測(cè)試發(fā)現(xiàn)倒角和文本并沒(méi)有觸發(fā)離屏渲染
是iOS系統(tǒng)做了優(yōu)化苗胀?還是手機(jī)硬件性能提升?
概念介紹
光柵化:將圖轉(zhuǎn)化為一個(gè)個(gè)柵格組成的圖像瓦堵。
光柵化特點(diǎn):每個(gè)元素對(duì)應(yīng)幀緩沖區(qū)中的一像素基协。
shouldRasterize = YES在其它屬性觸發(fā)離屏渲染的同時(shí),會(huì)將光柵化后的內(nèi)容緩存起來(lái)菇用,如果對(duì)應(yīng)的layer或者sublayers沒(méi)有發(fā)生改變澜驮,在下一幀的時(shí)候可以直接復(fù)用,從而減少渲染的頻率刨疼。
當(dāng)使用光柵化是泉唁,可以開(kāi)啟“Color Hits Green and Misses Red”來(lái)檢查該場(chǎng)景下是否適合選擇光柵化,綠色表示緩存被復(fù)用揩慕,紅色表示緩存在被重復(fù)創(chuàng)建亭畜。對(duì)于經(jīng)常變動(dòng)的內(nèi)容,不要開(kāi)啟迎卤,否則會(huì)造成性能的浪費(fèi)拴鸵。
彩色混合層
屏幕上的每個(gè)像素點(diǎn)的顏色是由當(dāng)前像素點(diǎn)上的多層層(如果存在)共同決定的,GPU會(huì)進(jìn)行計(jì)算出混合顏色的RGB值蜗搔,最終顯示在屏幕上劲藐。而這需要讓GPU計(jì)算,所以我們要盡量避免設(shè)置alpha樟凄,這樣GPU會(huì)忽略下面所有的layer聘芜,節(jié)約計(jì)算量。再提一下opaque這個(gè)屬性缝龄,網(wǎng)上普遍認(rèn)為view.opaque = YES汰现,GPU就不會(huì)進(jìn)行圖層混合計(jì)算了挂谍。這個(gè)結(jié)論是錯(cuò)誤的,其實(shí)view.opaque事實(shí)上并沒(méi)什么卵用瞎饲。
如果你真的想達(dá)到這個(gè)效果口叙,可以用layer.opaque,這個(gè)才是正確的做法