V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
jox0
V2EX  ›  iDev

请问 UIView 是怎么渲染自己的?

  •  
  •   jox0 · 2017-02-10 21:40:55 +08:00 · 3055 次点击
    这是一个创建于 2624 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如果不用 drawRect ,也不用 CALayer 的 contents 属性,一个 UIView 要怎么渲染自己的内容?比如一个背景颜色为黄色的、尺寸 100x100 的 UIView ,其中背景颜色使用 UIView 的 backgroundColor 或者 layer 的 backgroundColor 来设置。这个 UIView 的 layer 的 backing store bitmap data 是怎么生成的?
    第 1 条附言  ·  2017-02-13 11:20:11 +08:00
    根据已知的各种文档和 wwdc 视频,所有的 UIView 都是 layer backed ,所有的 layer 都会缓存一份 bitmap ,如果开发者不实现 drawRect ,也不使用 layer 的 contents 属性来为 layer 提供内容,那么 Core Animation 会使用内部的 drawing path ,这个内部的 drawing path 是使用硬件加速的,我很好奇在这种情况下 Core Animation 内部会怎么做。 apple 提供的 API 里可以把 UIView 的 layer 类型切换为 CAEAGLLayer ,这样就可以使用 OpenGL ES 来绘制 layer 的内容,比直接使用 OpenGL ES 绘图的 set up 过程要简单一些,我非常好奇 Core Animation 内部的实现是否与此类似,与直接使用 CAEAGLLayer 有什么不同
    5 条回复    2017-06-19 17:12:20 +08:00
    ningcool
        1
    ningcool  
       2017-02-13 11:10:25 +08:00
    1: UIView 无法渲染自己, UIView 是 CALayer 的一个包装,并实现了交互操作。
    2: 对 UIView 的创建,属性的设置,绘制都是默认调用了 CALayer 的属性和实现,并且禁用了 CALayer 的隐式动画,智能在 UIView 的 animation block 中设置属性才会有动画效果......
    3: CALayer 是 QuartzCore 框架中实现的,其本质是内存中的位图。 QuartzCore 又是 Core Foundation 框架下的, Core Foundation 框架底层是原始的 OpenGL 绘图。所以,这些绘制离不开 OpenGl 和 GPU 。

    4: backing store bitmap data :位图可以存储图片的每一个像素点的信息,其中就是颜色值,通过编辑这些颜色实现 CALayer 的颜色。其他叠加,混合等可能是更复杂的 GPU 处理了。。
    jox0
        2
    jox0  
    OP
       2017-02-13 11:13:59 +08:00
    @ningcool 非常感谢,您说的这些我都了解,我就是想知道 “这些绘制离不开 OpenGL 和 GPU ” 这部分的技术细节,请问您是否了解?
    ningcool
        3
    ningcool  
       2017-02-16 12:15:00 +08:00   ❤️ 1
    @jox0 我也只是了解一些宏观感念,没专门搞过: 计算机图形 基础就是 OpenGL 实现的算法逻辑,并在 GPU 实现计算渲染,最后输出屏幕。那么,界面上的图形控件肯定是封装了底层逻辑。至于 OpenGL 是怎么绘制图形的: 1 : 算法(算法很多,自己可以去了解一些)实现路径,计算像素点区域等(比如圆角路径,阴影路径,颜色等)。 2: 交给 GPU 处理路径填充,颜色渲染等,这些计算后的值需要映射到内存中,并输出屏幕。 不对的可以指出哈!!
    jox0
        4
    jox0  
    OP
       2017-02-16 12:55:41 +08:00
    @ningcool 3Q~ 我用了我的一张 RTI ,这两天正在通过邮件询问 Apple 的一个工程师这方面的问题,过两天如果有答案我再来这里更新
    jox0
        5
    jox0  
    OP
       2017-06-19 17:12:20 +08:00
    已经过去半年了,这段时间我学习了一下 opengl 绘图,想起来还有这么个帖子

    当时苹果的工程师也没有给太多具体的技术细节,只是提到了最终 Core Animation 会 issue OpenGL drawing command 来生成最终的 bitmap。

    随着新一代的绘图 API 的出现,现在 Core Animation 的底层很可能不再使用 OpenGL,而转而使用苹果新推出的 Metal。不过这都不重要,重要的是我当初提出的这个问题。

    对于一个 UIView,如果不提供 bitmap (设置 layer 的 contents 属性),也不实现 drawRect 或者 CALayer drawing 的那几个 draw 函数,那么一个 UIView 的内容会根据这个 UIView 的状态( backgroundColor,bounds,其实都是 layer 的状态),提交到 render server,并由 render server 调用底层的图形 API 来绘制这个 UIView 的内容,并将最终绘制的 bitmap 结果通过类似 glReadPixels 的 API 从显寸上复制到 CPU 内存里,这部分内存由 CALayer 的内部私有变量来负责持有,这部分数据目前是无法直接获取到的,只能通过 CALayer 的 renderInContext:等 API 间接的取到,这里与 CALayer 的 contents 属性不同,contents 只是用来为一个 CALayer 提供内容的。

    所以一个 UIView 有三种方式来生成内容,分别是 drawRect:,设置 layer 的 contents 属性,设置 UIView 本身或者 layer 的属性,这三种方式最终内存占用是一模一样的,但是消耗的 CPU 和 GPU 资源却不同,第一种需要调用 CPU 绘图 API 来绘制图形,CPU bound ;第二种虽然不需要调用 CPU 来绘图,但是可能会使用 CPU 来解压缩图片文件,所以也是 CPU bound ;第三种 CPU 只负责必要的状态修改,由 GPU 来完成主要的绘图工作,因为 GPU 绘图效率比 CPU 高,所以这种方式应该是效率最高的,整体的性能消耗也最低,GPU bound
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4290 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 01:03 · PVG 09:03 · LAX 18:03 · JFK 21:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.