Hi,
I've a venerable app that I've coerced from the Apple example code GLEssentials in obj-c to Swift 2 and now I'm trying to move to Swift 3. It has a NSOpenGLView at it's core, the main renderer is still not in Swift (I know: I'll have to bite the bullet soon and migrate to Metal or suchlike), but everything else is.
Currently in OSX 10.12, with Xcode 8 the window is just blank. I've had to make some compiler-suggested changes to the main (Swift) OpenGLView class to get it to compile and run succesfully in Swift 3, and I feel this is where the problem lies as the renderer class appears to be running just fine; I can get it to report an FPS of 60 and am able to place breakpoints that do halt the code every frame. My OpenGLView class sets up as below, and this is where most of the new Swift 3 changes have taken place:
class BQSOpenGLView: NSOpenGLView {
var m_renderer: OpenGLRenderer = OpenGLRenderer()
var have_setup_renderer: Bool = false
var displayLink: CVDisplayLink?
var has_setup = false
var is_fullscreen: Bool = false
var grid_size: QSGridSize = QSMakeGridSize(1, 1)
var backing_scalar_changed: Bool = false
var backing_scalar: GLfloat = 0.0
override func awakeFromNib() {
backing_scalar = GLfloat((self.window?.backingScaleFactor)!)
NotificationCenter.default.addObserver(self, selector: #selector(BQSOpenGLView.willEnterFullscreen(_:)), name: NSNotification.Name.NSWindowWillEnterFullScreen, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(BQSOpenGLView.willExitFullscreen(_:)), name: NSNotification.Name.NSWindowWillExitFullScreen, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(BQSOpenGLView.backingScaleChange(_:)), name: NSNotification.Name.NSWindowDidChangeBackingProperties, object: nil)
let attributes : [NSOpenGLPixelFormatAttribute] = [
NSOpenGLPixelFormatAttribute(NSOpenGLPFADoubleBuffer),
NSOpenGLPixelFormatAttribute(NSOpenGLPFADepthSize),
NSOpenGLPixelFormatAttribute(24),
NSOpenGLPixelFormatAttribute(NSOpenGLPFASampleBuffers),
NSOpenGLPixelFormatAttribute(1),
NSOpenGLPixelFormatAttribute(NSOpenGLPFASamples),
NSOpenGLPixelFormatAttribute(2),
NSOpenGLPixelFormatAttribute(NSOpenGLPFAOpenGLProfile),
NSOpenGLPixelFormatAttribute(NSOpenGLProfileVersion3_2Core),
NSOpenGLPixelFormatAttribute(0)
]
self.pixelFormat = NSOpenGLPixelFormat(attributes: attributes)
self.wantsBestResolutionOpenGLSurface = true
let context:NSOpenGLContext = NSOpenGLContext.init(format: self.pixelFormat!, share: nil)!
CGLEnable(context.cglContextObj!, kCGLCECrashOnRemovedFunctions)
self.openGLContext = context
}
override func prepareOpenGL() {
super.prepareOpenGL()
// The callback function is called everytime CVDisplayLink says its time to get a new frame.
func displayLinkOutputCallback(_ displayLink: CVDisplayLink, _ inNow: UnsafePointer<CVTimeStamp>, _ inOutputTime: UnsafePointer<CVTimeStamp>, _ flagsIn: CVOptionFlags, _ flagsOut: UnsafeMutablePointer<CVOptionFlags>, _ displayLinkContext: UnsafeMutableRawPointer?) -> CVReturn {
unsafeBitCast(displayLinkContext, to: BQSOpenGLView.self).renderFrame()
return kCVReturnSuccess
}
self.wantsLayer = true
self.wantsBestResolutionOpenGLSurface = true
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink)
let success = CVDisplayLinkSetOutputCallback(displayLink!, displayLinkOutputCallback, Unmanaged.passUnretained(self).toOpaque())
if success != kCVReturnSuccess {
Swift.print ("No opengl")
}
CVDisplayLinkStart(displayLink!)
has_setup = true
NotificationCenter.default.post(name: Notification.Name(rawValue: kOPENGL_SETUP_NOTE), object: nil)
self.backingScaleChange(nil)
}
//..
}
Is there a new Swift 3 way of setting up OpenGL or is the above code correct and the problem somewhere else?
EDIT: the render function in the view sub-class is:
func renderFrame() {
self.openGLContext?.makeCurrentContext()
CGLLockContext((self.openGLContext?.cglContextObj)!)
if !have_setup_renderer { //init only when locked all the context
self.backingScaleChange(nil)
m_renderer = OpenGLRenderer.init(defaultFBO: 0, screenSize: (self.window?.screen?.frame.size)!, backingScalar: self.backing_scalar)
have_setup_renderer = true
}
m_renderer.render()
CGLFlushDrawable((self.openGLContext?.cglContextObj)!)
CGLUnlockContext((self.openGLContext?.cglContextObj)!)
}