我觉得我可能漏掉了什么。我已经创建了 NSOpenGLView
的子类,并尝试在 drawRect:
方法中绘制一个 CIImage
。
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
let start = CFAbsoluteTimeGetCurrent()
openGLContext!.makeCurrentContext()
let cglContext = openGLContext!.CGLContextObj
let pixelFormat = openGLContext!.pixelFormat.CGLPixelFormatObj
let colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB)!
let options: [String: AnyObject] = [kCIContextOutputColorSpace: colorSpace]
let context = CIContext(CGLContext: cglContext, pixelFormat: pixelFormat, colorSpace: colorSpace, options: options)
context.drawImage(inputImage, inRect: self.bounds, fromRect: input.extent)
openGLContext!.flushBuffer()
let end = CFAbsoluteTimeGetCurrent()
Swift.print("updated view in \(end - start)")
}
我显然错误地认为
NSOpenGLContext
(及其底层的CGLContext
)可以包装在CIContext
中,并且通过这种方式进行渲染可以在视图中生成图像。但是,尽管上述代码正在执行,我不知道实际像素最终会出现在哪里(因为视图最终为空白)。如果我只是获取当前的
NSGraphicsContext
并将其渲染到其中,那么我就可以在NSOpenGLView
中得到一张图片,但是渲染似乎需要花费约10倍的时间(即通过将CIContext
声明更改为以下内容): // Works, but is slow
let context = NSGraphicsContext.currentContext()!.CIContext!
我也尝试过这个方法,它既慢而且没有实际显示图片,所以是双重失败。
// Doesn't work. AND it's slow.
input.drawInRect(bounds, fromRect: input.extent, operation: .CompositeDestinationAtop, fraction: 1.0)
简单的解决方案是将其渲染为
CGImage
,然后通过CGImage -> NSImage
和NSImageView
或支持CALayer
的方式将其弹出到屏幕上。但对于我的情况来说,这并不够高效。在我的应用程序中,我想要渲染几十个缩略图大小的图像,每个图像都有自己不同的CIFilters
链,并在其基础图像更改时实时刷新它们。虽然它们每个都需要几毫秒的时间进行渲染(使用当前的CGImage-bracketed
路径),但视图更新仍然每秒只有几帧。我目前使用的路径类似于
CGImageRef -> CIImage -> 一堆CIFilters -> CGImage -> 分配给CALayer显示
。但似乎在渲染链的两端都使用CGImages
会影响性能。经过分析,大部分时间都花费在复制内存上,这可能是预期的,但并不高效。支持
CALayer
的后备CGImage
需要被传输到GPU,然后被过滤,然后作为CGImage
返回到主内存,然后(可能)立即回到GPU以被缩放并由CALayer
显示。理想情况下,在过滤之前,根图像将只停留在GPU上,并且结果将直接呈现到视频内存中,但我不知道如何实现这一点。我的当前渲染路径在GPU上进行了像素处理(这很棒!),但是在传输内存以实际显示它时被淹没了。那么,有人可以告诉我如何使用端到端的路径进行Core Image过滤吗?(或者至少只需要交换数据一次?)如果我有一个基于IOSurface的CIImage,我如何直接将其绘制到UI而不会影响主内存?有任何提示吗?