/* 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 <execinfo.h>
+#endif
#if defined(VG_SERVER) || defined(VG_TOOLS)
#include "vg_steam.h"
#endif
-#ifndef VG_NON_CLIENT
-#include "vg_gldiag.h"
-#endif
-
#ifndef VG_NON_CLIENT
struct vg
const char *gamepad_name;
int gamepad_id;
}
-static vg = { .time_rate = 1.0 };
+VG_STATIC vg = { .time_rate = 1.0 };
struct 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 );
-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 );
* 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 )
* 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;
}
}
-static void vg_run_synced_content(void)
+VG_STATIC void vg_run_synced_content(void)
{
assert( vg_thread_info.purpose == k_thread_purpose_main );
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 );
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__) )
#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;
vg_framebuffer_resize(w,h);
}
-static int vg_bake_shaders(void)
+VG_STATIC void vg_bake_shaders(void)
{
vg_acquire_thread_sync();
+#if 0
vg_function_push( (struct vg_cmd)
{
.name = "shaders",
.function = vg_shaders_live_recompile
});
+#endif
- 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;
- }
+ 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 );
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 ) )
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 );
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_HIDDEN );
if( !gladLoadGLLoader((GLADloadproc)glfwGetProcAddress) )
{
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;
if( vg.is_loaded )
{
-#if 0
- 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 );
-#endif
-
if( !loaded )
{
vg_start();
/* 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 );
+ ui_set_mouse( vg.mouse[0], vg.mouse[1],
+ vg_get_button_state( "primary" ) );
vg_profile_drawn(
(struct vg_profile *[]){&vg_prof_update,&vg_prof_render}, 2,
vg.fixed_iterations,
(vg.accumulator/VG_TIMESTEP_FIXED)*100.0f );
- ui_text( &ui_global_ctx, (ui_rect){258, 4+24+12,0,0},perf, 1,0);
+ 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 );
}
}
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();
}
* 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<size; i++ )
+ vg_info( "%s\n", strings[i] );
+
+ vg_error( "---------------- gnu backtrace -------------\n" );
+ }
+
+ free( strings );
+
+#endif
+
vg_error( "Fatal error: %s\n", error );
assert( vg_semaphore_trywait( &vg.sem_fatal ) );
}
vg_audio_free(NULL);
-#ifndef _WIN32
while(1)
{
if( glfwWindowShouldClose( vg.window ) )
glfwSwapBuffers( vg.window );
}
-#endif
/* Can now shutdown and EXIT */
vg_loader_free();
- ui_default_free();
-
glfwTerminate();
exit(0);
}
#else
-static void vg_fatal_exit_loop( const char *error )
+VG_STATIC void vg_fatal_exit_loop( const char *error )
{
vg_error( "Fatal error: %s\n", error );
exit(0);