From: hgn Date: Fri, 7 Oct 2022 03:56:05 +0000 (+0100) Subject: Fix major overstep with last commit X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=commitdiff_plain;h=5729777dfec3f9f12c1821aa50db6a3c04cc359c Fix major overstep with last commit --- diff --git a/dep/stb/stb_include.h b/dep/stb/stb_include.h index c5db201..6a90097 100644 --- a/dep/stb/stb_include.h +++ b/dep/stb/stb_include.h @@ -53,9 +53,27 @@ char *stb_include_file(char *filename, char *inject, char *path_to_includes, cha #ifdef STB_INCLUDE_IMPLEMENTATION #include -#include #include +#ifndef STB_MALLOC + #define STB_STDLIB + #define STB_MALLOC malloc +#endif + +#ifndef STB_FREE + #define STB_STDLIB + #define STB_FREE free +#endif + +#ifndef STB_REALLOC + #define STB_STDLIB + #define STB_REALLOC realloc +#endif + +#ifdef STB_STDLIB + #include +#endif + static char *stb_include_load_file(char *filename, size_t *plen) { char *text; @@ -65,7 +83,7 @@ static char *stb_include_load_file(char *filename, size_t *plen) fseek(f, 0, SEEK_END); len = (size_t) ftell(f); if (plen) *plen = len; - text = (char *) malloc(len+1); + text = (char *) STB_MALLOC(len+1); if (text == 0) return 0; fseek(f, 0, SEEK_SET); fread(text, 1, len, f); @@ -84,7 +102,7 @@ typedef struct static include_info *stb_include_append_include(include_info *array, int len, int offset, int end, char *filename, int next_line) { - include_info *z = (include_info *) realloc(array, sizeof(*z) * (len+1)); + include_info *z = (include_info *)STB_REALLOC(array, sizeof(*z) * (len+1)); z[len].offset = offset; z[len].end = end; z[len].filename = filename; @@ -96,8 +114,8 @@ static void stb_include_free_includes(include_info *array, int len) { int i; for (i=0; i < len; ++i) - free(array[i].filename); - free(array); + STB_FREE(array[i].filename); + STB_FREE(array); } static int stb_include_isspace(int ch) @@ -130,7 +148,7 @@ static int stb_include_find_includes(char *text, include_info **plist) while (*t != '"' && *t != '\n' && *t != '\r' && *t != 0) ++t; if (*t == '"') { - char *filename = (char *) malloc(t-s+1); + char *filename = (char *) STB_MALLOC(t-s+1); memcpy(filename, s, t-s); filename[t-s] = 0; s=t; @@ -175,7 +193,7 @@ static void stb_include_itoa(char str[9], int n) static char *stb_include_append(char *str, size_t *curlen, char *addstr, size_t addlen) { - str = (char *) realloc(str, *curlen + addlen); + str = (char *)STB_REALLOC(str, *curlen + addlen); memcpy(str + *curlen, addstr, addlen); *curlen += addlen; return str; @@ -228,7 +246,7 @@ char *stb_include_string(char *str, char *inject, char *path_to_includes, char * return NULL; } text = stb_include_append(text, &textlen, inc, strlen(inc)); - free(inc); + STB_FREE(inc); } // write out line directive #ifndef STB_INCLUDE_LINE_NONE @@ -258,14 +276,14 @@ char *stb_include_strings(char **strs, int count, char *inject, char *path_to_in size_t length=0; for (i=0; i < count; ++i) length += strlen(strs[i]); - text = (char *) malloc(length+1); + text = (char *) STB_MALLOC(length+1); length = 0; for (i=0; i < count; ++i) { strcpy(text + length, strs[i]); length += strlen(strs[i]); } result = stb_include_string(text, inject, path_to_includes, filename, error); - free(text); + STB_FREE(text); return result; } @@ -281,7 +299,7 @@ char *stb_include_file(char *filename, char *inject, char *path_to_includes, cha return 0; } result = stb_include_string(text, inject, path_to_includes, filename, error); - free(text); + STB_FREE(text); return result; } diff --git a/src/vg/vg.h b/src/vg/vg.h index b076091..5b2ca81 100644 --- a/src/vg/vg.h +++ b/src/vg/vg.h @@ -3,13 +3,8 @@ #ifndef VG_HEADER_H #define VG_HEADER_H -#include -#include -#include -#include -#include -#include -#include +#include "vg_platform.h" + #if defined(VG_SERVER) || defined(VG_TOOLS) #define VG_NON_CLIENT @@ -20,14 +15,7 @@ #include "../../dep/glfw/glfw3.h" #endif -#define STB_DS_IMPLEMENTATION -#include "stb/stb_ds.h" - -#define QOI_IMPLEMENTATION -#include "phoboslab/qoi.h" - #include "vg_stdint.h" -#include "vg_platform.h" void vg_register_exit( void( *funcptr )(void), const char *name ); @@ -64,7 +52,6 @@ double vg_time, vg_time_last, vg_time_delta; - struct vg { /* Engine sync */ @@ -72,12 +59,22 @@ struct vg vg_mutex mux_context; vg_semaphore sem_allow_exec, - sem_exec_finished; + sem_exec_finished, + sem_loader, + sem_fatal; int exec_context; vg_mutex mux_engine_status; - int engine_running; + enum engine_status + { + k_engine_status_none, + k_engine_status_running, + k_engine_status_crashed + } + engine_status; + const char *str_const_engine_err; + int is_loaded; /* Gamepad */ GLFWgamepadstate gamepad; @@ -87,111 +84,158 @@ struct vg } static vg; +struct vg_thread_info +{ + enum vg_thread_purpose + { + k_thread_purpose_nothing, + k_thread_purpose_main, + k_thread_purpose_loader + } + purpose; + + int gl_context_level; +}; + +static VG_THREAD_LOCAL struct vg_thread_info vg_thread_info; + //#define VG_SYNC_DEBUG #ifdef VG_SYNC_DEBUG - #define VG_SYNC_LOG(...) vg_info(__VA_ARGS__) + #define VG_SYNC_LOG(STR,...) vg_info(STR,vg_thread_info.purpose,##__VA_ARGS__) #else #define VG_SYNC_LOG(...) #endif -/* - * Sync execution so that the OpenGL context is switched onto this thread. - * Anything after this call will be in a valid context. - */ -static int vg_acquire_thread_sync( int id ) +static void vg_fatal_exit_loop( const char *error ); + +static void vg_ensure_engine_running(void) { - if( id == 0 ) - { - /* no action */ - return 1; - } - else + /* Check if the engine is no longer running */ + vg_mutex_lock( &vg.mux_engine_status ); + if( vg.engine_status != k_engine_status_running ) { - /* Check if the engine is no longer running */ - vg_mutex_lock( &vg.mux_engine_status ); - if( !vg.engine_running ) + VG_SYNC_LOG( "[%d] Engine is no longer running\n"); + vg_mutex_unlock( &vg.mux_engine_status ); + + /* Safe to disregard loader thread from this point on, elswhere */ + if( vg_thread_info.purpose == k_thread_purpose_loader ) { - VG_SYNC_LOG( "[%d] Engine is no longer running\n", id ); - vg_mutex_unlock( &vg.mux_engine_status ); - return 0; + vg_semaphore_post( &vg.sem_loader ); } - vg_mutex_unlock( &vg.mux_engine_status ); + VG_SYNC_LOG( "[%d] about to kill\n"); + vg_thread_exit(); + } + vg_mutex_unlock( &vg.mux_engine_status ); +} - vg_mutex_lock( &vg.mux_context ); - VG_SYNC_LOG( "[%d] Signal to sync.\n", id ); - vg.exec_context = id; - vg_mutex_unlock( &vg.mux_context ); - - /* wait until told we can go */ - VG_SYNC_LOG( "[%d] Waiting to acuire sync.\n", id ); - vg_semaphore_wait( &vg.sem_allow_exec ); - glfwMakeContextCurrent( vg.window ); +/* + * 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) +{ + /* We dont want to do anything if this is the main thread */ + if( vg_thread_info.purpose == k_thread_purpose_main ) + return; - /* context now valid to work in while we hold up main thread */ - VG_SYNC_LOG( "[%d] Context acquired.\n", id ); + assert( vg_thread_info.purpose == k_thread_purpose_loader ); - return 1; + vg_ensure_engine_running(); + + /* Check if thread already has the context */ + if( vg_thread_info.gl_context_level ) + { + vg_thread_info.gl_context_level ++; + VG_SYNC_LOG( "[%d] We already have sync here\n" ); + return; } + + vg_mutex_lock( &vg.mux_context ); + VG_SYNC_LOG( "[%d] Signal to sync.\n" ); + vg.exec_context = 1; + vg_mutex_unlock( &vg.mux_context ); + + /* wait until told we can go */ + VG_SYNC_LOG( "[%d] Waiting to acuire sync.\n" ); + vg_semaphore_wait( &vg.sem_allow_exec ); + glfwMakeContextCurrent( vg.window ); + + /* context now valid to work in while we hold up main thread */ + VG_SYNC_LOG( "[%d] Context acquired.\n" ); + vg_thread_info.gl_context_level ++; } /* * 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( int id ) +static void vg_release_thread_sync(void) { - if( id == 0 ) - { - vg_mutex_lock( &vg.mux_context ); + if( vg_thread_info.purpose == k_thread_purpose_main ) + return; - if( vg.exec_context != 0 ) - { - VG_SYNC_LOG( "[%d] Allowing content (%d).\n", id, vg.exec_context ); + assert( vg_thread_info.purpose == k_thread_purpose_loader ); - /* allow operations to go */ - glfwMakeContextCurrent( NULL ); - vg_semaphore_post( &vg.sem_allow_exec ); + /* signal that we are done */ + vg_thread_info.gl_context_level --; - /* wait for operations to complete */ - VG_SYNC_LOG( "[%d] Waiting for content (%d).\n", id, vg.exec_context ); - vg_semaphore_wait( &vg.sem_exec_finished ); - - /* re-engage main thread */ - VG_SYNC_LOG( "[%d] Re-engaging.\n", id ); - vg.exec_context = 0; - glfwMakeContextCurrent( vg.window ); - } - - vg_mutex_unlock( &vg.mux_context ); - } - else + if( !vg_thread_info.gl_context_level ) { - /* signal that we are done */ - VG_SYNC_LOG( "[%d] Releasing context.\n", id ); + VG_SYNC_LOG( "[%d] Releasing context.\n" ); glfwMakeContextCurrent( NULL ); vg_semaphore_post( &vg.sem_exec_finished ); } } +static void vg_run_synced_content(void) +{ + assert( vg_thread_info.purpose == k_thread_purpose_main ); + + vg_mutex_lock( &vg.mux_context ); + + if( vg.exec_context != 0 ) + { + VG_SYNC_LOG( "[%d] Allowing content (%d).\n", vg.exec_context ); + + /* allow operations to go */ + vg_thread_info.gl_context_level = 0; + glfwMakeContextCurrent( NULL ); + vg_semaphore_post( &vg.sem_allow_exec ); + + /* wait for operations to complete */ + VG_SYNC_LOG( "[%d] Waiting for content (%d).\n", vg.exec_context ); + vg_semaphore_wait( &vg.sem_exec_finished ); + + /* check if we killed the engine */ + vg_ensure_engine_running(); + + /* re-engage main thread */ + VG_SYNC_LOG( "[%d] Re-engaging.\n" ); + vg.exec_context = 0; + glfwMakeContextCurrent( vg.window ); + vg_thread_info.gl_context_level = 1; + } + + vg_mutex_unlock( &vg.mux_context ); +} + static void vg_opengl_sync_init(void) { vg_semaphore_init( &vg.sem_allow_exec, 0 ); vg_semaphore_init( &vg.sem_exec_finished, 0 ); + vg_semaphore_init( &vg.sem_loader, 1 ); + vg_semaphore_init( &vg.sem_fatal, 1 ); vg_mutex_init( &vg.mux_context ); -} -static void vg_opengl_sync_free(void) -{ - vg_semaphore_free( &vg.sem_allow_exec ); - vg_semaphore_free( &vg.sem_exec_finished ); - vg_mutex_free( &vg.mux_context ); + vg_set_thread_name( "[vg] Main" ); + vg_thread_info.purpose = k_thread_purpose_main; + vg_thread_info.gl_context_level = 1; } - -int vg_checkgl( const char *src_info ); +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__) ) @@ -213,7 +257,7 @@ 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; -int vg_checkgl( const char *src_info ) +static void vg_checkgl( const char *src_info ) { int fail = 0; @@ -224,11 +268,10 @@ int vg_checkgl( const char *src_info ) fail = 1; } - return fail; + if( fail ) + vg_fatal_exit_loop( "OpenGL Error" ); } - - void vg_mouse_callback( GLFWwindow* ptrW, double xpos, double ypos ) { vg_mouse[0] = xpos; @@ -251,46 +294,39 @@ void vg_framebuffer_resize_callback( GLFWwindow *ptrW, int w, int h ) static int vg_bake_shaders(void) { - if( vg_acquire_thread_sync(1) ) - { - if( !vg_shaders_recompile() ) - { - vg_shaders_free(NULL); - vg_release_thread_sync(1); - return 0; - } - else - { - vg_release_thread_sync(1); + vg_acquire_thread_sync(); - if( !vg_loader_highwater( vg_shaders_free, NULL ) ) return 0; - else return 1; - } + if( !vg_shaders_recompile() ) + { + vg_shaders_free(NULL); + vg_release_thread_sync(); + return 0; + } + else + { + vg_release_thread_sync(); + vg_loader_highwater( NULL, vg_shaders_free, NULL ); + return 1; } - - return 0; } -int vg_preload(void); -int vg_load(void); -static int vg_load_full(void) +void vg_preload(void); +void vg_load(void); +static void vg_load_full(void) { - if( !vg_preload() ) return 0; + vg_preload(); /* internal */ - if( !vg_gamepad_init() ) return 0; - if( !vg_loader_highwater( NULL, NULL ) ) return 0; - - if( !vg_lines_init() ) return 0; - if( !vg_loader_highwater( vg_lines_free, NULL ) ) return 0; - - if( !vg_audio_init() ) return 0; - if( !vg_loader_highwater( vg_audio_free, NULL ) ) return 0; + vg_loader_highwater( vg_gamepad_init, NULL, NULL ); + vg_loader_highwater( vg_lines_init, vg_lines_free, NULL ); + vg_loader_highwater( vg_audio_init, vg_audio_free, NULL ); /* client */ - if( !vg_load() ) return 0; + vg_load(); - return 1; + vg_acquire_thread_sync(); + vg.is_loaded = 1; + vg_release_thread_sync(); } static void vg_enter( int argc, char *argv[], const char *window_name ) @@ -364,21 +400,17 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) goto il_exit_loader; vg_mutex_init( &vg.mux_engine_status ); - vg.engine_running = 1; + vg.engine_status = k_engine_status_running; vg_opengl_sync_init(); vg_loader_start(); int loaded = 0; - + int counter =0; while(1) { - vg_acquire_thread_sync( 0 ); - if( glfwWindowShouldClose( vg.window ) ) - { break; - } v2_copy( (v2f){ 0.0f, 0.0f }, vg_mouse_wheel ); glfwPollEvents(); @@ -387,9 +419,7 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) vg_time = glfwGetTime(); vg_time_delta = vg_minf( vg_time - vg_time_last, 0.1f ); - enum loader_status load_status = vg_loader_status(); - - if( load_status == k_loader_status_complete ) + 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 ); @@ -402,19 +432,19 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) } else { - if( load_status == k_loader_status_fail ) - { - break; - } - else - { - vg_loader_render(); - } + vg_loader_render(); } vg_update_inputs(); vg_update( loaded ); + counter ++; + +#if 0 + if( counter == 30 ) + vg_fatal_exit_loop( "Test crash from main, while loading (-O0)" ); +#endif + if( loaded ) { vg_render(); @@ -434,28 +464,17 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) } } - - - glfwSwapBuffers( vg.window ); - - if( VG_CHECK_GL_ERR() ) - break; - - vg_release_thread_sync( 0 ); + vg_run_synced_content(); } vg_console_write_persistent(); vg_mutex_lock( &vg.mux_engine_status ); - vg.engine_running = 0; + vg.engine_status = k_engine_status_none; vg_mutex_unlock( &vg.mux_engine_status ); - vg_loader_free(); - vg_opengl_sync_free(); - - vg_mutex_free( &vg.mux_engine_status ); il_exit_loader: ui_default_free(); @@ -464,6 +483,90 @@ il_exit_ui: glfwTerminate(); } +/* + * Immediately transfer away from calling thread into a safe loop, signal for + * others to shutdown, then free everything once the user closes the window. + */ +static void vg_fatal_exit_loop( const char *error ) +{ + vg_error( "Fatal error: %s\n", error ); + assert( vg_semaphore_trywait( &vg.sem_fatal ) ); + + vg_mutex_lock( &vg.mux_engine_status ); + + if( vg.engine_status == k_engine_status_none ) + { + vg_mutex_unlock( &vg.mux_engine_status ); + + /* TODO: Correct shutdown before other systems */ + exit(0); + } + else + { + vg_mutex_unlock( &vg.mux_engine_status ); + + /* + * if main + * if loader running + * wait until loader checks in, it will die + * else + * pass immediately + * else + * if have context + * pass immediately + * else + * wait for main to get to us, it will never be used again + * + * undefined behaviour: + * fatal_exit_loop is called in both threads, preventing an appropriate + * reaction to the crash. This *should* be made + * obvious by the assertion + */ + vg_acquire_thread_sync(); + + vg_mutex_lock( &vg.mux_engine_status ); + vg.engine_status = k_engine_status_crashed; + vg.str_const_engine_err = error; + vg_mutex_unlock( &vg.mux_engine_status ); + + /* + * Wait for loader to finish what it was doing, if it was running. + * Then we can continue in our nice error screen + */ + if( vg_thread_info.purpose == k_thread_purpose_main ) + { + vg_semaphore_wait( &vg.sem_loader ); + } + vg_audio_free(NULL); + + /* + * todo: draw error loop + */ + while(1) + { + if( glfwWindowShouldClose( vg.window ) ) + break; + + glfwPollEvents(); + + vg_time = glfwGetTime(); + vg_time_delta = vg_minf( vg_time - vg_time_last, 0.1f ); + + glClearColor( sinf(vg_time*20.0)*0.5f+0.5f, 0.0f, 0.0f,1.0f ); + glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); + + glfwSwapBuffers( vg.window ); + } + + /* Can now shutdown and EXIT */ + vg_loader_free(); + ui_default_free(); + + glfwTerminate(); + exit(0); + } +} + #endif /* diff --git a/src/vg/vg_audio.h b/src/vg/vg_audio.h index 8cdaa4a..ae37b2e 100644 --- a/src/vg/vg_audio.h +++ b/src/vg/vg_audio.h @@ -32,9 +32,14 @@ #pragma GCC optimize ("O3") #endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #define STB_VORBIS_MAX_CHANNELS 2 #include "stb/stb_vorbis.h" +#pragma GCC diagnostic pop + #ifdef __GNUC__ #pragma GCC pop_options #endif @@ -166,11 +171,7 @@ static void *audio_alloc( u32 size ) { u32 new_current = vg_audio.mem_current + size; if( new_current > vg_audio.mem_total ) - { - vg_error( "audio pool over budget!\n" ); - free( vg_audio.mem ); - return NULL; - } + vg_fatal_exit_loop( "Audio pool ran out of memory" ); void *ptr = vg_audio.mem + vg_audio.mem_current; vg_audio.mem_current = new_current; @@ -224,7 +225,7 @@ static void audio_unlock(void) static void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput, ma_uint32 frameCount ); -static int vg_audio_init(void) +static void vg_audio_init(void) { vg_mutex_init( &vg_audio.mux_checker ); vg_mutex_init( &vg_audio.mux_sync ); @@ -240,7 +241,7 @@ static int vg_audio_init(void) u32 decode_region = AUDIO_DECODE_SIZE * SFX_MAX_SYSTEMS; vg_audio.mem_total = 1024*1024*32; vg_audio.mem_current = 0; - vg_audio.mem = malloc( vg_audio.mem_total + decode_region ); + vg_audio.mem = vg_alloc( vg_audio.mem_total + decode_region ); vg_audio.decode_mem = &((u8 *)vg_audio.mem)[vg_audio.mem_total]; /* setup pool */ @@ -267,21 +268,18 @@ static int vg_audio_init(void) if( ma_device_init( NULL, dconf, device) != MA_SUCCESS ) { - vg_error( "ma_device failed to initialize" ); - return 0; + vg_fatal_exit_loop( "(audio) ma_device failed to initialize" ); } else { if( ma_device_start( device ) != MA_SUCCESS ) { ma_device_uninit( device ); - vg_error( "ma_device failed to start" ); - return 0; + vg_fatal_exit_loop( "(audio) ma_device failed to start" ); } } vg_success( "Ready\n" ); - return 1; } static void vg_audio_free(void * nothing) @@ -289,10 +287,8 @@ static void vg_audio_free(void * nothing) ma_device *device = &vg_audio.miniaudio_device; ma_device_uninit( device ); - free( vg_audio.mem ); - - vg_mutex_free( &vg_audio.mux_checker ); - vg_mutex_free( &vg_audio.mux_sync ); + vg_free( vg_audio.mem ); + vg_audio.mem = NULL; } /* @@ -879,8 +875,15 @@ static void audio_require_init( audio_player *player ) if( player->init ) return; - vg_error( "Must init before playing! (%s)\n", player->name ); - abort(); + vg_fatal_exit_loop( "Must init audio player before playing! \n" ); +} + +static void audio_require_clip_loaded( audio_clip *clip ) +{ + if( clip->data ) + return; + + vg_fatal_exit_loop( "Must load audio clip before playing! \n" ); } /* Play a clip using player. If its already playing something, it will @@ -889,6 +892,7 @@ static void audio_player_playclip( audio_player *player, audio_clip *clip ) { audio_require_lock(); audio_require_init( player ); + audio_require_clip_loaded( clip ); player->info.source = clip; audio_player_commit( player ); @@ -905,6 +909,7 @@ static void audio_player_playoneshot( audio_player *player, audio_clip *clip ) static void audio_play_oneshot( audio_clip *clip, float volume ) { audio_require_lock(); + audio_require_clip_loaded( clip ); if( vg_audio.queue_len >= vg_list_size( vg_audio.entity_queue ) ) { diff --git a/src/vg/vg_console.h b/src/vg/vg_console.h index 6ef2d78..fc2775c 100644 --- a/src/vg/vg_console.h +++ b/src/vg/vg_console.h @@ -6,7 +6,6 @@ #include "vg/vg_ui.h" #include "vg/vg_log.h" - struct vg_console { struct vg_convar @@ -49,6 +48,9 @@ struct vg_console const char *name; } *functions; + + u32 convar_count, convar_cap, + function_count, function_cap; char input[96]; int cursor_user, cursor_pos, string_length; @@ -99,12 +101,24 @@ static int vg_console_enabled(void) static void vg_convar_push( struct vg_convar cv ) { - arrpush( vg_console.convars, cv ); + vg_info( "Console variable '%s' registered\n", cv.name ); + vg_console.convars = buffer_reserve( vg_console.convars, + vg_console.convar_count, + &vg_console.convar_cap, 1, + sizeof( struct vg_convar ) ); + + vg_console.convars[ vg_console.convar_count ++ ] = cv; } static void vg_function_push( struct vg_cmd cmd ) { - arrpush( vg_console.functions, cmd ); + vg_info( "Console command '%s' registered\n", cmd.name ); + vg_console.functions = buffer_reserve( vg_console.functions, + vg_console.function_count, + &vg_console.function_cap, 1, + sizeof( struct vg_cmd ) ); + + vg_console.functions[ vg_console.function_count ++ ] = cmd; } static void vg_console_draw( void ) @@ -170,7 +184,7 @@ static void vg_console_draw( void ) static int vg_console_list( int argc, char const *argv[] ) { - for( int i = 0; i < arrlen( vg_console.functions ); i ++ ) + for( int i=0; iname ); @@ -178,7 +192,7 @@ static int vg_console_list( int argc, char const *argv[] ) vg_info( "* snowsound\n" ); - for( int i = 0; i < arrlen( vg_console.convars ); i ++ ) + for( int i=0; iname ); @@ -203,6 +217,12 @@ vg_info(" ' ' '--' [] '----- '----- ' ' '---' " return 0; } +static int _test_break( int argc, const char *argv[] ) +{ + vg_fatal_exit_loop( "Test crash from main, after loading (console)" ); + return 0; +} + static void vg_console_init(void) { vg_convar_push( (struct vg_convar) @@ -224,6 +244,12 @@ static void vg_console_init(void) .name = "chartest", .function = vg_console_chartest }); + + vg_function_push( (struct vg_cmd) + { + .name = "crash", + .function = _test_break + }); } static void vg_console_load_autos(void) @@ -252,7 +278,7 @@ static void vg_console_write_persistent(void) { FILE *fp = fopen( "cfg/auto.conf", "w" ); - for( int i = 0; i < arrlen( vg_console.convars ); i ++ ) + for( int i=0; iname, args[0] ) ) @@ -383,7 +409,7 @@ static void execute_console_input( const char *cmd ) /* * Find and excecute command */ - for( int i = 0; i < arrlen( vg_console.functions ); i ++ ) + for( int i=0; iname, args[0] ) ) @@ -511,166 +537,199 @@ static void console_history_get( char* buf, int entry_num ) strcpy( buf, vg_console.history[ pick ] ); } +/* Receed secondary cursor */ +static void _console_left_select(void) +{ + console_move_cursor( &vg_console.cursor_user, NULL, -1, 0 ); +} + +/* Match and receed both cursors */ +static void _console_left(void) +{ + int cursor_diff = vg_console.cursor_pos - vg_console.cursor_user? 0: 1; + + console_move_cursor( &vg_console.cursor_user, + &vg_console.cursor_pos, -cursor_diff, 1 ); +} + +static void _console_right_select(void) +{ + console_move_cursor( &vg_console.cursor_user, NULL, 1, 0 ); +} + +static void _console_right(void) +{ + int cursor_diff = vg_console.cursor_pos - vg_console.cursor_user? 0: 1; + + console_move_cursor( &vg_console.cursor_user, + &vg_console.cursor_pos, +cursor_diff, 1 ); +} + +static void _console_down(void) +{ + vg_console.history_pos = VG_MAX( 0, vg_console.history_pos-1 ); + console_history_get( vg_console.input, vg_console.history_pos ); + + console_move_cursor( &vg_console.cursor_user, + &vg_console.cursor_pos, + vg_list_size( vg_console.input ), 1 ); +} + +static void _console_up(void) +{ + vg_console.history_pos = VG_MAX + ( + 0, + VG_MIN + ( + vg_console.history_pos+1, + VG_MIN + ( + vg_list_size( vg_console.history ), + vg_console.history_count - 1 + ) + ) + ); + + console_history_get( vg_console.input, vg_console.history_pos ); + console_move_cursor( &vg_console.cursor_user, + &vg_console.cursor_pos, + vg_list_size( vg_console.input ), 1); +} + +static void _console_backspace(void) +{ + vg_console.cursor_user = console_delete_char( -1 ); + vg_console.cursor_pos = vg_console.cursor_user; +} + +static void _console_delete(void) +{ + vg_console.cursor_user = console_delete_char( 1 ); + vg_console.cursor_pos = vg_console.cursor_user; +} + +static void _console_home_select(void) +{ + console_move_cursor( &vg_console.cursor_user, NULL, -10000, 0 ); +} + +static void _console_home(void) +{ + console_move_cursor( &vg_console.cursor_user, + &vg_console.cursor_pos, -10000, 1 ); +} + +static void _console_end_select(void) +{ + console_move_cursor( &vg_console.cursor_user, NULL, 10000, 0 ); +} + +static void _console_end(void) +{ + console_move_cursor( &vg_console.cursor_user, + &vg_console.cursor_pos, + vg_list_size( vg_console.input ), 1 ); +} + +static void _console_select_all(void) +{ + console_move_cursor( &vg_console.cursor_user, NULL, 10000, 0); + console_move_cursor( &vg_console.cursor_pos, NULL, -10000, 0); +} + +static void _console_cut(void) +{ + console_to_clipboard(); + vg_console.cursor_user = console_delete_char(0); + vg_console.cursor_pos = vg_console.cursor_user; +} + +static void _console_enter(void) +{ + if( !strlen( vg_console.input ) ) + return; + + vg_info( "%s\n", vg_console.input ); + + if( strcmp( vg_console.input, + vg_console.history[ vg_console.history_last ]) ) + { + vg_console.history_last = ( vg_console.history_last + 1) % + vg_list_size(vg_console.history ); + vg_console.history_count = + VG_MIN( vg_list_size( vg_console.history ), + vg_console.history_count + 1 ); + strcpy( vg_console.history[ vg_console.history_last ], + vg_console.input ); + } + + vg_console.history_pos = -1; + execute_console_input( vg_console.input ); + console_move_cursor( &vg_console.cursor_user, + &vg_console.cursor_pos, -10000, 1 ); + vg_console.input[0] = '\0'; +} + static void console_proc_key( GLFWwindow* ptrW, int key, int scancode, - int action, int mods ) + int action, int mods ) { - if( action ) - { - int cursor_diff = vg_console.cursor_pos - vg_console.cursor_user? 0: 1; + if( !action ) + return; - if( key == GLFW_KEY_GRAVE_ACCENT ) - { - vg_console.enabled = !vg_console.enabled; - return; - } - - if( !vg_console.enabled ) - return; - - if( key == GLFW_KEY_LEFT ) - { - if( mods & GLFW_MOD_SHIFT ) /* Receed secondary cursor */ - { - console_move_cursor( &vg_console.cursor_user, NULL, -1, 0 ); - } - else /* Match and receed both cursors */ - { - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, -cursor_diff, 1 ); - } - } - else if( key == GLFW_KEY_RIGHT ) /* Advance secondary cursor */ - { - if( mods & GLFW_MOD_SHIFT ) - { - console_move_cursor( &vg_console.cursor_user, NULL, 1, 0 ); - } - else /* Match and advance both cursors */ - { - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, +cursor_diff, 1 ); - } - } - else if( key == GLFW_KEY_DOWN ) - { - if( mods & GLFW_MOD_SHIFT ){} - else - { - vg_console.history_pos = VG_MAX( 0, vg_console.history_pos-1 ); - console_history_get( vg_console.input, vg_console.history_pos ); - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, vg_list_size( vg_console.input ), 1 ); - } - } - else if( key == GLFW_KEY_UP ) - { - if( mods & GLFW_MOD_SHIFT ){} - else - { - vg_console.history_pos = VG_MAX - ( - 0, - VG_MIN - ( - vg_console.history_pos+1, - VG_MIN - ( - vg_list_size( vg_console.history ), - vg_console.history_count - 1 - ) - ) - ); - - console_history_get( vg_console.input, vg_console.history_pos ); - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, - vg_list_size( vg_console.input ), 1); - } - } - else if( key == GLFW_KEY_BACKSPACE ) /* Lookback delete */ - { - vg_console.cursor_user = console_delete_char( -1 ); - vg_console.cursor_pos = vg_console.cursor_user; - } - else if( key == GLFW_KEY_DELETE ) /* Lookforward delete */ - { - vg_console.cursor_user = console_delete_char( 1 ); - vg_console.cursor_pos = vg_console.cursor_user; - } - else if( key == GLFW_KEY_HOME ) /* Home key */ - { - if( mods & GLFW_MOD_SHIFT ) - console_move_cursor( &vg_console.cursor_user, NULL, -10000, 0 ); - else - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, -10000, 1 ); - } - else if( key == GLFW_KEY_END ) /* End key */ - { - if( mods & GLFW_MOD_SHIFT ) - console_move_cursor( &vg_console.cursor_user, NULL, 10000, 0 ); - else - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, - vg_list_size( vg_console.input ), 1 ); - } - else if( key == GLFW_KEY_A ) - { - if( mods & GLFW_MOD_CONTROL ) /* Select all */ - { - console_move_cursor( &vg_console.cursor_user, NULL, 10000, 0); - console_move_cursor( &vg_console.cursor_pos, NULL, -10000, 0); - } - } - else if( key == GLFW_KEY_C ) /* Copy */ - { - if( mods & GLFW_MOD_CONTROL ) - { - console_to_clipboard(); - } - } - else if( key == GLFW_KEY_X ) /* Cut */ - { - if( mods & GLFW_MOD_CONTROL ) - { - console_to_clipboard(); - vg_console.cursor_user = console_delete_char(0); - vg_console.cursor_pos = vg_console.cursor_user; - } - } - else if( key == GLFW_KEY_V ) /* Paste */ - { - if( mods & GLFW_MOD_CONTROL ) - { - console_clipboard_paste(); - } - } - else if( key == GLFW_KEY_ENTER ) - { - if( !strlen( vg_console.input ) ) - return; - - vg_info( "%s\n", vg_console.input ); - - if( strcmp( vg_console.input, - vg_console.history[ vg_console.history_last ]) ) - { - vg_console.history_last = ( vg_console.history_last + 1) % - vg_list_size(vg_console.history ); - vg_console.history_count = - VG_MIN( vg_list_size( vg_console.history ), - vg_console.history_count + 1 ); - strcpy( vg_console.history[ vg_console.history_last ], - vg_console.input ); - } - - vg_console.history_pos = -1; - execute_console_input( vg_console.input ); - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, -10000, 1 ); - vg_console.input[0] = '\0'; - } - } + /* Open / close console */ + if( key == GLFW_KEY_GRAVE_ACCENT ) + vg_console.enabled = !vg_console.enabled; + + if( !vg_console.enabled ) return; + + struct console_mapping + { + u32 mod, key; + void (*handler)(void); + } + mapping[] = + { + { 0, GLFW_KEY_LEFT, _console_left }, + { GLFW_MOD_SHIFT, GLFW_KEY_LEFT, _console_left_select }, + { 0, GLFW_KEY_RIGHT, _console_right }, + { GLFW_MOD_SHIFT, GLFW_KEY_RIGHT, _console_right_select }, + { 0, GLFW_KEY_DOWN, _console_down }, + { 0, GLFW_KEY_UP, _console_up }, + { 0, GLFW_KEY_BACKSPACE, _console_backspace }, + { 0, GLFW_KEY_DELETE, _console_delete }, + { 0, GLFW_KEY_HOME, _console_home }, + { GLFW_MOD_SHIFT, GLFW_KEY_HOME, _console_home_select }, + { 0, GLFW_KEY_END, _console_end }, + { GLFW_MOD_SHIFT, GLFW_KEY_END, _console_end_select }, + { GLFW_MOD_CONTROL, GLFW_KEY_A, _console_select_all }, + { GLFW_MOD_CONTROL, GLFW_KEY_C, console_to_clipboard }, + { GLFW_MOD_CONTROL, GLFW_KEY_X, _console_cut }, + { GLFW_MOD_CONTROL, GLFW_KEY_V, console_clipboard_paste }, + { 0, GLFW_KEY_ENTER, _console_enter } + }; + + for( int i=0; ikey == key ) + { + if( mk->mod == 0 ) + { + if( mods == 0 ) + { + mk->handler(); + return; + } + } + else if( (mods & mk->mod) == mk->mod ) + { + mk->handler(); + return; + } + } + } } /* Handle an OS based input of UTF32 character from the keyboard or such */ diff --git a/src/vg/vg_input.h b/src/vg/vg_input.h index 3985f3c..c338531 100644 --- a/src/vg/vg_input.h +++ b/src/vg/vg_input.h @@ -178,33 +178,29 @@ void vg_update_inputs(void) } } -static int vg_gamepad_init(void) +static void vg_gamepad_init(void) { - if( vg_acquire_thread_sync(1) ) + vg_acquire_thread_sync(); + + for( int id=0; id<=GLFW_JOYSTICK_LAST; id ++ ) { - for( int id=0; id<=GLFW_JOYSTICK_LAST; id ++ ) + if( glfwJoystickPresent( id ) ) { - if( glfwJoystickPresent( id ) ) - { - vg_info( "Joystick found: '%s'\n", glfwGetJoystickName(id) ); - } - - if( glfwJoystickIsGamepad( id ) ) - { - vg.gamepad_name = glfwGetGamepadName( id ); - vg_success( "Gamepad mapping registered: %s\n", vg.gamepad_name ); - - vg.gamepad_ready = 1; - vg.gamepad_id = id; - break; - } + vg_info( "Joystick found: '%s'\n", glfwGetJoystickName(id) ); } - vg_release_thread_sync(1); - return 1; + if( glfwJoystickIsGamepad( id ) ) + { + vg.gamepad_name = glfwGetGamepadName( id ); + vg_success( "Gamepad mapping registered: %s\n", vg.gamepad_name ); + + vg.gamepad_ready = 1; + vg.gamepad_id = id; + break; + } } - return 0; + vg_release_thread_sync(); } #endif diff --git a/src/vg/vg_io.h b/src/vg/vg_io.h index 19d468b..95e1623 100644 --- a/src/vg/vg_io.h +++ b/src/vg/vg_io.h @@ -25,17 +25,14 @@ static void *vg_disk_open_read( const char *path, int reserve_end, i64 *size ) if( f ) { i64 fsize = vg_file_size( f ); - void *buf = malloc( fsize + reserve_end ); + void *buf = vg_alloc( fsize + reserve_end ); - if( buf ) - { - /* Invalid / corrupt read */ - if( fread( buf, 1, fsize, f ) != fsize ) - { - free( buf ); - buf = NULL; - } - } + /* Invalid / corrupt read */ + if( fread( buf, 1, fsize, f ) != fsize ) + { + vg_free( buf ); + buf = NULL; + } *size = fsize; diff --git a/src/vg/vg_lines.h b/src/vg/vg_lines.h index 0c02bb1..82f1814 100644 --- a/src/vg/vg_lines.h +++ b/src/vg/vg_lines.h @@ -79,7 +79,7 @@ struct } vg_lines; -static int vg_lines_init(void) +static void vg_lines_init(void) { vg_info( "vg_lines_init\n" ); @@ -92,9 +92,8 @@ static int vg_lines_init(void) }); vg_shader_register( &_shader_lines ); - - if( vg_acquire_thread_sync(1) ) + vg_acquire_thread_sync(); { glGenVertexArrays( 1, &vg_lines.vao ); glGenBuffers( 1, &vg_lines.vbo ); @@ -107,12 +106,7 @@ static int vg_lines_init(void) glBufferData( GL_ARRAY_BUFFER, vg_lines.buffer_size, NULL, GL_DYNAMIC_DRAW ); glBindVertexArray( vg_lines.vao ); - - if( VG_CHECK_GL_ERR() ) - { - vg_release_thread_sync(1); - vg_error( "Failed\n" ); - } + VG_CHECK_GL_ERR(); /* Pointers */ glVertexAttribPointer( @@ -135,33 +129,21 @@ static int vg_lines_init(void) ); glEnableVertexAttribArray( 1 ); - if( VG_CHECK_GL_ERR() ) - goto il_delete_buffers_and_fail; + VG_CHECK_GL_ERR(); /* Alloc RAM */ - vg_lines.buffer = malloc( vg_lines.buffer_size ); - if( vg_lines.buffer ) - { - vg_success( "done\n" ); - vg_release_thread_sync(1); - return 1; - } - -il_delete_buffers_and_fail: - glDeleteBuffers( 1, &vg_lines.vbo ); - glDeleteVertexArrays( 1, &vg_lines.vao ); - vg_release_thread_sync(1); - return 0; + vg_lines.buffer = vg_alloc( vg_lines.buffer_size ); + vg_success( "done\n" ); } - return 0; + vg_release_thread_sync(); } static void vg_lines_free(void *nothing) { glDeleteVertexArrays( 1, &vg_lines.vao ); glDeleteBuffers( 1, &vg_lines.vbo ); - free( vg_lines.buffer ); + vg_free( vg_lines.buffer ); } static void vg_lines_drawall( float* projection ) diff --git a/src/vg/vg_loader.h b/src/vg/vg_loader.h index 2ba707e..6e3882a 100644 --- a/src/vg/vg_loader.h +++ b/src/vg/vg_loader.h @@ -14,18 +14,6 @@ static struct vg_loader { - /* Synchronization */ - vg_semaphore sem_loading; - vg_mutex mux_status; - - enum loader_status - { - k_loader_status_loading, - k_loader_status_complete, - k_loader_status_fail - } - status; - /* Shutdown steps */ struct loader_free_step { @@ -39,37 +27,24 @@ vg_loader; static int vg_loader_init(void) { - vg_semaphore_init( &vg_loader.sem_loading, 0 ); - vg_mutex_init( &vg_loader.mux_status ); return 1; } static void vg_loader_free(void) { - vg_semaphore_wait( &vg_loader.sem_loading ); - vg_semaphore_free( &vg_loader.sem_loading ); - vg_mutex_free( &vg_loader.mux_status ); + vg_info( "vg_loader_free\n" ); for( int i=0; i %p\n", step->fn_free ); step->fn_free( step->data ); } - free( vg_loader.step_buffer ); -} - -static enum loader_status vg_loader_status(void) -{ - enum loader_status answer; - - vg_mutex_lock( &vg_loader.mux_status ); - answer = vg_loader.status; - vg_mutex_unlock( &vg_loader.mux_status ); - - return answer; + vg_free( vg_loader.step_buffer ); + vg_info( "done\n" ); } static float hue_to_rgb( float p, float q, float t ) @@ -84,8 +59,8 @@ static float hue_to_rgb( float p, float q, float t ) static void vg_loader_render(void) { - float h = vg_fractf(vg_time*0.1), - s = 0.2f, + float h = vg_randf(), + s = 0.7f, l = 0.1f, //* (0.5f+vg_fractf(vg_time*40.0)*0.5f), q = l < 0.5f ? l * (1.0f + s) : l + s - l * s, p = 2.0f * l - q, @@ -131,65 +106,56 @@ static void vg_loader_render(void) } -static int vg_load_full(void); +static void vg_load_full(void); static void vg_loader_thread(void * nothing) { - /* Run client loader */ - int res = vg_load_full(); - - /* Propogate status */ - vg_mutex_lock( &vg_loader.mux_status ); - if( res ) - { - vg_loader.status = k_loader_status_complete; - } - else - { - vg_loader.status = k_loader_status_fail; - } - vg_mutex_unlock( &vg_loader.mux_status ); + vg_thread_info.gl_context_level = 0; + vg_thread_info.purpose = k_thread_purpose_loader; + vg_set_thread_name( "[vg] Loader" ); - vg_semaphore_post( &vg_loader.sem_loading ); + /* Run client loader */ + vg_load_full(); + vg_semaphore_post( &vg.sem_loader ); } static void vg_loader_start(void) { + vg_semaphore_wait( &vg.sem_loader ); vg_thread_run( vg_loader_thread, NULL ); } static void vg_free_libc_malloced( void *data ) { - free( data ); + vg_free( data ); } -static int vg_loader_push_free_step( struct loader_free_step step ) +static void vg_loader_push_free_step( struct loader_free_step step ) { - void *buf = buffer_reserve( vg_loader.step_buffer, vg_loader.step_count, + vg_loader.step_buffer = + buffer_reserve( vg_loader.step_buffer, vg_loader.step_count, &vg_loader.step_cap, 1, sizeof( struct loader_free_step ) ); - if( !buf ) - return 0; - - vg_loader.step_buffer = buf; vg_loader.step_buffer[ vg_loader.step_count ++ ] = step; - return 1; } + /* - * Schedule something to be freed + * Schedule something to be ran now, freed later */ -__attribute__((warn_unused_result)) -static int vg_loader_highwater( void( *fn_free )(void *), void *data ) +static void vg_loader_highwater( void( *fn_load )(void), + void( *fn_free )(void *), void *data ) { + if( fn_load ) + fn_load(); + if( fn_free ) { struct loader_free_step step; step.data = data; step.fn_free = fn_free; - if( !vg_loader_push_free_step( step ) ) - return 0; + vg_loader_push_free_step( step ); } else { @@ -199,152 +165,11 @@ static int vg_loader_highwater( void( *fn_free )(void *), void *data ) step.data = data; step.fn_free = vg_free_libc_malloced; - if( !vg_loader_push_free_step( step ) ) - return 0; + vg_loader_push_free_step( step ); } } - vg_mutex_lock( &vg.mux_engine_status ); - - if( !vg.engine_running ) - { - vg_mutex_unlock( &vg.mux_engine_status ); - return 0; - } - - vg_mutex_unlock( &vg.mux_engine_status ); - return 1; + vg_ensure_engine_running(); } #endif /* VG_LOADER_H */ - -#if 0 -#ifndef LOADER_H -#define LOADER_H - -#include "common.h" - -static struct loader -{ - MUTEX_TYPE mux; - - struct loader_step - { - int (*fn_load)(void); - void (*fn_free)(void); - - int require_opengl; - const char *name; - } - *step_buffer; - u32 step_count, step_cap, step_action, - low_water_mark; /* What is the minumum number of systems we can have? */ - - enum loader_status - { - k_loader_status_loading, - k_loader_status_complete, - k_loader_status_fail - } - status; - - int cancel; -} -loader; - -static void loader_add_stage( struct loader_step step ) -{ - loader.step_buffer = buffer_reserve( loader.step_buffer, loader.step_count, - &loader.step_cap, - 1, sizeof( struct loader_step ) ); - - loader.step_buffer[ loader.step_count ++ ] = step; -} - -static void loader_insert_stage( struct loader_step step ) -{ - -} - -static void loader_cancel(void) -{ - MUTEX_LOCK( loader.mux ); - loader.cancel = 1; - MUTEX_UNLOCK( loader.mux ); -} - -static void loader_worker_thread( void *nothing ) -{ - while(1) - { - vg_sleep_ms( 1000.0 ); - vg_info( "... loader ....\n" ); - - if( loader.cancel ) - { - return; - } - } -} - -static void loader_begin(void) -{ - if( loader.step_count == 0 ) - { - loader.status = k_loader_status_complete; - return; - } - - loader.status = k_loader_status_loading; - vg_thread_run( loader_worker_thread, NULL ); -} - -static void loader_free(void) -{ - /* TODO */ - for( int i=0; ifn_free ) - step->fn_free(); - } -} - -/* - * Returns 0 if loading is not happening - * Returns 1 if we are loading something - */ -static int loader_update(void) -{ - MUTEX_LOCK( loader.mux ); - - if( loader.status == k_loader_status_complete ) - { - MUTEX_UNLOCK( loader.mux ); - return 0; - } - else - { - struct loader_step *cstep = &loader.step_buffer[ loader.step_action ]; - - if( cstep->require_opengl ) - { - if( !cstep->fn_load() ) - { - loader.cancel = 1; - MUTEX_UNLOCK( loader.mux ); - - loader_free(); - vg_exit(); - } - - loader.step_action ++; - } - - MUTEX_UNLOCK( loader.mux ); - return 1; - } -} - -#endif /* LOADER_H */ -#endif diff --git a/src/vg/vg_m.h b/src/vg/vg_m.h index 417ca32..c28e477 100644 --- a/src/vg/vg_m.h +++ b/src/vg/vg_m.h @@ -1311,4 +1311,15 @@ static inline int vg_randint(int max) return rand()%max; } +static void eval_bezier_time( v3f p0, v3f p1, v3f h0, v3f h1, float t, v3f p ) +{ + float tt = t*t, + ttt = tt*t; + + v3_muls( p1, ttt, p ); + v3_muladds( p, h1, 3.0f*tt -3.0f*ttt, p ); + v3_muladds( p, h0, 3.0f*ttt -6.0f*tt +3.0f*t, p ); + v3_muladds( p, p0, 3.0f*tt -ttt -3.0f*t +1.0f, p ); +} + #endif /* VG_M_H */ diff --git a/src/vg/vg_module.h b/src/vg/vg_module.h new file mode 100644 index 0000000..15dfd47 --- /dev/null +++ b/src/vg/vg_module.h @@ -0,0 +1,29 @@ +#ifndef VG_MODULE_H +#define VG_MODULE_H + +#include "vg_shader.h" + +struct vg_module +{ + const char *name; + + struct + { + struct vg_shader *shaders; + u32 shader_count; + + vg_tex2d *textures; + u32 texture_count; + } + resources; + + int (*fn_load)(void); + void (*fn_free)(void); +}; + +static int vg_module_load( struct vg_module *m ) +{ + +} + +#endif /* VG_MODULE_H */ diff --git a/src/vg/vg_platform.h b/src/vg/vg_platform.h index d7c0a0c..ab9c927 100644 --- a/src/vg/vg_platform.h +++ b/src/vg/vg_platform.h @@ -2,6 +2,7 @@ #define VG_PLATFORM_H #include "vg.h" +#include "vg_stdint.h" /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */ @@ -30,41 +31,122 @@ struct vg_achievement #define vg_static_assert _Static_assert #define vg_list_size( A ) (sizeof(A)/sizeof(A[0])) +#define VG_MUST_USE_RESULT __attribute__((warn_unused_result)) #ifdef _WIN32 #include /* TODO */ +#define VG_DEPRECATED __declspec(deprecated) #else #include #include +#define VG_DEPRECATED __attribute__((deprecated)) + + #define VG_THREAD_LOCAL __thread + typedef sem_t vg_semaphore; typedef pthread_mutex_t vg_mutex; +#endif + +#include + +/* TODO: If there is no graphics, we dont need to do an exit loop */ + +static void vg_fatal_exit_loop( const char *error ); +static void *vg_alloc( size_t size ) +{ + void *ptr = malloc( size ); + + if( !ptr ) + vg_fatal_exit_loop( "Out of memory" ); + + return ptr; +} + +static void *vg_realloc( void *orig, size_t size ) +{ + void *ptr = realloc( orig, size ); + + if( !ptr ) + vg_fatal_exit_loop( "Out of memory" ); + + return ptr; +} + +/* seems to be a GCC bug when inlining this, its low priority anyway */ +__attribute__ ((noinline)) +static void vg_free( void *ptr ) +{ + free( ptr ); +} + +static void vg_required( void *ptr, const char *path ) +{ + if( !ptr ) + { + vg_fatal_exit_loop( path ); + } +} + +#define VG_REQUIRED_ASSET( TYPE, DECL, FN, PATH, ... ) \ + TYPE DECL = FN( PATH,##__VA_ARGS__ ); \ + vg_required( DECL, "Resource is required but failed to load: '" PATH "'" ); + +VG_DEPRECATED +void *malloc( size_t size ); + +VG_DEPRECATED +void *realloc( void *orig, size_t size ); + +VG_DEPRECATED +void free( void *ptr ); + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#else + +static void vg_thread_exit(void) +{ + pthread_exit(NULL); +} + +static void vg_set_thread_name( const char *name ) +{ + /* not defined but links?? */ +#if 0 + pthread_setname_np(pthread_self()); +#endif +} + static int vg_semaphore_init( vg_semaphore *sem, u32 value ) { - if( !sem_init( sem, 0, value ) ) - return 1; - else - return 0; + return !sem_init( sem, 0, value ); +} + +static int vg_semaphore_trywait( vg_semaphore *sem ) +{ + return !sem_trywait( sem ); } static int vg_semaphore_wait( vg_semaphore *sem ) { - if( !sem_wait( sem ) ) - return 1; - else - return 0; + return !sem_wait( sem ); } static int vg_semaphore_post( vg_semaphore *sem ) { - if( !sem_post( sem ) ) - return 1; - else - return 0; + return !sem_post( sem ); } static void vg_semaphore_free( vg_semaphore *sem ) @@ -96,7 +178,7 @@ static int vg_mutex_unlock( vg_mutex *mutex ) static void vg_mutex_free( vg_mutex *mutex ) { - + } #endif @@ -169,8 +251,7 @@ static void *buffer_reserve( void *buffer, u32 count, u32 *cap, u32 amount, if( count+amount > *cap ) { *cap = VG_MAX( (*cap)*2, (*cap)+amount ); - - return realloc( buffer, (*cap) * emsize ); + return vg_realloc( buffer, (*cap) * emsize ); } return buffer; @@ -179,7 +260,7 @@ static void *buffer_reserve( void *buffer, u32 count, u32 *cap, u32 amount, static void *buffer_fix( void *buffer, u32 count, u32 *cap, size_t emsize ) { *cap = count; - return realloc( buffer, (*cap) * emsize ); + return vg_realloc( buffer, (*cap) * emsize ); } #endif diff --git a/src/vg/vg_shader.h b/src/vg/vg_shader.h index a6c7a0b..2186c9d 100644 --- a/src/vg/vg_shader.h +++ b/src/vg/vg_shader.h @@ -8,10 +8,14 @@ #define STB_INCLUDE_IMPLEMENTATION #define STB_INCLUDE_LINE_GLSL +#define STB_MALLOC vg_alloc +#define STB_FREE vg_free +#define STB_REALLOC vg_realloc #include "stb/stb_include.h" const char *vg_shader_gl_ver = "#version 330 core\n"; +static struct vg_shader { GLuint id; @@ -28,6 +32,8 @@ struct vg_shader int compiled; } ** vg_shaders_active = NULL; +static u32 vg_shader_count, + vg_shader_cap; static GLuint vg_shader_subshader( const char *src, GLint gliShaderType ) { @@ -101,8 +107,8 @@ static int vg_shader_compile( struct vg_shader *shader ) vg_error( "Could not find shader source files (%s)\n", shader->vs.orig_file ); - free( avs ); - free( afs ); + vg_free( avs ); + vg_free( afs ); return 0; } @@ -115,8 +121,8 @@ static int vg_shader_compile( struct vg_shader *shader ) if( !static_src ) { - free( avs ); - free( afs ); + vg_free( avs ); + vg_free( afs ); } if( !vert || !frag ) @@ -165,7 +171,7 @@ static void vg_free_shader( struct vg_shader *shader ) static void vg_shaders_free(void *nothing) { - for( int i = 0; i < arrlen( vg_shaders_active ); i ++ ) + for( int i=0; iid ); } - arrfree( vg_shaders_active ); + vg_free( vg_shaders_active ); } static int vg_shaders_recompile(void) { vg_info( "Compiling shaders\n" ); - for( int i=0; icompiled = 0; shader->id = 0; /* TODO: make this an error shader */ - arrpush( vg_shaders_active, shader ); + vg_shaders_active = buffer_reserve( vg_shaders_active, vg_shader_count, + &vg_shader_cap, 1, + sizeof( struct vg_shader * ) ); + + vg_shaders_active[ vg_shader_count ++ ] = shader; } #endif /* VG_SHADER_H */ diff --git a/src/vg/vg_steam.h b/src/vg/vg_steam.h index 05fe1ac..ab135bc 100644 --- a/src/vg/vg_steam.h +++ b/src/vg/vg_steam.h @@ -537,7 +537,7 @@ static void steamworks_event_loop( HSteamPipe pipe ) SteamAPICallCompleted_t *pCallCompleted = (SteamAPICallCompleted_t *)callback.m_pubParam; - void *pTmpCallResult = malloc( pCallCompleted->m_cubParam ); + void *pTmpCallResult = vg_alloc( pCallCompleted->m_cubParam ); int bFailed; if( SteamAPI_ManualDispatch_GetAPICallResult( @@ -601,7 +601,7 @@ static void steamworks_event_loop( HSteamPipe pipe ) #endif } - free( pTmpCallResult ); + vg_free( pTmpCallResult ); } else { diff --git a/src/vg/vg_steam_auth.h b/src/vg/vg_steam_auth.h index 9d06c9c..1875999 100644 --- a/src/vg/vg_steam_auth.h +++ b/src/vg/vg_steam_auth.h @@ -1,6 +1,8 @@ #ifndef VG_STEAM_AUTH_H #define VG_STEAM_AUTH_H +#include "vg/vg_platform.h" + typedef u32 HAuthTicket; enum{ k_HAuthTicketInvalid = 0 }; @@ -120,7 +122,7 @@ static int vg_load_steam_symetric_key( const char *path, u8 *buf ) if( len < k_nSteamEncryptedAppTicketSymmetricKeyLen ) { vg_error( "Application key was invalid size\n" ); - free( text_src ); + vg_free( text_src ); return 0; } @@ -130,7 +132,7 @@ static int vg_load_steam_symetric_key( const char *path, u8 *buf ) vg_char_base16( text_src[i*2+1] ); } - free( text_src ); + vg_free( text_src ); return 1; } else diff --git a/src/vg/vg_tex.h b/src/vg/vg_tex.h index 9e0c56f..e92e5f1 100644 --- a/src/vg/vg_tex.h +++ b/src/vg/vg_tex.h @@ -11,6 +11,12 @@ #define VG_TEXTURE_NEAREST 0x8 #define VG_TEXTURE_ALLOCATED_INTERNAL 0x10 +#define QOI_IMPLEMENTATION +#define QOI_MALLOC vg_alloc +#define QOI_FREE vg_free + +#include "phoboslab/qoi.h" + struct vg_tex2d { const char *path; @@ -88,8 +94,8 @@ static GLuint vg_tex2d_rgba( const char *path ) glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, info.width, info.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_buffer ); - free( tex_buffer ); - free( src_data ); + vg_free( tex_buffer ); + vg_free( src_data ); } else { diff --git a/src/vg/vg_ui.h b/src/vg/vg_ui.h index 844194e..4e09338 100644 --- a/src/vg/vg_ui.h +++ b/src/vg/vg_ui.h @@ -175,14 +175,14 @@ static ui_colourset ui_default_colours = { static ui_ctx ui_global_ctx; -static void ui_context_free( ui_ctx *ctx ) +static void ui_context_vg_free( ui_ctx *ctx ) { glDeleteVertexArrays( 1, &ctx->vao ); glDeleteBuffers( 1, &ctx->vbo ); glDeleteBuffers( 1, &ctx->ebo ); - free( ctx->verts ); - free( ctx->indices ); + vg_free( ctx->verts ); + vg_free( ctx->indices ); } static int ui_init_context( ui_ctx *ctx, int index_buffer_size ) @@ -206,8 +206,7 @@ static int ui_init_context( ui_ctx *ctx, int index_buffer_size ) glBufferData( GL_ELEMENT_ARRAY_BUFFER, index_buffer_size * sizeof( u16 ), NULL, GL_DYNAMIC_DRAW ); - if( VG_CHECK_GL_ERR() ) - goto il_fail_alloc_gpu; + VG_CHECK_GL_ERR(); /* Set pointers */ u32 const stride = sizeof( struct ui_vert ); @@ -232,17 +231,15 @@ static int ui_init_context( ui_ctx *ctx, int index_buffer_size ) (void *)offsetof( struct ui_vert, clip ) ); glEnableVertexAttribArray( 3 ); - if( VG_CHECK_GL_ERR() ) - goto il_fail_attributes; - + VG_CHECK_GL_ERR(); /* Alloc RAM default context */ - ctx->verts = (struct ui_vert *)malloc( + ctx->verts = (struct ui_vert *)vg_alloc( vertex_buffer_size * sizeof(struct ui_vert) ); if( !ctx->verts ) goto il_fail_alloc_verts; - ctx->indices = (u16*)malloc( index_buffer_size * sizeof(u16) ); + ctx->indices = (u16*)vg_alloc( index_buffer_size * sizeof(u16) ); if( !ctx->indices ) goto il_fail_alloc_indices; @@ -251,14 +248,12 @@ static int ui_init_context( ui_ctx *ctx, int index_buffer_size ) return 1; - free( ctx->indices ); + vg_free( ctx->indices ); ctx->indices = NULL; il_fail_alloc_indices: - free( ctx->verts ); + vg_free( ctx->verts ); ctx->verts = NULL; il_fail_alloc_verts: -il_fail_attributes: -il_fail_alloc_gpu: glDeleteBuffers( 1, &ctx->ebo ); glDeleteBuffers( 1, &ctx->vbo ); glDeleteVertexArrays( 1, &ctx->vao ); @@ -274,8 +269,7 @@ static int ui_default_init(void) }; u32 pixels = 0, total = 256*256, data = 0; - u8 *image = malloc( total ); - if( !image ) goto il_fail_alloc_image; + u8 *image = vg_alloc( total ); while( pixels < total ) { @@ -293,18 +287,16 @@ static int ui_default_init(void) } glGenTextures( 1, &ui_glyph_texture ); - if( !ui_glyph_texture ) goto il_fail_gen_texture; - glBindTexture( GL_TEXTURE_2D, ui_glyph_texture ); glTexImage2D( GL_TEXTURE_2D, 0, GL_R8, 256, 256, 0, GL_RED, GL_UNSIGNED_BYTE, image ); + + vg_free( image ); - if( VG_CHECK_GL_ERR() ) goto il_fail_alloc_gpu; + VG_CHECK_GL_ERR(); vg_tex2d_clamp(); vg_tex2d_nearest(); - - free( image ); if( !ui_init_context( &ui_global_ctx, 20000 ) ) goto il_generic_fail; if( !vg_shader_compile( &_shader_ui ) ) goto il_shader_fail; @@ -312,14 +304,9 @@ static int ui_default_init(void) return 1; il_shader_fail: -il_fail_alloc_gpu: il_generic_fail: glDeleteTextures( 1, &ui_glyph_texture ); - -il_fail_gen_texture: - free( image ); - -il_fail_alloc_image: + vg_free( image ); return 0; } @@ -327,7 +314,7 @@ static void ui_default_free(void) { vg_free_shader( &_shader_ui ); glDeleteTextures( 1, &ui_glyph_texture ); - ui_context_free( &ui_global_ctx ); + ui_context_vg_free( &ui_global_ctx ); } static struct ui_vert *ui_fill_rect_uv( ui_ctx *ctx, ui_rect rect,