/** NSOpenGLView.m Context for openGL drawing Copyright (C) 1996 Free Software Foundation, Inc. Author: Frederic De Jaeger Date: 2002 This file is part of the GNUstep GUI Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; see the file COPYING.LIB. If not, see or write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #import #import #import #import "AppKit/NSOpenGL.h" #import "AppKit/NSOpenGLView.h" // Declare a private method of NSView @interface NSView (Private) - (void) _lockFocusInContext: (NSGraphicsContext *)ctxt inRect: (NSRect)rect; - (void) _viewWillMoveToWindow: (NSWindow*)newWindow; @end /** NSOpenGLView

This class is simply a view with a NSOpenGLContext attached to it. This is the simplest way to initialize a GL context within GNUstep.

There is a mechanism to update the context when the view is moved or resize.

*/ static NSOpenGLPixelFormat *fmt = nil; static NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFADepthSize, 16, NSOpenGLPFAColorSize, 1, 0 }; // NSOpenGLPixelFormatAttribute attrs[] = // { // NSOpenGLPFADoubleBuffer, // NSOpenGLPFADepthSize, 32, // 0 // }; @implementation NSOpenGLView /** return a standard NSOpenGLPixelFormat you can pass to the initWithFrame: pixelFormat: method */ + (NSOpenGLPixelFormat*) defaultPixelFormat { // Initialize it once if (!fmt) fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: attrs]; if (fmt) return fmt; else { NSWarnMLog(@"could not find a reasonable pixel format..."); return nil; } } /** detach from the current context. You should call it before releasing this object. */ - (void) clearGLContext { if (glcontext) { [glcontext clearDrawable]; DESTROY(glcontext); prepared = NO; } } - (void) setOpenGLContext: (NSOpenGLContext*)context { if ( context != glcontext ) { [self clearGLContext]; ASSIGN(glcontext, context); } } - (void) prepareOpenGL { } /** return the current gl context associated with this view */ - (NSOpenGLContext*) openGLContext { if (glcontext == nil) { NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat: pixel_format shareContext: nil]; [self setOpenGLContext: context]; [context setView: self]; RELEASE(context); } return glcontext; } -(id) initWithFrame: (NSRect)frameRect { return [self initWithFrame: frameRect pixelFormat: [[self class] defaultPixelFormat]]; } /** default initializer. Can be passed [NSOpenGLView defaultPixelFormat] as second argument */ - (id) initWithFrame: (NSRect)frameRect pixelFormat: (NSOpenGLPixelFormat*)format { self = [super initWithFrame: frameRect]; if (!self) return nil; ASSIGN(pixel_format, format); [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_frameChanged:) name: NSViewGlobalFrameDidChangeNotification object: self]; [self setPostsFrameChangedNotifications: YES]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_frameChanged:) name: NSViewFrameDidChangeNotification object: self]; return self; } - (void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver: self]; [self clearGLContext]; RELEASE(pixel_format); NSDebugMLLog(@"GL", @"deallocating"); [super dealloc]; } - (NSOpenGLPixelFormat*) pixelFormat { return pixel_format; } - (void) setPixelFormat: (NSOpenGLPixelFormat*)pixelFormat { ASSIGN(pixel_format, pixelFormat); } - (void) reshape { } - (void) update { NSOpenGLContext *context; context = [self openGLContext]; if ([context view] == self) { [context update]; } } - (BOOL) isOpaque { return YES; } - (void) _frameChanged: (NSNotification *) aNot { if (prepared) { [[self openGLContext] makeCurrentContext]; [self update]; [self reshape]; } } /* FIXME: this should be done in [lockFocus] or [lockFocusInRect:]. */ - (void) _lockFocusInContext: (NSGraphicsContext *)ctxt inRect: (NSRect)rect { NSOpenGLContext *context; context = [self openGLContext]; [super _lockFocusInContext: ctxt inRect: rect]; [context makeCurrentContext]; if ([context view] != self) { [context setView:self]; } if (!prepared) { [self prepareOpenGL]; prepared = YES; [self reshape]; } } -(void) _viewWillMoveToWindow: (NSWindow *) newWindow { [super _viewWillMoveToWindow: newWindow]; if ([self window] != newWindow) { // the context will be recreated in the new window if needed [[self openGLContext] clearDrawable]; } } - (id) initWithCoder: (NSCoder *)aDecoder { self = [super initWithCoder: aDecoder]; if (!self) return nil; if ([aDecoder allowsKeyedCoding]) { [self setPixelFormat: [aDecoder decodeObjectForKey: @"NSPixelFormat"]]; } else { [self setPixelFormat: [[self class] defaultPixelFormat]]; } [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_frameChanged:) name: NSViewGlobalFrameDidChangeNotification object: self]; [self setPostsFrameChangedNotifications: YES]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_frameChanged:) name: NSViewFrameDidChangeNotification object: self]; return self; } @end