Sources/GLView.mm
| /* | 
| Copyright (C) 2015 Apple Inc. All Rights Reserved. | 
| See LICENSE.txt for this sample’s licensing information | 
| Abstract: | 
| Custom OpenGL view for the application. | 
| */ | 
| #import <OpenGL/OpenGL.h> | 
| #import <OpenGL/gl3.h> | 
| #import "IOSurface2D.h" | 
| #import "GLQuad.h" | 
| #import "GLTextureDI.h" | 
| #import "GLView.h" | 
| static const GLfloat kGLClearColor[4] = {0.0, 0.0, 0.0, 0.0}; | 
| @implementation GLView | 
| { | 
| @private | 
| GLQuad* quad; | 
| GLTextureDI* tex2D; | 
| NSRect bounds; | 
| GLsizei _width; | 
| GLsizei _height; | 
| IOSurface2D* _surface; | 
| NSString* _resource; | 
| NSString* _path; | 
| NSURL* _URL; | 
| } | 
| + (NSOpenGLPixelFormat *) defaultPixelFormat | 
| { | 
| // Core profile pixel format for deep image support | 
| const NSOpenGLPixelFormatAttribute attributes[] = | 
|     { | 
| NSOpenGLPFADoubleBuffer, | 
| NSOpenGLPFAColorSize, 64, | 
| NSOpenGLPFAColorFloat, | 
| NSOpenGLPFAMultisample, | 
| NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core, | 
| 0 | 
| }; | 
| return [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease]; | 
| } // defaultPixelFormat | 
| // Release assets | 
| - (void) _cleanup | 
| { | 
| if(tex2D) | 
|     { | 
| [tex2D release]; | 
| } // if | 
| if(quad) | 
|     { | 
| [quad release]; | 
| } // if | 
| if(_surface) | 
|     { | 
| [_surface release]; | 
| } // if | 
| if(_resource) | 
|     { | 
| [_resource release]; | 
| } // if | 
| if(_path) | 
|     { | 
| [_path release]; | 
| } // if | 
| if(_URL) | 
|     { | 
| [_URL release]; | 
| } // if | 
| // If self isn't removed as an observer, the Notification Center | 
| // will continue sending notification objects to the deallocated | 
| // object. | 
| [[NSNotificationCenter defaultCenter] removeObserver:self]; | 
| } // _cleanup | 
| // Destructor | 
| - (void) dealloc | 
| { | 
| [self _cleanup]; | 
| [super dealloc]; | 
| } // dealloc | 
| // When application is terminating cleanup the objects | 
| - (void) _terminate:(NSNotification *)notification | 
| { | 
| [self _cleanup]; | 
| } // terminate | 
| - (void) awakeFromNib | 
| { | 
| // It's important to clean up our rendering objects before we terminate -- Cocoa will | 
| // not specifically release everything on application termination, so we explicitly | 
| // call our cleanup (private object destructor) routines. | 
| [[NSNotificationCenter defaultCenter] addObserver:self | 
| selector:@selector(_terminate:) | 
| name:@"NSApplicationWillTerminateNotification" | 
| object:NSApp]; | 
| } // awakeFromNib | 
| - (BOOL) isOpaque | 
| { | 
| return YES; | 
| } // isOpaque | 
| - (BOOL) acceptsFirstResponder | 
| { | 
| return YES; | 
| } // acceptsFirstResponder | 
| - (BOOL) becomeFirstResponder | 
| { | 
| return YES; | 
| } // becomeFirstResponder | 
| - (BOOL) resignFirstResponder | 
| { | 
| return YES; | 
| } // resignFirstResponder | 
| - (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication | 
| { | 
| return YES; | 
| } // applicationShouldTerminateAfterLastWindowClosed | 
| - (void) renewGState | 
| { | 
| [super renewGState]; | 
| [[self window] disableScreenUpdatesUntilFlush]; | 
| } // renewGState | 
| - (void) prepareOpenGL | 
| { | 
| // Prepare the base class | 
| [super prepareOpenGL]; | 
| // Extendend dynamic range | 
| self.wantsExtendedDynamicRangeOpenGLSurface = YES; | 
| // Set the swap interval | 
| GLint nSyncVR = GL_TRUE; | 
| [[self openGLContext] setValues:&nSyncVR | 
| forParameter:NSOpenGLCPSwapInterval]; | 
| // Set the bounds | 
| bounds = [self convertRectToBacking:[self bounds]]; | 
| _width = GLsizei(bounds.size.width); | 
| _height = GLsizei(bounds.size.height); | 
| // Prepare the quad | 
| quad = [[GLQuad alloc] initWithBounds:bounds]; | 
| } // prepareOpenGL | 
| // When the view is resized | 
| - (void) reshape | 
| { | 
| [super reshape]; | 
| // Get the view bounds | 
| bounds = [self convertRectToBacking:[self bounds]]; | 
| // Get the bound's width and height | 
| _width = GLsizei(bounds.size.width); | 
| _height = GLsizei(bounds.size.height); | 
| // Set the viewport to be the entire window | 
| glViewport(0, 0, _width, _height); | 
| } // reshape | 
| - (void) setSurface:(nullable IOSurface2D *)surface | 
| { | 
| if(surface != _surface) | 
|     { | 
| // Release the now obselete texture 2d | 
| if(tex2D) | 
|         { | 
| [tex2D release]; | 
| } // if | 
| // Release the now obselete i/o surface 2d | 
| if(_surface) | 
|         { | 
| [_surface release]; | 
| } // if | 
| // Retain the new i/o surface 2d | 
| _surface = [surface retain]; | 
| // Create a new texture rectangle from an I/O surface | 
| tex2D = [[GLTextureDI alloc] initWithSurface:_surface]; | 
| if(tex2D) | 
|         { | 
| // Texture rectangles require width and height | 
| quad.size = NSMakeSize(GLfloat(tex2D.width), GLfloat(tex2D.height)); | 
| } // if | 
| } // if | 
| } // setSurface | 
| - (void) setURL:(nullable NSURL *)URL | 
| { | 
| if(URL != _URL) | 
|     { | 
| // Release the now obselete texture 2d | 
| if(tex2D) | 
|         { | 
| [tex2D release]; | 
| } // if | 
| // Release the now obselete image url | 
| if(_URL) | 
|         { | 
| [_URL release]; | 
| } // if | 
| // Retain the new image url | 
| _URL = [URL retain]; | 
| // Create a new texture 2D from a 2D I/O surface. | 
| tex2D = [[GLTextureDI alloc] initWithURL:_URL]; | 
| } // if | 
| } // setUrl | 
| - (void) setPath:(nullable NSString *)path | 
| { | 
| if(path != _path) | 
|     { | 
| // Release the now obselete texture 2d | 
| if(tex2D) | 
|         { | 
| [tex2D release]; | 
| } // if | 
| // Release the now obselete image pathname | 
| if(_path) | 
|         { | 
| [_path release]; | 
| } // if | 
| // Retain the new image pathname | 
| _path = [path retain]; | 
| // Create a new texture 2D from a file located at an absolute path. | 
| tex2D = [[GLTextureDI alloc] initWithFile:_path]; | 
| } // if | 
| } // setResource | 
| - (void) setResource:(nullable NSString *)resource | 
| { | 
| if(resource != _resource) | 
|     { | 
| // Release the now obselete texture 2d | 
| if(tex2D) | 
|         { | 
| [tex2D release]; | 
| } // if | 
| // Release the now obselete image path in app's bundle | 
| if(_resource) | 
|         { | 
| [_resource release]; | 
| } // if | 
| // Retain the new image path in app's bundle | 
| _resource = [resource retain]; | 
| // Create a new texture 2D from a file in the application's bundle. | 
| tex2D = [[GLTextureDI alloc] initWithResource:_resource]; | 
| } // if | 
| } // setResource | 
| - (void) drawRect:(NSRect)dirtyRect | 
| { | 
| [[self openGLContext] makeCurrentContext]; | 
|     { | 
| // Set viewport | 
| glViewport(0, 0, _width, _height); | 
| // Clear the color buffer | 
| glClearBufferfv(GL_COLOR, 0, kGLClearColor); | 
| // Render the textured quad | 
| if(tex2D) | 
|         { | 
| [quad render:tex2D.texture]; | 
| } // if | 
| } | 
| [[self openGLContext] flushBuffer]; | 
| } // drawRect | 
| @end | 
Copyright © 2015 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2015-12-10