1
mirror of https://github.com/mpv-player/mpv synced 2024-08-28 05:46:13 +02:00

cocoa-cb: use libmpv's advanced rendering control and timing

this adds support for GPU rendered screenshots, DR (theoretically) and
possible other advanced functions in the future that need to be executed
from the rendering thread.
additionally frames that would be off screen or not be displayed when on
screen are being dropped now.
This commit is contained in:
Akemi 2018-06-12 02:48:31 +02:00 committed by Jan Ekström
parent 317d3ac266
commit 9e466ee621
4 changed files with 41 additions and 33 deletions

View File

@ -36,6 +36,7 @@ class MPVHelper: NSObject {
var mpctx: UnsafeMutablePointer<MPContext>?
var macOpts: macos_opts?
var fbo: GLint = 1
let deinitLock = NSLock()
init(_ mpv: OpaquePointer) {
super.init()
@ -58,6 +59,7 @@ class MPVHelper: NSObject {
}
func initRender() {
var advanced: CInt = 1
let api = UnsafeMutableRawPointer(mutating: (MPV_RENDER_API_TYPE_OPENGL as NSString).utf8String)
var pAddress = mpv_opengl_init_params(get_proc_address: getProcAddress,
get_proc_address_ctx: nil,
@ -65,6 +67,7 @@ class MPVHelper: NSObject {
var params: [mpv_render_param] = [
mpv_render_param(type: MPV_RENDER_PARAM_API_TYPE, data: api),
mpv_render_param(type: MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, data: &pAddress),
mpv_render_param(type: MPV_RENDER_PARAM_ADVANCED_CONTROL, data: &advanced),
mpv_render_param()
]
@ -110,13 +113,26 @@ class MPVHelper: NSObject {
func reportRenderFlip() {
if mpvRenderContext == nil { return }
mpv_render_context_report_swap(mpvRenderContext)
mpv_render_context_report_swap(mpvRenderContext)
}
func drawRender(_ surface: NSSize) {
func isRenderUpdateFrame() -> Bool {
deinitLock.lock()
if mpvRenderContext == nil {
deinitLock.unlock()
return false
}
let flags: UInt64 = mpv_render_context_update(mpvRenderContext)
deinitLock.unlock()
return flags & UInt64(MPV_RENDER_UPDATE_FRAME.rawValue) > 0
}
func drawRender(_ surface: NSSize, skip: Bool = false) {
deinitLock.lock()
if mpvRenderContext != nil {
var i: GLint = 0
var flip: CInt = 1
var skip: CInt = skip ? 1 : 0
glGetIntegerv(GLenum(GL_DRAW_FRAMEBUFFER_BINDING), &i)
// CAOpenGLLayer has ownership of FBO zero yet can return it to us,
// so only utilize a newly received FBO ID if it is nonzero.
@ -129,6 +145,7 @@ class MPVHelper: NSObject {
var params: [mpv_render_param] = [
mpv_render_param(type: MPV_RENDER_PARAM_OPENGL_FBO, data: &data),
mpv_render_param(type: MPV_RENDER_PARAM_FLIP_Y, data: &flip),
mpv_render_param(type: MPV_RENDER_PARAM_SKIP_RENDERING, data: &skip),
mpv_render_param()
]
mpv_render_context_render(mpvRenderContext, &params);
@ -136,6 +153,7 @@ class MPVHelper: NSObject {
glClearColor(0, 0, 0, 1)
glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
}
deinitLock.unlock()
}
func setRenderICCProfile(_ profile: NSColorSpace) {
@ -258,8 +276,10 @@ class MPVHelper: NSObject {
func deinitRender() {
mpv_render_context_set_update_callback(mpvRenderContext, nil, nil)
mp_render_context_set_control_callback(mpvRenderContext, nil, nil)
deinitLock.lock()
mpv_render_context_free(mpvRenderContext)
mpvRenderContext = nil
deinitLock.unlock()
}
func deinitMPV(_ destroy: Bool = false) {

View File

@ -28,9 +28,8 @@ class VideoLayer: CAOpenGLLayer {
let videoLock = NSLock()
let displayLock = NSLock()
var hasVideo: Bool = false
var needsFlip: Bool = false
var canDrawOffScreen: Bool = false
var forceDraw: Bool = false
var cglContext: CGLContextObj? = nil
var cglPixelFormat: CGLPixelFormatObj? = nil
var surfaceSize: NSSize?
@ -53,7 +52,7 @@ class VideoLayer: CAOpenGLLayer {
if inLiveResize {
isAsynchronous = true
}
update()
update(force: true)
}
}
@ -91,7 +90,8 @@ class VideoLayer: CAOpenGLLayer {
if inLiveResize == false {
isAsynchronous = false
}
return mpv != nil && cocoaCB.backendState == .initialized
return mpv != nil && cocoaCB.backendState == .initialized &&
(forceDraw || mpv.isRenderUpdateFrame())
}
override func draw(inCGLContext ctx: CGLContextObj,
@ -99,11 +99,8 @@ class VideoLayer: CAOpenGLLayer {
forLayerTime t: CFTimeInterval,
displayTime ts: UnsafePointer<CVTimeStamp>?) {
needsFlip = false
canDrawOffScreen = true
draw(ctx)
}
forceDraw = false
func draw(_ ctx: CGLContextObj) {
if draw.rawValue >= Draw.atomic.rawValue {
if draw == .atomic {
draw = .atomicEnd
@ -135,7 +132,7 @@ class VideoLayer: CAOpenGLLayer {
}
func atomicDrawingStart() {
if draw == .normal && hasVideo {
if draw == .normal {
NSDisableScreenUpdates()
draw = .atomic
}
@ -225,33 +222,22 @@ class VideoLayer: CAOpenGLLayer {
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()
if isUpdate && needsFlip {
CGLSetCurrentContext(cglContext!)
if mpv.isRenderUpdateFrame() {
mpv.drawRender(NSZeroSize, skip: true)
}
}
displayLock.unlock()
}
func setVideo(_ state: Bool) {
videoLock.lock()
hasVideo = state
videoLock.unlock()
}
func update() {
func update(force: Bool = false) {
if force { forceDraw = true }
queue.async {
self.videoLock.lock()
if !self.inLiveResize && self.hasVideo {
if self.forceDraw || !self.inLiveResize {
self.needsFlip = true
self.display()
}
self.videoLock.unlock()
}
}

View File

@ -613,6 +613,12 @@ class Window: NSWindow, NSWindowDelegate {
cocoaCB.updateCusorVisibility()
}
func windowDidChangeOcclusionState(_ notification: Notification) {
if occlusionState.contains(.visible) {
cocoaCB.layer.update(force: true)
}
}
func windowWillMove(_ notification: Notification) {
isMoving = true
}

View File

@ -72,7 +72,6 @@ class CocoaCB: NSObject {
}
func uninit() {
layer.setVideo(false)
window.orderOut(nil)
}
@ -81,7 +80,6 @@ class CocoaCB: NSObject {
DispatchQueue.main.sync { self.initBackend(vo) }
} else {
DispatchQueue.main.async {
self.layer.setVideo(true)
self.updateWindowSize(vo)
self.layer.update()
}
@ -106,7 +104,6 @@ class CocoaCB: NSObject {
window.makeMain()
window.makeKeyAndOrderFront(nil)
NSApp.activate(ignoringOtherApps: true)
layer.setVideo(true)
if Bool(opts.fullscreen) {
DispatchQueue.main.async {
@ -449,7 +446,6 @@ class CocoaCB: NSObject {
func shutdown(_ destroy: Bool = false) {
setCursorVisiblility(true)
layer.setVideo(false)
stopDisplaylink()
uninitLightSensor()
removeDisplayReconfigureObserver()