I'm working on an OSX app that is made of two NSOpengGLView
s (leftGLView
and rightGLView
) placed side-by-side inside the NSWindow contentView.
The two views don't share the NSOpenGLContext
but are both double-buffered and sync the buffer swap with the monitor retrace.
A CVDisplayLink
is setup and linked to the NSOpenGLContext
and NSOpenGLPixelFormat
of the first NSOpenGLView
(say the left hand side one).
Inside the CVDisplayLink callback I draw to both views with the following code:
-(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;
}
The issue with that approach is that the two flushBuffer
are not always synchronized. The right hand side NSOpenGLView sometimes updates later than the left hand side (possibly during the next monitor refresh).
This is not fully unexpected as the Apple documention about -flushBuffer
states:
According to the swap interval context attribute (see NSOpenGLCPSwapInterval), the copy may take place during the vertical retrace of the monitor, rather than immediately after flushBuffer is called. An implicit glFlush is done by flushBuffer before it returns. For optimal performance, an application should not call glFlush immediately before calling flushBuffer. Subsequent OpenGL commands can be issued immediately after calling flushBuffer, but are not executed until the buffer copy is completed.
However, in this case I have two different NSOpenGLContext
therefore flushing two buffers together should be possible.
To further investigate this, I assumed that -flushBuffer
returns only after having swapped (or copied) the buffer and since this only happens in sync with the monitor retrace, the second call to flushBuffer would be too late to happen on that retrace. This could explain the behavior I'm observing.
Therefore I tried to detach an auxiliary thread to perform the flushBuffer calls but it made no difference.
I have finally tried to use two different CVDisplayLink
s, one for the left hand side GLView and the other for the right hand side one. However also this technique doesn't seem to solve the problem and adds the additional complication of keeping the two CVDisplayLink threads in sync.
Is there a way to have the two flushBuffer
happening in sync between the two NSOpenGLViews?