(Sorry in advance for the seemingly large amount of code here) I'm trying to create a window with an OpenGL context with Cocoa, but I'm finding that I am unable to set the view property of the NSOpenGLContext
that I create.
I cannot simply use an NSOpenGLView
, since I need to interface with a C++ drawing backend and use multiple contexts. The code I post here is just me trying to get to grips with handling NSOpenGLContext
s, but it will be used in a much larger project. This is why I'm instantiating NSApplication
and my NSWindow
manually rather than through a NIB/NSApplicationMain
.
My main.m file:
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import "Delegate.h"
int main(int argc, const char * argv[]) {
[NSApplication sharedApplication];
Delegate* dlg = [[Delegate alloc] init];
[NSApp setDelegate:dlg];
[NSApp run];
return 0;
}
I then have my delegate class, and I'll refrain from posting the file Delegate.h since it'll be pretty obvious what's there given these contents of Delegate.m:
#import <Cocoa/Cocoa.h>
#import "Delegate.h"
#import <OpenGL/gl.h>
@implementation Delegate
- (void) draw
{
[self.glContext makeCurrentContext];
glClearColor(1, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
[self.glContext flushBuffer];
}
- (void) applicationDidFinishLaunching:(NSNotification *)notification
{
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
self.win = [[NSWindow alloc] initWithContentRect:NSMakeRect(30, 30, 300, 200)
styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask
backing:NSBackingStoreBuffered
defer:YES];
NSOpenGLPixelFormatAttribute glAttributes[] =
{
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
0
};
self.glContext = [[NSOpenGLContext alloc] initWithFormat:[[NSOpenGLPixelFormat alloc] initWithAttributes:glAttributes]
shareContext:nil];
[self.glContext setView: [self.win contentView]];
printf("view:%p, contentView:%p\n", [self.glContext view], [self.win contentView]);
[self.win makeKeyAndOrderFront:nil];
[NSTimer
scheduledTimerWithTimeInterval:.1
target:self
selector:@selector(draw)
userInfo:nil
repeats:YES];
}
The window opens just fine. I am able to tell that -applicationDidFinishLaunching
and -draw
are being called. The window shows up empty however.
The printf call shows that the view property of self.glContext
is equal to the address 0x0. I see no documentation or other forum threads about why I would be unable to set the drawable object of an NSOpenGLContext
.
I have tried putting the NSOpenGLContext
in its own subclass of NSView
and adding that subclass as a subview of the window's content view, but with no success.
Try setting the defer
parameter of -[NSWindow initWithContentRect:...]
to NO
. You may also wish to set the GL context's view after ordering the window on-screen.
Basically, -[NSOpenGLContext setView:]
can fail if the view's window doesn't yet have a "device". When that's happened to me, it usually logs a message to the console about an "invalid drawable", but I haven't checked in recent versions of the OS.
Also, you need to register as an observer of the NSViewGlobalFrameDidChangeNotification
notification from the view and, in response, call -update
on the GL context object.