X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=src%2Fvg%2Fvg.h;h=77d27e2fb9f80553cacad4469608b79f82a4678d;hb=3dd767bb10e6fee9cbffeb185d1a9685810c17b5;hp=4aec2496cdd0024caaa76f9f5546e698c969d932;hpb=103c2a3f69fdaa9837bd1e650f76ef71e6a43260;p=vg.git diff --git a/src/vg/vg.h b/src/vg/vg.h index 4aec249..77d27e2 100644 --- a/src/vg/vg.h +++ b/src/vg/vg.h @@ -1,9 +1,27 @@ /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */ +/* + * Memory model: + * [global (.data)] [temp-stack] [system-stack] [game-heap] + * + * 1. Program starts: .data memory is loaded + * 2. System initialization: + * 2a. the large heap buffer is allocated + * 2b. each engine system is initialized in order, using some of the + * system stack + * 2c. game systems are also put into here + */ + + #ifndef VG_HEADER_H #define VG_HEADER_H #include "vg_platform.h" +#include "vg_mem.h" + +#ifndef _WIN32 +#include +#endif #if defined(VG_SERVER) || defined(VG_TOOLS) @@ -35,10 +53,6 @@ void vg_register_exit( void( *funcptr )(void), const char *name ); #include "vg_steam.h" #endif -#ifndef VG_NON_CLIENT -#include "vg_gldiag.h" -#endif - #ifndef VG_NON_CLIENT struct vg @@ -70,13 +84,18 @@ struct vg samples; float refresh_rate; - v2f mouse, + double mouse_pos[2]; + v2f + mouse_delta, mouse_wheel; /* Runtime */ double time, - time_last, time_delta, + frame_delta, + time_real, + time_real_last, + time_rate, accumulator; int fixed_iterations; @@ -93,14 +112,21 @@ struct vg /* graphics */ m4x4f pv; + enum quality_profile + { + k_quality_profile_high = 0, + k_quality_profile_low = 1, + } + quality_profile; /* Gamepad */ GLFWgamepadstate gamepad; int gamepad_ready; const char *gamepad_name; int gamepad_id; + int gamepad_use_trackpad_look; } -static vg; +VG_STATIC vg = { .time_rate = 1.0 }; struct vg_thread_info { @@ -126,9 +152,17 @@ static VG_THREAD_LOCAL struct vg_thread_info vg_thread_info; #define VG_SYNC_LOG(...) #endif -static void vg_fatal_exit_loop( const char *error ); +VG_STATIC void vg_fatal_exit_loop( const char *error ); +VG_STATIC void vg_required( void *ptr, const char *path ) +{ + if( !ptr ) + { + vg_fatal_exit_loop( path ); + } +} -static void vg_ensure_engine_running(void) + +VG_STATIC void vg_ensure_engine_running(void) { /* Check if the engine is no longer running */ vg_mutex_lock( &vg.mux_engine_status ); @@ -153,7 +187,7 @@ static void vg_ensure_engine_running(void) * Sync execution so that the OpenGL context is switched onto this thread. * Anything after this call will be in a valid context. */ -static void vg_acquire_thread_sync(void) +VG_STATIC void vg_acquire_thread_sync(void) { /* We dont want to do anything if this is the main thread */ if( vg_thread_info.purpose == k_thread_purpose_main ) @@ -190,7 +224,7 @@ static void vg_acquire_thread_sync(void) * Signify that we are done with the OpenGL context in this thread. * Anything after this call will be in an undefined context. */ -static void vg_release_thread_sync(void) +VG_STATIC void vg_release_thread_sync(void) { if( vg_thread_info.purpose == k_thread_purpose_main ) return; @@ -208,7 +242,7 @@ static void vg_release_thread_sync(void) } } -static void vg_run_synced_content(void) +VG_STATIC void vg_run_synced_content(void) { assert( vg_thread_info.purpose == k_thread_purpose_main ); @@ -240,7 +274,7 @@ static void vg_run_synced_content(void) vg_mutex_unlock( &vg.mux_context ); } -static void vg_opengl_sync_init(void) +VG_STATIC void vg_opengl_sync_init(void) { vg_semaphore_init( &vg.sem_allow_exec, 0 ); vg_semaphore_init( &vg.sem_exec_finished, 0 ); @@ -253,7 +287,7 @@ static void vg_opengl_sync_init(void) vg_thread_info.gl_context_level = 1; } -static void vg_checkgl( const char *src_info ); +VG_STATIC void vg_checkgl( const char *src_info ); #define VG_STRINGIT( X ) #X #define VG_CHECK_GL_ERR() vg_checkgl( __FILE__ ":L" VG_STRINGIT(__LINE__) ) @@ -265,27 +299,26 @@ static void vg_checkgl( const char *src_info ); #include "vg_input.h" #include "vg_ui.h" #include "vg_lines.h" -#include "vg_debug.h" #include "vg_loader.h" #include "vg_opt.h" /* Diagnostic */ -static struct vg_profile vg_prof_update = {.name="update()"}, - vg_prof_render = {.name="render()"}; +VG_STATIC struct vg_profile vg_prof_update = {.name="update()"}, + vg_prof_render = {.name="render()"}; #define VG_GAMELOOP -static void vg_register(void) VG_GAMELOOP; -static void vg_start(void) VG_GAMELOOP; +VG_STATIC void vg_register(void) VG_GAMELOOP; +VG_STATIC void vg_start(void) VG_GAMELOOP; -static void vg_update(int loaded) VG_GAMELOOP; -static void vg_update_fixed(int loaded) VG_GAMELOOP; -static void vg_update_post(int loaded) VG_GAMELOOP; +VG_STATIC void vg_update(int loaded) VG_GAMELOOP; +VG_STATIC void vg_update_fixed(int loaded) VG_GAMELOOP; +VG_STATIC void vg_update_post(int loaded) VG_GAMELOOP; -static void vg_framebuffer_resize(int w, int h) VG_GAMELOOP; -static void vg_render(void) VG_GAMELOOP; -static void vg_ui(void) VG_GAMELOOP; +VG_STATIC void vg_framebuffer_resize(int w, int h) VG_GAMELOOP; +VG_STATIC void vg_render(void) VG_GAMELOOP; +VG_STATIC void vg_ui(void) VG_GAMELOOP; -static void vg_checkgl( const char *src_info ) +VG_STATIC void vg_checkgl( const char *src_info ) { int fail = 0; @@ -302,8 +335,11 @@ static void vg_checkgl( const char *src_info ) void vg_mouse_callback( GLFWwindow* ptrW, double xpos, double ypos ) { - vg.mouse[0] = xpos; - vg.mouse[1] = ypos; + vg.mouse_delta[0] += xpos - vg.mouse_pos[0]; + vg.mouse_delta[1] += ypos - vg.mouse_pos[1]; + + vg.mouse_pos[0] = xpos; + vg.mouse_pos[1] = ypos; } void vg_scroll_callback( GLFWwindow* ptrW, double xoffset, double yoffset ) @@ -326,33 +362,31 @@ void vg_framebuffer_resize_callback( GLFWwindow *ptrW, int w, int h ) vg_framebuffer_resize(w,h); } -static int vg_bake_shaders(void) +VG_STATIC void vg_bake_shaders(void) { vg_acquire_thread_sync(); - if( !vg_shaders_recompile() ) - { - vg_shaders_free(NULL); - vg_release_thread_sync(); - return 0; - } - else +#if 0 + vg_function_push( (struct vg_cmd) { - vg_release_thread_sync(); - vg_loader_highwater( NULL, vg_shaders_free, NULL ); - return 1; - } + .name = "shaders", + .function = vg_shaders_live_recompile + }); +#endif + + vg_shaders_compile(); + vg_release_thread_sync(); } -void vg_preload(void); -void vg_load(void); -static void vg_load_full(void) +VG_STATIC void vg_preload(void); +VG_STATIC void vg_load(void); +VG_STATIC void vg_load_full(void) { vg_preload(); /* internal */ vg_loader_highwater( vg_gamepad_init, NULL, NULL ); - vg_loader_highwater( vg_lines_init, vg_lines_free, NULL ); + vg_loader_highwater( vg_lines_init, NULL, NULL ); vg_loader_highwater( vg_audio_init, vg_audio_free, NULL ); vg_loader_highwater( vg_profiler_init, NULL, NULL ); @@ -364,7 +398,7 @@ static void vg_load_full(void) vg_release_thread_sync(); } -static void vg_enter( int argc, char *argv[], const char *window_name ) +VG_STATIC void vg_enter( int argc, char *argv[], const char *window_name ) { char *arg; while( vg_argp( argc, argv ) ) @@ -383,8 +417,19 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) { vg.samples = VG_MAX( 0, VG_MIN( 8, atoi( arg ) ) ); } - } + if( vg_long_opt( "use-libc-malloc" ) ) + { + vg_mem.use_libc_malloc = atoi( arg ); + } + + if( vg_long_opt( "high-performance" ) ) + { + vg.quality_profile = k_quality_profile_low; + } + } + + vg_alloc_quota(); vg_log_init(); vg_console_init(); @@ -392,7 +437,7 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 ); glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 ); glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE ); - glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE ); + //glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, GL_FALSE ); glfwWindowHint( GLFW_CONTEXT_RELEASE_BEHAVIOR, GLFW_RELEASE_BEHAVIOR_FLUSH ); glfwWindowHint( GLFW_RESIZABLE, GLFW_FALSE ); @@ -459,9 +504,10 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) glfwSetCharCallback( vg.window, console_proc_wchar ); glfwSetKeyCallback( vg.window, console_proc_key ); -#if 0 - glfwSetInputMode(vg_window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); -#endif + glfwSetInputMode( vg.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED ); + + if( glfwRawMouseMotionSupported() ) + glfwSetInputMode( vg.window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE ); if( !gladLoadGLLoader((GLADloadproc)glfwGetProcAddress) ) { @@ -472,13 +518,11 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) const unsigned char* glver = glGetString( GL_VERSION ); vg_success( "Load setup complete, OpenGL version: %s\n", glver ); - vg_run_gfx_diagnostics(); - if( !ui_default_init() ) - goto il_exit_ui; - - if( !vg_loader_init() ) - goto il_exit_loader; + /* init systems + * -----------------------------------------------------------------------*/ + ui_init_context(); + vg_loader_init(); vg_mutex_init( &vg.mux_engine_status ); vg.engine_status = k_engine_status_running; @@ -486,24 +530,29 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) vg_opengl_sync_init(); vg_loader_start(); + vg.accumulator = 0.75f * (1.0f/60.0f); + int loaded = 0; while(1) { if( glfwWindowShouldClose( vg.window ) ) break; - v2_copy( (v2f){ 0.0f, 0.0f }, vg.mouse_wheel ); + v2_zero( vg.mouse_wheel ); + v2_zero( vg.mouse_delta ); + glfwPollEvents(); - vg.time_last = vg.time; - vg.time = glfwGetTime(); - vg.time_delta = vg.time-vg.time_last; + vg.time_real_last = vg.time_real; + vg.time_real = glfwGetTime(); + vg.frame_delta = vg.time_real-vg.time_real_last; + + /* scaled time */ + vg.time_delta = vg.frame_delta * vg.time_rate; + vg.time += vg.time_delta; if( vg.is_loaded ) { - glClearColor( 0.0f,sinf(vg.time*20.0)*0.5f+0.5f,0.0f,1.0f ); - glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); - if( !loaded ) { vg_start(); @@ -530,9 +579,11 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) vg.accumulator += vg.time_delta; vg.fixed_iterations = 0; + vg_lines.allow_input = 1; while( vg.accumulator >= (VG_TIMESTEP_FIXED-0.00125) ) { vg_update_fixed( loaded ); + vg_lines.allow_input = 0; vg.accumulator -= VG_TIMESTEP_FIXED; vg.accumulator = VG_MAX( 0.0, vg.accumulator ); @@ -543,6 +594,7 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) break; } } + vg_lines.allow_input = 1; /* * Rendering @@ -563,9 +615,10 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) /* ui */ vg.engine_stage = k_engine_stage_ui; { - ui_begin( &ui_global_ctx, vg.window_x, vg.window_y ); - ui_set_mouse( &ui_global_ctx, vg.mouse[0], vg.mouse[1], - vg_get_button_state( "primary" ) ); + ui_begin( vg.window_x, vg.window_y ); + + /* TODO */ + ui_set_mouse( vg.mouse_pos[0], vg.mouse_pos[1], 0 ); vg_profile_drawn( (struct vg_profile *[]){&vg_prof_update,&vg_prof_render}, 2, @@ -573,12 +626,31 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) (ui_rect){ 4, 4, 250, 0 }, 0 ); + if( vg_profiler ) + { + + char perf[128]; + + snprintf( perf, 127, + "x: %d y: %d\n" + "refresh: %.1f (%.1fms)\n" + "samples: %d\n" + "iterations: %d (acc: %.3fms%%)\n", + vg.window_x, vg.window_y, + vg.refresh_rate, (1.0f/vg.refresh_rate)*1000.0f, + vg.samples, + vg.fixed_iterations, + (vg.accumulator/VG_TIMESTEP_FIXED)*100.0f ); + + ui_text( (ui_rect){258, 4+24+12,0,0},perf, 1,0); + } + audio_debug_ui( vg.pv ); vg_ui(); vg_console_draw(); - ui_resolve( &ui_global_ctx ); - ui_draw( &ui_global_ctx, NULL ); + ui_resolve(); + ui_draw( NULL ); } } @@ -596,10 +668,7 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) vg_loader_free(); -il_exit_loader: - ui_default_free(); - -il_exit_ui: + vg_success( "If you see this it means everything went.. \"well\".....\n" ); glfwTerminate(); } @@ -607,13 +676,41 @@ il_exit_ui: * Immediately transfer away from calling thread into a safe loop, signal for * others to shutdown, then free everything once the user closes the window. * - * FIXME(bug): glfwWindowShouldClose() never returns 1 in windows via wine, only + * FIXME(bug): glfwWindowShouldClose() never returns 1 in windows via wine, ONLY * when calling the program from outside its normal directory. - * - * A workaround is placed to skip the error loop on windows builds */ -static void vg_fatal_exit_loop( const char *error ) +VG_STATIC void vg_fatal_exit_loop( const char *error ) { + /* + * https://www.gnu.org/software/libc/manual/html_node/Backtraces.html + * thanks gnu <3 + * + * TODO: this on windows? + */ + +#ifndef _WIN32 + + void *array[20]; + char **strings; + int size, i; + + size = backtrace( array, 20 ); + strings = backtrace_symbols( array, size ); + + if( strings != NULL ) + { + vg_error( "---------------- gnu backtrace -------------\n" ); + + for( int i=0; i