summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkemi <der.richter@gmx.de>2018-03-21 21:09:05 +0100
committerKevin Mitchell <kevmitch@gmail.com>2018-03-25 16:24:23 -0700
commit965ba23303d980c239e2b0191488766cfa7b0f75 (patch)
tree752b6823e0668bf8eb4fbf4ef6aee10c2fe47591
parent9975835bdeec3f2b04b136ef40c70b02487bb0e6 (diff)
downloadmpv-965ba23303d980c239e2b0191488766cfa7b0f75.tar.bz2
mpv-965ba23303d980c239e2b0191488766cfa7b0f75.tar.xz
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.swift51
-rw-r--r--video/out/cocoa-cb/window.swift6
-rw-r--r--video/out/cocoa_cb_common.swift7
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()