cocoa-cb: add support for 10bit opengl rendering

this will request a 16bit half-float framebuffer instead if a 8bit
integer framebuffer.

Fixes #3613
This commit is contained in:
der richter 2019-05-25 19:29:34 +02:00
parent ff2aed2b56
commit 41f290f54e
6 changed files with 65 additions and 20 deletions

View File

@ -5075,6 +5075,13 @@ The following video options are currently all specific to ``--vo=gpu`` and
OS X only. OS X only.
``--cocoa-cb-10bit-context=<yes|no>``
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=<appearance>`` ``--macos-title-bar-appearance=<appearance>``
Sets the appearance of the title bar (default: auto). Not all combinations Sets the appearance of the title bar (default: auto). Not all combinations
of appearances and ``--macos-title-bar-material`` materials make sense or of appearances and ``--macos-title-bar-material`` materials make sense or

View File

@ -139,12 +139,13 @@ class MPVHelper: NSObject {
return flags & UInt64(MPV_RENDER_UPDATE_FRAME.rawValue) > 0 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() deinitLock.lock()
if mpvRenderContext != nil { if mpvRenderContext != nil {
var i: GLint = 0 var i: GLint = 0
var flip: CInt = 1 var flip: CInt = 1
var skip: CInt = skip ? 1 : 0 var skip: CInt = skip ? 1 : 0
var ditherDepth = depth
glGetIntegerv(GLenum(GL_DRAW_FRAMEBUFFER_BINDING), &i) glGetIntegerv(GLenum(GL_DRAW_FRAMEBUFFER_BINDING), &i)
// CAOpenGLLayer has ownership of FBO zero yet can return it to us, // CAOpenGLLayer has ownership of FBO zero yet can return it to us,
// so only utilize a newly received FBO ID if it is nonzero. // so only utilize a newly received FBO ID if it is nonzero.
@ -157,6 +158,7 @@ class MPVHelper: NSObject {
var params: [mpv_render_param] = [ var params: [mpv_render_param] = [
mpv_render_param(type: MPV_RENDER_PARAM_OPENGL_FBO, data: &data), 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_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(type: MPV_RENDER_PARAM_SKIP_RENDERING, data: &skip),
mpv_render_param() mpv_render_param()
] ]

View File

@ -23,6 +23,13 @@ extension NSAppearance.Name {
static let accessibilityHighContrastVibrantLight: NSAppearance.Name = NSAppearance.Name(rawValue: "NSAppearanceNameAccessibilityVibrantLight") static let accessibilityHighContrastVibrantLight: NSAppearance.Name = NSAppearance.Name(rawValue: "NSAppearanceNameAccessibilityVibrantLight")
static let accessibilityHighContrastVibrantDark: NSAppearance.Name = NSAppearance.Name(rawValue: "NSAppearanceNameAccessibilityVibrantDark") 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 #endif
extension NSPasteboard.PasteboardType { 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 { extension NSWindow.Level {
static func +(left: NSWindow.Level, right: Int) -> NSWindow.Level { static func +(left: NSWindow.Level, right: Int) -> NSWindow.Level {

View File

@ -28,6 +28,7 @@ struct macos_opts {
struct m_color macos_title_bar_color; struct m_color macos_title_bar_color;
int macos_fs_animation_duration; int macos_fs_animation_duration;
int cocoa_cb_sw_renderer; int cocoa_cb_sw_renderer;
int cocoa_cb_10bit_context;
}; };
// multithreaded wrapper for mpv_main // multithreaded wrapper for mpv_main

View File

@ -63,6 +63,7 @@ const struct m_sub_options macos_conf = {
({"default", -1})), ({"default", -1})),
OPT_CHOICE("cocoa-cb-sw-renderer", cocoa_cb_sw_renderer, 0, OPT_CHOICE("cocoa-cb-sw-renderer", cocoa_cb_sw_renderer, 0,
({"auto", -1}, {"no", 0}, {"yes", 1})), ({"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 " OPT_REMOVED("macos-title-bar-style", "Split into --macos-title-bar-appearance "
"and --macos-title-bar-material"), "and --macos-title-bar-material"),
{0} {0}
@ -72,6 +73,7 @@ const struct m_sub_options macos_conf = {
.macos_title_bar_color = {0, 0, 0, 0}, .macos_title_bar_color = {0, 0, 0, 0},
.macos_fs_animation_duration = -1, .macos_fs_animation_duration = -1,
.cocoa_cb_sw_renderer = -1, .cocoa_cb_sw_renderer = -1,
.cocoa_cb_10bit_context = 1
}, },
}; };

View File

@ -37,10 +37,16 @@ let glFormatSoftwareBase: [CGLPixelFormatAttribute] = [
kCGLPFADoubleBuffer kCGLPFADoubleBuffer
] ]
let glFormatOptional: [CGLPixelFormatAttribute] = [ let glFormatOptional: [[CGLPixelFormatAttribute]] = [
kCGLPFABackingStore, [kCGLPFABackingStore],
kCGLPFAAllowOfflineRenderers, [kCGLPFAAllowOfflineRenderers],
kCGLPFASupportsAutomaticGraphicsSwitching [kCGLPFASupportsAutomaticGraphicsSwitching]
]
let glFormat10Bit: [CGLPixelFormatAttribute] = [
kCGLPFAColorSize,
_CGLPixelFormatAttribute(rawValue: 64),
kCGLPFAColorFloat
] ]
let attributeLookUp: [UInt32:String] = [ let attributeLookUp: [UInt32:String] = [
@ -52,6 +58,8 @@ let attributeLookUp: [UInt32:String] = [
kCGLPFAAccelerated.rawValue: "kCGLPFAAccelerated", kCGLPFAAccelerated.rawValue: "kCGLPFAAccelerated",
kCGLPFADoubleBuffer.rawValue: "kCGLPFADoubleBuffer", kCGLPFADoubleBuffer.rawValue: "kCGLPFADoubleBuffer",
kCGLPFABackingStore.rawValue: "kCGLPFABackingStore", kCGLPFABackingStore.rawValue: "kCGLPFABackingStore",
kCGLPFAColorSize.rawValue: "kCGLPFAColorSize",
kCGLPFAColorFloat.rawValue: "kCGLPFAColorFloat",
kCGLPFAAllowOfflineRenderers.rawValue: "kCGLPFAAllowOfflineRenderers", kCGLPFAAllowOfflineRenderers.rawValue: "kCGLPFAAllowOfflineRenderers",
kCGLPFASupportsAutomaticGraphicsSwitching.rawValue: "kCGLPFASupportsAutomaticGraphicsSwitching", kCGLPFASupportsAutomaticGraphicsSwitching.rawValue: "kCGLPFASupportsAutomaticGraphicsSwitching",
] ]
@ -67,6 +75,7 @@ class VideoLayer: CAOpenGLLayer {
var needsFlip: Bool = false var needsFlip: Bool = false
var forceDraw: Bool = false var forceDraw: Bool = false
var surfaceSize: NSSize = NSSize(width: 0, height: 0) var surfaceSize: NSSize = NSSize(width: 0, height: 0)
var bufferDepth: GLint = 8
enum Draw: Int { case normal = 1, atomic, atomicEnd } enum Draw: Int { case normal = 1, atomic, atomicEnd }
var draw: Draw = .normal var draw: Draw = .normal
@ -92,12 +101,16 @@ class VideoLayer: CAOpenGLLayer {
init(cocoaCB ccb: CocoaCB) { init(cocoaCB ccb: CocoaCB) {
cocoaCB = ccb cocoaCB = ccb
cglPixelFormat = VideoLayer.createPixelFormat(ccb.mpv) (cglPixelFormat, bufferDepth) = VideoLayer.createPixelFormat(ccb.mpv)
cglContext = VideoLayer.createContext(ccb.mpv, cglPixelFormat) cglContext = VideoLayer.createContext(ccb.mpv, cglPixelFormat)
super.init() super.init()
autoresizingMask = [.layerWidthSizable, .layerHeightSizable] autoresizingMask = [.layerWidthSizable, .layerHeightSizable]
backgroundColor = NSColor.black.cgColor backgroundColor = NSColor.black.cgColor
if #available(macOS 10.12, *), bufferDepth > 8 {
contentsFormat = .RGBA16Float
}
var i: GLint = 1 var i: GLint = 1
CGLSetParameter(cglContext, kCGLCPSwapInterval, &i) CGLSetParameter(cglContext, kCGLCPSwapInterval, &i)
CGLSetCurrentContext(cglContext) CGLSetCurrentContext(cglContext)
@ -150,7 +163,7 @@ class VideoLayer: CAOpenGLLayer {
} }
updateSurfaceSize() updateSurfaceSize()
mpv.drawRender(surfaceSize, ctx) mpv.drawRender(surfaceSize, bufferDepth, ctx)
if needsICCUpdate { if needsICCUpdate {
needsICCUpdate = false needsICCUpdate = false
@ -206,7 +219,7 @@ class VideoLayer: CAOpenGLLayer {
if isUpdate && needsFlip { if isUpdate && needsFlip {
CGLSetCurrentContext(cglContext) CGLSetCurrentContext(cglContext)
if mpv.isRenderUpdateFrame() { if mpv.isRenderUpdateFrame() {
mpv.drawRender(NSZeroSize, cglContext, skip: true) mpv.drawRender(NSZeroSize, bufferDepth, cglContext, skip: true)
} }
} }
displayLock.unlock() 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 pix: CGLPixelFormatObj?
var depth: GLint = 8
var err: CGLError = CGLError(rawValue: 0) var err: CGLError = CGLError(rawValue: 0)
let swRender = mpv.macOpts?.cocoa_cb_sw_renderer ?? -1 let swRender = mpv.macOpts?.cocoa_cb_sw_renderer ?? -1
if swRender != 1 { if swRender != 1 {
(pix, err) = VideoLayer.findPixelFormat(mpv) (pix, depth, err) = VideoLayer.findPixelFormat(mpv)
} }
if (err != kCGLNoError || pix == nil) && swRender != 0 { 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 { guard let pixelFormat = pix, err == kCGLNoError else {
@ -240,10 +254,10 @@ class VideoLayer: CAOpenGLLayer {
exit(1) 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 pix: CGLPixelFormatObj?
var err: CGLError = CGLError(rawValue: 0) var err: CGLError = CGLError(rawValue: 0)
var npix: GLint = 0 var npix: GLint = 0
@ -251,22 +265,27 @@ class VideoLayer: CAOpenGLLayer {
for ver in glVersions { for ver in glVersions {
var glBase = software ? glFormatSoftwareBase : glFormatBase var glBase = software ? glFormatSoftwareBase : glFormatBase
glBase.insert(CGLPixelFormatAttribute(ver.rawValue), at: 1) 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) { var glFormat = [glBase]
let format = glFormat + [_CGLPixelFormatAttribute(rawValue: 0)] 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) err = CGLChoosePixelFormat(format, &pix, &npix)
if err == kCGLBadAttribute || err == kCGLBadPixelFormat || pix == nil { if err == kCGLBadAttribute || err == kCGLBadPixelFormat || pix == nil {
glFormat.remove(at: index) glFormat.remove(at: index)
} else { } else {
let attArray = glFormat.map({ (value: _CGLPixelFormatAttribute) -> String in let attArray = format.map({ (value: _CGLPixelFormatAttribute) -> String in
return attributeLookUp[value.rawValue] ?? "unknown attribute" return attributeLookUp[value.rawValue] ?? String(value.rawValue)
}) })
mpv.sendVerbose("Created CGL pixel format with attributes: " + mpv.sendVerbose("Created CGL pixel format with attributes: " +
"\(attArray.joined(separator: ", "))") "\(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") mpv.sendWarning("Falling back to software renderer")
} }
return (pix, err) return (pix, 8, err)
} }
class func createContext(_ mpv: MPVHelper, _ pixelFormat: CGLPixelFormatObj) -> CGLContextObj { class func createContext(_ mpv: MPVHelper, _ pixelFormat: CGLPixelFormatObj) -> CGLContextObj {