Began building out the osx platform layer

This commit is contained in:
Peter Slattery 2020-03-29 16:47:47 -07:00
parent b843937295
commit f874ba5289
9 changed files with 423 additions and 0 deletions

7
build_osx.sh Executable file
View File

@ -0,0 +1,7 @@
pushd build
clang++ ../osx/gs_osx.mm \
-g \
-Wno-c11-extensions -Wno-unused-variable -Wno-unused-function \
-framework Cocoa -framework OpenGL \
-o osx_foldhaus.out
popd

28
src/first.cpp Normal file
View File

@ -0,0 +1,28 @@
#include <stdio.h>
#include <objc/message.h>
#include <objc/runtime.h>
typedef struct AppDel {
Class isa;
id window;
} AppDelegate;
BOOL AppDel_didFinishLaunching(AppDelegate* self, SEL _command, id Notification)
{
return YES;
}
int main(int ArgCount, char** Args)
{
Class NSApplicationClass = (Class)objc_getClass("NSApplication");
Class AppDelegateClass = objc_allocateClassPair(NSApplicationClass, "AppDelegate", 0);
SEL MethodSelector = sel_getUid("applicationDidFinishLaunching:");
// NOTE(Peter): i = int, @ = object, : = method selector (SEL)
char MethodSignature[] = "i@:@";
class_addMethod(AppDelegateClass, MethodSelector, (IMP)AppDel_didFinishLaunching, "i@:@");
objc_registerClassPair(AppDelegateClass);
return 0;
}

76
src/gs_osx.mm Normal file
View File

@ -0,0 +1,76 @@
#include <Cocoa/Cocoa.h>
#include "gs_osx_memory.mm"
#include "gs_osx_window.mm"
#include "gs_osx_fileio.mm"
#include "gs_osx_lib.mm"
#include "gs_osx_opengl.mm"
#include "gs_osx_time.mm"
static void
gsosx_ProcessWindowEvents(NSApplication* App, NSWindow* Window)
{
// Process Events
while (true)
{
NSEvent* Event = [App nextEventMatchingMask: NSEventMaskAny untilDate: [NSDate distantPast] inMode: NSDefaultRunLoopMode dequeue: YES];
if (!Event) { break; }
switch([Event type])
{
case NSEventTypeKeyUp:
case NSEventTypeKeyDown:
{
// TODO: Handle Key Presses
}break;
// TODO: Mouse Input
default:
{
[App sendEvent: Event];
}break;
}
}
}
int main(int ArgCount, char** Args)
{
NSApplication* Application = [NSApplication sharedApplication];
[Application setActivationPolicy: NSApplicationActivationPolicyRegular];
gsosx_ApplicationDelegate* Delegate = [[gsosx_ApplicationDelegate alloc] init];
[Application setDelegate: Delegate];
int WindowWidth = 1024;
int WindowHeight = 768;
id AppName = @"Lumenarium";
NSWindow* Window = gsosx_CreateWindow(Application, WindowWidth, WindowHeight, AppName);
// A really cryptic way of asking the window to open
[Window makeKeyAndOrderFront: Application];
NSOpenGLContext* OpenGLContext = gsoo_CreateOpenGLContext(Window, WindowWidth, WindowHeight, true);
gsosx_time_info TimeInfo = gsosx_InitTime();
double TargetSecondsPerFrame = 1.0 / 60;
uint64_t LastFrameEnd = gsosx_GetTime(TimeInfo);
while (true)
{
gsosx_ProcessWindowEvents(Application, Window);
glClearColor(1, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gsoo_SwapBuffers(OpenGLContext);
uint64_t ThisFrameEnd = gsosx_GetTime(TimeInfo);
double FrameSeconds = gsosx_GetSecondsElapsed(LastFrameEnd, ThisFrameEnd, TimeInfo);
double SleepSeconds = TargetSecondsPerFrame - FrameSeconds;
if (SleepSeconds > 0)
{
gsosx_Sleep(SleepSeconds, TimeInfo);
}
}
return (0);
}

63
src/gs_osx_fileio.mm Normal file
View File

@ -0,0 +1,63 @@
#include <sys/stat.h>
static uint32_t
gsosx_GetLastFileWriteTime(char* Path)
{
int32_t Result = 0;
struct stat FileStat = {0};
if (stat(Path, &FileStat) == 0)
{
Result = FileStat.st_mtimespec.tv_sec;
}
else
{
// TODO: Asserts
}
return Result;
}
static uint32_t
gsosx_GetFilesize(char* Path)
{
uint32_t Result = 0;
int FileHandle = open(Path, O_RDONLY);
struct stat FileStat = {0};
fstat(FileHandle, &FileStat);
close(FileHandle);
Result = (uint32_t)FileStat.st_size;
return Result;
}
static bool
gsosx_LoadFileIntoMemory(char* Path, uint32_t FileSize, uint8_t* FileMemory)
{
bool Result = false;
int FileHandle = open(Path, O_RDONLY);
struct stat FileStat = {0};
fstat(FileHandle, &FileStat);
if (FileStat.st_size <= FileSize)
{
read(FileHandle, FileMemory, FileSize);
Result = true;
}
close(FileHandle);
return Result;
}
static bool
gsosx_WriteEntireFile(char* Path, uint32_t FileSize, uint8_t* FileMemory)
{
bool Result = false;
int FileHandle = open(Path, O_WRONLY | O_CREAT, 0777);
ssize_t SizeWritten = write(FileHandle, FileMemory, FileSize);
if (SizeWritten == FileSize)
{
Result = true;
}
close(FileHandle);
return Result;
}

30
src/gs_osx_lib.mm Normal file
View File

@ -0,0 +1,30 @@
#include <dlfcn.h>
static void*
gsosx_LoadDLL(char* Path)
{
void* LibHandle = 0;
LibHandle = dlopen(Path, RTLD_LAZY);
if (LibHandle)
{
dlerror(); // Clear Last Error
}
else
{
LibHandle = 0;
}
return LibHandle;
}
#define gsosx_GetProcAddress(libHandle, type, name) (type*)dlsym((libHandle), name)
static void
gsosx_UnloadDLL(void* LibHandle)
{
if (LibHandle)
{
dlclose(LibHandle);
}
}

30
src/gs_osx_memory.mm Normal file
View File

@ -0,0 +1,30 @@
#include <stdlib.h>
static uint8_t*
gsosx_Alloc(size_t Size)
{
uint8_t* Result = 0;
char* StartAddress = (char*)0;
int Prot = PROT_READ | PROT_WRITE;
int Flags = MAP_PRIVATE | MAP_ANON;
Result = (uint8_t*)mmap(StartAddress, Size, Prot, Flags, -1, 0);
return Result;
}
static void
gsosx_Free(uint8_t* Base, uint32_t Size)
{
munmap((void*)Base, (size_t)Size);
}
static uint8_t*
gsosx_Realloc(uint8_t* Base, uint32_t OldSize, uint32_t NewSize)
{
uint8_t* Result = gsosx_Alloc(NewSize);
for (int32_t i = 0; i < OldSize; i++)
{
Result[i] = Base[i];
}
gsosx_Free(Base, OldSize );
return Result;
}

65
src/gs_osx_opengl.mm Normal file
View File

@ -0,0 +1,65 @@
#include <OpenGL/gl.h>
struct gsoo_opengl_state
{
NSOpenGLContext* Context;
};
@interface gsoo_OpenGLView: NSOpenGLView @end
@implementation gsoo_OpenGLView : NSOpenGLView
- (void)
reshape
{
// TODO: framebufferWidth and Height were globals in the code I was pulling from
// Need some way to get the new window height in here.
CGRect FrameRect = self.frame;
glViewport(0, 0, FrameRect.size.width, FrameRect.size.height);
//glViewport(0, 0, framebufferWidth, framebufferHeight);
}
@end
static NSOpenGLContext*
gsoo_CreateOpenGLContext(NSWindow* Window, uint32_t Width, uint32_t Height, int32_t EnableVSync)
{
NSOpenGLContext* Result = 0;
NSOpenGLPixelFormatAttribute PixelFormatAttributes[] = {
NSOpenGLPFAClosestPolicy,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFASampleBuffers,
0,
0
};
NSOpenGLPixelFormat* PixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes: PixelFormatAttributes];
Result = [[NSOpenGLContext alloc] initWithFormat: PixelFormat shareContext: 0];
if (!Result)
{
// TODO: Assert/Handle
return 0;
}
[Result makeCurrentContext];
GLint VSync = EnableVSync;
[Result setValues: &VSync forParameter: NSOpenGLCPSwapInterval];
// Set Backbuffer Resolution
GLint BackbufferDimensions[] = { Width, Height };
CGLSetParameter(Result.CGLContextObj, kCGLCPSurfaceBackingSize, BackbufferDimensions);
CGLEnable(Result.CGLContextObj, kCGLCESurfaceBackingSize);
//
gsoo_OpenGLView* View = [[gsoo_OpenGLView alloc] init];
[Window setContentView: View];
[View setOpenGLContext: Result];
[View setPixelFormat: PixelFormat];
[Result setView: View];
return Result;
}
static void
gsoo_SwapBuffers(NSOpenGLContext* OpenGLContext)
{
[OpenGLContext flushBuffer];
}

46
src/gs_osx_time.mm Normal file
View File

@ -0,0 +1,46 @@
#include <mach/mach_time.h>
static const uint64_t NANOS_PER_USEC = 1000ULL;
static const uint64_t NANOS_PER_MILLISEC = 1000ULL * NANOS_PER_USEC;
static const uint64_t NANOS_PER_SEC = 1000ULL * NANOS_PER_MILLISEC;
struct gsosx_time_info
{
uint64_t StartTimeAbsolute;
mach_timebase_info_data_t MachTimeInfo;
};
static gsosx_time_info
gsosx_InitTime()
{
gsosx_time_info Result = {0};
Result.StartTimeAbsolute = mach_absolute_time();
mach_timebase_info(&Result.MachTimeInfo);
return Result;
}
static uint64_t
gsosx_GetTime(gsosx_time_info TimeInfo)
{
uint64_t Result = mach_absolute_time() - TimeInfo.StartTimeAbsolute;
return Result;
}
static double
gsosx_GetSecondsElapsed(uint64_t Start, uint64_t End, gsosx_time_info TimeInfo)
{
double Result = 0;
double Elapsed = (double)(End - Start);
Result = Elapsed * (double)(TimeInfo.MachTimeInfo.numer) / (double)NANOS_PER_SEC / (double)TimeInfo.MachTimeInfo.denom;
return Result;
}
static void
gsosx_Sleep(double Seconds, gsosx_time_info TimeInfo)
{
// NOTE(Peter): This isn't entirely precise, and can vary by up to 500 microseconds. We could implement a sleep combined witha busy wait
// to get more precise sleeping. Do this if necessary
uint64_t WaitTimeAbs = Seconds / (double)TimeInfo.MachTimeInfo.numer * (double)NANOS_PER_SEC * (double)TimeInfo.MachTimeInfo.denom;
uint64_t NowAbs = mach_absolute_time();
mach_wait_until(NowAbs + WaitTimeAbs);
}

78
src/gs_osx_window.mm Normal file
View File

@ -0,0 +1,78 @@
@interface gsosx_ApplicationDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate> @end
@implementation gsosx_ApplicationDelegate : NSObject
- (void)
applicationDidFinishLaunching: (NSNotification *)notification
{
[NSApp stop: nil];
NSAutoreleasePool* Pool = [[NSAutoreleasePool alloc] init];
[Pool drain];
}
- (NSApplicationTerminateReply)
applicationShouldTerminate: (NSApplication*) sender
{
return NO;
}
- (void)
dealloc
{
[super dealloc];
}
@end
@interface gsosx_WindowDelegate: NSObject<NSWindowDelegate> @end
@implementation gsosx_WindowDelegate : NSObject
- (BOOL)
windowShouldClose: (id)sender
{
// TODO(Peter): Stop Application Running?
NSLog(@"Close button pressed");
return NO;
}
- (void)
windowDidBecomeKey: (NSNotification*)notification
{
// TODO: ???
}
- (void)
windowDisResignKey: (NSNotification*)notification
{
// TODO: ???
}
@end
static NSWindow*
gsosx_CreateWindow(NSApplication* App, int Width, int Height, id Title)
{
int WindowStyleMask = NSWindowStyleMaskClosable;
NSRect WindowRect = NSMakeRect(0, 0, Width, Height);
NSWindow* Window = [[NSWindow alloc] initWithContentRect: WindowRect styleMask: WindowStyleMask backing: NSBackingStoreBuffered defer: YES];
Window.styleMask = NSWindowStyleMaskResizable | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable;
gsosx_WindowDelegate* WindowDelegate = [[gsosx_WindowDelegate alloc] init];
[Window setOpaque: YES];
[Window setDelegate: WindowDelegate];
[Window setTitle: Title];
NSMenu* MenuBar = [NSMenu alloc];
NSMenuItem* AppMenuItem = [NSMenuItem alloc];
[MenuBar addItem: AppMenuItem];
[App setMainMenu: MenuBar];
NSMenu* AppMenu = [NSMenu alloc];
id QuitTitle = [@"Quit " stringByAppendingString: Title];
id QuitMenuItem = [[NSMenuItem alloc] initWithTitle: QuitTitle action: @selector(terminate:) keyEquivalent: @"q"];
[AppMenu addItem: QuitMenuItem];
[AppMenuItem setSubmenu: AppMenu];
[App activateIgnoringOtherApps: YES];
return Window;
}