概述
大纲
CPU与GPU的职责和区别
计算机渲染原理
屏幕成像与卡顿
iOS下的渲染框架
View 与 CALayer 的关系
CoreAnimation渲染
CPU与GPU的职责和区别
CPU
运算核心、控制核心,资源调配,处理逻辑复杂的内容,相当于指挥者,依赖性高
架构:计算单元、控制单元、高级缓存
不是真正的并发,是时间片的快速切换
GPU
绘图运算的微处理器,GSLS语法,简单,不擅长处理逻辑复杂,跳转复杂,擅长单一,并行处理,类似于小工人,有很多的计算单元,真正的高并发,依赖性非常低的任务
架构:很多的计算单元,实现高并发,快速处理图像、视频计算
计算机渲染原理
计算机显示演变:
随机扫描显示:时间复杂度与图片复杂度成正比
光栅扫描显示:屏幕左上方,向右向后逐行横向扫描,和图像复杂度无关
渲染系统:
显示器(内容来自帧缓存区)
视频控制器(控制刷新的部件,负责帧缓存区与显示器的对应关系,进行显示绘制)
帧缓存区(双缓存、三缓存等) 帧缓存、显存(显示内存)
显存:存储处理后的渲染数据或即将显示的渲染数据
视觉暂留:一秒16帧,就会认为是连贯的,60帧是高清画质
渲染流程
系统总线把图片数据提交给CPU解码,CPU解码完拷贝一份解码数据给显示处理器,放在显示处理器存储器(显存)的帧缓存区,帧缓存区存放的是即将显示的渲染数据,显示控制器根据垂直同步Vsyn信号向帧缓存区获取渲染数据,然后提交给显示器显示
屏幕成像与卡顿
屏幕撕裂
img
显示控制器向帧缓存区获取渲染数据,从屏幕左上方,向右向后逐行横向扫描,然后提交给显示器,进行显示,当上一帧的渲染数据获取到了一半,帧缓存区完成新的渲染数据,显示控制器在帧缓存区获取到后半段的数据就是新的渲染数据,前一半是旧的渲染数据,后半段是新的渲染数据,最后提交给显示器显示,就会造成屏幕撕裂
如何防止屏幕撕裂?
垂直同步Vsync+双缓存:,垂直同步相当于加了一个锁,只有当当前渲染数据渲染完毕,才会继续渲染下一个新的渲染数据,防止屏幕撕裂,是以屏幕掉帧、卡顿为代价
三缓存区:合理使用CPU与GPU,减少掉帧的次数
什么是掉帧/卡顿?简单来说就是 屏幕重复显示同一帧数据的情况就是掉帧
如下图所示:当前屏幕显示的是A,显示控制器在收到垂直信号Vsync后,从帧缓存区获取渲染数据,由于CPU和GPU处理的B还没有准备好,帧缓存区的内容还是A,在帧缓存区拿到的还是A,所以最终,屏幕显示的仍然是A
img
View 与 CALayer 的关系
首先分别简单说下UIView和CALayer各自的作用
UIView
UIView属于UIKIt
负责绘制图形和动画操作
用于界面布局和子视图的管理
处理用户的点击事件
CALayer
CALayer属于CoreAnimation
只负责显示,且显示的是位图
CALayer既用于UIKit,也用于APPKit
UIKit是iOS平台的渲染框架,APPKit是Mac OSX系统下的渲染框架,
由于iOS和Mac两个系统的界面布局并不是一致的,iOS是基于多点触控的交互方式,而Mac OSX是基于鼠标键盘的交互方式,且分别在对应的框架中做了布局的操作,所以并不需要layer载体去布局,且不用迎合任何布局方式。
【面试题】UIView和CALayer的关系
UIView基于UIKit框架,可以处理用户触摸事件,并管理子视图
CALayer基于CoreAnimation,而CoreAnimation是基于QuartzCode的。所以CALayer只负责显示,不能处理用户的触摸事件
从父类来说,CALayer继承的是NSObject,而UIView是直接继承自UIResponder的,所以UIVIew相比CALayer而言,只是多了事件处理功能,
从底层来说,UIView属于UIKit的组件,而UIKit的组件到最后都会被分解成layer,存储到图层树中
在应用层面来说,需要与用户交互时,使用UIView,不需要交互时,使用两者都可以
UIView和CALayer的渲染
界面触发的方式有两种
通过loadView中子View的drawRect方法触发:会回调CoreAnimation中监听Runloop的BeforeWaiting的RunloopObserver,通过RunloopObserver来进一步调用CoreAnimation内部的CA::Transaction::commit(),进而一步步走到drawRect方法
用户点击事件触发:唤醒Runloop,由source1处理(__IOHIDEventSystemClientQueueCallback),并且在下一个runloop里由source0转发给UIApplication(_UIApplicationHandleEventQueue),从而能通过source0里的事件队列来调用CoreAnimation内部的CA::Transaction::commit();方法,进而一步一步的调用drawRect。
最终都会走到CoreAnimation中的CA::Transaction::commit()方法,从而来触发UIView和CALayer的渲染
这时,已经到了CoreAnimation的内部,即调用CA::Transaction::commit();来创建CATrasaction,然后进一步调用 CALayer drawInContext:()
回调CALayer的Delegate(UIView),问UIView没有需要画的内容,即回调到drawRect:方法
在drawRect:方法里可以通过CoreGraphics函数或UIKit中对CoreGraphics封装的方法进行画图操作
将绘制好的位图交由CALayer,由OpenGL ES 传送到GPU的帧缓冲区
等屏幕接收到垂直信号后,就读取帧缓冲区的数据,显示到屏幕上
iOS下的渲染框架
CoreGraphics
CoreAnimation
CoreImage
不论是CoreGraphics、CoreAnimation还是CoreImage,最终都是通过OpenGL ES或者OpenGL Metal驱动GPU进行干活渲染绘制
CoreAnimation渲染
img
CoreAnimation过程:
Application处理Handle Event各种事件
Commit Transaction提交事务给Render Server渲染服务
Render Server进行解码,在下一个RunLoop到来的时候进行绘制
OpenGL
绘制提交给OpenGL来处理
通过OpenGL驱动GPU干活
GPU拿到顶点数据传给顶点着色器
顶点着色器后进行图元装配
图元装配完进行光栅化
光栅化获取到像素范围,把颜色附着到像素点上去
然后把数据传给片元着色器
最后进行屏幕显示
最后
以上就是自然跳跳糖为你收集整理的计算机显示渲染原理,二、OpenGL了解渲染原理的全部内容,希望文章能够帮你解决计算机显示渲染原理,二、OpenGL了解渲染原理所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复