如何从CVDisplayLink回调中绘制到NSView图形上下文?

时间:2011-06-19 20:09:11

标签: cocoa macos quartz-2d

我有一个简单的游戏,它将2D图形渲染到帧缓冲区(不使用任何OpenGL)。我打算使用CVDisplayLink来获得干净的帧速率,但网上的大多数示例都涉及OpenGL或QuickTime。

到目前为止,我有一个NSView的子类:

@interface GameView : NSView {
@private
    CVDisplayLinkRef displayLink;
}

- (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime;
@end

我设置了CVDisplayLink回调:

CVDisplayLinkSetOutputCallback(displayLink, MyDisplayLinkCallback, self);

我有回调函数:

CVReturn MyDisplayLinkCallback (CVDisplayLinkRef displayLink,
                                const CVTimeStamp *inNow,
                                const CVTimeStamp *inOutputTime,
                                CVOptionFlags flagsIn,
                                CVOptionFlags *flagsOut,
                                void *displayLinkContext)
{
    CVReturn error = [(GameView*)displayLinkContext getFrameForTime:inOutputTime];

    return error;
}

我遇到的部分是在getFrameForTime:中要做什么来绘制GameView中的图形上下文。我的第一个猜测是以与drawRect:

相同的方式进行绘图
- (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime
{
    CGContextRef ctxCurrent = [[NSGraphicsContext currentContext] graphicsPort];

    //.. Drawing code follows
}

ctxCurrentnil我认为我理解 - 通常会在drawRect:之前发生一些设置,使您的视图成为当前上下文。我认为这是我缺少的部分。如何获取我的观点的上下文?

或者我是否以错误的方式解决这个问题?

2 个答案:

答案 0 :(得分:2)

您可以将您的绘图代码保留在‑drawRect:中,然后在MyDisplayLinkCallback()中将ivar设置为当前时间,并在您的视图上调用‑display。这会强制您的视图立即重绘。

‑drawRect:方法中,只需使用时间ivar的值来执行为当前动画帧更新视图所需的任何绘图。

答案 1 :(得分:0)

您应该创建一个单独的-draw:方法,并从MyDisplayLinkCallback()-drawRect:调用该方法。

我根据自己的喜好找到了Rob Keniger的response并试了一下;遗憾的是,如果你从你的显示链接回拨-display回调你的应用程序可能会在你终止应用程序时陷入僵局,让你强行退出应用程序(对我而言,这种情况经常发生)。