From: John Tsiombikas Date: Tue, 5 Sep 2023 20:07:00 +0000 (+0300) Subject: started macos port by adapting the old SGL code X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=commitdiff_plain;h=cf7d57d72f809ee0c5840683547227167049be99;p=miniglut started macos port by adapting the old SGL code --- diff --git a/Makefile b/Makefile index c110e36..55d55c7 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,10 @@ ifeq ($(sys), mingw) bin = test.exe LDFLAGS = -mconsole -lopengl32 -lgdi32 -lwinmm +else ifeq ($(sys), Darwin) + olib += miniglut_osx.o + CFLAGS += -DMINIGLUT_USE_LIBC + LDFLAFS = -framework OpenGL -framework Cocoa else ifeq ($(sys)-$(isx86), Linux-x86) CFLAGS += -I/usr/X11R6/include diff --git a/miniglut.c b/miniglut.c index 16bb7b9..75de147 100644 --- a/miniglut.c +++ b/miniglut.c @@ -34,7 +34,6 @@ along with this program. If not, see . static Display *dpy; static Window win, root; static Colormap cmap; -static int cmap_size; static int scr; static GLXContext ctx; static Atom xa_wm_proto, xa_wm_del_win; @@ -58,12 +57,13 @@ static HWND win; static HDC dc; static HGLRC ctx; static HPALETTE cmap; -static int cmap_size; #else -#error unsupported platform +/*#error unsupported platform*/ #endif -#include + +static int cmap_size; + #include "miniglut.h" #ifdef _MSC_VER diff --git a/miniglut.h b/miniglut.h index 9eebee0..bfb279b 100644 --- a/miniglut.h +++ b/miniglut.h @@ -30,7 +30,12 @@ along with this program. If not, see . #endif /* MSVC */ #endif + +#ifdef __APPLE__ +#include +#else #include +#endif /* mode flags for glutInitDisplayMode */ #define GLUT_RGB 0 diff --git a/miniglut_osx.m b/miniglut_osx.m new file mode 100644 index 0000000..e52a6d9 --- /dev/null +++ b/miniglut_osx.m @@ -0,0 +1,525 @@ +/* +MiniGLUT - minimal GLUT subset without dependencies +Copyright (C) 2020-2023 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + */ +#import +#include "miniglut.h" + +@interface OpenGLView : NSOpenGLView +{ + int foo; +} + +-(id) initWithFrame: (NSRect) frame pixelFormat: (NSOpenGLPixelFormat*) pf; + +-(void) drawRect: (NSRect) rect; +-(void) reshape; +-(void) keyDown: (NSEvent*) ev; +-(void) keyUp: (NSEvent*) ev; +-(void) mouseDown: (NSEvent*) ev; +-(void) mouseUp: (NSEvent*) ev; +-(void) rightMouseDown: (NSEvent*) ev; +-(void) rightMouseUp: (NSEvent*) ev; +-(void) otherMouseDown: (NSEvent*) ev; +-(void) otherMouseUp: (NSEvent*) ev; +-(void) mouseDragged: (NSEvent*) ev; +-(void) rightMouseDragged: (NSEvent*) ev; +-(void) otherMouseDragged: (NSEvent*) ev; + +-(BOOL) acceptsFirstResponder; +@end + + +@interface AppDelegate : NSObject +{ + int foo; +} + +-(void) applicationWillFinishLaunching: (NSNotification*) notification; +-(void) applicationDidFinishLaunching: (NSNotification*) notification; + +-(BOOL) applicationShouldTerminate: (NSApplication*) app; +-(BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication*) app; +-(void) applicationWillTerminate: (NSNotification*) notification; +@end + +struct window; + +@interface WinDelegate : NSObject +{ + @public + struct window *win; +} +-(id) init; +-(void) dealloc; + +-(void) windowDidExpose: (NSNotification*) notification; +-(void) windowDidResize: (NSNotification*) notification; +-(BOOL) windowShouldClose: (id) win; +-(void) windowWillClose: (NSNotification*) notification; +@end + + +static int init(void); +static void shutdown(void); + +/* video mode switching */ +static int set_vidmode(int xsz, int ysz); +static int get_vidmode(int *xsz, int *ysz); + +/* create/destroy windows */ +static int create_window(int xsz, int ysz, unsigned int flags); +static void close_window(void); + +/* window management */ +static int set_title(const char *str); +static void redisplay(void); +static void swap_buffers(void); + +static int get_modifiers(void); + +/* event handling and friends */ +static void set_event(int idx, int enable); +static int process_events(void); + +static void select_event_window(NSEvent *ev); +static void handle_key(NSEvent *ev, int state); +static void handle_mouse(NSEvent *ev, int state); +static void handle_motion(NSEvent *ev); + +static void fill_attr(NSOpenGLPixelFormatAttribute *attr, unsigned int flags); + + +static glut_cb cb_display; +static glut_cb cb_idle; +static glut_cb_reshape cb_reshape; +static glut_cb_state cb_vis, cb_entry; +static glut_cb_keyb cb_keydown, cb_keyup; +static glut_cb_special cb_skeydown, cb_skeyup; +static glut_cb_mouse cb_mouse; +static glut_cb_motion cb_motion, cb_passive; +static glut_cb_sbmotion cb_sball_motion, cb_sball_rotate; +static glut_cb_sbbutton cb_sball_button; + +static int win_width, win_height; +static NSWindow *glwin; +static OpenGLView *glview; +static NSOpenGLContext *glctx; +static int needs_redisplay; +static int quit_main_loop; + +static NSAutoreleasePool *global_pool; + + +void glutInit(int *argc, char **argv) +{ +} + + + +@implementation OpenGLView + +-(id) initWithFrame: (NSRect) frame pixelFormat: (NSOpenGLPixelFormat*) pf +{ + self = [super initWithFrame: frame pixelFormat: pf]; + return self; +} + +-(void) drawRect: (NSRect) rect +{ + cb_display(); +} + +-(void) reshape +{ + NSSize sz = [self bounds].size; + + if(cb_reshape && (sz.width != win_width || sz.height != win_height)) { + win_width = sz.width; + win_height = sz.height; + cb_reshape(sz.width, sz.height); + } +} + +-(void) keyDown: (NSEvent*) ev +{ + handle_key(ev, 1); +} + +-(void) keyUp: (NSEvent*) ev +{ + handle_key(ev, 0); +} + +-(void) mouseDown: (NSEvent*) ev +{ + handle_mouse(ev, 1); +} + +-(void) mouseUp: (NSEvent*) ev +{ + handle_mouse(ev, 0); +} + +-(void) rightMouseDown: (NSEvent*) ev +{ + handle_mouse(ev, 1); +} + +-(void) rightMouseUp: (NSEvent*) ev +{ + handle_mouse(ev, 0); +} + +-(void) otherMouseDown: (NSEvent*) ev +{ + handle_mouse(ev, 1); +} + +-(void) otherMouseUp: (NSEvent*) ev +{ + handle_mouse(ev, 0); +} + +-(void) mouseDragged: (NSEvent*) ev +{ + handle_motion(ev); +} + +-(void) rightMouseDragged: (NSEvent*) ev +{ + handle_motion(ev); +} + +-(void) otherMouseDragged: (NSEvent*) ev +{ + handle_motion(ev); +} + + +-(BOOL) acceptsFirstResponder +{ + return YES; +} +@end + +@implementation AppDelegate +-(void) applicationWillFinishLaunching: (NSNotification*) notification +{ +} + +-(void) applicationDidFinishLaunching: (NSNotification*) notification +{ +} + +-(BOOL) applicationShouldTerminate: (NSApplication*) app +{ + return NSTerminateNow; +} + +-(BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication*) app +{ + return YES; +} + +-(void) applicationWillTerminate: (NSNotification*) notification +{ + /*[NSApp setDelegate: nil]; + [global_pool drain];*/ +} +@end + +@implementation WinDelegate +-(id) init +{ + self = [super init]; + return self; +} + +-(void) dealloc +{ + [super dealloc]; +} + +-(void) windowDidExpose: (NSNotification*) notification +{ +} + +-(void) windowDidResize: (NSNotification*) notification +{ +} + +-(BOOL) windowShouldClose: (id) win +{ + close_window(); + return YES; +} + +-(void) windowWillClose: (NSNotification*) notification +{ + /*[NSApp terminate: nil];*/ +} +@end + +static int init(void) +{ + AppDelegate *delegate; + + global_pool = [[NSAutoreleasePool alloc] init]; + + [NSApplication sharedApplication]; + + delegate = [[AppDelegate alloc] init]; + [NSApp setDelegate: delegate]; + return 0; +} + +static void shutdown(void) +{ + close_window(); + + quit_main_loop = 1; + [NSApp terminate: nil]; +} + + +/* create/destroy windows */ +static int create_window(int xsz, int ysz, unsigned int flags) +{ + NSAutoreleasePool *pool; + WinDelegate *delegate; + NSWindow *nswin; + NSRect rect; + OpenGLView *view; + NSOpenGLPixelFormat *pf; + NSOpenGLPixelFormatAttribute attr[32]; + unsigned int style; + + pool = [[NSAutoreleasePool alloc] init]; + + /* create the view */ + fill_attr(attr, flags); + pf = [[[NSOpenGLPixelFormat alloc] initWithAttributes: attr] autorelease]; + view = [[OpenGLView alloc] initWithFrame: rect pixelFormat: pf]; + + /* create the window and attach the OpenGL view */ + rect.origin.x = rect.origin.y = 0; + rect.size.width = xsz; + rect.size.height = ysz; + + style = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | + NSResizableWindowMask; + + nswin = [[NSWindow alloc] initWithContentRect: rect styleMask: style + backing: NSBackingStoreBuffered defer: YES]; + + delegate = [[WinDelegate alloc] init]; + + [nswin setDelegate: delegate]; + [nswin setTitle: @"OpenGL/Cocoa"]; + [nswin setReleasedWhenClosed: YES]; + [nswin setContentView: view]; + [nswin makeFirstResponder: view]; + [nswin makeKeyAndOrderFront: nil]; + [view release]; + + glwin = nswin; + glview = view; + glctx = [view openGLContext]; + needs_redisplay = 1; + + delegate->win = glwin; + + [glctx makeCurrentContext]; + [pool drain]; + return win->wid; +} + +static void close_window(void) +{ + [glwin close]; + shutdown(); +} + +static int set_title(const char *str) +{ + NSString *nsstr; + + nsstr = [[NSString alloc] initWithCString: str encoding: NSASCIIStringEncoding]; + [glwin setTitle: nsstr]; + [nsstr release]; + return 0; +} + +static void redisplay(void) +{ + needs_redisplay = 1; +} + +static void swap_buffers(void) +{ + [glctx flushBuffer]; +} + + +static int get_modifiers(void) +{ + unsigned int nsmod = [NSEvent modifierFlags]; + unsigned int mod = 0; + + if(nsmod & NSShiftKeyMask) { + mod |= GLUT_ACTIVE_SHIFT; + } + if(nsmod & NSControlKeyMask) { + mod |= GLUT_ACTIVE_CTRL; + } + if(nsmod & NSAlternateKeyMask) { + mod |= GLUT_ACTIVE_ALT; + } + return mod; +} + +static int process_events(void) +{ + NSAutoreleasePool *pool; + NSRunLoop *runloop; + NSDate *block, *nonblock, *limdate; + + pool = [[NSAutoreleasePool alloc] init]; + + if(needs_redisplay) { + needs_redisplay = 0; + cb_display(); + } + + runloop = [[NSRunLoop currentRunLoop] retain]; + block = [runloop limitDateForMode: NSDefaultRunLoopMode]; + nonblock = [[NSDate distantPast] retain]; + limdate = idle ? nonblock : block; + + while(!quit_main_loop) { + NSEvent *ev = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: limdate + inMode: NSDefaultRunLoopMode dequeue: YES]; + if(!ev) break; + + [NSApp sendEvent: ev]; + if(limdate == block) { + limdate = nonblock; + } + } + + if(cb_idle) { + cb_idle(); + } + + [runloop release]; + [pool drain]; + + return quit_main_loop ? -1 : 0; +} + +static void handle_key(NSEvent *ev, int state) +{ + NSPoint pt; + NSString *str; + unichar c; + + str = [ev characters]; + if(![str length]) { + return; + } + + pt = [ev locationInWindow]; + c = [str characterAtIndex: 0]; + if(state) { + if(c < 256) { + if(cb_keydown) cb_keydown(c, pt.x, pt.y); + } else { + if(cb_skeydown) cb_skeydown(c, pt.x, pt.y); + } + } else { + if(c < 256) { + if(cb_keyup) cb_keyup(c, pt.x, pt.y); + } else { + if(cb_skeyup) cb_skeyup(c, pt.x, pt.y); + } + } +} + +static void handle_mouse(NSEvent *ev, int state) +{ + int bn; + NSPoint pt; + + if(cb_mouse) { + bn = [ev buttonNumber]; + if(bn == 2) { + bn = 1; + } else if(bn == 1) { + bn = 2; + } + pt = [ev locationInWindow]; + + cb_mouse(0, bn, state, pt.x, pt.y - 1); + } +} + +static void handle_motion(NSEvent *ev) +{ + NSPoint pt; + + if(cb_motion) { + pt = [ev locationInWindow]; + cb_motion(0, pt.x, pt.y - 1); + } +} + +static void fill_attr(NSOpenGLPixelFormatAttribute *attr, unsigned int flags) +{ + int i = 0; + + /* this is very important. makes pixelformat selection behave like GLX + * where any non-zero value will denote "choose highest possible". This + * is pretty much what we intend, as the user doesn't actually pass any + * of these numbers. + */ + attr[i++] = NSOpenGLPFAMaximumPolicy; + + attr[i++] = NSOpenGLPFAColorSize; + attr[i++] = 1; + + if(flags & SGL_DOUBLE) { + attr[i++] = NSOpenGLPFADoubleBuffer; + } + if(flags & SGL_DEPTH) { + attr[i++] = NSOpenGLPFADepthSize; + attr[i++] = 1; + } + if(flags & SGL_STENCIL) { + attr[i++] = NSOpenGLPFAStencilSize; + attr[i++] = 8; /* max-policy has no effect on stencil selection */ + } + if(flags & SGL_STEREO) { + attr[i++] = NSOpenGLPFAStereo; + } + if(flags & SGL_MULTISAMPLE) { + attr[i++] = NSOpenGLPFASampleBuffers; + attr[i++] = 1; + attr[i++] = NSOpenGLPFASamples; + attr[i++] = 4; /* TODO don't hardcode, query */ + } + attr[i++] = 0; +}