0

我正在开发一个由两个NSOpengGLViews (leftGLViewrightGLView) 并排放置在 NSWindow contentView 内的 OSX 应用程序。这两个视图不共享NSOpenGLContext但都是双缓冲的,并将缓冲区交换与监视器回溯同步。

ACVDisplayLink已设置并链接到第一个的NSOpenGLContextand (比如左侧)。NSOpenGLPixelFormatNSOpenGLView

在 CVDisplayLink 回调中,我使用以下代码绘制到两个视图:

-(CVReturn)draw {

     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

     CGLLockContext([[leftGLView openGLContext] CGLContextObj]);
     [[leftGLView openGLContext] makeCurrentContext];
     ... draw code ...
     [[leftGLView openGLContext] flushBuffer];
     CGLUnlockContext([[leftGLView openGLContext] CGLContextObj]);

     CGLLockContext([[rightGLView openGLContext] CGLContextObj]);
     [[rightGLView openGLContext] makeCurrentContext];
     ... draw code ...
     [[rightGLView openGLContext] flushBuffer];
     CGLUnlockContext([[rightGLView openGLContext] CGLContextObj]);

     [pool release];
     return kCVReturnSuccess;
}

这种方法的问题是两者flushBuffer并不总是同步的。右侧 NSOpenGLView 有时会比左侧更新晚(可能在下一次显示器刷新期间)。这并不完全出乎意料,因为苹果文档中关于-flushBuffer状态:

根据交换间隔上下文属性(参见 NSOpenGLCPSwapInterval),复制可能发生在监视器的垂直回溯期间,而不是在调用 flushBuffer 之后立即发生。一个隐式的 glFlush 在它返回之前由 flushBuffer 完成。为了获得最佳性能,应用程序不应在调用 flushBuffer 之前立即调用 glFlush。后续的 OpenGL 命令可以在调用 flushBuffer 后立即发出,但直到缓冲区复制完成后才会执行。

但是,在这种情况下,我有两个不同的NSOpenGLContext缓冲区,因此应该可以将两个缓冲区一起刷新。

为了进一步研究这一点,我假设-flushBuffer仅在交换(或复制)缓冲区后才返回,并且由于这仅与监视器回溯同步发生,因此对 flushBuffer 的第二次调用在该回溯上发生为时已晚。这可以解释我观察到的行为。因此,我尝试分离一个辅助线程来执行 flushBuffer 调用,但没有任何区别。

我终于尝试使用两种不同CVDisplayLink的 s,一种用于左侧 GLView,另一种用于右侧。然而,这种技术似乎也没有解决问题,并且增加了保持两个 CVDisplayLink 线程同步的额外复杂性。

有没有办法让这两个flushBuffer在两个 NSOpenGLViews 之间同步发生?

4

0 回答 0