diff --git a/src/core/platform.h b/src/core/platform.h index 5784b8e5..4f127777 100644 --- a/src/core/platform.h +++ b/src/core/platform.h @@ -56,10 +56,11 @@ typedef void (*keyboardCallback)(KeyCode key, ButtonAction action); bool lovrPlatformInit(void); void lovrPlatformDestroy(void); const char* lovrPlatformGetName(void); -void lovrPlatformPollEvents(void); double lovrPlatformGetTime(void); void lovrPlatformSetTime(double t); +void lovrPlatformSleep(double seconds); void lovrPlatformOpenConsole(void); +void lovrPlatformPollEvents(void); bool lovrPlatformCreateWindow(WindowFlags* flags); bool lovrPlatformHasWindow(void); void lovrPlatformGetWindowSize(int* width, int* height); @@ -75,7 +76,6 @@ void lovrPlatformGetMousePosition(double* x, double* y); void lovrPlatformSetMouseMode(MouseMode mode); bool lovrPlatformIsMouseDown(MouseButton button); bool lovrPlatformIsKeyDown(KeyCode key); -void lovrPlatformSleep(double seconds); #ifdef _WIN32 #include HANDLE lovrPlatformGetWindow(void); diff --git a/src/core/platform_glfw.c.h b/src/core/platform_glfw.c.h index 00f7624a..80435f65 100644 --- a/src/core/platform_glfw.c.h +++ b/src/core/platform_glfw.c.h @@ -18,31 +18,35 @@ static struct { windowResizeCallback onWindowResize; mouseButtonCallback onMouseButton; keyboardCallback onKeyboardEvent; -} state; +} glfwState; + +static void onError(int code, const char* description) { + lovrThrow(description); +} static void onWindowClose(GLFWwindow* window) { - if (state.onWindowClose) { - state.onWindowClose(); + if (glfwState.onWindowClose) { + glfwState.onWindowClose(); } } static void onWindowResize(GLFWwindow* window, int width, int height) { - if (state.onWindowResize) { + if (glfwState.onWindowResize) { glfwGetFramebufferSize(window, &width, &height); - state.onWindowResize(width, height); + glfwState.onWindowResize(width, height); } } static void onMouseButton(GLFWwindow* window, int b, int a, int mods) { - if (state.onMouseButton && (b == GLFW_MOUSE_BUTTON_LEFT || b == GLFW_MOUSE_BUTTON_RIGHT)) { + if (glfwState.onMouseButton && (b == GLFW_MOUSE_BUTTON_LEFT || b == GLFW_MOUSE_BUTTON_RIGHT)) { MouseButton button = (b == GLFW_MOUSE_BUTTON_LEFT) ? MOUSE_LEFT : MOUSE_RIGHT; ButtonAction action = (a == GLFW_PRESS) ? BUTTON_PRESSED : BUTTON_RELEASED; - state.onMouseButton(button, action); + glfwState.onMouseButton(button, action); } } static void onKeyboardEvent(GLFWwindow* window, int k, int scancode, int a, int mods) { - if (state.onKeyboardEvent) { + if (glfwState.onKeyboardEvent) { KeyCode key; switch (k) { case GLFW_KEY_W: key = KEY_W; break; @@ -60,7 +64,7 @@ static void onKeyboardEvent(GLFWwindow* window, int k, int scancode, int a, int default: return; } ButtonAction action = (a == GLFW_PRESS) ? BUTTON_PRESSED : BUTTON_RELEASED; - state.onKeyboardEvent(key, action); + glfwState.onKeyboardEvent(key, action); } } @@ -90,39 +94,25 @@ static int convertKeyCode(KeyCode key) { } } -static void onGlfwError(int code, const char* description) { - lovrThrow(description); -} - -bool lovrPlatformInit() { - glfwSetErrorCallback(onGlfwError); -#ifndef EMSCRIPTEN - glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE); -#endif - return glfwInit(); -} - -void lovrPlatformDestroy() { - glfwTerminate(); -} - void lovrPlatformPollEvents() { - glfwPollEvents(); -} - -double lovrPlatformGetTime() { - return glfwGetTime(); -} - -void lovrPlatformSetTime(double t) { - glfwSetTime(t); + if (glfwState.window) { + glfwPollEvents(); + } } bool lovrPlatformCreateWindow(WindowFlags* flags) { - if (state.window) { + if (glfwState.window) { return true; } + glfwSetErrorCallback(onError); +#ifdef __APPLE__ + glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE); +#endif + if (!glfwInit()) { + return false; + } + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); @@ -143,36 +133,36 @@ bool lovrPlatformCreateWindow(WindowFlags* flags) { glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate); } - state.window = glfwCreateWindow(width, height, flags->title, flags->fullscreen ? monitor : NULL, NULL); + glfwState.window = glfwCreateWindow(width, height, flags->title, flags->fullscreen ? monitor : NULL, NULL); - if (!state.window) { + if (!glfwState.window) { return false; } if (flags->icon.data) { - glfwSetWindowIcon(state.window, 1, &(GLFWimage) { + glfwSetWindowIcon(glfwState.window, 1, &(GLFWimage) { .pixels = flags->icon.data, .width = flags->icon.width, .height = flags->icon.height }); } - glfwMakeContextCurrent(state.window); - glfwSetWindowCloseCallback(state.window, onWindowClose); - glfwSetWindowSizeCallback(state.window, onWindowResize); - glfwSetMouseButtonCallback(state.window, onMouseButton); - glfwSetKeyCallback(state.window, onKeyboardEvent); + glfwMakeContextCurrent(glfwState.window); + glfwSetWindowCloseCallback(glfwState.window, onWindowClose); + glfwSetWindowSizeCallback(glfwState.window, onWindowResize); + glfwSetMouseButtonCallback(glfwState.window, onMouseButton); + glfwSetKeyCallback(glfwState.window, onKeyboardEvent); lovrPlatformSetSwapInterval(flags->vsync); return true; } bool lovrPlatformHasWindow() { - return state.window; + return glfwState.window; } void lovrPlatformGetWindowSize(int* width, int* height) { - if (state.window) { - glfwGetWindowSize(state.window, width, height); + if (glfwState.window) { + glfwGetWindowSize(glfwState.window, width, height); } else { if (*width) *width = 0; if (*height) *height = 0; @@ -180,8 +170,8 @@ void lovrPlatformGetWindowSize(int* width, int* height) { } void lovrPlatformGetFramebufferSize(int* width, int* height) { - if (state.window) { - glfwGetFramebufferSize(state.window, width, height); + if (glfwState.window) { + glfwGetFramebufferSize(glfwState.window, width, height); } else { if (*width) *width = 0; if (*height) *height = 0; @@ -197,7 +187,7 @@ void lovrPlatformSetSwapInterval(int interval) { } void lovrPlatformSwapBuffers() { - glfwSwapBuffers(state.window); + glfwSwapBuffers(glfwState.window); } void* lovrPlatformGetProcAddress(const char* function) { @@ -205,50 +195,50 @@ void* lovrPlatformGetProcAddress(const char* function) { } void lovrPlatformOnWindowClose(windowCloseCallback callback) { - state.onWindowClose = callback; + glfwState.onWindowClose = callback; } void lovrPlatformOnWindowResize(windowResizeCallback callback) { - state.onWindowResize = callback; + glfwState.onWindowResize = callback; } void lovrPlatformOnMouseButton(mouseButtonCallback callback) { - state.onMouseButton = callback; + glfwState.onMouseButton = callback; } void lovrPlatformOnKeyboardEvent(keyboardCallback callback) { - state.onKeyboardEvent = callback; + glfwState.onKeyboardEvent = callback; } void lovrPlatformGetMousePosition(double* x, double* y) { - if (state.window) { - glfwGetCursorPos(state.window, x, y); + if (glfwState.window) { + glfwGetCursorPos(glfwState.window, x, y); } else { *x = *y = 0.; } } void lovrPlatformSetMouseMode(MouseMode mode) { - if (state.window) { + if (glfwState.window) { int m = (mode == MOUSE_MODE_GRABBED) ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL; - glfwSetInputMode(state.window, GLFW_CURSOR, m); + glfwSetInputMode(glfwState.window, GLFW_CURSOR, m); } } bool lovrPlatformIsMouseDown(MouseButton button) { - return state.window ? glfwGetMouseButton(state.window, convertMouseButton(button)) == GLFW_PRESS : false; + return glfwState.window ? glfwGetMouseButton(glfwState.window, convertMouseButton(button)) == GLFW_PRESS : false; } bool lovrPlatformIsKeyDown(KeyCode key) { - return state.window ? glfwGetKey(state.window, convertKeyCode(key)) == GLFW_PRESS : false; + return glfwState.window ? glfwGetKey(glfwState.window, convertKeyCode(key)) == GLFW_PRESS : false; } #ifdef _WIN32 HANDLE lovrPlatformGetWindow() { - return (HANDLE) glfwGetWin32Window(state.window); + return (HANDLE) glfwGetWin32Window(glfwState.window); } HGLRC lovrPlatformGetContext() { - return glfwGetWGLContext(state.window); + return glfwGetWGLContext(glfwState.window); } #endif diff --git a/src/core/platform_linux.c.h b/src/core/platform_linux.c.h index 1b99f36f..1eb5d3fb 100644 --- a/src/core/platform_linux.c.h +++ b/src/core/platform_linux.c.h @@ -4,15 +4,41 @@ #include "platform_glfw.c.h" +static uint64_t epoch; +#define NS_PER_SEC 1000000000ULL + +static uint64_t getTime() { + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return (uint64_t) t.tv_sec * NS_PER_SEC + (uint64_t) t.tv_nsec; +} + +bool lovrPlatformInit() { + epoch = getTime(); + return true; +} + +void lovrPlatformDestroy() { + glfwTerminate(); +} + const char* lovrPlatformGetName() { return "Linux"; } +double lovrPlatformGetTime() { + return (getTime() - epoch) / (double) NS_PER_SEC; +} + +void lovrPlatformSetTime(double t) { + epoch = getTime() - (uint64_t) (t * NS_PER_SEC + .5); +} + void lovrPlatformSleep(double seconds) { seconds += .5e-9; struct timespec t; t.tv_sec = seconds; - t.tv_nsec = (seconds - t.tv_sec) * 1e9L; + t.tv_nsec = (seconds - t.tv_sec) * NS_PER_SEC; while (nanosleep(&t, &t)); } diff --git a/src/core/platform_macos.c.h b/src/core/platform_macos.c.h index 70ca4005..caa8e89b 100644 --- a/src/core/platform_macos.c.h +++ b/src/core/platform_macos.c.h @@ -1,15 +1,47 @@ #include "platform.h" #include -#include +#include +#include #include "platform_glfw.c.h" +static uint64_t epoch; +static uint64_t frequency; + +static uint64_t getTime() { + return mach_absolute_time(); +} + +bool lovrPlatformInit() { + mach_timebase_info_data_t info; + mach_timebase_info(&info); + frequency = (info.denom * 1e9) / info.numer; + epoch = getTime(); + return true; +} + +void lovrPlatformDestroy() { + glfwTerminate(); +} + const char* lovrPlatformGetName() { return "macOS"; } +double lovrPlatformGetTime() { + return (getTime() - epoch) / (double) frequency; +} + +void lovrPlatformSetTime(double t) { + epoch = getTime() - (uint64_t) (t * frequency + .5); +} + void lovrPlatformSleep(double seconds) { - usleep((unsigned int) (seconds * 1000000)); + seconds += .5e-9; + struct timespec t; + t.tv_sec = seconds; + t.tv_nsec = (seconds - t.tv_sec) * NS_PER_SEC; + while (nanosleep(&t, &t)); } void lovrPlatformOpenConsole() { diff --git a/src/core/platform_web.c.h b/src/core/platform_web.c.h index 8ffc2713..d0ad2008 100644 --- a/src/core/platform_web.c.h +++ b/src/core/platform_web.c.h @@ -3,12 +3,32 @@ #include "platform_glfw.c.h" +static double epoch; +#define TIMER_FREQUENCY 1000 + +bool lovrPlatformInit() { + epoch = emscripten_get_now(); + return true; +} + +void lovrPlatformDestroy() { + glfwTerminate(); +} + const char* lovrPlatformGetName() { return "Web"; } +double lovrPlatformGetTime() { + return (emscripten_get_now() - epoch) / TIMER_FREQUENCY; +} + +void lovrPlatformSetTime(double t) { + epoch = emscripten_get_now() - (t * TIMER_FREQUENCY); +} + void lovrPlatformSleep(double seconds) { - emscripten_sleep((unsigned int) (seconds * 1000)); + emscripten_sleep((unsigned int) (seconds * 1000 + .5)); } void lovrPlatformOpenConsole() { diff --git a/src/core/platform_windows.c.h b/src/core/platform_windows.c.h index 4ea9ef2f..a3141215 100644 --- a/src/core/platform_windows.c.h +++ b/src/core/platform_windows.c.h @@ -4,10 +4,39 @@ #include "platform_glfw.c.h" +static uint64_t epoch; +static uint64_t frequency; + +static uint64_t getTime() { + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + return t.QuadPart; +} + +bool lovrPlatformInit() { + LARGE_INTEGER f; + QueryPerformanceFrequency(&f); + frequency = f.QuadPart; + epoch = getTime(); + return true; +} + +void lovrPlatformDestroy() { + glfwTerminate(); +} + const char* lovrPlatformGetName() { return "Windows"; } +double lovrPlatformGetTime() { + return (getTime() - epoch) / (double) frequency; +} + +void lovrPlatformSetTime(double t) { + epoch = getTime() - (uint64_t) (t * frequency + .5); +} + void lovrPlatformSleep(double seconds) { Sleep((unsigned int) (seconds * 1000)); } diff --git a/src/main.c b/src/main.c index b7f9e760..4f2345b9 100644 --- a/src/main.c +++ b/src/main.c @@ -104,7 +104,6 @@ typedef enum { // What flag is being searched for? lua_State* lovrInit(lua_State* L, int argc, char** argv) { lovrAssert(lovrPlatformInit(), "Failed to initialize platform"); - lovrPlatformSetTime(0.); // arg table // Args follow the lua standard https://en.wikibooks.org/wiki/Lua_Programming/command_line_parameter