cocoa-cb: change handling of window aspect ratio changes

i tried being smart and handle aspect ratio differences manually via
atomic drawing and resizing to aspect fitted frames. there were a few
issues with that. like unexpected visibility of certain System GUI
elements on entering fullscreen or visually dropped frames due to the
atomic drawing. now we rely on system mechanics to keep the proper
aspect ratio of our layer, the recommended way. as a side effect it also
fixes a segfault.

Fixes #5581
This commit is contained in:
Akemi 2018-03-05 02:11:25 +01:00 committed by Kevin Mitchell
parent 33cffdcbac
commit 8bfeecbc6f
3 changed files with 16 additions and 34 deletions

View File

@ -30,11 +30,10 @@ class VideoLayer: CAOpenGLLayer {
var hasVideo: Bool = false var hasVideo: Bool = false
var neededFlips: Int = 0 var neededFlips: Int = 0
var cglContext: CGLContextObj? = nil var cglContext: CGLContextObj? = nil
var surfaceSize: NSSize?
enum Draw: Int { case normal = 1, atomic, atomicEnd } enum Draw: Int { case normal = 1, atomic, atomicEnd }
var draw: Draw = .normal var draw: Draw = .normal
let drawLock = NSLock()
var surfaceSize: NSSize?
var canDrawOffScreen: Bool = false var canDrawOffScreen: Bool = false
var lastThread: Thread? = nil var lastThread: Thread? = nil
@ -49,10 +48,7 @@ class VideoLayer: CAOpenGLLayer {
var inLiveResize: Bool = false { var inLiveResize: Bool = false {
didSet { didSet {
if inLiveResize == false { if inLiveResize {
isAsynchronous = false
neededFlips += 1
} else {
isAsynchronous = true isAsynchronous = true
} }
} }
@ -86,6 +82,9 @@ class VideoLayer: CAOpenGLLayer {
pixelFormat pf: CGLPixelFormatObj, pixelFormat pf: CGLPixelFormatObj,
forLayerTime t: CFTimeInterval, forLayerTime t: CFTimeInterval,
displayTime ts: UnsafePointer<CVTimeStamp>?) -> Bool { displayTime ts: UnsafePointer<CVTimeStamp>?) -> Bool {
if inLiveResize == false {
isAsynchronous = false
}
return mpv != nil && cocoaCB.backendState == .init return mpv != nil && cocoaCB.backendState == .init
} }
@ -100,13 +99,7 @@ class VideoLayer: CAOpenGLLayer {
} }
func draw(_ ctx: CGLContextObj) { func draw(_ ctx: CGLContextObj) {
drawLock.lock() if draw.rawValue >= Draw.atomic.rawValue {
updateSurfaceSize()
let aspectRatioDiff = fabs( (surfaceSize!.width/surfaceSize!.height) -
(bounds.size.width/bounds.size.height) )
if aspectRatioDiff <= 0.005 && draw.rawValue >= Draw.atomic.rawValue {
if draw == .atomic { if draw == .atomic {
draw = .atomicEnd draw = .atomicEnd
} else { } else {
@ -114,9 +107,9 @@ class VideoLayer: CAOpenGLLayer {
} }
} }
updateSurfaceSize()
mpv.drawRender(surfaceSize!) mpv.drawRender(surfaceSize!)
CGLFlushDrawable(ctx) CGLFlushDrawable(ctx)
drawLock.unlock()
if needsICCUpdate { if needsICCUpdate {
needsICCUpdate = false needsICCUpdate = false
@ -148,7 +141,7 @@ class VideoLayer: CAOpenGLLayer {
NSEnableScreenUpdates() NSEnableScreenUpdates()
draw = .normal draw = .normal
} }
} }
override func copyCGLPixelFormat(forDisplayMask mask: UInt32) -> CGLPixelFormatObj { override func copyCGLPixelFormat(forDisplayMask mask: UInt32) -> CGLPixelFormatObj {
let glVersions: [CGLOpenGLProfile] = [ let glVersions: [CGLOpenGLProfile] = [

View File

@ -246,20 +246,18 @@ class Window: NSWindow, NSWindowDelegate {
} }
func window(_ window: NSWindow, startCustomAnimationToEnterFullScreenWithDuration duration: TimeInterval) { func window(_ window: NSWindow, startCustomAnimationToEnterFullScreenWithDuration duration: TimeInterval) {
let cRect = contentRect(forFrameRect: frame) cocoaCB.view.layerContentsPlacement = .scaleProportionallyToFit
var intermediateFrame = aspectFit(rect: cRect, in: targetScreen!.frame)
intermediateFrame = frameRect(forContentRect: intermediateFrame)
hideTitleBar() hideTitleBar()
NSAnimationContext.runAnimationGroup({ (context) -> Void in NSAnimationContext.runAnimationGroup({ (context) -> Void in
context.duration = getFsAnimationDuration(duration - 0.05) context.duration = getFsAnimationDuration(duration - 0.05)
window.animator().setFrame(intermediateFrame, display: true) window.animator().setFrame(targetScreen!.frame, display: true)
}, completionHandler: { }) }, completionHandler: { })
} }
func window(_ window: NSWindow, startCustomAnimationToExitFullScreenWithDuration duration: TimeInterval) { func window(_ window: NSWindow, startCustomAnimationToExitFullScreenWithDuration duration: TimeInterval) {
let newFrame = calculateWindowPosition(for: targetScreen!, withoutBounds: targetScreen == screen) let newFrame = calculateWindowPosition(for: targetScreen!, withoutBounds: targetScreen == screen)
let intermediateFrame = aspectFit(rect: newFrame, in: screen!.frame) let intermediateFrame = aspectFit(rect: newFrame, in: screen!.frame)
cocoaCB.view.layerContentsPlacement = .scaleProportionallyToFill
hideTitleBar() hideTitleBar()
setFrame(intermediateFrame, display: true) setFrame(intermediateFrame, display: true)
@ -281,6 +279,7 @@ class Window: NSWindow, NSWindowDelegate {
isInFullscreen = false isInFullscreen = false
cocoaCB.flagEvents(VO_EVENT_FULLSCREEN_STATE) cocoaCB.flagEvents(VO_EVENT_FULLSCREEN_STATE)
endAnimation(calculateWindowPosition(for: targetScreen!, withoutBounds: targetScreen == screen)) endAnimation(calculateWindowPosition(for: targetScreen!, withoutBounds: targetScreen == screen))
cocoaCB.view.layerContentsPlacement = .scaleProportionallyToFit
} }
func windowDidFailToEnterFullScreen(_ window: NSWindow) { func windowDidFailToEnterFullScreen(_ window: NSWindow) {
@ -293,6 +292,7 @@ class Window: NSWindow, NSWindowDelegate {
let newFrame = targetScreen!.frame let newFrame = targetScreen!.frame
setFrame(newFrame, display: true) setFrame(newFrame, display: true)
endAnimation() endAnimation()
cocoaCB.view.layerContentsPlacement = .scaleProportionallyToFit
} }
func endAnimation(_ newFrame: NSRect = NSZeroRect) { func endAnimation(_ newFrame: NSRect = NSZeroRect) {
@ -304,6 +304,7 @@ class Window: NSWindow, NSWindowDelegate {
} }
isAnimating = false isAnimating = false
cocoaCB.layer.neededFlips += 1
cocoaCB.isShuttingDown = false cocoaCB.isShuttingDown = false
} }
@ -385,21 +386,7 @@ class Window: NSWindow, NSWindowDelegate {
override func setFrame(_ frameRect: NSRect, display flag: Bool) { override func setFrame(_ frameRect: NSRect, display flag: Bool) {
let newFrame = !isAnimating && isInFullscreen ? targetScreen!.frame : let newFrame = !isAnimating && isInFullscreen ? targetScreen!.frame :
frameRect frameRect
let aspectRatioDiff = fabs( (newFrame.width/newFrame.height) -
(frame.width/frame.height) )
let isNotUserLiveResize = isAnimating || !(!isAnimating && inLiveResize)
if aspectRatioDiff > 0.005 && isNotUserLiveResize {
cocoaCB.layer.drawLock.lock()
cocoaCB.layer.atomicDrawingStart()
}
super.setFrame(newFrame, display: flag) super.setFrame(newFrame, display: flag)
cocoaCB.layer.neededFlips += 1
if aspectRatioDiff > 0.005 && isNotUserLiveResize {
cocoaCB.layer.drawLock.unlock()
}
if keepAspect { if keepAspect {
contentAspectRatio = unfsContentFrame!.size contentAspectRatio = unfsContentFrame!.size

View File

@ -57,6 +57,7 @@ class CocoaCB: NSObject {
layer = VideoLayer(cocoaCB: self) layer = VideoLayer(cocoaCB: self)
view.layer = layer view.layer = layer
view.wantsLayer = true view.wantsLayer = true
view.layerContentsPlacement = .scaleProportionallyToFit
} }
func setMpvHandle(_ ctx: OpaquePointer) { func setMpvHandle(_ ctx: OpaquePointer) {
@ -133,6 +134,7 @@ class CocoaCB: NSObject {
if !window.isVisible { if !window.isVisible {
window.makeKeyAndOrderFront(nil) window.makeKeyAndOrderFront(nil)
} }
layer.atomicDrawingStart()
window.updateSize(wr.size) window.updateSize(wr.size)
} }
} }