图层支持NSOpenGLView +动画计时器=奇怪的绘图行为



我正在创建一个子类NSOpenGLView的应用程序来做一些OpenGL绘图。现在我想添加一个覆盖控件,类似于QuickTime x。我尝试的第一件事是将NSOpenGLCPSurfaceOrder设置为-1,并使我的窗口不透明。它确实有效,但我失去了窗口的阴影,所以不是一个可行的解决方案。

然后我通过调用[setWantsLayer:YES]并添加我的控制框作为子视图,使我的NSOpenGLView子类层支持。它是有效的,但我注意到性能有很大的下降。我做了一些研究,发现了这个:

我使用一个NSTimer对象每秒调用方法[timerFired:] 60次。完美的工作。我在这个方法中做的唯一一件事是调用[self setNeedsDisplay:YES],因为当使用层支持的OpenGLView时,需要重载[drawRect:rect]方法并在那里做所有的OpenGL绘图。问题:[drawRect:rect]经常被调用,尽管定时器没有触发。

起初我想"它当然会,它会绘制NSOpenGLView,所以它可能会被窗口管理器或其他东西调用"因此,删除了我的计时器对象,以确定它是如何在[timerFired:]调用之间调用的。结果是:它根本不会被调用,至少在不调整窗口大小或拖动窗口时不会被调用。

所以接下来我试验了我的定时器的时间间隔。结果表明,在每秒55次之前,[drawRect:rect]每秒被调用60到70次,而从每秒59次的计时器间隔开始,[drawRect:rect]每秒被调用100到120次。

我怀疑这种高度不可预测的方式,我的绘图被称为导致性能损失,要么是不均匀的,要么是通过阻塞线程与大量的OpenGL绘图,没有足够的时间来执行或其他东西。我也读到图层支持的OpenGLViews不与vsync一起工作,尽管我不能确认这一点。

有人能解释一下吗?有没有人对如何只画我的OpenGL定时器火灾的想法?

我已经尝试了朴素的方法,并添加了一个布尔变量,在我的[timerFired:]中设置为真,并使我的[drawRect:rect]仅在变量为真时调用OpenGL绘图方法。结果是一个非常闪烁和断断续续的动画,所以不走运。

如何使用CAOpenGLLayer与异步动画顺序CVDisplayLink?两者都有帮助吗?

edit另一件事可能是有用的信息:我已经使用[setNeedsDisplay:YES]没有我的视图是层支持,所以我可以很容易地切换层支持和非层支持,我没有上面描述的任何问题,所以它肯定与我的视图是层支持有关。只要调用[setWantsLayer:YES],一切都会变得一团糟。

所以我用CVDisplayLink替换了我的NSTimer对象,一切又顺利了。虽然我也不明白为什么。似乎请求一个支持层打破了垂直同步,但它并没有解释随机调用drawRect出现无处。

我也想如果vsync工作与一个层支持NSOpenGLView和/或CAOpenGLLayer。我找不到任何官方信息。

最新更新