2016-01-29 30 views
3

我觉得我必须在这里丢失一些东西。我已经分类NSOpenGLView,我试图在drawRect:调用中画一个CIImage将CIImage绘制成NSOpenGLView(没有碰到主内存)

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声明此IE):

// 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,和TH en弹出到屏幕上(通过CGImage -> NSImage,然后NSImageView,或支持CALayer)。但是这对我的情况来说不够高效。在我的应用程序中,我正在寻找渲染几十个缩略图大小的图像,每个图像都有自己的不同链CIFilters,并随着底层基础图像的更改而实时刷新它们。虽然它们每个都在几毫秒内呈现(使用我当前的路径),但视图更新仍然是每秒几帧的数量级。

我目前有一个类似于CGImageRef -> CIImage -> Bunch of CIFilters -> CGImage -> assign to CALayer for display的路径。但似乎在渲染链的两端有CGImages正在查杀性能。

分析后,似乎大部分时间都花在了复制内存的周围,我认为这是预期的,但效率不高。支持CGImage需要穿梭到GPU,然后过滤,然后返回主存储器作为CGImage,然后(大概)直接返回到GPU以缩放并显示CALayer。理想情况下,根图像(在过滤之前)只能放在GPU上,结果会直接呈现给视频内存,但我不知道如何完成此操作。我目前的渲染路径是在GPU上进行像素粉碎(这真是太棒了!),但是通过穿梭存储器来实际显示所摧毁的东西而淹没了它。

因此,任何人都可以启发我如何做核心图像过滤与保持在GPU端到端的事情的途径? (或者至少只需要将数据交换一次?)如果我有一个IOSurface支持的CIImage,那么如何直接将UI绘制到UI而不碰到主内存?任何提示?

回答

0

敲我的头靠在这个墙上,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的坐标系统是不同的。视图是2.0x2.0单位,原点为0,0(花了一段时间才算出来)。除此之外,这与我原来的问题中的非工作代码基本相同(除了,你知道,它实际上在这里工作)。也许NSOpenGLView类没有返回正确的上下文。谁知道。仍然对为什么感兴趣,但至少我现在可以继续。

0

代码应与下列补充/修改工作:

var ciContext: CIContext! 

override func drawRect(dirtyRect: NSRect) { 
    super.drawRect(dirtyRect) 
    let start = CFAbsoluteTimeGetCurrent() 

    openGLContext!.makeCurrentContext() 
    let cglContext = openGLContext!.CGLContextObj 
    let attr = [ 
     NSOpenGLPixelFormatAttribute(NSOpenGLPFAAccelerated), 
     NSOpenGLPixelFormatAttribute(NSOpenGLPFANoRecovery), 
     NSOpenGLPixelFormatAttribute(NSOpenGLPFAColorSize), 32, 
     0 
    ] 
    let pixelFormat = NSOpenGLPixelFormat(attributes: attr) 
    let colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB)! 
    let options: [String: AnyObject] = [kCIContextOutputColorSpace:colorSpace, kCIContextWorkingColorSpace:colorSpace] 
    ciContext = CIContext(CGLContext: cglContext, pixelFormat: pixelFormat!.CGLPixelFormatObj, colorSpace: colorSpace, options: options) 
    glClearColor(0.0, 0.0, 0.0, 0.0) 
    glClear(GLbitfield(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) 
    // setup viewing projection 
    glMatrixMode(GLenum(GL_PROJECTION)) 
    // start with identity matrix 
    glLoadIdentity(); 

    // Create an image 
    let image = NSImage(contentsOfFile: "/Users/kuestere/Pictures/DSCI0004.JPG") 
    let imageData = image?.TIFFRepresentation! 
    let ciImage = CIImage(data: imageData!) 
    if (ciImage == nil) { 
     Swift.print("ciImage loading error") 
    } 
    let imageFrame = ciImage!.extent 
    let viewFrame = self.visibleRect 
    // setup a viewing world left, right, bottom, top, zNear, zFar 
    glOrtho(0.0, Double(viewFrame.width), 0.0, Double(viewFrame.height), -1.0, 1.0); 
    ciContext.drawImage(ciImage!, inRect: self.visibleRect, fromRect: imageFrame) 
    glFlush(); 
    let end = CFAbsoluteTimeGetCurrent() 
    Swift.print("updated view in \(end - start)") 
} 
+1

这将有助于解释的原代码所做的任何更改,以及他们为什么被做了。 – miken32