// // OpenGLView.m // ElectrEm // // Created by Thomas Harte on 16/07/2015. // Copyright © 2015 Thomas Harte. All rights reserved. // #import "OpenGLView.h" @import CoreVideo; #import @implementation CSOpenGLView { CVDisplayLinkRef displayLink; } - (void)prepareOpenGL { // Synchronize buffer swaps with vertical refresh rate GLint swapInt = 1; [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; // Create a display link capable of being used with all active displays CVDisplayLinkCreateWithActiveCGDisplays(&displayLink); // Set the renderer output callback function CVDisplayLinkSetOutputCallback(displayLink, DisplayLinkCallback, (__bridge void * __nullable)(self)); // Set the display link for the current renderer CGLContextObj cglContext = [[self openGLContext] CGLContextObj]; CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj]; CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat); // Activate the display link CVDisplayLinkStart(displayLink); } static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) { CSOpenGLView *view = (__bridge CSOpenGLView *)displayLinkContext; [view.delegate openGLView:view didUpdateToTime:*now]; return kCVReturnSuccess; } - (void)dealloc { // Release the display link CVDisplayLinkRelease(displayLink); } - (void)reshape { [super reshape]; CGSize viewSize = [self convertSize:self.bounds.size toView:self]; glViewport(0, 0, viewSize.width, viewSize.height); } - (void)drawRect:(NSRect)dirtyRect { [self.openGLContext makeCurrentContext]; [self.delegate openGLViewDrawView:self]; glSwapAPPLE(); } - (void) awakeFromNib { NSOpenGLPixelFormatAttribute attributes[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, 0 }; NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; #ifdef DEBUG // When we're using a CoreProfile context, crash if we call a legacy OpenGL function // This will make it much more obvious where and when such a function call is made so // that we can remove such calls. // Without this we'd simply get GL_INVALID_OPERATION error for calling legacy functions // but it would be more difficult to see where that function was called. CGLEnable([context CGLContextObj], kCGLCECrashOnRemovedFunctions); #endif self.pixelFormat = pixelFormat; self.openGLContext = context; self.wantsBestResolutionOpenGLSurface = YES; } @end