我是macOS开发的新手。
目前,我正在使用第三方库实施NSOpenGLView
。
update
函数是来自库的回调函数,将在新帧到达时调用。由于预计会立即返回,因此应该异步调用绘图。DispatchQueue.main.async()
但是我发现它会阻止主线程,例如调整容器窗口大小时不会有动画。所以我创建了一个用于绘图的调度队列。(更新:仅在启用双缓冲时才会出现问题)
func update() {
videoView.glQueue.async {
videoView.drawRect()
}
}
class VideoView: NSOpenGLView {
lazy var glQueue: DispatchQueue = DispatchQueue(label: "gl", attributes: .serial)
override func draw(_ dirtyRect: NSRect) {
self.drawRect()
}
func drawRect() {
openGLContext?.lock()
openGLContext?.makeCurrentContext()
doDrawing()
openGLContext?.flushBuffer()
openGLContext?.unlock()
}
}
我尝试了几种解决方案。
videoView.drawRect()
调用将完全阻止调整大小。update()
或draw()
将消除故障,但UI线程仍然非常慢,并且调整大小不稳定。class VideoView: NSOpenGLView {
override func update() {
// lock with NSLock / lock the context
super.update()
// unlock
}
}
window.inLiveResize
,如果为真则停止呼叫videoView.drawRect()
。调整大小时,会自动调用draw()函数。这种方法适用于非常平滑的调整大小,但是当暂停拖动时,视图将冻结,因为LiveResize事件未完成。func update() {
if !(videoView.window!.inLiveResize) {
videoView.glQueue.async {
videoView.drawRect()
}
}
}
我终于找到了解决方法,但它仍然不完善,我确定它不是正确的方向。
请建议我是否以正确的方式执行此操作,或者更好地解决绘制而不阻止UI 的解决方案/最佳做法。谢谢!