iOS面试题:离屏渲染及UIView的渲染机制

本文深入探讨了计算机渲染原理,CPU与GPU在图片处理中的角色,以及UI视图的渲染机制。讲解了卡顿的原因、图片渲染流程,特别关注了离屏渲染现象,指出设置cornerRadius可能导致离屏渲染。同时,详细阐述了UIView的渲染流程,包括从提交待处理任务到屏幕显示的整个过程。最后,通过实例展示了如何触发drawRect方法并解释了drawRect中获取图形上下文的重要性。
摘要由CSDN通过智能技术生成

一 首先要了解计算机的渲染原理

1.CPU:图片的解码、显示等

2.GPU:人脸识别、编码音视频,进行一些复杂的计算。

3.得到像素信息,然后显示到屏幕上,像素信息缓存到物理屏幕上。

  • CPU通过一系列的计算,然后GPU去渲染,通过帧缓存之后被视频控制器读取,最后显示到屏幕上。成像的原理是通过水平同步信号+垂直同步信号一帧帧的绘制而成。
  • 卡顿的原因:由于CPU要先计算-GPU渲染,假如CPU/GPU处理的事情较多,在固定的帧率下,未完成需要处理的事情,此时垂直同步信号已经到来,两者交叉就会造成视觉上的卡顿
  • 图片渲染的过程:以图片为例,顶点着色器:几何处理单元;光栅化:确定图片在屏幕上有哪些像素点需要填充;片元着色器:往屏幕上的颜色点进行填充。
  • CoreAnimation:渲染流水线:布局计算,Render Server图片解码,等待下一个loop执行Draw call。CP拿到位图、着色器进行绘制。

离屏渲染:对于前后依赖的图层,需要重新开辟一个空间,用于临时渲染,渲染完成后,在渲染到当前的缓冲区,这个叫临时渲染,也可以理解为离屏渲染。(多个图层重组)

设置cornerRadius 一定会触发离屏渲染吗?

记住原理:如果只是一个图层的话,是不会造成离屏渲染的,当出现多图片情况,因为GPU需要一个图层一个图层的绘制,最后合成一个图层。这种情况会造成离屏渲染。

二,UIView的渲染机制

/*

   当在操作 UI 时,比如改变了 Frame、更新了 UIView/CALayer 的层次时,或者手动调用了 UIView/CALayer 的 setNeedsLayout/setNeedsDisplay方法后,这个 UIView/CALayer 就被标记为待处理,并被提交到一个全局的容器去。

   苹果注册了一个 Observer 监听 BeforeWaiting(即将进入休眠) 和 Exit (即将退出Loop) 事件,回调去执行一个很长的函数:

   _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv()。这个函数里会遍历所有待处理的 UIView/CAlayer 以执行实际的绘制和调整,并更新 UI 界面。

   这个函数内部的调用栈大概是这样的:

   _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv()

   QuartzCore:CA::Transaction::observer_callback:

   CA::Transaction::commit();

   CA::Context::commit_transaction();

   CA::Layer::layout_and_display_if_needed();

   CA::Layer::layout_if_needed();

   [CALayer layoutSublayers];

   [UIView layoutSubviews];

   CA::Layer::display_if_needed();

   [CALayer display];

   [UIView drawRect];

   */

//    程序启动 UIApplicationMain()主线程:我是UI线程不能停,Runloop来和我一起吧。MainRunloop create and run MainRunloop:我想睡觉了,observer,你那边有事吗?observer:我去检查一下_ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv()我去看看 图层树中有没有待处理的对象有没有?CPU:我在更新图层树,一会交给Core Animation运走Core Animation:把待处理的图层对象 通过IPC发送到渲染服务进程GPU:渲染服务进程开始渲染工作GPU:Compositing\Offscreen Rendering 展示到屏幕 告诉runloop 让它睡会吧。有东西,我在叫你observer。yesno

    

   XZZView *view = [[XZZView alloc] init];

   view.backgroundColor = [UIColor whiteColor];

   view.bounds = CGRectMake(0, 0, 100, 100);

   view.center = CGPointMake(100, 100);

    //注释掉,则不调用drawRect,所以addSubview会触发drawInRect

    [self.view addSubview:view];

    //在调用drawInRect之前,先调用了[UIView(CALayerDelegate) drawLayer:inContext:] 和 [CALayer drawInContext:]

    //drawrect方法内为何第一行代码总要获取图形的上下文???

    

    /*

     每一个UIView都有一个layer,每一个layer都有个content,这个content指向的是一块缓存,叫做backing store

     当UIView被绘制时(从 CA::Transaction::commit:以后),CPU执行drawRect,通过context将数据写入backing store

     当backing store写完后,通过render server交给GPU去渲染,将backing store中的bitmap数据显示在屏幕上

     所以在 drawRect 方法中 要首先获取 context

     */

    

    //图像的绘制???

    /*

     CPU会为layer分配一块内存来绘制bitmap,叫作backing store

     layer创建指向这块bitmap缓存区的指针,叫作CGContextRef

     通过CoreGraphic的api 也叫Quartz2D绘制bitmap

     将layer的content指向生成的bitmap

     CGContextRef的创建过程就是CPU的工程过程

     CPU讲view变成了bitmap完成了自己的工作

     */

    //view渲染机制和GPU之间关系???

    /*

     GPU的处理单位是texture

     控制GPU都是通过OpenGL来完成的,从bitmap到texture之间是通过Core Animati衔接的

     

     */

    

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值