summaryrefslogtreecommitdiffstats
path: root/video/out/cocoa-cb/video_layer.swift
diff options
context:
space:
mode:
authorder richter <der.richter@gmx.de>2019-03-30 21:26:31 +0100
committerJan Ekström <jeebjp@gmail.com>2019-04-25 23:02:19 +0300
commit71ad1e2f4c2b87e677d01c639dbd3d28c118ac55 (patch)
treebf564e6374790a96f025ea0c44fc57ac7f9f6f5f /video/out/cocoa-cb/video_layer.swift
parentedbc1999145b5593098f09042947bf1b79323d2e (diff)
downloadmpv-71ad1e2f4c2b87e677d01c639dbd3d28c118ac55.tar.bz2
mpv-71ad1e2f4c2b87e677d01c639dbd3d28c118ac55.tar.xz
cocoa-cb: remove all force unwrappings of optionals
the force unwrapping of optionals caused many unpredictable segfaults instead of gracefully exiting or falling back. besides that, it is bad practice and the code is a lot more stable now.
Diffstat (limited to 'video/out/cocoa-cb/video_layer.swift')
-rw-r--r--video/out/cocoa-cb/video_layer.swift207
1 files changed, 113 insertions, 94 deletions
diff --git a/video/out/cocoa-cb/video_layer.swift b/video/out/cocoa-cb/video_layer.swift
index 5de57b9e00..895d9faf29 100644
--- a/video/out/cocoa-cb/video_layer.swift
+++ b/video/out/cocoa-cb/video_layer.swift
@@ -19,63 +19,61 @@ import Cocoa
import OpenGL.GL
import OpenGL.GL3
+let glVersions: [CGLOpenGLProfile] = [
+ kCGLOGLPVersion_3_2_Core,
+ kCGLOGLPVersion_Legacy
+]
+
+let glFormatBase: [CGLPixelFormatAttribute] = [
+ kCGLPFAOpenGLProfile,
+ kCGLPFAAccelerated,
+ kCGLPFADoubleBuffer
+]
+
+let glFormatSoftwareBase: [CGLPixelFormatAttribute] = [
+ kCGLPFAOpenGLProfile,
+ kCGLPFARendererID,
+ CGLPixelFormatAttribute(UInt32(kCGLRendererGenericFloatID)),
+ kCGLPFADoubleBuffer
+]
+
+let glFormatOptional: [CGLPixelFormatAttribute] = [
+ kCGLPFABackingStore,
+ kCGLPFAAllowOfflineRenderers,
+ kCGLPFASupportsAutomaticGraphicsSwitching
+]
+
+let attributeLookUp: [UInt32:String] = [
+ kCGLOGLPVersion_3_2_Core.rawValue: "kCGLOGLPVersion_3_2_Core",
+ kCGLOGLPVersion_Legacy.rawValue: "kCGLOGLPVersion_Legacy",
+ kCGLPFAOpenGLProfile.rawValue: "kCGLPFAOpenGLProfile",
+ UInt32(kCGLRendererGenericFloatID): "kCGLRendererGenericFloatID",
+ kCGLPFARendererID.rawValue: "kCGLPFARendererID",
+ kCGLPFAAccelerated.rawValue: "kCGLPFAAccelerated",
+ kCGLPFADoubleBuffer.rawValue: "kCGLPFADoubleBuffer",
+ kCGLPFABackingStore.rawValue: "kCGLPFABackingStore",
+ kCGLPFAAllowOfflineRenderers.rawValue: "kCGLPFAAllowOfflineRenderers",
+ kCGLPFASupportsAutomaticGraphicsSwitching.rawValue: "kCGLPFASupportsAutomaticGraphicsSwitching",
+]
+
class VideoLayer: CAOpenGLLayer {
weak var cocoaCB: CocoaCB!
- var mpv: MPVHelper! {
- get { return cocoaCB == nil ? nil : cocoaCB.mpv }
- }
+ var mpv: MPVHelper { get { return cocoaCB.mpv } }
let videoLock = NSLock()
let displayLock = NSLock()
+ let cglContext: CGLContextObj
+ let cglPixelFormat: CGLPixelFormatObj
var needsFlip: Bool = false
var forceDraw: Bool = false
- var cglContext: CGLContextObj? = nil
- var cglPixelFormat: CGLPixelFormatObj? = nil
- var surfaceSize: NSSize?
+ var surfaceSize: NSSize = NSSize(width: 0, height: 0)
enum Draw: Int { case normal = 1, atomic, atomicEnd }
var draw: Draw = .normal
let queue: DispatchQueue = DispatchQueue(label: "io.mpv.queue.draw")
- let glVersions: [CGLOpenGLProfile] = [
- kCGLOGLPVersion_3_2_Core,
- kCGLOGLPVersion_Legacy
- ]
-
- let glFormatBase: [CGLPixelFormatAttribute] = [
- kCGLPFAOpenGLProfile,
- kCGLPFAAccelerated,
- kCGLPFADoubleBuffer
- ]
-
- let glFormatSoftwareBase: [CGLPixelFormatAttribute] = [
- kCGLPFAOpenGLProfile,
- kCGLPFARendererID,
- CGLPixelFormatAttribute(UInt32(kCGLRendererGenericFloatID)),
- kCGLPFADoubleBuffer
- ]
-
- let glFormatOptional: [CGLPixelFormatAttribute] = [
- kCGLPFABackingStore,
- kCGLPFAAllowOfflineRenderers,
- kCGLPFASupportsAutomaticGraphicsSwitching
- ]
-
- let attributeLookUp: [UInt32:String] = [
- kCGLOGLPVersion_3_2_Core.rawValue: "kCGLOGLPVersion_3_2_Core",
- kCGLOGLPVersion_Legacy.rawValue: "kCGLOGLPVersion_Legacy",
- kCGLPFAOpenGLProfile.rawValue: "kCGLPFAOpenGLProfile",
- UInt32(kCGLRendererGenericFloatID): "kCGLRendererGenericFloatID",
- kCGLPFARendererID.rawValue: "kCGLPFARendererID",
- kCGLPFAAccelerated.rawValue: "kCGLPFAAccelerated",
- kCGLPFADoubleBuffer.rawValue: "kCGLPFADoubleBuffer",
- kCGLPFABackingStore.rawValue: "kCGLPFABackingStore",
- kCGLPFAAllowOfflineRenderers.rawValue: "kCGLPFAAllowOfflineRenderers",
- kCGLPFASupportsAutomaticGraphicsSwitching.rawValue: "kCGLPFASupportsAutomaticGraphicsSwitching",
- ]
-
var needsICCUpdate: Bool = false {
didSet {
if needsICCUpdate == true {
@@ -95,24 +93,30 @@ class VideoLayer: CAOpenGLLayer {
init(cocoaCB ccb: CocoaCB) {
cocoaCB = ccb
+ cglPixelFormat = VideoLayer.createPixelFormat(ccb.mpv)
+ cglContext = VideoLayer.createContext(ccb.mpv, cglPixelFormat)
super.init()
autoresizingMask = [.layerWidthSizable, .layerHeightSizable]
backgroundColor = NSColor.black.cgColor
- cglPixelFormat = copyCGLPixelFormat(forDisplayMask: 0)
- CGLCreateContext(cglPixelFormat!, nil, &cglContext)
var i: GLint = 1
- CGLSetParameter(cglContext!, kCGLCPSwapInterval, &i)
- CGLSetCurrentContext(cglContext!)
+ CGLSetParameter(cglContext, kCGLCPSwapInterval, &i)
+ CGLSetCurrentContext(cglContext)
mpv.initRender()
mpv.setRenderUpdateCallback(updateCallback, context: self)
mpv.setRenderControlCallback(cocoaCB.controlCallback, context: cocoaCB)
}
+ //necessary for when the layer containing window changes the screen
override init(layer: Any) {
- let oldLayer = layer as! VideoLayer
+ guard let oldLayer = layer as? VideoLayer else {
+ fatalError("init(layer: Any) passed an invalid layer")
+ }
cocoaCB = oldLayer.cocoaCB
+ surfaceSize = oldLayer.surfaceSize
+ cglPixelFormat = oldLayer.cglPixelFormat
+ cglContext = oldLayer.cglContext
super.init()
}
@@ -127,7 +131,7 @@ class VideoLayer: CAOpenGLLayer {
if inLiveResize == false {
isAsynchronous = false
}
- return mpv != nil && cocoaCB.backendState == .initialized &&
+ return cocoaCB.backendState == .initialized &&
(forceDraw || mpv.isRenderUpdateFrame())
}
@@ -147,7 +151,7 @@ class VideoLayer: CAOpenGLLayer {
}
updateSurfaceSize()
- mpv.drawRender(surfaceSize!, ctx)
+ mpv.drawRender(surfaceSize, ctx)
if needsICCUpdate {
needsICCUpdate = false
@@ -158,12 +162,12 @@ class VideoLayer: CAOpenGLLayer {
func updateSurfaceSize() {
var dims: [GLint] = [0, 0, 0, 0]
glGetIntegerv(GLenum(GL_VIEWPORT), &dims)
- surfaceSize = NSMakeSize(CGFloat(dims[2]), CGFloat(dims[3]))
+ surfaceSize = NSSize(width: CGFloat(dims[2]), height: CGFloat(dims[3]))
- if NSEqualSizes(surfaceSize!, NSZeroSize) {
+ if NSEqualSizes(surfaceSize, NSZeroSize) {
surfaceSize = bounds.size
- surfaceSize!.width *= contentsScale
- surfaceSize!.height *= contentsScale
+ surfaceSize.width *= contentsScale
+ surfaceSize.height *= contentsScale
}
}
@@ -182,28 +186,65 @@ class VideoLayer: CAOpenGLLayer {
}
override func copyCGLPixelFormat(forDisplayMask mask: UInt32) -> CGLPixelFormatObj {
- if cglPixelFormat != nil { return cglPixelFormat! }
+ return cglPixelFormat
+ }
+
+ override func copyCGLContext(forPixelFormat pf: CGLPixelFormatObj) -> CGLContextObj {
+ contentsScale = cocoaCB.window?.backingScaleFactor ?? 1.0
+ return cglContext
+ }
+
+ let updateCallback: mpv_render_update_fn = { (ctx) in
+ let layer: VideoLayer = unsafeBitCast(ctx, to: VideoLayer.self)
+ layer.update()
+ }
+
+ override func display() {
+ displayLock.lock()
+ let isUpdate = needsFlip
+ super.display()
+ CATransaction.flush()
+ if isUpdate && needsFlip {
+ CGLSetCurrentContext(cglContext)
+ if mpv.isRenderUpdateFrame() {
+ mpv.drawRender(NSZeroSize, cglContext, skip: true)
+ }
+ }
+ displayLock.unlock()
+ }
+
+ func update(force: Bool = false) {
+ if force { forceDraw = true }
+ queue.async {
+ if self.forceDraw || !self.inLiveResize {
+ self.needsFlip = true
+ self.display()
+ }
+ }
+ }
+ class func createPixelFormat(_ mpv: MPVHelper) -> CGLPixelFormatObj {
var pix: CGLPixelFormatObj?
var err: CGLError = CGLError(rawValue: 0)
+ let swRender = mpv.macOpts?.cocoa_cb_sw_renderer ?? -1
- if mpv.macOpts!.cocoa_cb_sw_renderer != 1 {
- (pix, err) = createPixelFormat()
+ if swRender != 1 {
+ (pix, err) = VideoLayer.findPixelFormat(mpv)
}
- if (err != kCGLNoError || pix == nil) && mpv.macOpts!.cocoa_cb_sw_renderer != 0 {
- (pix, err) = createPixelFormat(software: true)
+ if (err != kCGLNoError || pix == nil) && swRender != 0 {
+ (pix, err) = VideoLayer.findPixelFormat(mpv, software: true)
}
- if err != kCGLNoError || pix == nil {
+ guard let pixelFormat = pix, err == kCGLNoError else {
mpv.sendError("Couldn't create any CGL pixel format")
exit(1)
}
- return pix!
+ return pixelFormat
}
- func createPixelFormat(software: Bool = false) -> (CGLPixelFormatObj?, CGLError) {
+ class func findPixelFormat(_ mpv: MPVHelper, software: Bool = false) -> (CGLPixelFormatObj?, CGLError) {
var pix: CGLPixelFormatObj?
var err: CGLError = CGLError(rawValue: 0)
var npix: GLint = 0
@@ -221,7 +262,7 @@ class VideoLayer: CAOpenGLLayer {
glFormat.remove(at: index)
} else {
let attArray = glFormat.map({ (value: _CGLPixelFormatAttribute) -> String in
- return attributeLookUp[value.rawValue]!
+ return attributeLookUp[value.rawValue] ?? "unknown attribute"
})
mpv.sendVerbose("Created CGL pixel format with attributes: " +
@@ -236,45 +277,23 @@ class VideoLayer: CAOpenGLLayer {
"\(software ? "software" : "hardware accelerated") " +
"CGL pixel format: \(errS) (\(err.rawValue))")
- if software == false && mpv.macOpts!.cocoa_cb_sw_renderer == -1 {
+ if software == false && (mpv.macOpts?.cocoa_cb_sw_renderer ?? -1) == -1 {
mpv.sendWarning("Falling back to software renderer")
}
return (pix, err)
}
- override func copyCGLContext(forPixelFormat pf: CGLPixelFormatObj) -> CGLContextObj {
- contentsScale = cocoaCB.window.backingScaleFactor
- return cglContext!
- }
+ class func createContext(_ mpv: MPVHelper, _ pixelFormat: CGLPixelFormatObj) -> CGLContextObj {
+ var context: CGLContextObj?
+ let error = CGLCreateContext(pixelFormat, nil, &context)
- let updateCallback: mpv_render_update_fn = { (ctx) in
- let layer: VideoLayer = MPVHelper.bridge(ptr: ctx!)
- layer.update()
- }
-
- override func display() {
- displayLock.lock()
- let isUpdate = needsFlip
- super.display()
- CATransaction.flush()
- if isUpdate && needsFlip {
- CGLSetCurrentContext(cglContext!)
- if mpv.isRenderUpdateFrame() {
- mpv.drawRender(NSZeroSize, cglContext!, skip: true)
- }
+ guard let cglContext = context, error == kCGLNoError else {
+ let errS = String(cString: CGLErrorString(error))
+ mpv.sendError("Couldn't create a CGLContext: " + errS)
+ exit(1)
}
- displayLock.unlock()
- }
- func update(force: Bool = false) {
- if force { forceDraw = true }
- queue.async {
- if self.forceDraw || !self.inLiveResize {
- self.needsFlip = true
- self.display()
- }
- }
+ return cglContext
}
-
}