在iOS上,CALayer位图(CGImage对象)如何显示在显卡上



在iOS上,我能够创建3个CGImage对象,并使用60fps的CADisplayLink来做

self.view.layer.contents = (__bridge id) imageArray[counter++ % 3];

ViewController内,每次都会将图像设置为视图的 CALayer contents,即位图。

而这一切本身,可以改变屏幕显示的内容。 屏幕将以 3fps 的速度循环浏览这 60 张图像。 没有UIView的drawRect,没有CALayer的displaydrawInContext,或CALayer的代表drawLayerInContext。 它所做的只是改变CALayer的contents

我还尝试向self.view.layer添加一个较小尺寸的子图层,并改为设置该子图层的contents。 该子图层将在这 3 个图像中循环。

所以这与过去非常相似,甚至在苹果][甚至国王的任务III时代,这是DOS视频游戏,其中有1个位图,屏幕只是不断显示位图是什么。

除了这次,它不是 1 位图,而是一棵树或位图的链接列表,显卡不断使用画家模型将这些位图(具有位置和不透明度)绘制到主屏幕上。 所以看来,drawRect,CALayer,一切,都是为了达到这个最终目的而设计的。

是这样工作的吗? 图形卡是采用位图的有序列表还是位图树? (然后不断展示它们。 为了简化起见,我们不考虑 CA 框架中的隐式动画)显卡处理层实际上发生了什么? (实际上,这种方法在iOS,Mac OS X和PC上几乎相同吗?

(这个问题旨在了解我们的图形编程实际上是如何在现代图形卡中呈现的,因为例如,如果我们需要了解UIView和CALayer的工作原理,甚至直接使用CALayer的位图,我们确实需要了解图形体系结构。

现代显示库(如 iOS 和 Mac OS 中使用的 Quartz)使用硬件加速合成。其工作原理与OpenGL等计算机图形库的工作方式非常相似。从本质上讲,每个 CALayer 都保留为一个单独的表面,由视频硬件缓冲和渲染,就像 3D 游戏中的纹理一样。这在iOS中得到了非常好的实现,这就是为什么iPhone以流畅的UI而闻名的原因。

在"过去"(即Windows 9x,Mac OS Classic等)中,屏幕基本上是一个大的帧缓冲区,并且通过移动窗口等方式暴露的所有内容都必须由每个应用程序手动重绘。重绘主要由CPU完成,这限制了动画性能的上限。由于涉及重绘,动画通常非常"闪烁"。此技术主要适用于没有太多动画的桌面应用程序。值得注意的是,Android使用(或至少曾经使用)这种技术,这在将iOS应用程序移植到Android时是一个大问题。

过去的游戏(例如DOS,街机等,在Mac OS经典版上也大量使用),一种称为精灵动画的东西用于通过将运动图像保留在由硬件渲染并与显示器的vblank同步的屏幕外缓冲区中来提高性能并减少闪烁,这意味着即使在非常低端的系统上,动画也很流畅。然而,这些图像的尺寸非常有限,屏幕分辨率也很低,甚至只有当今iPhone屏幕像素的10-15%左右。

你有一个合理的直觉,但在contents和显示之间还有几个步骤。首先,contents不一定是CGImage。它通常是一个名为CABackingStorage的私人类,这并不完全相同。在许多情况下,正在进行硬件优化,以绕过将图像渲染到主内存,然后将其复制到视频内存。而且由于各个层的contents都是合成在一起的,因此您仍然与"真实"显示内存相去甚远。更不用说对contents的修改只会直接影响模型层,而不是表示层或渲染层。此外,还有CGLayer对象可以直接将其图像存储在视频内存中。有很多不同的事情正在发生。

所以答案是不,视频"卡"(芯片;它是PowerVR BTW)不需要一堆有序的层。它以未充分记录的方式获取较低级别的数据。有些东西(特别是核心动画的一部分,也许还有CGLayer)似乎是OpenGL纹理的包装器,但其他东西可能是核心图形直接访问硬件本身。一旦你到达堆栈的这个级别,它都是私有的,可以在版本之间以及设备之间更改。

你也可以在这里发现布拉德·拉尔森的回应很有用:iOS:Core Graphics是在OpenGL之上实现的吗?

您可能还对iOS:PTL的第6章感兴趣。虽然它没有涉及实现细节,但它确实包括许多关于如何提高绘图性能和最好地利用核心图形硬件的实际讨论。第7章详细介绍了CALayer绘图中涉及的所有开发人员可访问的步骤。

最新更新