diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | app/demo/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | app/include/gfx/app.h | 30 | ||||
| -rw-r--r-- | app/src/app.c | 44 |
4 files changed, 41 insertions, 37 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 7703ccb..588ee87 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | cmake_minimum_required(VERSION 3.0) | 1 | cmake_minimum_required(VERSION 3.5) |
| 2 | 2 | ||
| 3 | add_subdirectory(contrib/glad) | 3 | add_subdirectory(contrib/glad) |
| 4 | 4 | ||
diff --git a/app/demo/CMakeLists.txt b/app/demo/CMakeLists.txt index bbb3aae..58d77cc 100644 --- a/app/demo/CMakeLists.txt +++ b/app/demo/CMakeLists.txt | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | cmake_minimum_required(VERSION 3.0) | 1 | cmake_minimum_required(VERSION 3.5) |
| 2 | 2 | ||
| 3 | project(gfxappdemo) | 3 | project(gfxappdemo) |
| 4 | 4 | ||
diff --git a/app/include/gfx/app.h b/app/include/gfx/app.h index 77b6ad2..639fa2d 100644 --- a/app/include/gfx/app.h +++ b/app/include/gfx/app.h | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | #pragma once | 1 | #pragma once |
| 2 | 2 | ||
| 3 | #include <stdbool.h> | 3 | typedef struct GfxApp GfxApp; |
| 4 | |||
| 5 | typedef struct GfxAppState GfxAppState; | 4 | typedef struct GfxAppState GfxAppState; |
| 6 | 5 | ||
| 7 | /// Application settings. | 6 | /// Application settings. |
| @@ -16,11 +15,11 @@ typedef struct GfxAppDesc { | |||
| 16 | GfxAppState* app_state; | 15 | GfxAppState* app_state; |
| 17 | } GfxAppDesc; | 16 | } GfxAppDesc; |
| 18 | 17 | ||
| 19 | typedef bool (*GfxAppInit)(GfxAppState*, int argc, const char** argv); | 18 | typedef bool (*GfxAppInit)(GfxApp*, GfxAppState*, int argc, const char** argv); |
| 20 | typedef void (*GfxAppShutdown)(GfxAppState*); | 19 | typedef void (*GfxAppShutdown)(GfxApp*, GfxAppState*); |
| 21 | typedef void (*GfxAppUpdate)(GfxAppState*, double t, double dt); | 20 | typedef void (*GfxAppUpdate)(GfxApp*, GfxAppState*, double t, double dt); |
| 22 | typedef void (*GfxAppRender)(GfxAppState*); | 21 | typedef void (*GfxAppRender)(const GfxApp*, GfxAppState*); |
| 23 | typedef void (*GfxAppResize)(GfxAppState*, int width, int height); | 22 | typedef void (*GfxAppResize)(GfxApp*, GfxAppState*, int width, int height); |
| 24 | 23 | ||
| 25 | /// Application callback functions. | 24 | /// Application callback functions. |
| 26 | typedef struct GfxAppCallbacks { | 25 | typedef struct GfxAppCallbacks { |
| @@ -74,13 +73,13 @@ extern "C" { | |||
| 74 | bool gfx_app_run(const GfxAppDesc*, const GfxAppCallbacks*); | 73 | bool gfx_app_run(const GfxAppDesc*, const GfxAppCallbacks*); |
| 75 | 74 | ||
| 76 | /// Get the mouse coordinates relative to the app's window. | 75 | /// Get the mouse coordinates relative to the app's window. |
| 77 | void gfx_app_get_mouse_position(double* x, double* y); | 76 | void gfx_app_get_mouse_position(GfxApp*, double* x, double* y); |
| 78 | 77 | ||
| 79 | /// Return if the given mouse button is pressed. | 78 | /// Return if the given mouse button is pressed. |
| 80 | bool gfx_app_is_mouse_button_pressed(MouseButton); | 79 | bool gfx_app_is_mouse_button_pressed(GfxApp*, MouseButton); |
| 81 | 80 | ||
| 82 | /// Return true if the given key is pressed. | 81 | /// Return true if the given key is pressed. |
| 83 | bool gfx_app_is_key_pressed(Key); | 82 | bool gfx_app_is_key_pressed(GfxApp*, Key); |
| 84 | 83 | ||
| 85 | #ifdef __cplusplus | 84 | #ifdef __cplusplus |
| 86 | } // extern "C" | 85 | } // extern "C" |
| @@ -102,11 +101,10 @@ bool gfx_app_is_key_pressed(Key); | |||
| 102 | .title = TITLE, \ | 101 | .title = TITLE, \ |
| 103 | .app_state = &app_state, \ | 102 | .app_state = &app_state, \ |
| 104 | }, \ | 103 | }, \ |
| 105 | &(GfxAppCallbacks){ \ | 104 | &(GfxAppCallbacks){.init = Init, \ |
| 106 | .init = (GfxAppInit)Init, \ | 105 | .shutdown = Shutdown, \ |
| 107 | .shutdown = (GfxAppShutdown)Shutdown, \ | 106 | .update = Update, \ |
| 108 | .update = (GfxAppUpdate)Update, \ | 107 | .render = Render, \ |
| 109 | .render = (GfxAppRender)Render, \ | 108 | .resize = Resize}); \ |
| 110 | .resize = (GfxAppResize)Resize}); \ | ||
| 111 | return 0; \ | 109 | return 0; \ |
| 112 | } | 110 | } |
diff --git a/app/src/app.c b/app/src/app.c index 9b816ee..a7bb9c9 100644 --- a/app/src/app.c +++ b/app/src/app.c | |||
| @@ -24,7 +24,7 @@ static GfxApp g_gfx_app; | |||
| 24 | 24 | ||
| 25 | /// Called by GLFW when the window is resized. | 25 | /// Called by GLFW when the window is resized. |
| 26 | static void on_resize(GLFWwindow* window, int width, int height) { | 26 | static void on_resize(GLFWwindow* window, int width, int height) { |
| 27 | (*g_gfx_app.callbacks.resize)(g_gfx_app.app_state, width, height); | 27 | (*g_gfx_app.callbacks.resize)(&g_gfx_app, g_gfx_app.app_state, width, height); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | /// Run the application's main loop. | 30 | /// Run the application's main loop. |
| @@ -41,12 +41,13 @@ static void loop(GfxApp* app) { | |||
| 41 | 41 | ||
| 42 | // Warm up the update to initialize the application's state. | 42 | // Warm up the update to initialize the application's state. |
| 43 | (*app->callbacks.update)( | 43 | (*app->callbacks.update)( |
| 44 | app->app_state, time_delta_to_sec(time), time_delta_to_sec(update_dt)); | 44 | app, app->app_state, time_delta_to_sec(time), |
| 45 | time_delta_to_sec(update_dt)); | ||
| 45 | 46 | ||
| 46 | // Warm up the rendering before entering the main loop. A renderer can | 47 | // Warm up the rendering before entering the main loop. A renderer can |
| 47 | // compile shaders and do other initialization the first time it renders a | 48 | // compile shaders and do other initialization the first time it renders a |
| 48 | // scene. | 49 | // scene. |
| 49 | (*app->callbacks.render)(app->app_state); | 50 | (*app->callbacks.render)(app, app->app_state); |
| 50 | glfwSwapBuffers(app->window); | 51 | glfwSwapBuffers(app->window); |
| 51 | 52 | ||
| 52 | timer_start(&timer); | 53 | timer_start(&timer); |
| @@ -56,14 +57,14 @@ static void loop(GfxApp* app) { | |||
| 56 | 57 | ||
| 57 | while (time_budget >= update_dt) { | 58 | while (time_budget >= update_dt) { |
| 58 | (*app->callbacks.update)( | 59 | (*app->callbacks.update)( |
| 59 | app->app_state, time_delta_to_sec(time), | 60 | app, app->app_state, time_delta_to_sec(time), |
| 60 | time_delta_to_sec(update_dt)); | 61 | time_delta_to_sec(update_dt)); |
| 61 | 62 | ||
| 62 | time += update_dt; | 63 | time += update_dt; |
| 63 | time_budget -= update_dt; | 64 | time_budget -= update_dt; |
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | (*app->callbacks.render)(app->app_state); | 67 | (*app->callbacks.render)(app, app->app_state); |
| 67 | glfwSwapBuffers(app->window); | 68 | glfwSwapBuffers(app->window); |
| 68 | glfwPollEvents(); | 69 | glfwPollEvents(); |
| 69 | 70 | ||
| @@ -85,7 +86,7 @@ bool gfx_app_run(const GfxAppDesc* desc, const GfxAppCallbacks* callbacks) { | |||
| 85 | g_gfx_app.callbacks = *callbacks; | 86 | g_gfx_app.callbacks = *callbacks; |
| 86 | g_gfx_app.max_fps = desc->max_fps; | 87 | g_gfx_app.max_fps = desc->max_fps; |
| 87 | g_gfx_app.update_delta_time = desc->update_delta_time; | 88 | g_gfx_app.update_delta_time = desc->update_delta_time; |
| 88 | g_gfx_app.window = 0; | 89 | g_gfx_app.window = nullptr; |
| 89 | 90 | ||
| 90 | if (!glfwInit()) { | 91 | if (!glfwInit()) { |
| 91 | LOGE("glfwInit() failed"); | 92 | LOGE("glfwInit() failed"); |
| @@ -112,28 +113,33 @@ bool gfx_app_run(const GfxAppDesc* desc, const GfxAppCallbacks* callbacks) { | |||
| 112 | } | 113 | } |
| 113 | glfwMakeContextCurrent(g_gfx_app.window); | 114 | glfwMakeContextCurrent(g_gfx_app.window); |
| 114 | 115 | ||
| 115 | // Load GL before calling the application init clalback. | 116 | // Request adaptive sync if supported. |
| 116 | if (!gladLoadGL()) { | 117 | glfwSwapInterval(-1); |
| 117 | LOGE("Failed loading glad!"); | 118 | |
| 118 | return 0; | 119 | // Load GL before calling the application init callback. |
| 120 | // Use the GLFW loader. See: https://github.com/apitrace/apitrace/issues/954 | ||
| 121 | if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { | ||
| 122 | LOGE("Failed loading glad"); | ||
| 123 | goto cleanup; | ||
| 119 | } | 124 | } |
| 120 | 125 | ||
| 121 | // Initialize the application's state before setting any callbacks. | 126 | // Initialize the application's state before setting any callbacks. |
| 122 | if (!(*g_gfx_app.callbacks.init)( | 127 | if (!(*g_gfx_app.callbacks.init)( |
| 123 | g_gfx_app.app_state, desc->argc, desc->argv)) { | 128 | &g_gfx_app, g_gfx_app.app_state, desc->argc, desc->argv)) { |
| 124 | LOGE("Failed to initialize application"); | 129 | LOGE("Failed to initialize application"); |
| 125 | goto cleanup; | 130 | goto cleanup; |
| 126 | } | 131 | } |
| 127 | 132 | ||
| 128 | // Trigger an initial resize for convenience. | 133 | // Trigger an initial resize for convenience. |
| 129 | (*g_gfx_app.callbacks.resize)(g_gfx_app.app_state, desc->width, desc->height); | 134 | (*g_gfx_app.callbacks.resize)( |
| 135 | &g_gfx_app, g_gfx_app.app_state, desc->width, desc->height); | ||
| 130 | 136 | ||
| 131 | // Set GLFW callbacks now that the application has been initialized. | 137 | // Set GLFW callbacks now that the application has been initialized. |
| 132 | glfwSetWindowSizeCallback(g_gfx_app.window, on_resize); | 138 | glfwSetWindowSizeCallback(g_gfx_app.window, on_resize); |
| 133 | 139 | ||
| 134 | loop(&g_gfx_app); | 140 | loop(&g_gfx_app); |
| 135 | 141 | ||
| 136 | (*g_gfx_app.callbacks.shutdown)(g_gfx_app.app_state); | 142 | (*g_gfx_app.callbacks.shutdown)(&g_gfx_app, g_gfx_app.app_state); |
| 137 | 143 | ||
| 138 | success = true; | 144 | success = true; |
| 139 | 145 | ||
| @@ -145,21 +151,21 @@ cleanup: | |||
| 145 | return success; | 151 | return success; |
| 146 | } | 152 | } |
| 147 | 153 | ||
| 148 | void gfx_app_get_mouse_position(double* x, double* y) { | 154 | void gfx_app_get_mouse_position(GfxApp* app, double* x, double* y) { |
| 149 | glfwGetCursorPos(g_gfx_app.window, x, y); | 155 | glfwGetCursorPos(app->window, x, y); |
| 150 | } | 156 | } |
| 151 | 157 | ||
| 152 | static int to_glfw_mouse_button(MouseButton button); | 158 | static int to_glfw_mouse_button(MouseButton button); |
| 153 | 159 | ||
| 154 | bool gfx_app_is_mouse_button_pressed(MouseButton button) { | 160 | bool gfx_app_is_mouse_button_pressed(GfxApp* app, MouseButton button) { |
| 155 | return glfwGetMouseButton(g_gfx_app.window, to_glfw_mouse_button(button)) == | 161 | return glfwGetMouseButton(app->window, to_glfw_mouse_button(button)) == |
| 156 | GLFW_PRESS; | 162 | GLFW_PRESS; |
| 157 | } | 163 | } |
| 158 | 164 | ||
| 159 | static int to_glfw_key(Key key); | 165 | static int to_glfw_key(Key key); |
| 160 | 166 | ||
| 161 | bool gfx_app_is_key_pressed(Key key) { | 167 | bool gfx_app_is_key_pressed(GfxApp* app, Key key) { |
| 162 | return glfwGetKey(g_gfx_app.window, to_glfw_key(key)) == GLFW_PRESS; | 168 | return glfwGetKey(app->window, to_glfw_key(key)) == GLFW_PRESS; |
| 163 | } | 169 | } |
| 164 | 170 | ||
| 165 | static int to_glfw_mouse_button(MouseButton button) { | 171 | static int to_glfw_mouse_button(MouseButton button) { |
