diff --git a/Makefile.am b/Makefile.am index e290a5f..4c8566b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS = foreign subdir-objects -Wall bin_PROGRAMS = forge -forge_SOURCES = src/main.c src/args.c src/forge.c src/file.c src/window.c src/shaders.c $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/linmath.h +forge_SOURCES = src/main.c src/args.c src/forge.c src/file.c src/window.c src/shaders.c src/timer.c $(top_srcdir)/include/glad/gl.h forge_CFLAGS = -Ofast -march=native -flto -funroll-loops -fprefetch-loop-arrays -fno-exceptions -fopenmp -I$(top_srcdir)/include -DGLFW_INCLUDE_NONE forge_LDADD = -lm -lGL -lglfw -include_HEADERS = src/main.h src/args.h src/config.h src/types.h src/forge.h src/file.h src/constants.h src/window.h src/shaders.h src/logs.h \ No newline at end of file +include_HEADERS = src/main.h src/args.h src/config.h src/types.h src/forge.h src/file.h src/constants.h src/window.h src/shaders.h src/logs.h src/timer.h $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/linmath.h \ No newline at end of file diff --git a/README.md b/README.md index 5e8ad70..0ad84c2 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,7 @@ make -f Makefile.dev release-arch - [x] Specify fragment shader path - [x] Force fullscreen - [x] Select screen as argument / config + - [x] fps in window title - [x] Clean code - [ ] Multi-stage shaders - [ ] Test 2 stages with render to texture diff --git a/configure.ac b/configure.ac index f935fff..674709b 100644 --- a/configure.ac +++ b/configure.ac @@ -10,6 +10,7 @@ AC_CHECK_HEADERS([time.h]) AC_CHECK_HEADERS([math.h]) AC_CHECK_HEADERS([sys/stat.h]) AC_CHECK_HEADERS([sys/types.h]) +AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_HEADERS([GLFW/glfw3.h]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT \ No newline at end of file diff --git a/src/forge.c b/src/forge.c index 30d2338..1d2caac 100644 --- a/src/forge.c +++ b/src/forge.c @@ -2,9 +2,11 @@ #include #include +#include "config.h" #include "file.h" #include "logs.h" #include "shaders.h" +#include "timer.h" #include "types.h" #include "window.h" @@ -23,10 +25,23 @@ static void key_callback(Window *window, int key, } } +void compute_fps(Window *window, Timer *timer) { + double fps; + char title[100]; + + if (inc_timer(timer)) { + fps = reset_and_count(timer); + sprintf(title, PACKAGE " " VERSION " - %.0ffps", fps); + update_window_title(window, title); + } +} + void loop(Window *window, ShaderProgram program, bool hot_reload, - File *fragment_shader) { + File *fragment_shader, Timer *timer) { Context context; + compute_fps(window, timer); + if (hot_reload && should_update_file(*fragment_shader)) { update_file(fragment_shader); update_program(program, *fragment_shader); @@ -36,29 +51,35 @@ void loop(Window *window, ShaderProgram program, bool hot_reload, apply_program(program, context); - update_window(window); + refresh_window(window); } void forge_run(Parameters params) { + File fragment_shader; + ShaderProgram program; Window *window; + Timer timer; - File fragment_shader = read_file(params.frag_path); + fragment_shader = read_file(params.frag_path); if (fragment_shader.error) { exit(EXIT_FAILURE); } - window = init_window(params, error_callback, key_callback); + window = init_window(PACKAGE " " VERSION, params.screen, error_callback, + key_callback); - ShaderProgram program = init_program(fragment_shader); + program = init_program(fragment_shader); if (program.error) { close_window(window, true); exit(EXIT_FAILURE); } + timer = create_timer(60); + while (!window_should_close(window)) { - loop(window, program, params.hot_reload, &fragment_shader); + loop(window, program, params.hot_reload, &fragment_shader, &timer); } close_window(window, true); diff --git a/src/timer.c b/src/timer.c new file mode 100644 index 0000000..e615964 --- /dev/null +++ b/src/timer.c @@ -0,0 +1,31 @@ +#include + +#include "types.h" + +Timer create_timer(const unsigned int target) { + Timer output = { + .counter = 0, + .target = target, + }; + + gettimeofday(&output.start, NULL); + + return output; +} + +bool inc_timer(Timer *timer) { + timer->counter += 1; + return timer->counter >= timer->target; +} + +double reset_and_count(Timer *timer) { + struct timeval stop; + double secs, per_secs; + gettimeofday(&stop, NULL); + secs = (double)(stop.tv_usec - timer->start.tv_usec) / 1000000 + + (double)(stop.tv_sec - timer->start.tv_sec); + per_secs = ((float)timer->counter) / secs; + timer->start = stop; + timer->counter = 0; + return per_secs; +} \ No newline at end of file diff --git a/src/timer.h b/src/timer.h new file mode 100644 index 0000000..c24a79f --- /dev/null +++ b/src/timer.h @@ -0,0 +1,12 @@ +#include "types.h" + +#ifndef TIMER_H +#define TIMER_H + +Timer create_timer(const unsigned int target); + +bool inc_timer(Timer *timer); + +double reset_and_count(Timer *timer); + +#endif \ No newline at end of file diff --git a/src/types.h b/src/types.h index 9cce66d..2a1f1dc 100644 --- a/src/types.h +++ b/src/types.h @@ -1,10 +1,9 @@ -#include -#include - +#include #include #include - -#include +#include +#include +#include #ifndef TYPES_H #define TYPES_H @@ -51,4 +50,10 @@ typedef struct Context { double time; } Context; +typedef struct Timer { + struct timeval start; + unsigned int counter; + unsigned int target; +} Timer; + #endif \ No newline at end of file diff --git a/src/window.c b/src/window.c index b8a6214..5c6e7f6 100644 --- a/src/window.c +++ b/src/window.c @@ -3,7 +3,6 @@ #include #include -#include "config.h" #include "logs.h" #include "types.h" @@ -33,23 +32,23 @@ void init_glfw(void (*error_callback)(int, const char *)) { log_success("[GLFS] Initialized..."); } -GLFWmonitor *get_monitor(unsigned char screen_index) { +GLFWmonitor *get_monitor(unsigned char monitor_index) { // detect monitors int count; GLFWmonitor **monitors = glfwGetMonitors(&count); // check selected monitor availability - if (screen_index >= count) { - log_error("[GLFW] Screen %d is out of range [0-%d]", screen_index, + if (monitor_index >= count) { + log_error("[GLFW] Screen %d is out of range [0-%d]", monitor_index, count - 1); glfwTerminate(); exit(EXIT_FAILURE); } - return monitors[screen_index]; + return monitors[monitor_index]; } -GLFWwindow *create_window(GLFWmonitor *monitor, +GLFWwindow *create_window(GLFWmonitor *monitor, char *title, void (*key_callback)(Window *, int, int, int, int)) { log_info("[GLFW] Creating window..."); @@ -61,8 +60,7 @@ GLFWwindow *create_window(GLFWmonitor *monitor, glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE); // create fullscreen window in selected monitor - GLFWwindow *window = - glfwCreateWindow(1, 1, PACKAGE " " VERSION, monitor, NULL); + GLFWwindow *window = glfwCreateWindow(1, 1, title, monitor, NULL); // handle window creation fail if (!window) { @@ -90,7 +88,7 @@ void use_window(GLFWwindow *window) { glfwSwapInterval(1); } -Window *init_window(Parameters params, +Window *init_window(char *title, unsigned char monitor_index, void (*error_callback)(int, const char *), void (*key_callback)(Window *, int, int, int, int)) { GLFWwindow *window; @@ -98,16 +96,20 @@ Window *init_window(Parameters params, init_glfw(error_callback); - monitor = get_monitor(params.screen); + monitor = get_monitor(monitor_index); - window = create_window(monitor, key_callback); + window = create_window(monitor, title, key_callback); use_window(window); return window; } -void update_window(Window *window) { +void update_window_title(Window *window, char *title) { + glfwSetWindowTitle(window, title); +} + +void refresh_window(Window *window) { // swap front and back buffers glfwSwapBuffers(window); // listen to mouse and keyboard events diff --git a/src/window.h b/src/window.h index 58711fc..3a41a27 100644 --- a/src/window.h +++ b/src/window.h @@ -3,11 +3,13 @@ #ifndef WINDOW_H #define WINDOW_H -Window *init_window(Parameters params, +Window *init_window(char *title, unsigned char monitor_index, void (*error_callback)(int, const char *), void (*key_callback)(Window *, int, int, int, int)); -void update_window(Window *window); +void update_window_title(Window *window, char *title); + +void refresh_window(Window *window); Context get_window_context(Window *window);