-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.mm
169 lines (146 loc) · 5.69 KB
/
main.mm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#import <Cocoa/Cocoa.h>
#import <QuartzCore/CVDisplayLink.h>
#import <OpenGL/gl.h>
// implement startup/update/shutdown, watch the threading: startup/shutdown are called on the main ui thread, update is called in the DisplayLink thread
// grab input events through the Window class below
// grab window resize event in app delegate
void minigl_startup()
{
NSLog(@"!! startup on thread: %@ %@", [NSThread currentThread].name, [NSThread currentThread]);
}
// not on main thread
void minigl_update()
{
NSLog(@"!! update on thread: %@ %@", [NSThread currentThread].name, [NSThread currentThread]);
glClearColor(0, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
}
void minigl_shutdown()
{
NSLog(@"!! shutdown on thread: %@ %@", [NSThread currentThread].name, [NSThread currentThread]);
}
///////////////////////////////////////////////////
static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
NSOpenGLView* glview = (__bridge NSOpenGLView*)displayLinkContext;
NSOpenGLContext* glcontext = [glview openGLContext];
[glcontext makeCurrentContext];
minigl_update();
[glcontext flushBuffer];
return kCVReturnSuccess;
}
@interface LEAppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate>
{
CVDisplayLinkRef _displayLink;
}
@property (assign) IBOutlet NSWindow *window;
@end
@implementation LEAppDelegate
@synthesize window;
-(void)dealloc
{
CVDisplayLinkRelease(_displayLink);
}
- (void) quitAction: (id)sender
{
CVDisplayLinkStop(_displayLink);
minigl_shutdown();
[[NSApplication sharedApplication] terminate: nil];
}
- (void)windowDidResize:(NSNotification *)notification
{
//NSRect curFrame = [self.window contentRectForFrameRect:self.window.frame];
// TODO: send resize event
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
GLint swapInt = 1;
NSOpenGLView* glview = (NSOpenGLView*)self.window.contentView;
NSOpenGLContext* glcontext = glview.openGLContext;
[glcontext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
CVDisplayLinkSetOutputCallback(_displayLink, &displayLinkCallback, (__bridge void*)glview);
CGLContextObj cglContext = (CGLContextObj)[glcontext CGLContextObj];
CGLPixelFormatObj cglPixelFormat = (CGLPixelFormatObj)[[glview pixelFormat] CGLPixelFormatObj];
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(_displayLink, cglContext, cglPixelFormat);
CVDisplayLinkStart(_displayLink);
}
@end
@interface LEWindow : NSWindow
@end
@implementation LEWindow
-(void)keyDown:(NSEvent *)theEvent {}
-(void)keyUp:(NSEvent *)theEvent {}
-(void)mouseDown:(NSEvent *)theEvent {}
-(void)mouseUp:(NSEvent *)theEvent {}
-(void)mouseDragged:(NSEvent *)theEvent {}
-(void)mouseMoved:(NSEvent *)theEvent {}
@end
int main(int argc, char *argv[])
{
NSApplication* app = [NSApplication sharedApplication];
LEAppDelegate* appDelegate = [[LEAppDelegate alloc] init]; // required for some important callbacks
// setup very basic menu so we can at least CMD-Q quit
NSMenu *menu;
NSMenuItem *menu_item, *temp_item;
NSString* title = nil;
NSDictionary* app_dictionary = [[NSBundle mainBundle] infoDictionary];
if (app_dictionary)
{
title = [app_dictionary objectForKey: @"CFBundleName"];
}
if (title == nil)
{
title = [[NSProcessInfo processInfo] processName];
}
NSMenu *main_menu = [[NSMenu alloc] initWithTitle: @"temp"];
[app setMainMenu: main_menu];
menu = [[NSMenu alloc] initWithTitle: @"temp"];
temp_item = [[NSMenuItem alloc]
initWithTitle: @"temp"
action: NULL
keyEquivalent: @""];
[[app mainMenu] addItem: temp_item];
[[app mainMenu] setSubmenu: menu forItem: temp_item];
NSString *quit = [@"Quit " stringByAppendingString: title];
menu_item = [[NSMenuItem alloc]
initWithTitle: quit
action: @selector(quitAction:)
keyEquivalent: @"q"];
[menu_item setKeyEquivalentModifierMask: NSCommandKeyMask];
[menu_item setTarget: appDelegate];
[menu addItem: menu_item];
[app setDelegate: appDelegate];
CGFloat width = 640;
CGFloat height = 480;
CGRect fr = CGRectMake(0, 0, width, height);
const NSOpenGLPixelFormatAttribute windowedAttributes[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
NSOpenGLPFAColorSize, [[[NSUserDefaults standardUserDefaults] objectForKey:@"colorDepth"] unsignedIntValue],
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFADepthSize, 32,
0
};
NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes: windowedAttributes];
NSOpenGLView* glview = [[NSOpenGLView alloc] initWithFrame:fr pixelFormat:pixelFormat];
// make context current for this thread to be able to safely call startup
[[glview openGLContext] makeCurrentContext];
minigl_startup();
[NSOpenGLContext clearCurrentContext]; // then clear the context for this thread, so it's later only active on the render thread
LEWindow* window = [[LEWindow alloc]
initWithContentRect: fr
styleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask
backing: NSBackingStoreBuffered
defer: NO];
[window setTitle: @"Minimal GL App"];
[window setAcceptsMouseMovedEvents: YES];
[window setContentView: glview];
[window setDelegate: appDelegate];
[window setReleasedWhenClosed: NO];
[window makeKeyAndOrderFront:nil]; // shows and focuses the window
appDelegate.window = window;
[app run]; // runs the actual app, doesn't return
return EXIT_SUCCESS;
}