【发布时间】:2015-12-01 00:02:28
【问题描述】:
在用于科学研究的 OS X 中,我们使用 NSOpenGLView 在第二个 LCD 显示器上渲染图形。如果我们将绘图代码放在 drawRect: 中并使用计时器驱动它,那效果很好。但是,我们需要更好地与帧速率同步,因此我们正在尝试迁移到 CVDisplayLink,如Apple Q&A 1385 中所述。
我们使用了该示例的清单 1 中的代码,除了调用 CVDisplayLinkCreateWithActiveCGDisplays() 之外,我们调用 CVDisplayLinkCreateWithCGDisplay() 并传入第二个 LCD 显示器的 ID。
我们已将绘图代码从 -drawRect: 移至一个新的 -draw 方法,该方法由我们的 CVDisplayLink 回调调用,如下面的代码所示。
我注意到 OS X 创建的不是一个而是 两个 线程,名为 CVDisplayLink。他们交替调用我们的回调。这正常吗?
随机地,在大约 10% 的帧上,我们的绘图代码创建的场景会根据需要出现在第二个 LCD 显示器上。对于其他 90% 的帧,此显示显示垃圾或纯白色,即使我认为我们正在回调中清除显示。
哦,我继承了这个项目,并且是 OpenGL 的新手,所以它可能非常简单,或者与我的描述完全无关。我会很感激任何线索。
- (void)prepareOpenGL
{
GLint swapInt = 1;
stimGLContext = [self openGLContext];
[stimGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
// Create a display link capable
CVDisplayLinkCreateWithCGDisplay(self.displayID, &displayLink);
// Set the renderer output callback function
CVDisplayLinkSetOutputCallback(
displayLink,
&MyDisplayLinkCallback,
(__bridge void *)(self));
// Set the display link for the current renderer
CGLContextObj cglContext = [[self openGLContext] CGLContextObj];
CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(
displayLink,
cglContext,
cglPixelFormat);
// Activate the display link
CVDisplayLinkStart(displayLink);
}
// Renderer output callback function
static CVReturn MyDisplayLinkCallback(
CVDisplayLinkRef displayLink,
const CVTimeStamp* now,
const CVTimeStamp* outputTime,
CVOptionFlags flagsIn,
CVOptionFlags* flagsOut,
void* displayLinkContext)
{
CVReturn result = [(__bridge StimulusGLView*)displayLinkContext getFrameForTime:outputTime];
return result;
}
- (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime
{
/* We are on a secondary "CVDisplayLink" thread here. */
NSOpenGLContext* context = [self openGLContext];
[context makeCurrentContext];
CGLLockContext([context CGLContextObj]);
[self draw] ;
CGLFlushDrawable([context CGLContextObj]);
CGLUnlockContext([context CGLContextObj]);
return kCVReturnSuccess;
}
- (void)draw
{
// Clear out and show a solid blue background
glClearColor((GLclampf)0, (GLclampf), (GLclampf).8, 0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
... more glXxxxx() drawing statements follow here
}
【问题讨论】: