gpt4 book ai didi

objective-c - 将 CIImage 绘制到 NSOpenGLView(不访问主内存)

转载 作者:可可西里 更新时间:2023-10-31 23:44:16 28 4
gpt4 key购买 nike

我觉得我一定在这里遗漏了一些东西。我已将 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 中,而且渲染到其中将在 View 中生成图像。但是在上面的代码中完成工作时,我不知道实际像素在哪里结束(因为 View 最终是空白的)。

如果我只是抓取当前的 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 路径),但 View 更新仍然在每秒几帧的数量级。

我目前使用的路径看起来像 CGImageRef -> CIImage -> Bunch of CIFilters -> CGImage -> assign to CALayer for display。但在渲染链的两端使用 CGImages 似乎会降低性能。

分析后,似乎大部分时间都花在了复制内存上,我想这是预料之中的,但效率不高。支持 CGImage 需要传送到 GPU,然后过滤,然后作为 CGImage 返回到主内存,然后(大概)直接返回到 GPU由 CALayer 缩放和显示。理想情况下,根图像(在过滤之前)将仅位于 GPU 上,结果将直接呈现到视频内存中,但我不知道如何实现这一点。我当前的渲染路径在 GPU 上进行像素粉碎(这太棒了!),但被四处穿梭的内存所淹没以实际显示该死的东西。

那么谁能告诉我如何通过将事物端到端地保存在 GPU 上的途径来进行 Core Image 过滤? (或者至少只需要一次交换该数据?)如果我有一个 IOSurface 支持的 CIImage,我如何在不触及主内存的情况下将其直接绘制到 UI?有什么提示吗?

最佳答案

在为此苦苦思索了一天之后,NSOpenGLView 仍然没有成功...但是,我想我可以通过 CAOpenGLLayer< 做我想做的事 相反,这对我来说很好:

class GLLayer: CAOpenGLLayer {
var image: CIImage?

override func drawInCGLContext(ctx: CGLContextObj, pixelFormat pf: CGLPixelFormatObj, forLayerTime t: CFTimeInterval, displayTime ts: UnsafePointer<CVTimeStamp>) {
if image == nil {
let url = NSURL(fileURLWithPath: "/Users/doug/Desktop/test.jpg")
image = CIImage(contentsOfURL: url)!
}

let colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB)!
let options: [String: AnyObject] = [kCIContextOutputColorSpace: colorSpace]
let context = CIContext(CGLContext: ctx, pixelFormat: pf, colorSpace: colorSpace, options: options)
let targetRect = CGRectMake(-1, -1, 2, 2)
context.drawImage(image!, inRect: targetRect, fromRect: image!.extent)
}
}

请注意一件事 - CAOpenGLView 的坐标系不同。 View 为 2.0x2.0 单位,原点为 0,0(花了一些时间才弄明白)。除此之外,这与我最初问题中的非工作代码基本相同(除了,你知道,它实际上在这里工作)。也许 NSOpenGLView 类没有返回正确的上下文。谁知道。仍然对原因感兴趣,但至少我现在可以继续前进了。

关于objective-c - 将 CIImage 绘制到 NSOpenGLView(不访问主内存),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35078535/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com