初始化/同步 OpenGL for NSView 的正确方法



我按照Apple的文档创建了一个自定义的OpenGLView,而不是使用NSOpenGLView。绘图似乎很好,除了我似乎在这里有线程同步问题。由于 NSView 应该在主线程中,然后如何同步线程,我的意思是CADisplayLink似乎在不同的线程上工作,因此在旋转或缩放到 3D 场景后,一些节点会保持其旧转换(缓慢转换),直到旋转/缩放完成。但是如果我在显示链接绘制中使用dispatch_sync/dispatch_async似乎是正确的。但我不确定它会如何损害性能。

Q1:在显示链接cb中使用dispatch_sync是否正确?或者更好的选择是什么?

Q2:我也不是画全屏视图,会有可可控件或多个 opengl视图。由于主线程不专用于opengl,我不知道它如何影响FPS或可可控件。那么是否可以在单独的线程中运行 opengl 绘图操作?

对于缩放/旋转情况,我有一个解决方案,我正在向场景或节点添加一个标志(当缩放/旋转更改时),然后在渲染功能中我正在检查该标志然后应用转换。渲染/绘图似乎也是正确的。但这只是一种情况;将来还会有一些其他问题。所以我需要同步我认为的线程

CVReturn
displaylink_cb(CVDisplayLinkRef    CV_NONNULL  displayLink,
const CVTimeStamp * CV_NONNULL  inNow,
const CVTimeStamp * CV_NONNULL  inOutputTime,
CVOptionFlags                   flagsIn,
CVOptionFlags     * CV_NONNULL  flagsOut,
void              * CV_NULLABLE displayLinkContext) {
dispatch_sync(dispatch_get_main_queue(), ^{
[(__bridge GLView *)displayLinkContext renderOnce];
});
return kCVReturnSuccess;
}
- (void)syncWithCurrentDisplay {
NSOpenGLContext  *openGLContext;
CGLContextObj     cglContext;
CGLPixelFormatObj cglPixelFormat;
GLint             swapInt;
openGLContext = [self openGLContext];
swapInt       = 1;
/* Synchronize buffer swaps with vertical refresh rate */
[openGLContext setValues: &swapInt
forParameter: NSOpenGLCPSwapInterval];
/* Create a display link capable of being used with all active displays */
CVDisplayLinkCreateWithActiveCGDisplays(&m_displayLink);
/* Set the renderer output callback function */
CVDisplayLinkSetOutputCallback(m_displayLink,
display_link_cb,
(__bridge void *)self);
/* Set the display link for the current renderer */
cglContext     = [openGLContext CGLContextObj];
cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(m_displayLink,
cglContext,
cglPixelFormat);
}
- (void) renderOnce {
NSOpenGLContext *context;
context = [self openGLContext];
[context makeCurrentContext];
/* because display link is threaded */
CGLLockContext([context CGLContextObj]);
[[self delegate] render];
[context flushBuffer];
CGLUnlockContext([context CGLContextObj]);
}

OpenGL 渲染可以在任何线程上进行,只要一次只发生在一个线程上。仅仅因为您有 NSView 并不意味着您的上下文必须在主线程上呈现。

请参阅下面的示例。渲染是在显示链接的线程上完成的,除非在主线程上发生的视图帧更改通知期间,因此代码使用锁在主线程上呈现该帧(这实际上不是必需的,但如果这样做,锁将显示如何做到这一点)。

https://developer.apple.com/library/content/samplecode/GLFullScreen/Introduction/Intro.html

最新更新