diff options
| author | 3gg <3gg@shellblade.net> | 2026-05-02 14:59:18 -0700 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2026-05-02 14:59:18 -0700 |
| commit | 456d7f883ca34ec83692ff3879ca5f5717e82b33 (patch) | |
| tree | 9bc29d8aa999d98d220419bbf87a02e9639afc64 /app/src/app.c | |
| parent | 5c7204d7b334855b18761ba95f61fea0aefddd52 (diff) | |
Diffstat (limited to 'app/src/app.c')
| -rw-r--r-- | app/src/app.c | 46 |
1 files changed, 17 insertions, 29 deletions
diff --git a/app/src/app.c b/app/src/app.c index 8262378..c056ddd 100644 --- a/app/src/app.c +++ b/app/src/app.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include <GLFW/glfw3.h> | 5 | #include <GLFW/glfw3.h> |
| 6 | #include <log/log.h> | 6 | #include <log/log.h> |
| 7 | #include <simloop.h> | ||
| 7 | #include <timer.h> | 8 | #include <timer.h> |
| 8 | 9 | ||
| 9 | #include <assert.h> | 10 | #include <assert.h> |
| @@ -13,9 +14,8 @@ | |||
| 13 | typedef struct GfxApp { | 14 | typedef struct GfxApp { |
| 14 | GfxAppState* app_state; | 15 | GfxAppState* app_state; |
| 15 | GfxAppCallbacks callbacks; | 16 | GfxAppCallbacks callbacks; |
| 16 | int max_fps; | ||
| 17 | double update_delta_time; | ||
| 18 | GLFWwindow* window; | 17 | GLFWwindow* window; |
| 18 | Simloop simloop; | ||
| 19 | } GfxApp; | 19 | } GfxApp; |
| 20 | 20 | ||
| 21 | /// Storing the application state in a global variable so that we can call the | 21 | /// Storing the application state in a global variable so that we can call the |
| @@ -32,17 +32,9 @@ static void loop(GfxApp* app) { | |||
| 32 | assert(app); | 32 | assert(app); |
| 33 | assert(app->window); | 33 | assert(app->window); |
| 34 | 34 | ||
| 35 | const time_delta min_frame_time = | 35 | time_delta time = 0; |
| 36 | app->max_fps > 0 ? time_delta_from_sec(1.0 / (double)(app->max_fps)) : 0; | 36 | Timer timer = timer_make(); |
| 37 | const time_delta update_dt = time_delta_from_sec(app->update_delta_time); | 37 | SimloopOut simout = {}; |
| 38 | time_delta time = 0; | ||
| 39 | time_delta time_budget = 0; | ||
| 40 | Timer timer = timer_make(); | ||
| 41 | |||
| 42 | // Warm up the update to initialize the application's state. | ||
| 43 | (*app->callbacks.update)( | ||
| 44 | app, app->app_state, time_delta_to_sec(time), | ||
| 45 | time_delta_to_sec(update_dt)); | ||
| 46 | 38 | ||
| 47 | // Warm up the rendering before entering the main loop. A renderer can | 39 | // Warm up the rendering before entering the main loop. A renderer can |
| 48 | // compile shaders and do other initialization the first time it renders a | 40 | // compile shaders and do other initialization the first time it renders a |
| @@ -53,25 +45,21 @@ static void loop(GfxApp* app) { | |||
| 53 | timer_start(&timer); | 45 | timer_start(&timer); |
| 54 | while (!glfwWindowShouldClose(app->window)) { | 46 | while (!glfwWindowShouldClose(app->window)) { |
| 55 | timer_tick(&timer); | 47 | timer_tick(&timer); |
| 56 | time_budget += timer.delta_time; | 48 | simloop_update(&app->simloop, timer.delta_time, &simout); |
| 49 | |||
| 50 | glfwPollEvents(); | ||
| 57 | 51 | ||
| 58 | while (time_budget >= update_dt) { | 52 | if (simout.should_update) { |
| 59 | (*app->callbacks.update)( | 53 | (*app->callbacks.update)( |
| 60 | app, app->app_state, time_delta_to_sec(time), | 54 | app, app->app_state, time_delta_to_sec(time), |
| 61 | time_delta_to_sec(update_dt)); | 55 | time_delta_to_sec(simout.update_dt)); |
| 62 | |||
| 63 | time += update_dt; | ||
| 64 | time_budget -= update_dt; | ||
| 65 | } | 56 | } |
| 66 | 57 | ||
| 67 | (*app->callbacks.render)(app, app->app_state); | 58 | (*app->callbacks.render)(app, app->app_state); |
| 68 | glfwSwapBuffers(app->window); | 59 | glfwSwapBuffers(app->window); |
| 69 | glfwPollEvents(); | ||
| 70 | 60 | ||
| 71 | const time_point frame_end = time_now(); | 61 | if (simout.throttle > 0) { |
| 72 | const time_delta frame_time = time_diff(timer.last_tick, frame_end); | 62 | time_sleep(simout.throttle); |
| 73 | if ((min_frame_time > 0) && (frame_time < min_frame_time)) { | ||
| 74 | time_sleep(min_frame_time - frame_time); | ||
| 75 | } | 63 | } |
| 76 | } | 64 | } |
| 77 | } | 65 | } |
| @@ -82,11 +70,9 @@ bool gfx_app_run(const GfxAppDesc* desc, const GfxAppCallbacks* callbacks) { | |||
| 82 | 70 | ||
| 83 | bool success = false; | 71 | bool success = false; |
| 84 | 72 | ||
| 85 | g_gfx_app.app_state = desc->app_state; | 73 | g_gfx_app.app_state = desc->app_state; |
| 86 | g_gfx_app.callbacks = *callbacks; | 74 | g_gfx_app.callbacks = *callbacks; |
| 87 | g_gfx_app.max_fps = desc->max_fps; | 75 | g_gfx_app.window = nullptr; |
| 88 | g_gfx_app.update_delta_time = desc->update_delta_time; | ||
| 89 | g_gfx_app.window = nullptr; | ||
| 90 | 76 | ||
| 91 | if (!glfwInit()) { | 77 | if (!glfwInit()) { |
| 92 | LOGE("glfwInit() failed"); | 78 | LOGE("glfwInit() failed"); |
| @@ -138,6 +124,8 @@ bool gfx_app_run(const GfxAppDesc* desc, const GfxAppCallbacks* callbacks) { | |||
| 138 | // Set GLFW callbacks now that the application has been initialized. | 124 | // Set GLFW callbacks now that the application has been initialized. |
| 139 | glfwSetWindowSizeCallback(g_gfx_app.window, on_resize); | 125 | glfwSetWindowSizeCallback(g_gfx_app.window, on_resize); |
| 140 | 126 | ||
| 127 | g_gfx_app.simloop = simloop_make(&(SimloopArgs){ | ||
| 128 | .update_fps = desc->update_fps, .max_render_fps = desc->max_render_fps}); | ||
| 141 | loop(&g_gfx_app); | 129 | loop(&g_gfx_app); |
| 142 | 130 | ||
| 143 | (*g_gfx_app.callbacks.shutdown)(&g_gfx_app, g_gfx_app.app_state); | 131 | (*g_gfx_app.callbacks.shutdown)(&g_gfx_app, g_gfx_app.app_state); |
