|IMP| | |.------------- vg_start(void) ---------------'
| | | |
| | | v
-|IMP| | vg_update( int loaded )
+|IMP| | vg_update(void)
| | | |
| | | .-----+.
| | | | |
| | | | v
-|IMP| | '- vg_update_fixed( int loaded )
+|IMP| | '- vg_update_fixed(void)
| | | |
| | | .-'
| | | |
VG_STATIC void vg_start(void);
VG_STATIC void vg_framebuffer_resize(int w, int h);
-VG_STATIC void vg_update(int loaded);
-VG_STATIC void vg_update_fixed(int loaded);
-VG_STATIC void vg_update_post(int loaded);
+VG_STATIC void vg_update(void);
+VG_STATIC void vg_update_fixed(void);
+VG_STATIC void vg_update_post(void);
VG_STATIC void vg_render(void);
VG_STATIC void vg_ui(void);
SDL_threadID thread_id_main,
thread_id_loader,
thread_id_with_opengl_context;
- int context_ownership_refcount;
+ int context_ownership_depth;
int exec_context;
}
VG_STATIC vg = { .time_rate = 1.0 };
-struct vg_thread_info
+enum vg_thread_purpose
{
- enum vg_thread_purpose
- {
- k_thread_purpose_nothing,
- k_thread_purpose_main,
- k_thread_purpose_loader
- }
- purpose;
-
- int gl_context_level;
+ k_thread_purpose_nothing,
+ k_thread_purpose_main,
+ k_thread_purpose_loader
};
VG_STATIC void vg_fatal_exit_loop( const char *error );
-VG_STATIC void vg_ensure_engine_running(void)
+/*
+ * Checks if the engine is running
+ */
+VG_STATIC void _vg_ensure_engine_running(void)
{
- VG_SYNC_LOG( "[%d] Checks if engine is running\n" );
-
/* Check if the engine is no longer running */
SDL_AtomicLock( &vg.sl_context );
+ enum engine_status status = vg.engine_status;
+ SDL_AtomicUnlock( &vg.sl_context );
- if( vg.engine_status != k_engine_status_running )
+ if( status != k_engine_status_running )
{
- VG_SYNC_LOG( "[%d] Engine is no longer running\n");
-
- /* Safe to disregard loader thread from this point on, elswhere */
- if( vg.thread_id_loader == SDL_GetThreadID(NULL) )
+ while(1)
{
- SDL_SemPost( vg.sem_loader );
+ VG_SYNC_LOG( "[%d] No longer running...\n");
+ SDL_Delay(1000);
}
-
- SDL_AtomicUnlock( &vg.sl_context );
-
- VG_SYNC_LOG( "[%d] is just going to hang around and wait to die\n");
- while(1) SDL_Delay(1000);
}
-
- SDL_AtomicUnlock( &vg.sl_context );
}
-/*
- * Sync execution so that the OpenGL context is switched onto this thread.
- * Anything after this call will be in a valid context.
- */
-VG_STATIC void vg_acquire_thread_sync(void)
+VG_STATIC enum vg_thread_purpose vg_thread_purpose(void)
{
- VG_SYNC_LOG( "[%d] Starts acquiring sync\n" );
-
- /* We dont want to do anything if this is the main thread */
SDL_AtomicLock( &vg.sl_context );
+
if( vg.thread_id_main == SDL_GetThreadID(NULL) )
{
SDL_AtomicUnlock( &vg.sl_context );
- return;
+ return k_thread_purpose_main;
}
- SDL_AtomicUnlock( &vg.sl_context );
-
- vg_ensure_engine_running();
-
- /* Check if thread already has the context */
- SDL_AtomicLock( &vg.sl_context );
- if( vg.thread_id_with_opengl_context == SDL_GetThreadID(NULL) )
+ else
{
- vg.context_ownership_refcount ++;
SDL_AtomicUnlock( &vg.sl_context );
-
- VG_SYNC_LOG( "[%d] We already have sync here\n" );
- return;
+ return k_thread_purpose_loader;
}
+}
- VG_SYNC_LOG( "[%d] Signal to sync.\n" );
- vg.exec_context = 1;
- SDL_AtomicUnlock( &vg.sl_context );
-
- /* wait until told we can go */
- VG_SYNC_LOG( "[%d] Waiting to acuire sync.\n" );
-
- SDL_SemWait( vg.sem_allow_exec );
- SDL_GL_MakeCurrent( vg.window, vg.gl_context );
+/*
+ * Sync execution so that the OpenGL context is switched onto this thread.
+ * Anything after this call will be in a valid context.
+ */
+VG_STATIC void vg_acquire_thread_sync(void)
+{
+ /* We dont want to do anything if this is the main thread */
- VG_SYNC_LOG( "[%d] Allow exec passed\n" );
+ if( vg_thread_purpose() == k_thread_purpose_loader )
+ {
+ VG_SYNC_LOG( "[%d] vg_acquire_thread_sync()\n" );
+ _vg_ensure_engine_running();
- /* context now valid to work in while we hold up main thread */
- SDL_AtomicLock( &vg.sl_context );
- vg.context_ownership_refcount ++;
- SDL_AtomicUnlock( &vg.sl_context );
+ SDL_AtomicLock( &vg.sl_context );
+ if( vg.context_ownership_depth == 0 )
+ {
+ vg.context_ownership_depth ++;
+ vg.exec_context = 1;
+ SDL_AtomicUnlock( &vg.sl_context );
+
+ /* wait until told we can go */
+ VG_SYNC_LOG( "[%d] Waiting to acuire sync.\n" );
+ SDL_SemWait( vg.sem_allow_exec );
+
+ _vg_ensure_engine_running();
- VG_SYNC_LOG( "[%d] Context acquired.\n" );
+ SDL_GL_MakeCurrent( vg.window, vg.gl_context );
+ VG_SYNC_LOG( "[%d] granted\n" );
+ }
+ else
+ {
+ vg.context_ownership_depth ++;
+ VG_SYNC_LOG( "[%d] granted\n" );
+ SDL_AtomicUnlock( &vg.sl_context );
+ }
+ }
}
/*
*/
VG_STATIC void vg_release_thread_sync(void)
{
- VG_SYNC_LOG( "[%d] Releases sync\n" );
-
- SDL_AtomicLock( &vg.sl_context );
- if( vg.thread_id_main == SDL_GetThreadID(NULL) )
- {
- SDL_AtomicUnlock( &vg.sl_context );
- return;
- }
-
- /* signal that we are done */
- vg.context_ownership_refcount --;
- if( !vg.context_ownership_refcount )
+ if( vg_thread_purpose() == k_thread_purpose_loader )
{
- SDL_AtomicUnlock( &vg.sl_context );
+ VG_SYNC_LOG( "[%d] vg_release_thread_sync()\n" );
- VG_SYNC_LOG( "[%d] Releasing context.\n" );
+ SDL_AtomicLock( &vg.sl_context );
+ vg.context_ownership_depth --;
- SDL_GL_MakeCurrent( NULL, NULL );
- SDL_SemPost( vg.sem_exec_finished );
+ if( vg.context_ownership_depth == 0 )
+ {
+ SDL_AtomicUnlock( &vg.sl_context );
+ VG_SYNC_LOG( "[%d] Releasing context.\n" );
+ SDL_GL_MakeCurrent( NULL, NULL );
+ SDL_SemPost( vg.sem_exec_finished );
+ }
+ else
+ SDL_AtomicUnlock( &vg.sl_context );
}
- else
- SDL_AtomicUnlock( &vg.sl_context );
}
-VG_STATIC void vg_run_synced_content(void)
+VG_STATIC void _vg_run_synced(void)
{
SDL_AtomicLock( &vg.sl_context );
if( vg.exec_context != 0 )
{
- VG_SYNC_LOG( "[%d] Allowing content (%d).\n", vg.exec_context );
+ VG_SYNC_LOG( "[%d] _vg_run_synced() (%d).\n", vg.exec_context );
vg.exec_context = 0;
SDL_AtomicUnlock( &vg.sl_context );
SDL_SemWait( vg.sem_exec_finished );
/* check if we killed the engine */
- vg_ensure_engine_running();
+ _vg_ensure_engine_running();
/* re-engage main thread */
VG_SYNC_LOG( "[%d] Re-engaging.\n" );
SDL_GL_MakeCurrent( vg.window, vg.gl_context );
}
else
+ {
+ VG_SYNC_LOG( "[%d] Nothing to do.\n" );
SDL_AtomicUnlock( &vg.sl_context );
+ }
}
-VG_STATIC void vg_opengl_sync_init(void)
+VG_STATIC void _vg_opengl_sync_init(void)
{
vg.sem_allow_exec = SDL_CreateSemaphore(0);
vg.sem_exec_finished = SDL_CreateSemaphore(0);
vg_release_thread_sync();
}
-VG_STATIC void vg_load_full(void)
+VG_STATIC void _vg_load_full(void)
{
vg_preload();
/* internal */
- vg_loader_highwater( vg_input_init, vg_input_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_loader_step( vg_input_init, vg_input_free );
+ vg_loader_step( vg_lines_init, NULL );
+ vg_loader_step( vg_audio_init, vg_audio_free );
+ vg_loader_step( vg_profiler_init, NULL );
/* client */
vg_load();
-
- vg_acquire_thread_sync();
- vg.is_loaded = 1;
- vg_release_thread_sync();
}
-VG_STATIC void vg_process_events(void)
+VG_STATIC void _vg_process_events(void)
{
/* Update timers */
vg.time_real_last = vg.time_real;
vg_update_inputs();
}
-VG_STATIC void vg_gameloop_update( int post_start )
+VG_STATIC void _vg_gameloop_update(void)
{
vg_profile_begin( &vg_prof_update );
vg.engine_stage = k_engine_stage_update;
- vg_update( post_start );
+ vg_update();
/* Fixed update loop */
vg.engine_stage = k_engine_stage_update_fixed;
vg_lines.allow_input = 1;
while( vg.accumulator >= (VG_TIMESTEP_FIXED-0.00125) )
{
- vg_update_fixed( post_start );
+ vg_update_fixed();
vg_lines.allow_input = 0;
vg.accumulator -= VG_TIMESTEP_FIXED;
vg_lines.allow_input = 1;
vg.engine_stage = k_engine_stage_update;
- vg_update_post( post_start );
+ vg_update_post();
vg_profile_end( &vg_prof_update );
}
-VG_STATIC void vg_gameloop_render( int post_start )
+VG_STATIC void _vg_gameloop_render(void)
{
vg_profile_begin( &vg_prof_render );
- if( post_start )
+ if( vg.is_loaded )
{
/* render */
vg.engine_stage = k_engine_stage_rendering;
audio_debug_ui( vg.pv );
vg_ui();
- vg_console_draw();
+ _vg_console_draw();
ui_resolve();
ui_draw( NULL );
vg_profile_end( &vg_prof_render );
}
-VG_STATIC void vg_gameloop(void)
+VG_STATIC void _vg_gameloop(void)
{
vg.accumulator = 0.75f * (1.0f/60.0f);
int post_start = 0;
while(1)
{
- vg_process_events();
+ _vg_process_events();
if( vg.window_should_close )
break;
}
else
{
- vg_loader_render();
+ _vg_loader_render();
}
- vg_gameloop_update( post_start );
- vg_gameloop_render( post_start );
+ _vg_gameloop_update();
+ _vg_gameloop_render();
SDL_GL_SwapWindow( vg.window );
- vg_run_synced_content();
+ _vg_run_synced();
}
}
-VG_STATIC void vg_process_launch_opts_internal( int argc, char *argv[] )
+VG_STATIC void _vg_process_launch_opts_internal( int argc, char *argv[] )
{
char *arg;
while( vg_argp( argc, argv ) )
}
}
-VG_STATIC void vg_init_window( const char *window_name )
+VG_STATIC void _vg_init_window( const char *window_name )
{
if( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_GAMECONTROLLER) != 0 )
{
SDL_WINDOWPOS_UNDEFINED,
mode.w, mode.h,
- SDL_WINDOW_FULLSCREEN |
+ SDL_WINDOW_FULLSCREEN_DESKTOP |
SDL_WINDOW_OPENGL |
SDL_WINDOW_INPUT_GRABBED )))
{
VG_STATIC void vg_enter( int argc, char *argv[], const char *window_name )
{
- vg_process_launch_opts_internal( argc, argv );
+ _vg_process_launch_opts_internal( argc, argv );
/* Systems init */
vg_alloc_quota();
- vg_log_init();
- vg_console_init();
- vg_init_window( window_name );
+ _vg_log_init();
+ _vg_console_init();
+ _vg_init_window( window_name );
SDL_SetRelativeMouseMode(1);
vg.thread_id_main = SDL_GetThreadID(NULL);
/* Opengl-required systems */
- ui_init_context();
- vg_loader_init();
+ _vg_ui_init();
+ _vg_loader_init();
vg.engine_status = k_engine_status_running;
- vg_opengl_sync_init();
- vg_loader_start();
-
- /* main */
- vg_gameloop();
+ _vg_opengl_sync_init();
+ vg_loader_start( _vg_load_full );
+ _vg_gameloop();
/* Shutdown */
- vg_console_write_persistent();
+ _vg_console_write_persistent();
SDL_AtomicLock( &vg.sl_context );
vg.engine_status = k_engine_status_none;
SDL_AtomicUnlock( &vg.sl_context );
- vg_loader_free();
+ _vg_loader_free();
vg_success( "If you see this it means everything went.. \"well\".....\n" );
else
{
SDL_AtomicUnlock( &vg.sl_context );
-
- /*
- * 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();
- SDL_AtomicUnlock( &vg.sl_context );
+ SDL_AtomicLock( &vg.sl_context );
vg.engine_status = k_engine_status_crashed;
vg.str_const_engine_err = error;
+ SDL_AtomicUnlock( &vg.sl_context );
- /*
- * 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_id_main == SDL_GetThreadID(NULL) )
+ /* Notify other thread for curtosey */
+ if( vg_thread_purpose() == k_thread_purpose_main )
{
+ SDL_AtomicLock( &vg.sl_context );
+
+ if( vg.exec_context != 0 )
+ SDL_SemPost( vg.sem_allow_exec );
+
SDL_AtomicUnlock( &vg.sl_context );
- SDL_SemWait( vg.sem_loader );
}
- else
- SDL_AtomicUnlock( &vg.sl_context );
- vg_audio_free(NULL);
+ vg_audio_free();
while(1)
{
- vg_process_events();
+ _vg_process_events();
if( vg.window_should_close )
break;
glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
glViewport( 0,0, vg.window_x, vg.window_y );
- vg_render_log();
+ _vg_render_log();
SDL_GL_SwapWindow( vg.window );
}
/* Can now shutdown and EXIT */
- vg_loader_free();
+ _vg_loader_free();
SDL_GL_DeleteContext( vg.gl_context );
SDL_Quit();
exit(0);
}
vg_console;
-VG_STATIC void vg_convar_push( struct vg_convar cv );
-VG_STATIC void vg_function_push( struct vg_cmd cmd );
+VG_STATIC void vg_convar_push( struct vg_convar cv );
+VG_STATIC void vg_function_push( struct vg_cmd cmd );
-VG_STATIC void vg_console_draw( void );
-void vg_console_println( const char *str );
-VG_STATIC int vg_console_list( int argc, char const *argv[] );
-VG_STATIC void vg_console_init(void);
-VG_STATIC void vg_console_write_persistent(void);
-VG_STATIC void vg_console_free(void);
-VG_STATIC void execute_console_input( const char *cmd );
+VG_STATIC void _vg_console_draw( void );
+void _vg_console_println( const char *str );
+VG_STATIC int _vg_console_list( int argc, char const *argv[] );
+VG_STATIC void _vg_console_init(void);
+VG_STATIC void _vg_console_write_persistent(void);
+VG_STATIC void _vg_console_free(void);
+VG_STATIC void vg_execute_console_input( const char *cmd );
/*
* Console interface
VG_STATIC void console_clipboard_paste(void);
VG_STATIC void console_put_char( char c );
VG_STATIC void console_history_get( char* buf, int entry_num );
-VG_STATIC int vg_console_enabled(void);
+VG_STATIC int _vg_console_enabled(void);
VG_STATIC void console_proc_key( SDL_Keysym ev );
/*
* Implementation
*/
-VG_STATIC int vg_console_enabled(void)
+VG_STATIC int _vg_console_enabled(void)
{
return vg_console.enabled;
}
vg_console.functions[ vg_console.function_count ++ ] = cmd;
}
-VG_STATIC void vg_console_draw( void )
+VG_STATIC void _vg_console_draw( void )
{
if( !vg_console.enabled )
return;
SDL_AtomicUnlock( &log_print_sl );
}
-VG_STATIC int vg_console_list( int argc, char const *argv[] )
+VG_STATIC int _vg_console_list( int argc, char const *argv[] )
{
for( int i=0; i<vg_console.function_count; i ++ )
{
return 0;
}
-VG_STATIC void vg_console_init(void)
+VG_STATIC void _vg_console_init(void)
{
vg_function_push( (struct vg_cmd)
{
.name = "list",
- .function = vg_console_list
+ .function = _vg_console_list
});
vg_function_push( (struct vg_cmd)
if( line[0] != 0x00 )
{
- execute_console_input( line );
+ vg_execute_console_input( line );
}
}
}
}
-VG_STATIC void vg_console_write_persistent(void)
+VG_STATIC void _vg_console_write_persistent(void)
{
FILE *fp = fopen( "cfg/auto.conf", "w" );
fclose( fp );
}
-VG_STATIC void vg_console_free(void)
+VG_STATIC void _vg_console_free(void)
{
- vg_console_write_persistent();
+ _vg_console_write_persistent();
}
-VG_STATIC void execute_console_input( const char *cmd )
+VG_STATIC void vg_execute_console_input( const char *cmd )
{
char temp[512];
char const *args[9];
}
vg_console.history_pos = -1;
- execute_console_input( vg_console.input );
+ vg_execute_console_input( vg_console.input );
console_move_cursor( &vg_console.cursor_user,
&vg_console.cursor_pos, -10000, 1 );
vg_console.input[0] = '\0';
#include "common.h"
+VG_STATIC void vg_loader_start( void(*pfn)(void) );
+VG_STATIC void vg_loader_step( void( *fn_load )(void), void( *fn_free )(void) );
+
static struct vg_shader _shader_loader =
{
.name = "[vg] loader",
"void main()"
"{"
"float dither=fract(dot(vec2(171.0,231.0),gl_FragCoord.xy)/71.0)-0.5;"
- "float grad = 1.0-(aUv.y*0.5+0.5);"
+ "float grad = 1.0-(aUv.y*0.5+0.5)*0.5;"
"float fmt1 = step( 0.5, grad+dither );"
"vec3 col = 0.5+0.5*sin( uTime + aUv.xyx + vec3(0.0,2.0,4.0) );"
- "FragColor = vec4(col*grad*fmt1,1.0);"
+ "FragColor = vec4(vec3(0.5,0.5,0.5)*grad*fmt1,1.0);"
"}"
}
};
/* Shutdown steps */
struct loader_free_step
{
- void (*fn_free)(void *);
- void *data;
+ void (*fn_free)(void);
}
step_buffer[16];
u32 step_count, step_action;
}
vg_loader;
-VG_STATIC void vg_loader_init(void)
+VG_STATIC void _vg_loader_init(void)
{
float quad[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f };
vg_fatal_exit_loop( "failed to compile shader" );
}
-VG_STATIC void vg_loader_free(void)
+VG_STATIC void _vg_loader_free(void)
{
vg_info( "vg_loader_free\n" );
glDeleteVertexArrays( 1, &vg_loader.vao );
&vg_loader.step_buffer[vg_loader.step_count -1 -i];
vg_info( " -> %p\n", step->fn_free );
- step->fn_free( step->data );
+ step->fn_free();
}
vg_info( "done\n" );
}
-VG_STATIC float hue_to_rgb( float p, float q, float t )
-{
- if(t < 0.0f) t += 1.0f;
- if(t > 1.0f) t -= 1.0f;
- if(t < 1.0f/6.0f) return p + (q - p) * 6.0f * t;
- if(t < 1.0f/2.0f) return q;
- if(t < 2.0f/3.0f) return p + (q - p) * (2.0f/3.0f - t) * 6.0f;
- return p;
-}
-
-VG_STATIC void vg_render_log(void)
+VG_STATIC void _vg_render_log(void)
{
ui_begin( vg.window_x, vg.window_y );
SDL_AtomicLock( &log_print_sl );
ui_draw( NULL );
}
-VG_STATIC void vg_loader_render(void)
+VG_STATIC void _vg_loader_render(void)
{
glViewport( 0,0, vg.window_x, vg.window_y );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glBindVertexArray( vg_loader.vao );
glDrawArrays( GL_TRIANGLES, 0, 6 );
- vg_render_log();
+ _vg_render_log();
}
VG_STATIC void vg_load_full(void);
-VG_STATIC int vg_loader_thread(void * nothing)
+VG_STATIC int _vg_loader_thread(void *pfn)
{
SDL_AtomicLock( &vg.sl_context );
vg.thread_id_loader = SDL_GetThreadID(NULL);
+ VG_SYNC_LOG( "[%d] Loader thread begins\n" );
SDL_AtomicUnlock( &vg.sl_context );
/* Run client loader */
- vg_load_full();
+ void (*call_func)(void) = pfn;
+ call_func();
SDL_SemPost( vg.sem_loader );
vg.thread_id_loader = 0;
+ vg_acquire_thread_sync();
+ vg.is_loaded = 1;
+ vg_release_thread_sync();
+
return 0;
}
-VG_STATIC void vg_loader_start(void)
+VG_STATIC void vg_loader_start( void(*pfn)(void) )
{
+ vg.is_loaded = 0;
SDL_SemWait( vg.sem_loader );
- SDL_CreateThread( vg_loader_thread, "Loader thread", NULL );
-}
-
-/* this is maybe probably unused now */
-VG_STATIC void vg_free_libc_malloced( void *data )
-{
- free( data );
-}
-
-VG_STATIC void vg_loader_push_free_step( struct loader_free_step step )
-{
- if( vg_loader.step_count == vg_list_size(vg_loader.step_buffer) )
- vg_fatal_exit_loop( "Too many free steps" );
-
- vg_loader.step_buffer[ vg_loader.step_count ++ ] = step;
+ SDL_CreateThread( _vg_loader_thread, "Loader thread", pfn );
}
/*
* Schedule something to be ran now, freed later. Checks in with engine status
*/
-VG_STATIC void vg_loader_highwater( void( *fn_load )(void),
- void( *fn_free )(void *), void *data )
+VG_STATIC void vg_loader_step( void( *fn_load )(void), void( *fn_free )(void) )
{
if( fn_load )
fn_load();
if( fn_free )
{
struct loader_free_step step;
- step.data = data;
step.fn_free = fn_free;
- vg_loader_push_free_step( step );
- }
- else
- {
- if( data )
- {
- struct loader_free_step step;
- step.data = data;
- step.fn_free = vg_free_libc_malloced;
-
- vg_loader_push_free_step( step );
- }
+ if( vg_loader.step_count == vg_list_size(vg_loader.step_buffer) )
+ vg_fatal_exit_loop( "Too many free steps" );
+
+ vg_loader.step_buffer[ vg_loader.step_count ++ ] = step;
}
- vg_ensure_engine_running();
+ _vg_ensure_engine_running();
}
#endif /* VG_LOADER_H */