From 41f290f54e385f28257bd24e8f399bcb7f3727b7 Mon Sep 17 00:00:00 2001 From: der richter Date: Sat, 25 May 2019 19:29:34 +0200 Subject: cocoa-cb: add support for 10bit opengl rendering this will request a 16bit half-float framebuffer instead if a 8bit integer framebuffer. Fixes #3613 --- DOCS/man/options.rst | 7 +++++ osdep/macOS_mpv_helper.swift | 4 ++- osdep/macOS_swift_compat.swift | 14 +++++++++ osdep/macosx_application.h | 1 + osdep/macosx_application.m | 2 ++ video/out/cocoa-cb/video_layer.swift | 57 ++++++++++++++++++++++++------------ 6 files changed, 65 insertions(+), 20 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 68bc01eafd..bad627fd68 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -5075,6 +5075,13 @@ The following video options are currently all specific to ``--vo=gpu`` and OS X only. +``--cocoa-cb-10bit-context=`` + Creates a 10bit capable pixel format for the context creation (default: yes). + Instead of 8bit integer framebuffer a 16bit half-float framebuffer is + requested. + + OS X only. + ``--macos-title-bar-appearance=`` Sets the appearance of the title bar (default: auto). Not all combinations of appearances and ``--macos-title-bar-material`` materials make sense or diff --git a/osdep/macOS_mpv_helper.swift b/osdep/macOS_mpv_helper.swift index fdc458e834..3494c60cfd 100644 --- a/osdep/macOS_mpv_helper.swift +++ b/osdep/macOS_mpv_helper.swift @@ -139,12 +139,13 @@ class MPVHelper: NSObject { return flags & UInt64(MPV_RENDER_UPDATE_FRAME.rawValue) > 0 } - func drawRender(_ surface: NSSize, _ ctx: CGLContextObj, skip: Bool = false) { + func drawRender(_ surface: NSSize, _ depth: GLint, _ ctx: CGLContextObj, skip: Bool = false) { deinitLock.lock() if mpvRenderContext != nil { var i: GLint = 0 var flip: CInt = 1 var skip: CInt = skip ? 1 : 0 + var ditherDepth = depth 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. @@ -157,6 +158,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_DEPTH, data: &ditherDepth), mpv_render_param(type: MPV_RENDER_PARAM_SKIP_RENDERING, data: &skip), mpv_render_param() ] diff --git a/osdep/macOS_swift_compat.swift b/osdep/macOS_swift_compat.swift index 381398e1bf..c14aa08282 100644 --- a/osdep/macOS_swift_compat.swift +++ b/osdep/macOS_swift_compat.swift @@ -23,6 +23,13 @@ extension NSAppearance.Name { static let accessibilityHighContrastVibrantLight: NSAppearance.Name = NSAppearance.Name(rawValue: "NSAppearanceNameAccessibilityVibrantLight") static let accessibilityHighContrastVibrantDark: NSAppearance.Name = NSAppearance.Name(rawValue: "NSAppearanceNameAccessibilityVibrantDark") } + +@available(OSX 10.12, *) +extension String { + static let RGBA16Float: String = kCAContentsFormatRGBA16Float + static let RGBA8Uint: String = kCAContentsFormatRGBA8Uint + static let gray8Uint: String = kCAContentsFormatGray8Uint +} #endif extension NSPasteboard.PasteboardType { @@ -73,6 +80,13 @@ extension Array { } } +extension Array where Element == [CGLPixelFormatAttribute] { + + func contains(_ obj: [CGLPixelFormatAttribute]) -> Bool { + return self.contains(where:{ $0 == obj }) + } +} + extension NSWindow.Level { static func +(left: NSWindow.Level, right: Int) -> NSWindow.Level { diff --git a/osdep/macosx_application.h b/osdep/macosx_application.h index 7c22abaf84..7e233987fd 100644 --- a/osdep/macosx_application.h +++ b/osdep/macosx_application.h @@ -28,6 +28,7 @@ struct macos_opts { struct m_color macos_title_bar_color; int macos_fs_animation_duration; int cocoa_cb_sw_renderer; + int cocoa_cb_10bit_context; }; // multithreaded wrapper for mpv_main diff --git a/osdep/macosx_application.m b/osdep/macosx_application.m index 08b3fce901..a07f4f5db9 100644 --- a/osdep/macosx_application.m +++ b/osdep/macosx_application.m @@ -63,6 +63,7 @@ const struct m_sub_options macos_conf = { ({"default", -1})), OPT_CHOICE("cocoa-cb-sw-renderer", cocoa_cb_sw_renderer, 0, ({"auto", -1}, {"no", 0}, {"yes", 1})), + OPT_FLAG("cocoa-cb-10bit-context", cocoa_cb_10bit_context, 0), OPT_REMOVED("macos-title-bar-style", "Split into --macos-title-bar-appearance " "and --macos-title-bar-material"), {0} @@ -72,6 +73,7 @@ const struct m_sub_options macos_conf = { .macos_title_bar_color = {0, 0, 0, 0}, .macos_fs_animation_duration = -1, .cocoa_cb_sw_renderer = -1, + .cocoa_cb_10bit_context = 1 }, }; diff --git a/video/out/cocoa-cb/video_layer.swift b/video/out/cocoa-cb/video_layer.swift index 301b900de9..95727ee01f 100644 --- a/video/out/cocoa-cb/video_layer.swift +++ b/video/out/cocoa-cb/video_layer.swift @@ -37,10 +37,16 @@ let glFormatSoftwareBase: [CGLPixelFormatAttribute] = [ kCGLPFADoubleBuffer ] -let glFormatOptional: [CGLPixelFormatAttribute] = [ - kCGLPFABackingStore, - kCGLPFAAllowOfflineRenderers, - kCGLPFASupportsAutomaticGraphicsSwitching +let glFormatOptional: [[CGLPixelFormatAttribute]] = [ + [kCGLPFABackingStore], + [kCGLPFAAllowOfflineRenderers], + [kCGLPFASupportsAutomaticGraphicsSwitching] +] + +let glFormat10Bit: [CGLPixelFormatAttribute] = [ + kCGLPFAColorSize, + _CGLPixelFormatAttribute(rawValue: 64), + kCGLPFAColorFloat ] let attributeLookUp: [UInt32:String] = [ @@ -52,6 +58,8 @@ let attributeLookUp: [UInt32:String] = [ kCGLPFAAccelerated.rawValue: "kCGLPFAAccelerated", kCGLPFADoubleBuffer.rawValue: "kCGLPFADoubleBuffer", kCGLPFABackingStore.rawValue: "kCGLPFABackingStore", + kCGLPFAColorSize.rawValue: "kCGLPFAColorSize", + kCGLPFAColorFloat.rawValue: "kCGLPFAColorFloat", kCGLPFAAllowOfflineRenderers.rawValue: "kCGLPFAAllowOfflineRenderers", kCGLPFASupportsAutomaticGraphicsSwitching.rawValue: "kCGLPFASupportsAutomaticGraphicsSwitching", ] @@ -67,6 +75,7 @@ class VideoLayer: CAOpenGLLayer { var needsFlip: Bool = false var forceDraw: Bool = false var surfaceSize: NSSize = NSSize(width: 0, height: 0) + var bufferDepth: GLint = 8 enum Draw: Int { case normal = 1, atomic, atomicEnd } var draw: Draw = .normal @@ -92,12 +101,16 @@ class VideoLayer: CAOpenGLLayer { init(cocoaCB ccb: CocoaCB) { cocoaCB = ccb - cglPixelFormat = VideoLayer.createPixelFormat(ccb.mpv) + (cglPixelFormat, bufferDepth) = VideoLayer.createPixelFormat(ccb.mpv) cglContext = VideoLayer.createContext(ccb.mpv, cglPixelFormat) super.init() autoresizingMask = [.layerWidthSizable, .layerHeightSizable] backgroundColor = NSColor.black.cgColor + if #available(macOS 10.12, *), bufferDepth > 8 { + contentsFormat = .RGBA16Float + } + var i: GLint = 1 CGLSetParameter(cglContext, kCGLCPSwapInterval, &i) CGLSetCurrentContext(cglContext) @@ -150,7 +163,7 @@ class VideoLayer: CAOpenGLLayer { } updateSurfaceSize() - mpv.drawRender(surfaceSize, ctx) + mpv.drawRender(surfaceSize, bufferDepth, ctx) if needsICCUpdate { needsICCUpdate = false @@ -206,7 +219,7 @@ class VideoLayer: CAOpenGLLayer { if isUpdate && needsFlip { CGLSetCurrentContext(cglContext) if mpv.isRenderUpdateFrame() { - mpv.drawRender(NSZeroSize, cglContext, skip: true) + mpv.drawRender(NSZeroSize, bufferDepth, cglContext, skip: true) } } displayLock.unlock() @@ -222,17 +235,18 @@ class VideoLayer: CAOpenGLLayer { } } - class func createPixelFormat(_ mpv: MPVHelper) -> CGLPixelFormatObj { + class func createPixelFormat(_ mpv: MPVHelper) -> (CGLPixelFormatObj, GLint) { var pix: CGLPixelFormatObj? + var depth: GLint = 8 var err: CGLError = CGLError(rawValue: 0) let swRender = mpv.macOpts?.cocoa_cb_sw_renderer ?? -1 if swRender != 1 { - (pix, err) = VideoLayer.findPixelFormat(mpv) + (pix, depth, err) = VideoLayer.findPixelFormat(mpv) } if (err != kCGLNoError || pix == nil) && swRender != 0 { - (pix, err) = VideoLayer.findPixelFormat(mpv, software: true) + (pix, depth, err) = VideoLayer.findPixelFormat(mpv, software: true) } guard let pixelFormat = pix, err == kCGLNoError else { @@ -240,10 +254,10 @@ class VideoLayer: CAOpenGLLayer { exit(1) } - return pixelFormat + return (pixelFormat, depth) } - class func findPixelFormat(_ mpv: MPVHelper, software: Bool = false) -> (CGLPixelFormatObj?, CGLError) { + class func findPixelFormat(_ mpv: MPVHelper, software: Bool = false) -> (CGLPixelFormatObj?, GLint, CGLError) { var pix: CGLPixelFormatObj? var err: CGLError = CGLError(rawValue: 0) var npix: GLint = 0 @@ -251,22 +265,27 @@ class VideoLayer: CAOpenGLLayer { for ver in glVersions { var glBase = software ? glFormatSoftwareBase : glFormatBase glBase.insert(CGLPixelFormatAttribute(ver.rawValue), at: 1) - var glFormat = glBase + glFormatOptional - for index in stride(from: glFormat.count-1, through: glBase.count-1, by: -1) { - let format = glFormat + [_CGLPixelFormatAttribute(rawValue: 0)] + var glFormat = [glBase] + if (mpv.macOpts?.cocoa_cb_10bit_context == 1) { + glFormat += [glFormat10Bit] + } + glFormat += glFormatOptional + + for index in stride(from: glFormat.count-1, through: 0, by: -1) { + let format = glFormat.flatMap { $0 } + [_CGLPixelFormatAttribute(rawValue: 0)] err = CGLChoosePixelFormat(format, &pix, &npix) if err == kCGLBadAttribute || err == kCGLBadPixelFormat || pix == nil { glFormat.remove(at: index) } else { - let attArray = glFormat.map({ (value: _CGLPixelFormatAttribute) -> String in - return attributeLookUp[value.rawValue] ?? "unknown attribute" + let attArray = format.map({ (value: _CGLPixelFormatAttribute) -> String in + return attributeLookUp[value.rawValue] ?? String(value.rawValue) }) mpv.sendVerbose("Created CGL pixel format with attributes: " + "\(attArray.joined(separator: ", "))") - return (pix, err) + return (pix, glFormat.contains(glFormat10Bit) ? 16 : 8, err) } } } @@ -280,7 +299,7 @@ class VideoLayer: CAOpenGLLayer { mpv.sendWarning("Falling back to software renderer") } - return (pix, err) + return (pix, 8, err) } class func createContext(_ mpv: MPVHelper, _ pixelFormat: CGLPixelFormatObj) -> CGLContextObj { -- cgit v1.2.3