started macos port by adapting the old SGL code macos
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 5 Sep 2023 20:07:00 +0000 (23:07 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 5 Sep 2023 20:07:00 +0000 (23:07 +0300)
Makefile
miniglut.c
miniglut.h
miniglut_osx.m [new file with mode: 0644]

index c110e36..55d55c7 100644 (file)
--- 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
index 16bb7b9..75de147 100644 (file)
@@ -34,7 +34,6 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 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 <GL/gl.h>
+
+static int cmap_size;
+
 #include "miniglut.h"
 
 #ifdef _MSC_VER
index 9eebee0..bfb279b 100644 (file)
@@ -30,7 +30,12 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 #endif /* MSVC */
 
 #endif
+
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#else
 #include <GL/gl.h>
+#endif
 
 /* mode flags for glutInitDisplayMode */
 #define GLUT_RGB                       0
diff --git a/miniglut_osx.m b/miniglut_osx.m
new file mode 100644 (file)
index 0000000..e52a6d9
--- /dev/null
@@ -0,0 +1,525 @@
+/*
+MiniGLUT - minimal GLUT subset without dependencies
+Copyright (C) 2020-2023  John Tsiombikas <nuclear@member.fsf.org>
+
+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 <https://www.gnu.org/licenses/>.
+ */
+#import <Cocoa/Cocoa.h>
+#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 <NSWindowDelegate>
+{
+       @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;
+}