OpenGL 无法在 macOS Mojave 上呈现

OpenGL not rendering on macOS Mojave

如果您在 macOS Mojave 上创建 NSView 和自定义 NSOpenGLContext,则 window 在调整大小之前不会被渲染。但如果您改用 NSOpenGLView ,一切都会正常。 我看到很多以编程方式调整 window 大小的 hacks (http://people.bath.ac.uk/abscjkw/ComputerPrograms/C++programs/OpenGL/MojaveOpenGL.cpp) before rendering into it or call [NSOpenGLContext update] twice (https://github.com/go-gl/glfw/pull/229/commits/9e6129a572227a13ff9acb4904443d2ae7d66e77),但它们看起来真的很 hacky 和不可靠。

我拆解了 Apple 的框架,发现它们改变了 OpenGL 在 Mojave 上的渲染方式。似乎即使您通过将 NSViewwantsLayer 设置为 NO 来禁用分层支持,NSView 仍然会创建一个图层并将其附加到您在 Mojave 上的视图。在渲染之前调整 window 的大小是可行的,因为这通常会导致调用 [NSOpenGLContext update]。调用更新两次是有效的,因为在第一帧 NSView 中没有附加层,更新方法只在第二帧上什么都不做,层在那里并且 [NSOpenGLContext update] 实际上初始化了帧缓冲区。

所以解决方法是在设置NSView层的时候手动调用[NSOpenGLContext update],像这样:

@interface OpenGLView: ViewMacOS
{
    NSOpenGLContext* _openGLContext;
}
@end

@implementation OpenGLView

-(void)setLayer:(CALayer*)layer
{
    [super setLayer:layer];

    [_openGLContext update];
}

@end

我测试了它,它在 Mojave 和旧版本的 macOS 上都有效([NSView setLayer:] 在 macOS 10.13 和旧版本上没有被调用)。这是我为 Ouzel 引擎所做的完整提交:https://github.com/elnormous/ouzel/commit/7e708636189d970bad6b013ecd5375cfe693f3f3

在手动管理 NSOpenGLContext 的 NSView 子类上,我需要调用 NSView.displayIfNeeded 而不是 NSView.display 来进行缓冲区交换。覆盖 NSView.setLayer 并调用 NSOpenGLContext.update 没有帮助。

请注意我的用法类似于 SDL,其中我使用自定义 运行 循环,因此海报程序中可能并非如此。

更新到 Mojave 10.14.3 和 Xcode 10.1 后,此问题已得到修复。