在iOS系统中,CALayer位图(即CGImage对象)如何显示到显卡上?

5
在iOS上,我能够创建3个CGImage对象,并使用60fps的CADisplayLink进行操作。
self.view.layer.contents = (__bridge id) imageArray[counter++ % 3];

ViewController内部,每次都会将图像设置为视图的CALayer contents,这是一个位图。仅凭这一点就可以改变屏幕显示的内容。屏幕将以60fps循环显示这3个图像。没有UIView的drawRect,也没有CALayer的displaydrawInContext或CALayer代理的drawLayerInContext。它所做的就是更改CALayer的contents
我还尝试向self.view.layer添加一个较小的子层,并设置该子层的contents。那个子层将循环显示这3个图像。
因此,这与旧日的Apple ][甚至King's Quest III时代非常相似,这些都是DOS视频游戏,在那里只有1个位图,屏幕只会不断显示该位图。
除了这次不是1个位图,而是一棵树或位图的链接列表,图形卡不断使用画家模型将这些位图(带有位置和不透明度)绘制到主屏幕上。因此,似乎drawRect、CALayer和所有其他东西都是为了实现这个最终目的而设计的。
它是如何工作的?图形卡是否接受有序的位图列表或位图树?(然后不断显示它们。为简化起见,我们不考虑CA框架中的隐式动画)在图形卡处理层下实际发生了什么?(实际上,在iOS、Mac OS X和PC上,这种方法几乎相同吗?)
(本问题旨在了解我们的图形编程实际上是如何在现代图形卡中呈现的,因为例如,如果我们需要了解UIView以及CALayer的工作原理,甚至直接使用CALayer的位图,我们确实需要了解图形体系结构。)
2个回答

5
现代显示库(例如iOS和Mac OS中使用的Quartz)使用硬件加速合成。其工作原理与计算机图形库(如OpenGL)非常相似。实质上,每个CALayer都被保留为单独的表面,由视频硬件缓冲和渲染,就像3D游戏中的纹理一样。这在iOS中得到了极好的实现,这就是为什么iPhone以具有流畅用户界面而闻名的原因。
在“旧时代”(即Windows 9x,Mac OS Classic等),屏幕本质上是一个大的帧缓冲区,每个应用程序必须手动重新绘制移动窗口等所暴露的所有内容。重新绘制主要由CPU完成,这限制了动画性能的上限。由于涉及重新绘制,动画通常非常“闪烁”。这种技术大多适用于没有太多动画的桌面应用程序。值得注意的是,Android使用(或至少曾经使用)这种技术,这在将iOS应用程序移植到Android时是一个大问题。
过去的游戏(如DOS,街机等)在Mac OS经典版上也经常使用一种称为精灵动画的东西来提高性能并减少闪烁,通过将移动图像保留在屏幕外缓冲区中,并由硬件渲染并与监视器的垂直消隐同步,从而使动画即使在非常低端的系统上也是流畅的。但是,这些图像的大小非常有限,屏幕分辨率很低,仅约为今天iPhone屏幕的10-15%。

3
你的直觉很合理,但是在“contents”和显示之间仍有几个步骤。首先,“contents”不一定是“CGImage”,通常是一个名为“CABackingStorage”的私有类,它不完全相同。在许多情况下,存在硬件优化以绕过将图像渲染到主内存,然后将其复制到视频内存。由于各种图层的“contents”都被合成在一起,您仍然需要距离“真正”的显示内存有一段距离。更不用说,对“contents”的修改只会直接影响模型层,而不是表现或渲染层。此外,可以在视频内存中直接存储其图像的“CGLayer”对象也存在。有许多不同的东西正在发生。
因此,答案是否定的,“视频卡”(芯片;顺便说一句,这是PowerVR)不会接受排序好的一堆图层。它采用低级数据的方式,这些方式没有得到很好的文档记录。一些东西(尤其是Core Animation的一部分,以及可能是CGLayer)似乎是OpenGL纹理的包装器,但其他东西可能是Core Graphics直接访问硬件本身。一旦到达此堆栈的这个级别,所有内容均为私有内容,并且可能会因版本和设备而改变。
你也可能会发现Brad Larson的回答在这里很有用:iOS: is Core Graphics implemented on top of OpenGL? 你还可能对iOS:PTL的第6章感兴趣。虽然它没有涉及实现细节,但它包括了大量关于如何提高绘图性能以及如何更好地利用Core Graphics硬件的实际讨论。第7章详细介绍了CALayer绘制所涉及的所有开发者可访问步骤。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接