/* * aquaOpenGLView.m */ #include #include #include #include "aquaOpenGLView.h" @implementation aquaOpenGLView + (NSOpenGLPixelFormat*)defaultPixelFormat { NSOpenGLPixelFormatAttribute attribs[] = {0}; return [[(NSOpenGLPixelFormat *)[NSOpenGLPixelFormat alloc] initWithAttributes:attribs] autorelease]; } - (id)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat*)format { self = [super initWithFrame:frameRect]; if (self != nil) { _pixelFormat = [format retain]; } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_surfaceNeedsUpdate:) name:NSViewGlobalFrameDidChangeNotification object:self]; return self; } - (void)dealloc { // get rid of the context and pixel format [[NSNotificationCenter defaultCenter] removeObserver:self name:NSViewGlobalFrameDidChangeNotification object:self]; [self clearGLContext]; [_pixelFormat release]; [super dealloc]; } - (void)setOpenGLContext:(NSOpenGLContext*)context { [self clearGLContext]; _openGLContext = [context retain]; } - (NSOpenGLContext*)openGLContext { // create a context the first time through if (_openGLContext == NULL) { _openGLContext = [[NSOpenGLContext alloc] initWithFormat:_pixelFormat != nil ? _pixelFormat : [[self class] defaultPixelFormat] shareContext:nil]; [_openGLContext makeCurrentContext]; [self prepareOpenGL]; // call to initialize OpenGL state here } return _openGLContext; } - (void)clearGLContext { if (_openGLContext != nil) { if ([_openGLContext view] == self) { [_openGLContext clearDrawable]; } [_openGLContext release]; _openGLContext = nil; } } - (void)prepareOpenGL { // for overriding to initialize OpenGL state, occurs after context creation } - (BOOL)isOpaque { return YES; } - (void)setPixelFormat:(NSOpenGLPixelFormat*)pixelFormat { [_pixelFormat release]; _pixelFormat = [pixelFormat retain]; } - (NSOpenGLPixelFormat*)pixelFormat { return _pixelFormat; } - (void)lockFocus { // get context. will create if we don't have one yet NSOpenGLContext* context = [self openGLContext]; // make sure we are ready to draw [super lockFocus]; // when we are about to draw, make sure we are linked to the view if ([context view] != self) { [context setView:self]; } // make us the current OpenGL context [context makeCurrentContext]; } - (void)drawRect { // get context. will create if we don't have one yet NSOpenGLContext* context = [self openGLContext]; [context makeCurrentContext]; //perform drawing here [context flushBuffer]; } // no reshape will be called since NSView does not export a specific reshape method - (void)update { if ([_openGLContext view] == self) { [_openGLContext update]; } } - (void) _surfaceNeedsUpdate:(NSNotification*)notification { [self update]; } - (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; if (![coder allowsKeyedCoding]) { [coder encodeValuesOfObjCTypes:"@iii", &_pixelFormat]; } else { [coder encodeObject:_pixelFormat forKey:@"NSPixelFormat"]; } } - (id)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; if (![coder allowsKeyedCoding]) { [coder decodeValuesOfObjCTypes:"@iii", &_pixelFormat]; } else { _pixelFormat = [[coder decodeObjectForKey:@"NSPixelFormat"] retain]; } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_surfaceNeedsUpdate:) name:NSViewGlobalFrameDidChangeNotification object:self]; return self; } @end