diff options
author | Akemi <der.richter@gmx.de> | 2018-03-21 21:09:05 +0100 |
---|---|---|
committer | Kevin Mitchell <kevmitch@gmail.com> | 2018-03-25 16:24:23 -0700 |
commit | 965ba23303d980c239e2b0191488766cfa7b0f75 (patch) | |
tree | 752b6823e0668bf8eb4fbf4ef6aee10c2fe47591 | |
parent | 9975835bdeec3f2b04b136ef40c70b02487bb0e6 (diff) |
cocoa-cb: render on a dedicated dispatch queue
we rendered on the displaylink thread which wasn't the best idea. if
rendering took too long or was blocking it also blocked the displaylink
callback. when that happened new vsyncs were reported delayed or not at
all. consequently the mpv_render_context_report_swap function wasn't
called consistently and that could cause bad video playback. so the
rendering is moved to a dedicated dispatch queue. furthermore the update
callback starts a layer update directly instead of the displaylink
callback, making the rendering a bit more consistent.
-rw-r--r-- | video/out/cocoa-cb/video_layer.swift | 51 | ||||
-rw-r--r-- | video/out/cocoa-cb/window.swift | 6 | ||||
-rw-r--r-- | video/out/cocoa_cb_common.swift | 7 |
3 files changed, 36 insertions, 28 deletions
diff --git a/video/out/cocoa-cb/video_layer.swift b/video/out/cocoa-cb/video_layer.swift index 51d14f84a3..2e347ba22e 100644 --- a/video/out/cocoa-cb/video_layer.swift +++ b/video/out/cocoa-cb/video_layer.swift @@ -27,21 +27,22 @@ class VideoLayer: CAOpenGLLayer { } let videoLock = NSLock() + let displayLock = NSLock() var hasVideo: Bool = false - var neededFlips: Int = 0 + var needsFlip: Bool = false + var canDrawOffScreen: Bool = false var cglContext: CGLContextObj? = nil var surfaceSize: NSSize? enum Draw: Int { case normal = 1, atomic, atomicEnd } var draw: Draw = .normal - var canDrawOffScreen: Bool = false - var lastThread: Thread? = nil + let queue: DispatchQueue = DispatchQueue(label: "io.mpv.queue.draw") var needsICCUpdate: Bool = false { didSet { if needsICCUpdate == true { - neededFlips += 1 + update() } } } @@ -51,6 +52,7 @@ class VideoLayer: CAOpenGLLayer { if inLiveResize { isAsynchronous = true } + update() } } @@ -92,9 +94,8 @@ class VideoLayer: CAOpenGLLayer { pixelFormat pf: CGLPixelFormatObj, forLayerTime t: CFTimeInterval, displayTime ts: UnsafePointer<CVTimeStamp>?) { - neededFlips = 0 - canDrawOffScreen = Thread.current == lastThread - lastThread = Thread.current + needsFlip = false + canDrawOffScreen = true draw(ctx) } @@ -197,36 +198,42 @@ class VideoLayer: CAOpenGLLayer { let updateCallback: mpv_render_update_fn = { (ctx) in let layer: VideoLayer = MPVHelper.bridge(ptr: ctx!) - layer.neededFlips += 1 + layer.update() } override func display() { + displayLock.lock() + let isUpdate = needsFlip super.display() CATransaction.flush() + if isUpdate { + if !cocoaCB.window.occlusionState.contains(.visible) && + needsFlip && canDrawOffScreen + { + CGLSetCurrentContext(cglContext!) + draw(cglContext!) + } else if needsFlip { + update() + } + } + displayLock.unlock() } func setVideo(_ state: Bool) { videoLock.lock() hasVideo = state - neededFlips = 0 videoLock.unlock() } - func reportFlip() { - mpv.reportRenderFlip() - videoLock.lock() - if !isAsynchronous && neededFlips > 0 && hasVideo { - if !cocoaCB.window.occlusionState.contains(.visible) && - neededFlips > 1 && canDrawOffScreen - { - CGLSetCurrentContext(cglContext!) - draw(cglContext!) - display() - } else { - display() + func update() { + queue.async { + self.videoLock.lock() + if !self.inLiveResize && self.hasVideo { + self.needsFlip = true + self.display() } + self.videoLock.unlock() } - videoLock.unlock() } } diff --git a/video/out/cocoa-cb/window.swift b/video/out/cocoa-cb/window.swift index b296eb25c8..b3db7aeb8f 100644 --- a/video/out/cocoa-cb/window.swift +++ b/video/out/cocoa-cb/window.swift @@ -305,7 +305,7 @@ class Window: NSWindow, NSWindowDelegate { } isAnimating = false - cocoaCB.layer.neededFlips += 1 + cocoaCB.layer.update() cocoaCB.checkShutdown() } @@ -316,7 +316,7 @@ class Window: NSWindow, NSWindowDelegate { endAnimation() isInFullscreen = true cocoaCB.flagEvents(VO_EVENT_FULLSCREEN_STATE) - cocoaCB.layer.neededFlips += 1 + cocoaCB.layer.update() } func setToWindow() { @@ -327,7 +327,7 @@ class Window: NSWindow, NSWindowDelegate { endAnimation() isInFullscreen = false cocoaCB.flagEvents(VO_EVENT_FULLSCREEN_STATE) - cocoaCB.layer.neededFlips += 1 + cocoaCB.layer.update() } func getFsAnimationDuration(_ def: Double) -> Double{ diff --git a/video/out/cocoa_cb_common.swift b/video/out/cocoa_cb_common.swift index e8d8bb44f4..659f9f84ce 100644 --- a/video/out/cocoa_cb_common.swift +++ b/video/out/cocoa_cb_common.swift @@ -86,7 +86,7 @@ class CocoaCB: NSObject { } else { layer.setVideo(true) updateWindowSize() - layer.neededFlips += 1 + layer.update() } } @@ -150,7 +150,7 @@ class CocoaCB: NSObject { flagsOut: UnsafeMutablePointer<CVOptionFlags>, displayLinkContext: UnsafeMutableRawPointer?) -> CVReturn in let ccb: CocoaCB = MPVHelper.bridge(ptr: displayLinkContext!) - ccb.layer.reportFlip() + ccb.mpv.reportRenderFlip() return kCVReturnSuccess } @@ -160,7 +160,7 @@ class CocoaCB: NSObject { CVDisplayLinkSetCurrentCGDisplay(link!, displayId) if #available(macOS 10.12, *) { CVDisplayLinkSetOutputHandler(link!) { link, now, out, inFlags, outFlags -> CVReturn in - self.layer.reportFlip() + self.mpv.reportRenderFlip() return kCVReturnSuccess } } else { @@ -454,6 +454,7 @@ class CocoaCB: NSObject { func shutdown(_ destroy: Bool = false) { setCursorVisiblility(true) + layer.setVideo(false) stopDisplaylink() uninitLightSensor() removeDisplayReconfigureObserver() |