Fix major overstep with last commit
authorhgn <hgodden00@gmail.com>
Fri, 7 Oct 2022 03:56:05 +0000 (04:56 +0100)
committerhgn <hgodden00@gmail.com>
Fri, 7 Oct 2022 03:56:05 +0000 (04:56 +0100)
16 files changed:
dep/stb/stb_include.h
src/vg/vg.h
src/vg/vg_audio.h
src/vg/vg_console.h
src/vg/vg_input.h
src/vg/vg_io.h
src/vg/vg_lines.h
src/vg/vg_loader.h
src/vg/vg_m.h
src/vg/vg_module.h [new file with mode: 0644]
src/vg/vg_platform.h
src/vg/vg_shader.h
src/vg/vg_steam.h
src/vg/vg_steam_auth.h
src/vg/vg_tex.h
src/vg/vg_ui.h

index c5db20138a23b0a760252960966c6720f5f05153..6a90097144265a958bfa25b9fcb8dadf8bfa3019 100644 (file)
@@ -53,9 +53,27 @@ char *stb_include_file(char *filename, char *inject, char *path_to_includes, cha
 #ifdef STB_INCLUDE_IMPLEMENTATION
 
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 
+#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 <stdlib.h>
+#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;
 }
 
index b076091d1c627ba252d32ccf81d38165b94895f9..5b2ca81ac824d8dcc9d9ac5f72b6ebba8703851b 100644 (file)
@@ -3,13 +3,8 @@
 #ifndef VG_HEADER_H
 #define VG_HEADER_H
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <dirent.h>
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <math.h>
+#include "vg_platform.h"
+
 
 #if defined(VG_SERVER) || defined(VG_TOOLS)
  #define VG_NON_CLIENT
 #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
 
 /*
index 8cdaa4acb744e1c165de6f95e0d663dbbec96b0f..ae37b2e5078000476f2d2f879fbec4d872817609 100644 (file)
   #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 ) )
    {
index 6ef2d7837774fc01f29331915e0a148e46fbd6a2..fc2775ca49115efeb343b8207f5e70ba2e1ed592 100644 (file)
@@ -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; i<vg_console.function_count; i ++ )
        {
                struct vg_cmd *cmd = &vg_console.functions[ i ];
                vg_info( "* %s\n", cmd->name );
@@ -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; i<vg_console.convar_count; i ++ )
        {
                struct vg_convar *cv = &vg_console.convars[ i ];
                vg_info( "%s\n", cv->name );
@@ -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; i<vg_console.convar_count; i ++ )
        {
                struct vg_convar *cv = &vg_console.convars[i];
 
@@ -280,8 +306,8 @@ static void vg_console_free(void)
 {
        vg_console_write_persistent();
 
-       arrfree( vg_console.convars );
-       arrfree( vg_console.functions );
+   vg_free( vg_console.convars );
+   vg_free( vg_console.functions );
 }
 
 static void execute_console_input( const char *cmd )
@@ -329,7 +355,7 @@ static void execute_console_input( const char *cmd )
        int data_int;
    float data_float;
        
-       for( int i = 0; i < arrlen( vg_console.convars ); i ++ )
+       for( int i=0; i<vg_console.convar_count; i ++ )
        {
                struct vg_convar *cv = &vg_console.convars[ i ];
                if( !strcmp( cv->name, 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; i<vg_console.function_count; i ++ )
        {
                struct vg_cmd *cmd = &vg_console.functions[ i ];
                if( !strcmp( cmd->name, 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; i<vg_list_size( mapping ); i++ )
+   {
+      struct console_mapping *mk = &mapping[i];
+
+      if( mk->key == 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 */
index 3985f3c26975dcc89acb5dcfeb1776e078a58898..c33853136ceb01e15dd8ff94dbd7c383ddd8eff6 100644 (file)
@@ -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
index 19d468b8e1ce39634cdbe31dcdac7e1447c6a363..95e16231d4a998dfbabf74a851f095e1ef1d6a28 100644 (file)
@@ -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;
                
index 0c02bb19fbd2faaaa6e5adeb74d1258ae411dd59..82f1814add1126f90df1dc98abfc3967f6be4515 100644 (file)
@@ -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 )
index 2ba707e0d03c83739c65451ee9a4ddbb5e18b784..6e3882af4c2bd5696f7c09e4b451e172136e483e 100644 (file)
 
 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<vg_loader.step_count; i++ )
    {
       struct loader_free_step *step = 
          &vg_loader.step_buffer[vg_loader.step_count -1 -i];
 
+      vg_info( " -> %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; i<loader.step_count; i++ )
-   {
-      struct loader_step *step = &loader.step_buffer[ loader.step_count -i -1 ];
-      if( step->fn_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
index 417ca32607d392bd48bf8b8785b8e1a1b70a42d9..c28e477e606f497c86abd6c73e34edc21208111f 100644 (file)
@@ -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 (file)
index 0000000..15dfd47
--- /dev/null
@@ -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 */
index d7c0a0cff6ee13d0a08ff5ef1e09bcbef45ba449..ab9c927b79a1582fb383235cf648ee552aa6754b 100644 (file)
@@ -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 <windows.h>
 
 /* TODO */
+#define VG_DEPRECATED __declspec(deprecated)
 
 #else
        #include <pthread.h>
    #include <semaphore.h>
 
+#define VG_DEPRECATED __attribute__((deprecated))
+
+   #define VG_THREAD_LOCAL       __thread
+
    typedef sem_t                 vg_semaphore;
    typedef pthread_mutex_t       vg_mutex;
 
+#endif
+
+#include <stdlib.h>
+
+/* 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 <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <math.h>
+#include <assert.h>
+
+#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
index a6c7a0b13ff4723e86927dd3d15e04513225fb4c..2186c9dace606b9e3e8b3e54dc4b1d9e9b3f39bc 100644 (file)
@@ -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; i<vg_shader_count; i ++ )
        {
                struct vg_shader *shader = vg_shaders_active[i];
                
@@ -173,14 +179,14 @@ static void vg_shaders_free(void *nothing)
                        glDeleteProgram( shader->id );
        }
        
-       arrfree( vg_shaders_active );
+       vg_free( vg_shaders_active );
 }
 
 static int vg_shaders_recompile(void)
 {
        vg_info( "Compiling shaders\n" );
 
-       for( int i=0; i<arrlen( vg_shaders_active ); i ++ )
+       for( int i=0; i<vg_shader_count; i ++ )
        {
                struct vg_shader *shader = vg_shaders_active[i];
 
@@ -195,7 +201,11 @@ static void vg_shader_register( struct vg_shader *shader )
 {
    shader->compiled = 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 */
index 05fe1acaeea72e69968d8b7261e6fa48cb4e6d1b..ab135bcc675ea02d434d66f8ae8c323d28a0330a 100644 (file)
@@ -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 
                {
index 9d06c9c852c1bdac329cc16d97b469dc90cbc709..1875999ce27430b581830625e33dcf88bac17e6b 100644 (file)
@@ -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
index 9e0c56f6e18bebb8551edaa7add1ab586759dd3b..e92e5f152582258af9b0c73d59713a68f1be8764 100644 (file)
 #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
        {
index 844194e73867e9e468c70d9b9fcb732d983e9e2d..4e09338dc2985149ea84f711e596433754ba37f4 100644 (file)
@@ -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,