我有一个NSOpenGLView和OpenGL代码,可以在主循环中运行NSTimer(调用setNeedsDisplay和drawRect)。我想使用CVDisplayLink,所以我可以获得更好的帧速率而不会过度驱动定时器。我从apple的OSXGLEssentials示例中复制了大部分代码。显示链接启动并且回调运行,但实际上屏幕上没有任何内容。 glGetError返回GL_INVALID_FRAMEBUFFER_OPERATION。
glCheckFramebufferStatus为GL_FRAMEBUFFER,GL_DRAW_FRAMEBUFFER和GL_READ_FRAMEBUFFER返回GL_FRAMEBUFFER_UNDEFINED。
文档中的信息:
如果target是默认值,则返回GL_FRAMEBUFFER_UNDEFINED framebuffer,但默认的帧缓冲不存在。
以下是相关的代码:
- (void)awakeFromNib {
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, // Core Profile !
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFAAllowOfflineRenderers,
0
};
NSOpenGLPixelFormat *format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:format shareContext: nil];
// [context setView: self];
[self setPixelFormat: format];
[self setOpenGLContext: context];
}
- (void)prepareOpenGL {
[super prepareOpenGL];
NSOpenGLContext* context = [self openGLContext];
[context makeCurrentContext];
// Synchronize buffer swaps with vertical refresh rate
GLint swapInt = 1;
[context setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
MyDisplay_setup();
MyDisplay_initScene(_bounds.size.width, _bounds.size.height);
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
CVDisplayLinkSetOutputCallback(displayLink, &displayLinkCallback, (__bridge void *)self);
CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [context CGLContextObj], cglPixelFormat);
CVDisplayLinkStart(displayLink);
}
static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime,
CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) {
@autoreleasepool {
[(__bridge MyView*)displayLinkContext redraw];
}
return kCVReturnSuccess;
}
- (void)redraw {
NSOpenGLContext* context = [self openGLContext];
[context makeCurrentContext];
CGLLockContext([context CGLContextObj]);
MyDisplay_drawScene();
CGLFlushDrawable([context CGLContextObj]);
CGLUnlockContext([context CGLContextObj]);
}
答案 0 :(得分:1)
这是一个老问题,但这个问题仍然存在,所以这就是我的答案。作为参考,我根本不使用Xcode,我在Vim中编写代码并使用Clang编译,因此这是默认行为,与IB无关。我只使用NSOpenGLView,NSOpenGLContext和CGDisplayLink进行渲染。我有一台运行macOS Sierra的MacBook Pro(Retina,15英寸,2014年中)。
调试时我发现NSOpenGLContext的view属性在启动显示链接后的前几帧中返回nil。如果在视图未附加的情况下进行任何渲染(除glClear之外),这足以破坏上下文,并导致相同的GL_FRAMEBUFFER_UNDEFINED错误。
我发现解决这个问题的最简单方法是在创建之后将NSOpenGLView分配给它的NSOpenGLContext:
NSOpenGLView *view = ...;
view.openglContext.view = view;
我很困惑,显然,即使NSOpenGLContext是由NSOpenGLView创建的,但仍然需要这样做,但它确实如此。
答案 1 :(得分:0)
诀窍是打开View Effects检查器并取消选中Core Animation Layer部分中的父View。