Ios 如何将CIContext drawImage:inRect:fromRect:与CADisplayLink一起使用

Ios 如何将CIContext drawImage:inRect:fromRect:与CADisplayLink一起使用,ios,objective-c,cocoa-touch,core-image,Ios,Objective C,Cocoa Touch,Core Image,: 。。在iOS 6上,此方法是异步的 因此,如果我在一个应用程序中使用它,它会遇到一个问题,因为它将以60fps的速度不断启动异步绘图,而实际绘图可能无法跟上 - (void) displayLinkDidFire:(CADisplayLink *)displatLink; { CFTimeInterval duration = [displatLink duration]; CGFloat fps = round (1.0 / duration); NSLog(@"%

:

。。在iOS 6上,此方法是异步的

因此,如果我在一个应用程序中使用它,它会遇到一个问题,因为它将以60fps的速度不断启动异步绘图,而实际绘图可能无法跟上

- (void) displayLinkDidFire:(CADisplayLink *)displatLink;
{
    CFTimeInterval duration = [displatLink duration];
    CGFloat fps = round (1.0 / duration);
    NSLog(@"%f fps", fps); // Always logs 60 fps since drawImage is async

    // This method is fast since a CIImage is just a 'recipe' for an image
    CIImage * result = [Helper generateCIImage];

    // This drawing is unable to keep up with the calls to the displayLinkDidFire method
    [self.ciContext drawImage:result
                       inRect:self.destFrame
                     fromRect:self.targetFrame];
}
我如何回避这个问题


编辑-更多信息

我正在使用CoreImage和
EAGLContext
(根据WWDCs获得更好的绘图性能)


解决方案是使用“OpenGL ES渲染循环”,而不是尝试使用
CADisplayLink
构建一个循环。幸运的是,这很容易,因为a自动执行此操作:

GLKViewController类提供所有标准视图控制器功能,但还实现了OpenGL ES渲染循环

唯一不好的一面是,这将您与使用
GLKViewController
紧密联系在一起,而不是仅仅将
GLKView
添加到现有的UIView。要解决这个问题,您需要了解如何实现自己的OpenGL ES渲染循环

// The GLKViewController automatically calls this method
- (void) updateScreen
{        
    CIImage * result = [Helper generateCoreImage];

    // Clears the screen to a grey color 
    glClearColor(0.5, 0.5, 0.5, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

    [self.ciContext drawImage:result
                       inRect:self.destFrame
                     fromRect:self.targetFrame];

    // `display` needs to be called here according to the docs.
    GLKView *view = (GLKView *)self.view;
    [view display];
}

通常,显示链接将执行它所需的操作,然后调用
setNeedsDisplay
通知视图刷新。这不会导致任何异步计时问题。@Rob我认为显示链接不会调用
-setNeedsDisplay
。它独立于标准的
-drawRect:
视图更新周期工作。@Rob-感谢您的评论。我在我的设备上获得了大约0.5 fps的可视速度,而displayLink的速度是60 fps,所以我认为异步是问题所在。你是说drawImage是异步的,或者我应该使用非
CADisplayLink
的东西来触发绘图,这不重要吗?@Robert你要么需要加快绘图速度,要么降低刷新率以适应绘图速度,要么需要跳过帧。如果绘制图像需要2秒钟,则CADisplayLink对您没有多大用处。您还可以使用while()循环。根据您的更新,我建议在开始渲染之前,使用图像数据加载适当的OpenGL纹理。从文件加载到内存中,然后复制到帧缓冲区可能太慢了。@BoredAstronaut同意,它不会自动调用
setNeedsDisplay
,但在制作自己的动画时,通常使用
CADisplayLink
处理程序调用
setNeedsDisplay
。显示链接调用的频率将自动匹配动画的FPS。
// The GLKViewController automatically calls this method
- (void) updateScreen
{        
    CIImage * result = [Helper generateCoreImage];

    // Clears the screen to a grey color 
    glClearColor(0.5, 0.5, 0.5, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

    [self.ciContext drawImage:result
                       inRect:self.destFrame
                     fromRect:self.targetFrame];

    // `display` needs to be called here according to the docs.
    GLKView *view = (GLKView *)self.view;
    [view display];
}