最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

iOS離屏渲染過程示例解析

 更新時間:2023年08月21日 14:16:52   作者:奶茶大叔  
這篇文章主要為大家介紹了iOS離屏渲染過程示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

界面渲染

UIView繼承自UIResponder,可以處理系統(tǒng)傳遞過來的事件,如:UIApplication、UIViewController、UIView,以及所有從UIView派生出來的UIKit類。每個UIView內(nèi)部都有一個CALayer提供內(nèi)容的繪制和顯示,并且作為內(nèi)部RootLayer的代理視圖。

下圖為CALayer的結(jié)構(gòu)圖:

RunLoop有一個60fps的回調(diào),即每16.7ms繪制一次屏幕,所以view的繪制必須在這個時間內(nèi)完成,view內(nèi)容的繪制是CPU的工作,然后把繪制的內(nèi)容交給GPU渲染,包括多個View的拼接(Compositing)、紋理的渲染(Texture)等等,最后顯示在屏幕上。但是,如果無法是16.7ms內(nèi)完成繪制,就會出現(xiàn)丟幀的問題,一般情況下,如果幀率保證在30fps以上,界面卡頓效果不明顯,那么就需要在33.4ms內(nèi)完成View的繪制,而低于這個幀率,就會產(chǎn)生卡頓的效果,影響體驗。

渲染的過程

UIView的layer層有一個content,指向一塊緩存,即backing store
UIView繪制時,會調(diào)用drawRect方法,通過context將數(shù)據(jù)寫入backing store
在backing store寫完后,通過render server交給GPU去渲染,將backing store中的bitmap數(shù)據(jù)顯示在屏幕上

渲染的過程

ios離屏渲染

On-Screen Rendering:當前屏幕渲染,指的是 GPU 的渲染操作是在當前用于顯示的屏幕緩沖區(qū)中進行
Off-Screen Rendering:離屏渲染,分為 CPU 離屏渲染和 GPU 離屏渲染兩種形式。GPU 離屏渲染指的是 GPU 在當前屏幕緩沖區(qū)外新開辟一個緩沖區(qū)進行渲染操作

為什么會使用離屏渲染

當使用圓角,陰影,遮罩的時候,圖層屬性的混合體被指定為在未預合成之前不能直接在屏幕中繪制,所以就需要屏幕外渲染被喚起。

GPU 離屏渲染的代價是很大的
離屏渲染之所以會特別消耗性能,是因為要創(chuàng)建一個屏幕外的緩沖區(qū),然后從當屏緩沖區(qū)切換到屏幕外的緩沖區(qū),然后再完成渲染;其中,創(chuàng)建緩沖區(qū)和切換上下文最消耗性能,而繪制其實不是性能損耗的主要原因。

上下文之間的切換這個過程的消耗會比較昂貴,涉及到 OpenGL的 pipeline 跟 barrier,而且 offscreen-render 在每一幀都會涉及到,因此處理不當肯定會對性能產(chǎn)生一定的影響。另外由于離屏渲染會增加 GPU 的工作量,可能會導致 CPU+GPU 的處理時間超出 16.7ms,導致掉幀卡頓。

離屏渲染的場景和優(yōu)化

圓角優(yōu)化

方法一:

一般情況下我們會用這個方法去設置圓角:

iv.layer.cornerRadius = 30;
iv.layer.masksToBounds = YES;

使用cornerRadius進行切圓角,在iOS9之前會產(chǎn)生離屏渲染,比較消耗性能,而之后系統(tǒng)做了優(yōu)化,則不會產(chǎn)生離屏渲染,但是操作最簡單

方法二:

利用mask設置圓角,利用的是UIBezierPath和CAShapeLayer來完成

CAShapeLayer *mask = [[CAShapeLayer alloc] init];
mask1.opacity = 0.3;
mask1.path = [UIBezierPath bezierPathWithOvalInRect:iv.bounds].CGPath;
iv.layer.mask = mask;

方法三:

利用CoreGraphics畫一個圓形上下文,然后把圖片繪制上去,得到一個圓形的圖片

- (UIImage *)drawCircleImage:(UIImage*)image
{
    CGFloat side = MIN(image.size.width, image.size.height);
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(side, side), false, [UIScreen mainScreen].scale);
    CGContextAddPath(UIGraphicsGetCurrentContext(), [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, side, side)].CGPath);
    CGContextClip(UIGraphicsGetCurrentContext());
    CGFloat marginX = -(image.size.width - side) * 0.5;
    CGFloat marginY = -(image.size.height - side) * 0.5;
    [image drawInRect:CGRectMake(marginX, marginY, image.size.width, image.size.height)];
    CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

三種方法里面,方法三是性能最好的。

當然了,直接讓美工畫一個圓角的圖效率是最高的。

shadow優(yōu)化

我們可以通過設置shadowPath來優(yōu)化性能,能大幅提高性能

imageView.layer.shadowColor=[UIColorgrayColor].CGColor;
imageView.layer.shadowOpacity=1.0;
imageView.layer.shadowRadius=2.0;
UIBezierPath *path=[UIBezierPathbezierPathWithRect:imageView.frame];
imageView.layer.shadowPath=path.CGPath;

組不透明

開啟CALayer的 allowsGroupOpacity 屬性后,子 layer 在視覺上的透明度的上限是其父 layer 的 opacity (對應UIView的 alpha ),并且從 iOS 7 以后默認全局開啟了這個功能,這樣做是為了讓子視圖與其容器視圖保持同樣的透明度。

所以,可以關閉 allowsGroupOpacity 屬性,按產(chǎn)品需求自己控制layer透明度。

關閉抗鋸齒

allowsEdgeAntialiasing屬性為YES(默認為NO)

離屏渲染的檢測

Instruments的Core Animation工具中有幾個和離屏渲染相關的檢查選項:

Color Offscreen-Rendered Yellow

開啟后會把那些需要離屏渲染的圖層高亮成黃色,這就意味著黃色圖層可能存在性能問題。

Color Hits Green and Misses Red

如果shouldRasterize被設置成YES,對應的渲染結(jié)果會被緩存,如果圖層是綠色,就表示這些緩存被復用;如果是紅色就表示緩存會被重復創(chuàng)建,這就表示該處存在性能問題了。

iOS版本上的優(yōu)化

iOS 9.0 之前UIimageView跟UIButton設置圓角都會觸發(fā)離屏渲染

iOS 9.0 之后UIButton設置圓角會觸發(fā)離屏渲染,而UIImageView里png圖片設置圓角不會觸發(fā)離屏渲染了,如果設置其他陰影效果之類的還是會觸發(fā)離屏渲染的。

善用離屏渲染

盡管離屏渲染開銷很大,但是當我們無法避免它的時候,可以想辦法把性能影響降到最低。優(yōu)化思路也很簡單:既然已經(jīng)花了不少精力把圖片裁出了圓角,如果我能把結(jié)果緩存下來,那么下一幀渲染就可以復用這個成果,不需要再重新畫一遍了。

CALayer為這個方案提供了對應的解法:shouldRasterize。一旦被設置為true,Render Server就會強制把layer的渲染結(jié)果(包括其子layer,以及圓角、陰影、group opacity等等)保存在一塊內(nèi)存中,這樣一來在下一幀仍然可以被復用,而不會再次觸發(fā)離屏渲染。有幾個需要注意的點:

shouldRasterize的主旨在于降低性能損失,但總是至少會觸發(fā)一次離屏渲染。如果你的layer本來并不復雜,也沒有圓角陰影等等,打開這個開關反而會增加一次不必要的離屏渲染
離屏渲染緩存有空間上限,最多不超過屏幕總像素的2.5倍大小
一旦緩存超過100ms沒有被使用,會自動被丟棄
layer的內(nèi)容(包括子layer)必須是靜態(tài)的,因為一旦發(fā)生變化(如resize,動畫),之前辛苦處理得到的緩存就失效了。如果這件事頻繁發(fā)生,我們就又回到了“每一幀都需要離屏渲染”的情景,而這正是開發(fā)者需要極力避免的。針對這種情況,Xcode提供了“Color Hits Green and Misses Red”的選項,幫助我們查看緩存的使用是否符合預期
其實除了解決多次離屏渲染的開銷,shouldRasterize在另一個場景中也可以使用:如果layer的子結(jié)構(gòu)非常復雜,渲染一次所需時間較長,同樣可以打開這個開關,把layer繪制到一塊緩存,然后在接下來復用這個結(jié)果,這樣就不需要每次都重新繪制整個layer樹了

什么時候需要CPU渲染

絕大多數(shù)情況下,得益于GPU針對圖形處理的優(yōu)化,我們都會傾向于讓GPU來完成渲染任務,而給CPU留出足夠時間處理各種各樣復雜的App邏輯。為此Core Animation做了大量的工作,盡量把渲染工作轉(zhuǎn)換成適合GPU處理的形式(也就是所謂的硬件加速,如layer composition,設置backgroundColor等等)。

但是對于一些情況,如文字(CoreText使用CoreGraphics渲染)和圖片(ImageIO)渲染,由于GPU并不擅長做這些工作,不得不先由CPU來處理好以后,再把結(jié)果作為texture傳給GPU。除此以外,有時候也會遇到GPU實在忙不過來的情況,而CPU相對空閑(GPU瓶頸),這時可以讓CPU分擔一部分工作,提高整體效率。

一個典型的例子是,我們經(jīng)常會使用CoreGraphics給圖片加上圓角(將圖片中圓角以外的部分渲染成透明)。整個過程全部是由CPU完成的。這樣一來既然我們已經(jīng)得到了想要的效果,就不需要再另外給圖片容器設置cornerRadius。另一個好處是,我們可以靈活地控制裁剪和緩存的時機,巧妙避開CPU和GPU最繁忙的時段,達到平滑性能波動的目的。

但要注意的是:

渲染不是CPU的強項,調(diào)用CoreGraphics會消耗其相當一部分計算時間,并且我們也不愿意因此阻塞用戶操作,因此一般來說CPU渲染都在后臺線程完成(這也是AsyncDisplayKit的主要思想),然后再回到主線程上,把渲染結(jié)果傳回CoreAnimation。這樣一來,多線程間數(shù)據(jù)同步會增加一定的復雜度

同樣因為CPU渲染速度不夠快,因此只適合渲染靜態(tài)的元素,如文字、圖片(想象一下沒有硬件加速的視頻解碼,性能慘不忍睹)

作為渲染結(jié)果的bitmap數(shù)據(jù)量較大(形式上一般為解碼后的UIImage),消耗內(nèi)存較多,所以應該在使用完及時釋放,并在需要的時候重新生成,否則很容易導致OOM

如果你選擇使用CPU來做渲染,那么就沒有理由再觸發(fā)GPU的離屏渲染了,否則會同時存在兩塊內(nèi)容相同的內(nèi)存,而且CPU和GPU都會比較辛苦。

以上就是iOS離屏渲染過程示例解析的詳細內(nèi)容,更多關于iOS離屏渲染的資料請關注腳本之家其它相關文章!

相關文章

  • ios微信瀏覽器返回不刷新問題完美解決方法

    ios微信瀏覽器返回不刷新問題完美解決方法

    這篇文章主要介紹了ios微信瀏覽器返回不刷新問題完美解決方法,需要的朋友可以參考下
    2017-09-09
  • 詳解 swift3.0 可選綁定共用同一塊內(nèi)存空間的實例

    詳解 swift3.0 可選綁定共用同一塊內(nèi)存空間的實例

    這篇文章主要介紹了詳解 swift3.0 可選綁定共用同一塊內(nèi)存空間的實例的相關資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • iOS實現(xiàn)手勢滑動解鎖功能簡析

    iOS實現(xiàn)手勢滑動解鎖功能簡析

    本篇文章主要介紹了iOS實現(xiàn)手勢滑動解鎖功能簡析,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • iOS禁止所有輸入法表情的方法

    iOS禁止所有輸入法表情的方法

    這篇文章主要為大家詳細介紹了iOS禁止所有輸入法表情的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • IOS之UIWebView的使用(基本知識)

    IOS之UIWebView的使用(基本知識)

    在Android開發(fā)中有WebView作為混合模式開發(fā)的橋梁,當然在IOS中也同樣有一個 UIWebView 組件來作為混合模式開發(fā)的橋梁,那么下面就對UIWebView的一些基本知識詳解一下
    2016-02-02
  • Objective-C之Category實現(xiàn)分類示例詳解

    Objective-C之Category實現(xiàn)分類示例詳解

    這篇文章主要為大家介紹了Objective-C之Category實現(xiàn)分類示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • swift MD5加密源碼的實例詳解

    swift MD5加密源碼的實例詳解

    這篇文章主要介紹了swift MD5加密源碼的實例詳解的相關資料,希望通過本文能幫助到大家實現(xiàn)MD5加密,需要的朋友可以參考下
    2017-09-09
  • iOS導航欄控制的一些總結(jié)

    iOS導航欄控制的一些總結(jié)

    這篇文章主要給大家介紹了關于iOS導航欄控制的相關資料,文中通過示例代碼介紹的非常詳細,對各位iOS開發(fā)者們具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-07-07
  • IOS代碼筆記之勾選

    IOS代碼筆記之勾選"記住密碼"整體button

    這篇文章主要為大家詳細介紹了IOS實現(xiàn)勾選"記住密碼"整體button效果的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-07-07
  • iOS開發(fā)之數(shù)字每隔3位用逗號分隔

    iOS開發(fā)之數(shù)字每隔3位用逗號分隔

    以前在做電商app時經(jīng)常會針對稍大的金額展示出來,需要每隔千位添加逗號便于用戶識別,下面通過本文給大家分享ios中數(shù)字每隔3位用逗號分隔的實例代碼,需要的朋友參考下吧
    2017-09-09

最新評論

阿克陶县| 阿勒泰市| 巩义市| 海丰县| 铜陵市| 汕头市| 南川市| 天峨县| 锦屏县| 信宜市| 梁河县| 察雅县| 甘孜县| 上栗县| 乐都县| 宁海县| 博乐市| 兖州市| 抚顺市| 边坝县| 交口县| 婺源县| 探索| 广河县| 宝山区| 慈利县| 建阳市| 新龙县| 武安市| 南澳县| 方城县| 武邑县| 河津市| 龙南县| 克山县| 莱阳市| 庆元县| 石家庄市| 临泉县| 大石桥市| 会泽县|