update linear allocator to stacks vg3
authorhgn <hgodden00@gmail.com>
Sat, 28 Jun 2025 01:33:53 +0000 (02:33 +0100)
committerhgn <hgodden00@gmail.com>
Sat, 28 Jun 2025 01:33:53 +0000 (02:33 +0100)
26 files changed:
vg_audio.c
vg_audio.h
vg_audio_dsp.c
vg_build.h
vg_bvh.c
vg_bvh.h
vg_engine.c
vg_engine.h
vg_framebuffer.c
vg_framebuffer.h
vg_io.c
vg_io.h
vg_kv.c [new file with mode: 0644]
vg_kv.h [new file with mode: 0644]
vg_lines.c
vg_lines.h
vg_mem.c
vg_mem.h
vg_mem_view.c
vg_render.c
vg_steam_auth.h
vg_steam_auth_server.h [new file with mode: 0644]
vg_tex.c
vg_ui/imgui.c
vg_ui/imgui.h
vg_ui/imgui_impl_opengl.c

index 3113fc77f92a6a321eb69aaf6de02c65e4f5d4a0..69000b0b59181f854e42ecb5e5be11bf44f777b1 100644 (file)
@@ -68,10 +68,10 @@ static void vg_audio_assert_lock(void)
 /* clip loading from disk
  * -------------------------------------------------------------------------------
  */
-void audio_clip_load( audio_clip *clip, void *lin_alloc )
+void audio_clip_load( audio_clip *clip, vg_stack_allocator *stack )
 {
-   if( lin_alloc == NULL )
-      lin_alloc = _vg_audio.data_allocator;
+   if( stack == NULL )
+      stack = _vg_audio.permanent_stack;
 
    if( _vg_audio.always_keep_clips_compressed )
    {
@@ -98,7 +98,7 @@ void audio_clip_load( audio_clip *clip, void *lin_alloc )
          vg_error( "No path specified, embeded vorbis unsupported\n" );
 
       vg_audio_lock();
-      clip->any_data = vg_file_read( lin_alloc, clip->path, &clip->size );
+      clip->any_data = vg_file_read( stack, clip->path, &clip->size, 0 );
       vg_audio_unlock();
 
       if( !clip->any_data )
@@ -125,7 +125,7 @@ void audio_clip_load( audio_clip *clip, void *lin_alloc )
       if( total_size > AUDIO_DECODE_SIZE )
          vg_error( "Bird coding too long, and exceeds maximum decode size\n" );
 
-      struct synth_bird *bird = vg_linear_alloc( lin_alloc, total_size );
+      struct synth_bird *bird = vg_stack_allocate( stack, total_size, 8, NULL );
       memcpy( &bird->settings, clip->any_data, clip->size );
 
       clip->any_data = bird;
@@ -136,19 +136,17 @@ void audio_clip_load( audio_clip *clip, void *lin_alloc )
    else
    {
       if( !clip->path )
-      {
          vg_error( "No path specified, embeded mono unsupported\n" );
-      }
 
-      vg_linear_clear( vg_mem.scratch );
+      vg_stack_clear( &vg.scratch );
       u32 fsize;
 
       stb_vorbis_alloc alloc = {
-         .alloc_buffer = vg_linear_alloc( vg_mem.scratch, AUDIO_DECODE_SIZE ),
+         .alloc_buffer = vg_stack_allocate( &vg.scratch, AUDIO_DECODE_SIZE, 8, NULL ),
          .alloc_buffer_length_in_bytes = AUDIO_DECODE_SIZE
       };
 
-      void *filedata = vg_file_read( vg_mem.scratch, clip->path, &fsize );
+      void *filedata = vg_file_read( &vg.scratch, clip->path, &fsize, 0 );
 
       int err;
       stb_vorbis *decoder = stb_vorbis_open_memory( filedata, fsize, &err, &alloc );
@@ -166,7 +164,7 @@ void audio_clip_load( audio_clip *clip, void *lin_alloc )
           data_size      = length_samples * sizeof(i16);
 
       vg_audio_lock();
-      clip->any_data = vg_linear_alloc( lin_alloc, vg_align8(data_size) );
+      clip->any_data = vg_stack_allocate( stack, data_size, 8, NULL );
       clip->size = length_samples;
       vg_audio_unlock();
 
@@ -177,10 +175,10 @@ void audio_clip_load( audio_clip *clip, void *lin_alloc )
    }
 }
 
-void audio_clip_loadn( audio_clip *arr, int count, void *lin_alloc )
+void audio_clip_loadn( audio_clip *arr, int count, vg_stack_allocator *stack )
 {
    for( int i=0; i<count; i++ )
-      audio_clip_load( &arr[i], lin_alloc );
+      audio_clip_load( &arr[i], stack );
 }
 
 /* 
@@ -1481,14 +1479,12 @@ void vg_audio_init(void)
       vg_fatal_error( "SDL2: %s\n", SDL_GetError() );
 
    _vg_profile_reg_set( &_vg_prof_audio );
-
-   /* allocate memory */
-   /* 32mb fixed */
-   _vg_audio.data_allocator = vg_create_linear_allocator( vg_mem.rtmemory, 1024*1024*32, VG_MEMORY_SYSTEM );
+   _vg_audio.permanent_stack = vg_stack_make_substack( &vg.rtmem, VG_MB(32), "Permanent audio data" );
+   vg_stack_set_flags( _vg_audio.permanent_stack, VG_STACK_ALLOCATOR_METADATA );
 
    /* fixed */
    u32 decode_size = AUDIO_DECODE_SIZE * AUDIO_CHANNELS;
-   _vg_audio.decoding_buffer = vg_linear_alloc( vg_mem.rtmemory, decode_size );
+   _vg_audio.decoding_buffer = vg_stack_allocate( &vg.rtmem, decode_size, 8, "Decoding buffers" );
 
    struct audio_master_controls *master_controls = &_vg_audio.controls;
    master_controls->dsp_enabled = _vg_audio.dsp_enabled_ui;
index f47f450a766ffbd5110bdf61462ccdefc3f8b889..3be329bbb458f0d0e2c6b7e014af8f43a32c6311 100644 (file)
@@ -181,8 +181,8 @@ struct vg_audio
    SDL_AudioDeviceID sdl_output_device;
    vg_str device_choice; /* buffer is null? use default from OS */
 
-   void *data_allocator; /* allocator for practically static sound data */
-   void *decoding_buffer; /* place where raw samples get decoded into */
+   vg_stack_allocator *permanent_stack;
+   void *decoding_buffer;
 
    SDL_mutex *mutex;
    u32 samples_written_last_audio_frame;
@@ -221,8 +221,8 @@ void vg_audio_device_init(void);
 void vg_audio_init(void);
 void vg_audio_free(void);
 
-void audio_clip_load( audio_clip *clip, void *lin_alloc );
-void audio_clip_loadn( audio_clip *arr, int count, void *lin_alloc );
+void audio_clip_load( audio_clip *clip, vg_stack_allocator *stack );
+void audio_clip_loadn( audio_clip *arr, int count, vg_stack_allocator *stack );
 
 void vg_audio_lock(void);
 void vg_audio_unlock(void);
index 4a3536eac611ab79e324f96134a91a42e4a79bcc..7d6bd1af8293c44313061b684916a6b5867caf21 100644 (file)
@@ -133,7 +133,7 @@ static struct dsp_schroeder __diffusion_chain[8];
 void vg_dsp_init( void )
 {
    vg_rand_seed( &vg_dsp.rand, 461 );
-   vg_dsp.buffer = vg_linear_alloc( vg_mem.rtmemory, 1024*1024*1 );
+   vg_dsp.buffer = vg_stack_allocate( &vg.rtmem, VG_MB(1), 8, "Audio DSP Buffer" );
 
    /* temporary global design */
    dsp_init_lpf( &__lpf_mud_free, 125.0f );
index 40266908c921f4721dd75a258c2779c2503d1217..c34f3932e2645efe897bc977c0f3c94c24071c41 100644 (file)
@@ -282,6 +282,7 @@ vg_compiler_run( struct vg_project *project,
    vg_strcat( &cmd, "  -Wall -ferror-limit=10\\\n"
       "    -Wno-unused-function -Wno-unused-variable\\\n"
       "    -Wno-unused-command-line-argument -Wno-unused-but-set-variable\\\n"
+      "    -Wunused-result\\\n"
    );
 
    if( env->compiler != k_compiler_clang )
index b33b0315569b3b0e93d33edba7bf26884e353915..05edae7271895bc1262888271d3b7db9601557bb 100644 (file)
--- a/vg_bvh.c
+++ b/vg_bvh.c
@@ -91,23 +91,21 @@ void bh_rebuild( bh_tree *bh, u32 item_count )
       bh_subdivide( bh, 0 );
 }
 
-bh_tree *bh_create( void *lin_alloc, bh_system *system, 
-                    void *user, u32 item_count, u32 max_per_leaf )
+bh_tree *bh_create( vg_stack_allocator *stack, bh_system *system, void *user, u32 item_count, u32 max_per_leaf )
 {
    u32 alloc_count = VG_MAX( 1, item_count );
 
    u32 totsize = sizeof(bh_tree) + sizeof(bh_node)*(alloc_count*2-1);
-   bh_tree *bh = lin_alloc? vg_linear_alloc( lin_alloc, vg_align8(totsize) ):
-                            malloc( totsize );
+   bh_tree *bh = stack? vg_stack_allocate( stack, totsize, 8, "BVH Tree" ): vg_malloc( totsize );
    bh->system = system;
    bh->user = user;
    bh->max_per_leaf = max_per_leaf;
    bh_rebuild( bh, item_count );
 
-   if( lin_alloc ){
-      totsize = vg_align8(sizeof(bh_tree) + sizeof(bh_node) * bh->node_count);
-      bh = vg_linear_resize( lin_alloc, bh, totsize );
-   }
+   totsize = sizeof(bh_tree) + sizeof(bh_node) * bh->node_count;
+
+   if( stack ) vg_stack_resize_last( stack, totsize );
+   else        bh = vg_realloc( bh, totsize );
 
    vg_success( "BVH done, size: %u/%u\n", bh->node_count, (alloc_count*2-1) );
    return bh;
@@ -121,8 +119,10 @@ void bh_debug_leaf( bh_tree *bh, bh_node *node )
 {
    vg_line_boxf( node->bbx, 0xff00ff00 );
 
-   if( bh->system->item_debug ){
-      for( u32 i=0; i<node->count; i++ ){
+   if( bh->system->item_debug )
+   {
+      for( u32 i=0; i<node->count; i++ )
+      {
          u32 idx = node->start+i;
          bh->system->item_debug( bh->user, idx );
       }
index 1adb3d8cbdebbd1c432365d3bae60706ff380e0e..3592bc64e174851dc6bcd1e69200d75cf7c90adb 100644 (file)
--- a/vg_bvh.h
+++ b/vg_bvh.h
@@ -78,8 +78,8 @@ struct bh_system{
 void bh_update_bounds( bh_tree *bh, u32 inode );
 void bh_subdivide( bh_tree *bh, u32 inode );
 void bh_rebuild( bh_tree *bh, u32 item_count );
-bh_tree *bh_create( void *lin_alloc, bh_system *system, 
-                    void *user, u32 item_count, u32 max_per_leaf );
+
+bh_tree *bh_create( vg_stack_allocator *stack, bh_system *system, void *user, u32 item_count, u32 max_per_leaf );
 
 
 void bh_debug_leaf( bh_tree *bh, bh_node *node );
index db310fcdb1db385a9311c49084bba814ca589506..2b17501249a5be92405374dfddc5abfd47f93ec6 100644 (file)
@@ -514,7 +514,7 @@ static void _vg_init_window( const char *window_name )
 
    char *exe_basepath = SDL_GetBasePath();
    u32 len = vg_align8( strlen(exe_basepath)+1 );
-   char *dest  = vg_linear_alloc( vg_mem.rtmemory, len );
+   char *dest = vg_stack_allocate( &vg.rtmem, len, 1, "Exe basepath" );
    strcpy( dest, exe_basepath );
    SDL_free( exe_basepath );
    vg.base_path = dest;
@@ -660,12 +660,6 @@ static void _vg_terminate(void)
    exit(0);
 }
 
-static int cmd_log_memory( int argc, const char *argv[] )
-{
-   vg_mem_log( vg_mem.rtmemory, 0, "rtmemory" );
-   return 0;
-}
-
 static int _vg_loader_thread( void *pfn )
 {
    SDL_TLSSet( vg.thread_purpose, &_thread_purpose_loader, NULL );
@@ -715,9 +709,6 @@ void vg_init( int argc, const char *argv[], const char *window_name )
    if( (arg = vg_long_opt_arg( "samples", "Rendering samples per pixel" )) )
       vg.samples = VG_MAX( 0, VG_MIN( 8, atoi( arg ) ) );
 
-   if( vg_long_opt( "use-libc-malloc", "Use standard libc allocator" ) )
-      vg_mem.use_libc_malloc = 1;
-
    if( vg_long_opt( "high-performance", "Turn graphics to lowest quality" ) )
       vg.quality_profile = k_quality_profile_low;
 
@@ -740,7 +731,6 @@ void vg_run(void)
       exit(0);
 
    /* Systems init */
-   vg_alloc_quota();
    vg_console_init();
    vg_magi_init();
    
@@ -755,7 +745,6 @@ void vg_run(void)
    vg_console_load_autos();
 
    vg_console_reg_cmd( "vg_settings", cmd_vg_settings_toggle, NULL );
-   vg_console_reg_cmd( "vg_rtmemory", cmd_log_memory, NULL );
    _vg_init_window( vg.window_name );
    SDL_SetRelativeMouseMode(1);
    
index 2cc8b6d18808b7bb1eda3f0138d07d27a9908e0e..b44f4415e580052ba21254e0fe343675d43435be 100644 (file)
@@ -68,6 +68,8 @@ enum engine_status
 
 struct vg_engine 
 {
+   vg_stack_allocator rtmem, scratch;
+
    /* Engine sync */
    SDL_Window     *window;
    SDL_GLContext  gl_context;
index 95776b74b8fac514d41710294053777348554142..95f94bb10f2a751d9f013bfa544338d62ffd30ce 100644 (file)
@@ -226,9 +226,9 @@ static void vg_framebuffer_allocate_texture( vg_framebuffer *fb,
    }
 }
 
-vg_framebuffer *vg_framebuffer_allocate( void *alloc, u32 attachment_count, bool track )
+vg_framebuffer *vg_framebuffer_allocate( vg_stack_allocator *stack, u32 attachment_count, bool track )
 {
-   vg_framebuffer *fb = vg_linear_alloc( alloc, sizeof(vg_framebuffer) );
+   vg_framebuffer *fb = VG_STACK_ALLOCATE_STRUCT( stack, vg_framebuffer );
 
    if( track )
    {
@@ -242,9 +242,8 @@ vg_framebuffer *vg_framebuffer_allocate( void *alloc, u32 attachment_count, bool
       }
    }
 
-   fb->attachments = vg_linear_alloc( alloc, sizeof(vg_framebuffer_attachment) * attachment_count );
+   fb->attachments = vg_stack_allocate( stack, sizeof(vg_framebuffer_attachment) * attachment_count, 8, NULL );
    fb->attachment_count = attachment_count;
-
    return fb;
 }
 
index 788c01105dc8e19f54db9472578f21e50651478a..98bd7edb333e487c13b07657e205c4745dd3c0d7 100644 (file)
@@ -87,7 +87,7 @@ void vg_framebuffer_bind_texture( vg_framebuffer *fb, int attachment, int slot )
  * Allocation of a framebuffer memory. Optionally, track this framebuffer in 
  * debugging systems.
  */
-vg_framebuffer *vg_framebuffer_allocate( void *alloc, u32 attachment_count, bool track );
+vg_framebuffer *vg_framebuffer_allocate( vg_stack_allocator *stack, u32 attachment_count, bool track );
 
 /*
  * Allocate graphics memory and initialize 
diff --git a/vg_io.c b/vg_io.c
index dbb51e9064cfbe023a3dd4953ce785ea88f14c33..a293958c13b56086832bbc1c6151599a286df27b 100644 (file)
--- a/vg_io.c
+++ b/vg_io.c
@@ -187,34 +187,35 @@ void vg_file_error_info( FILE *fp )
    }
 }
 
-#define VG_FILE_IO_CHUNK_SIZE 1024*256
+#define VG_FILE_IO_CHUNK_SIZE VG_KB(256)
 
 /* read entire binary file */
-void *vg_file_read( void *lin_alloc, const char *path, u32 *size )
+void *vg_file_read( vg_stack_allocator *stack, const char *path, u32 *size, bool text )
 {
        FILE *f = fopen( path, "rb" );
        if( f )
    {
-      void *buffer = lin_alloc? vg_linear_alloc( lin_alloc, 0 ): NULL;
+      if( !stack )
+      {
+         stack = alloca( sizeof(vg_stack_allocator) );
+         vg_stack_init( stack, NULL, VG_FILE_IO_CHUNK_SIZE, "Stretchy file buffer" );
+         vg_stack_set_flags( stack, VG_STACK_ALLOCATOR_DOUBLE_IF_FULL );
+      }
+
+      u8 *buffer = vg_stack_allocate( stack, 0, 8, "File data" );
       u64 current = 0;
 
       /* read in chunks */
       for( u32 i=0; 1; i++ )
       {
-         if( lin_alloc )
-            buffer = vg_linear_extend( lin_alloc,buffer,VG_FILE_IO_CHUNK_SIZE );
-         else 
-            buffer = realloc( buffer, current + VG_FILE_IO_CHUNK_SIZE );
-
+         vg_stack_extend_last( stack, VG_FILE_IO_CHUNK_SIZE );
          u64 l = fread( buffer + current, 1, VG_FILE_IO_CHUNK_SIZE, f );
          current += l;
 
          if( l != VG_FILE_IO_CHUNK_SIZE )
          {
             if( feof( f ) )
-            {
                break;
-            }
             else
             {
                if( ferror( f ) )
@@ -235,75 +236,47 @@ void *vg_file_read( void *lin_alloc, const char *path, u32 *size )
          }
       }
 
-      if( lin_alloc )
-         buffer = vg_linear_resize( lin_alloc, buffer, vg_align8(current) );
-      else
-         buffer = realloc( buffer, vg_align8(current) );
+      if( text )
+      {
+         vg_stack_extend_last( stack, 1 );
+         buffer[ current ++ ] = '\0';
+      }
 
+      vg_stack_resize_last( stack, current );
                fclose( f );
 
       *size = (u32)current;
       return buffer;
        }
-       else{
+       else
+   {
       vg_error( "vg_disk_open_read: %s (file: %s)\n", strerror(errno), path );
                return NULL;
        }
 }
 
-/* read entire file and append a null on the end */
-char *vg_file_read_text( void *lin_alloc, const char *path, u32 *sz )
-{
-   u32 size;
-   char *str = vg_file_read( lin_alloc, path, &size );
-
-   if( !str )
-      return NULL;
-
-   /* include null terminator */
-   if( lin_alloc )
-      str = vg_linear_extend( lin_alloc, str, 1 );
-   else
-      str = realloc( str, size+1 );
-
-   str[ size ] = '\0';
-   *sz = size+1;
-
-   return str;
-}
-
-
-int vg_asset_write( const char *path, void *data, i64 size )
+bool vg_asset_write( const char *path, void *data, i64 size )
 {
        FILE *f = fopen( path, "wb" );
-       if( f ){
+       if( f )
+   {
                fwrite( data, size, 1, f );
                fclose( f );
                return 1;
        }
-       else{
+       else
                return 0;
-       }
-}
-
-/* TODO: error handling if read fails */
-int vg_file_copy( const char *src, const char *dst, void *lin_alloc )
-{
-   vg_info( "vg_file_copy( %s -> %s )\n", src, dst );
-   u32 size;
-   void *data = vg_file_read( lin_alloc, src, &size );
-   return vg_asset_write( dst, data, size );
 }
 
 const char *vg_path_filename( const char *path )
 {
    const char *base = path;
-   
-   for( int i=0; i<1024; i++ ){
-      if( path[i] == '\0' ) break;
-      if( path[i] == '/' ){
+   for( int i=0; i<1024; i++ )
+   {
+      if( path[i] == '\0' ) 
+         break;
+      if( path[i] == '/' )
          base = path+i+1;
-      }
    }
 
    return base;
diff --git a/vg_io.h b/vg_io.h
index 4f549b8d4c9ed0cf6c7e6ae1e7167ae2ec94071d..6a84aaf984a7c1e5c8410e8c7d99beb44593afd2 100644 (file)
--- a/vg_io.h
+++ b/vg_io.h
@@ -54,13 +54,9 @@ bool vg_make_directory( const char *path );
  * File I/O
  */
 
-/* read entire binary file */
-void *vg_file_read( void *lin_alloc, const char *path, u32 *size );
+/* read entire binary file, if text is 1, appends a nul to the end of the buffer */
+void *vg_file_read( vg_stack_allocator *stack, const char *path, u32 *size, bool text );
 
-/* read entire file and append a null on the end */
-char *vg_file_read_text( void *lin_alloc, const char *path, u32 *sz );
-
-int vg_asset_write( const char *path, void *data, i64 size );
-int vg_file_copy( const char *src, const char *dst, void *lin_alloc );
+bool vg_asset_write( const char *path, void *data, i64 size );
 const char *vg_path_filename( const char *path );
 void vg_file_error_info( FILE *fp );
diff --git a/vg_kv.c b/vg_kv.c
new file mode 100644 (file)
index 0000000..39f7831
--- /dev/null
+++ b/vg_kv.c
@@ -0,0 +1,3 @@
+#include "vg_kv.h"
+
+
diff --git a/vg_kv.h b/vg_kv.h
new file mode 100644 (file)
index 0000000..ee11558
--- /dev/null
+++ b/vg_kv.h
@@ -0,0 +1,20 @@
+#pragma once
+#include "vg_platform.h"
+
+struct vg_kv
+{
+   u32 key_info;      /* 20 bit hash, 10 bit key length, 2 bit type */
+   u32 key_offset;    /* into the raw text buffer */
+   u32 brother_offset;/* 24 bits, relative jump past all descendents to the next key */
+
+   union
+   {
+      struct
+      {
+         u16 offset_from_key, length;
+      }
+      value;
+
+      u32 children; /* 24 bits */
+   };
+};
index 364bd1aba151f991038c0d5cc47a5f40b41659c4..40eff0c686ea71fbd46919c5871b219a256187e6 100644 (file)
@@ -45,7 +45,7 @@ static struct vg_shader _shader_lines = {
    }
 };
 
-#define VG_LINES_BUFFER_SIZE 50000 * sizeof( struct vg_lines_vert )
+#define VG_LINES_MAX_VERTS 50000
 
 static void async_vg_lines_init( void *_ )
 {
@@ -55,8 +55,7 @@ static void async_vg_lines_init( void *_ )
    glGenBuffers( 1, &vg_lines.vbo );
    glBindVertexArray( vg_lines.vao );
    glBindBuffer( GL_ARRAY_BUFFER, vg_lines.vbo );
-   
-   glBufferData( GL_ARRAY_BUFFER, VG_LINES_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW );
+   glBufferData( GL_ARRAY_BUFFER, VG_LINES_MAX_VERTS*sizeof(struct vg_lines_vert), NULL, GL_DYNAMIC_DRAW );
    glBindVertexArray( vg_lines.vao );
 
    /* Pointers */
@@ -84,8 +83,9 @@ static void async_vg_lines_init( void *_ )
 void vg_lines_init(void)
 {
    THREAD_1;
+   vg_lines.vertex_buffer = vg_stack_allocate( &vg.rtmem, VG_LINES_MAX_VERTS*sizeof(struct vg_lines_vert), 
+                                                          8, "Debugging Lines" );
 
-   vg_lines.vertex_buffer = vg_create_linear_allocator( vg_mem.rtmemory, VG_LINES_BUFFER_SIZE, VG_MEMORY_REALTIME);
    vg_async_call( &vg.main_tasks, async_vg_lines_init, NULL );
    vg_console_reg_var( "vg_lines", &vg_lines.render, k_var_dtype_i32, VG_VAR_CHEAT );
    vg_shader_register( &_shader_lines );
@@ -94,51 +94,54 @@ void vg_lines_init(void)
 void vg_lines_drawall( void )
 {
        glUseProgram( _shader_lines.id );
-
-   glUniformMatrix4fv( glGetUniformLocation( _shader_lines.id, "uPv" ), 
-     1, GL_FALSE, (float *)vg.pv );
+   glUniformMatrix4fv( glGetUniformLocation( _shader_lines.id, "uPv" ), 1, GL_FALSE, (f32 *)vg.pv );
 
        glBindVertexArray( vg_lines.vao );
        glBindBuffer( GL_ARRAY_BUFFER, vg_lines.vbo );
-
-   u32 bufusage = vg_linear_get_cur(vg_lines.vertex_buffer);
-       glBufferSubData( GL_ARRAY_BUFFER, 0, bufusage, vg_lines.vertex_buffer );
+       glBufferSubData( GL_ARRAY_BUFFER, 0, vg_lines.vertex_count*sizeof(struct vg_lines_vert), vg_lines.vertex_buffer );
 
        glEnable( GL_BLEND );
        glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
        glBlendEquation( GL_FUNC_ADD );
 
    if( vg_lines.render )
-      glDrawArrays( GL_LINES, 0, bufusage / sizeof(struct vg_lines_vert) );
+      glDrawArrays( GL_LINES, 0, vg_lines.vertex_count );
        
        glDisable( GL_BLEND );
-   vg_linear_clear( vg_lines.vertex_buffer );
+   vg_lines.vertex_count = 0;
 }
 
 void vg_line2( line_co from, line_co to, u32 fc, u32 tc )
 {
-   if( !vg_lines.enabled ) return;
+   if( !vg_lines.enabled ) 
+      return;
 
-   u32 size = 2 * sizeof(struct vg_lines_vert);
-       struct vg_lines_vert *v = vg_linear_alloc( vg_lines.vertex_buffer, size );
+   if( vg_lines.vertex_count < VG_LINES_MAX_VERTS )
+   {
+      struct vg_lines_vert *v = &vg_lines.vertex_buffer[ vg_lines.vertex_count ];
 
-       v3_copy( from, v[0].co );
-       v3_copy( to, v[1].co );
+      v3_copy( from, v[0].co );
+      v3_copy( to, v[1].co );
 
-       v[0].colour = fc;
-       v[1].colour = tc;
+      v[0].colour = fc;
+      v[1].colour = tc;
+
+      vg_lines.vertex_count += 2;
+   }
 }
 
 void vg_line( line_co from, line_co to, u32 colour )
 {
-   if( !vg_lines.enabled ) return;
+   if( !vg_lines.enabled ) 
+      return;
 
        vg_line2( from, to, colour, colour );
 }
 
-void vg_line_arrow( line_co co, line_co dir, float size, u32 colour )
+void vg_line_arrow( line_co co, line_co dir, f32 size, u32 colour )
 {
-   if( !vg_lines.enabled ) return;
+   if( !vg_lines.enabled ) 
+      return;
 
    v3f p1, tx, ty, p2, p3;
    v3_muladds( co, dir, size, p1 );
@@ -155,26 +158,27 @@ void vg_line_arrow( line_co co, line_co dir, float size, u32 colour )
 
 void vg_line_box_verts( boxf box, v3f verts[8] )
 {
-   if( !vg_lines.enabled ) return;
+   if( !vg_lines.enabled ) 
+      return;
 
-   for( u32 i=0; i<8; i++ ){
-      for( u32 j=0; j<3; j++ ){
+   for( u32 i=0; i<8; i++ )
+      for( u32 j=0; j<3; j++ )
          verts[i][j] = i&(0x1<<j)? box[1][j]: box[0][j];
-      }
-   }
 }
 
-void vg_line_mesh( v3f verts[], u32 indices[][2], u32 indice_count,u32 colour ){
-   if( !vg_lines.enabled ) return;
+void vg_line_mesh( v3f verts[], u32 indices[][2], u32 indice_count,u32 colour )
+{
+   if( !vg_lines.enabled ) 
+      return;
 
-   for( u32 i=0; i<indice_count; i++ ){
+   for( u32 i=0; i<indice_count; i++ )
       vg_line( verts[indices[i][0]], verts[indices[i][1]], colour );
-   }
 }
 
 void vg_line_boxf( boxf box, u32 colour )
 {
-   if( !vg_lines.enabled ) return;
+   if( !vg_lines.enabled ) 
+      return;
 
    v3f verts[8];
    vg_line_box_verts( box, verts );
@@ -187,14 +191,14 @@ void vg_line_boxf( boxf box, u32 colour )
 
 void vg_line_boxf_transformed( m4x3f m, boxf box, u32 colour )
 {
-   if( !vg_lines.enabled ) return;
+   if( !vg_lines.enabled ) 
+      return;
 
    v3f verts[8];
    vg_line_box_verts( box, verts );
 
-   for( u32 i=0; i<8; i++ ){
+   for( u32 i=0; i<8; i++ )
       m4x3_mulv( m, verts[i], verts[i] );
-   }
 
    u32 indices[][2] = {{0,1},{1,3},{3,2},{2,0},
                        {4,5},{5,7},{7,6},{6,4},
@@ -203,9 +207,10 @@ void vg_line_boxf_transformed( m4x3f m, boxf box, u32 colour )
    vg_line_mesh( verts, indices, VG_ARRAY_LEN(indices), colour );
 }
 
-void vg_line_cross(v3f pos,u32 colour, float scale)
+void vg_line_cross(v3f pos,u32 colour, f32 scale)
 {
-   if( !vg_lines.enabled ) return;
+   if( !vg_lines.enabled ) 
+      return;
 
    v3f p0, p1;
    v3_add( (v3f){ scale,0.0f,0.0f}, pos, p0 );
@@ -219,9 +224,10 @@ void vg_line_cross(v3f pos,u32 colour, float scale)
    vg_line( p0, p1, colour );
 }
 
-void vg_line_point( v3f pt, float size, u32 colour )
+void vg_line_point( v3f pt, f32 size, u32 colour )
 {
-   if( !vg_lines.enabled ) return;
+   if( !vg_lines.enabled ) 
+      return;
 
    boxf box =
    {
@@ -233,18 +239,19 @@ void vg_line_point( v3f pt, float size, u32 colour )
 }
 
 
-void vg_line_sphere( m4x3f m, float radius, u32 colour )
+void vg_line_sphere( m4x3f m, f32 radius, u32 colour )
 {
-   if( !vg_lines.enabled ) return;
+   if( !vg_lines.enabled ) 
+      return;
 
    v3f ly = { 0.0f, 0.0f, radius },
        lx = { 0.0f, radius, 0.0f },
        lz = { 0.0f, 0.0f, radius };
    
    for( int i=0; i<16; i++ ){
-      float t = ((float)(i+1) * (1.0f/16.0f)) * VG_PIf * 2.0f,
-            s = sinf(t),
-            c = cosf(t);
+      f32 t = ((f32)(i+1) * (1.0f/16.0f)) * VG_PIf * 2.0f,
+          s = sinf(t),
+          c = cosf(t);
 
       v3f py = { s*radius, 0.0f, c*radius },
           px = { s*radius, c*radius, 0.0f },
@@ -268,16 +275,17 @@ void vg_line_sphere( m4x3f m, float radius, u32 colour )
    }
 }
 
-void vg_line_capsule( m4x3f m, float radius, float h, u32 colour )
+void vg_line_capsule( m4x3f m, f32 radius, f32 h, u32 colour )
 {
-   if( !vg_lines.enabled ) return;
+   if( !vg_lines.enabled ) 
+      return;
    
    v3f ly = { 0.0f, 0.0f, radius },
        lx = { 0.0f, radius, 0.0f },
        lz = { 0.0f, 0.0f, radius };
 
-   float s0 = sinf(0.0f)*radius,
-         c0 = cosf(0.0f)*radius;
+   f32 s0 = sinf(0.0f)*radius,
+       c0 = cosf(0.0f)*radius;
 
    v3f p0, p1, up, right, forward;
    m3x3_mulv( m, (v3f){0.0f,1.0f,0.0f}, up );
@@ -301,10 +309,11 @@ void vg_line_capsule( m4x3f m, float radius, float h, u32 colour )
    vg_line( a0, a1, colour );
    vg_line( b0, b1, colour );
    
-   for( int i=0; i<16; i++ ){
-      float t = ((float)(i+1) * (1.0f/16.0f)) * VG_PIf * 2.0f,
-            s1 = sinf(t)*radius,
-            c1 = cosf(t)*radius;
+   for( int i=0; i<16; i++ )
+   {
+      f32 t = ((f32)(i+1) * (1.0f/16.0f)) * VG_PIf * 2.0f,
+          s1 = sinf(t)*radius,
+          c1 = cosf(t)*radius;
 
       v3f e0 = { s0, 0.0f, c0 },
           e1 = { s1, 0.0f, c1 },
@@ -328,13 +337,15 @@ void vg_line_capsule( m4x3f m, float radius, float h, u32 colour )
       vg_line( a0, a1, colour );
       vg_line( b0, b1, colour );
 
-      if( c0 < 0.0f ){
+      if( c0 < 0.0f )
+      {
          v3_add( p0, e2, a0 );
          v3_add( p0, e3, a1 );
          v3_add( p0, e4, b0 );
          v3_add( p0, e5, b1 );
       }
-      else{
+      else
+      {
          v3_add( p1, e2, a0 );
          v3_add( p1, e3, a1 );
          v3_add( p1, e4, b0 );
index 3730b6b00f1e467ea0cd4d61cfd5f7b7a2be2199..18dcdb9117f965f1657e2883954d55cba3211ba5 100644 (file)
@@ -22,11 +22,13 @@ struct vg_lines
    u32 enabled, 
        render;
        
-   struct vg_lines_vert{
+   struct vg_lines_vert
+   {
       v3f co;
       u32 colour;
    } 
    *vertex_buffer;
+   u32 vertex_count;
 
        GLuint vao, vbo;
 }
index c9a108c835527d99fc6620efb68e03c15827e97e..2e69ad6a9971b87073caff7fa4c96cb7cb3db904 100644 (file)
--- a/vg_mem.c
+++ b/vg_mem.c
@@ -7,8 +7,35 @@
 #include <stdlib.h>
 #include <malloc.h>
 
-struct vg_global_mem vg_mem;
+void *vg_malloc( u64 size )
+{
+   void *buf = malloc( size );
+   if( !buf )
+      vg_fatal_error( "Out of memory (OS)\n" );
+   return buf;
+}
+
+void vg_free( void *buf )
+{
+   free( buf );
+}
+
+void *vg_realloc( void *buf, u64 size )
+{
+   buf = realloc( buf, size );
+   if( !buf )
+      vg_fatal_error( "Out of memory (OS)\n" );
+   return buf;
+}
+
+void vg_zero_mem( void *buffer, u32 length )
+{
+   u8 *u8s = buffer;
+   for( u32 i=0; i<length; i++ )
+      u8s[i] = 0;
+}
 
+/* NOT USED IN THIS FILE */
 u32 vg_align16( u32 s )
 {
    u32 m = (s + 15) >> 4;
@@ -27,320 +54,162 @@ u32 vg_align4( u32 s )
    return m << 2;
 }
 
-/* Returns allocator structure from data pointer */
-vg_linear_allocator *vg_linear_header( void *data )
+void vg_stack_init( vg_stack_allocator *stack, void *buffer, u32 capacity, const char *debug_name )
 {
-   vg_linear_allocator *ptr = data;
-   ptr --;
+   VG_ASSERT( sizeof( vg_allocation_meta ) == 24 );
+   VG_ASSERT( sizeof( vg_stack_allocator ) == 24 );
 
-   return ptr;
+   vg_zero_mem( stack, sizeof(vg_stack_allocator) );
+   stack->data = buffer? buffer: vg_malloc( capacity );
+   stack->capacity = capacity;
+   stack->flags = buffer? 0: VG_STACK_ALLOCATOR_BUFFER_FROM_MALLOC;
 }
 
-/* allocate something from a linear allocator */
-__attribute__((warn_unused_result))
-void *_vg_linear_alloc( void *buffer, u32 size, const char *constr_name )
+vg_stack_allocator *vg_stack_make_substack( vg_stack_allocator *parent, u32 capacity, const char *debug_name )
 {
-   if( size % 8 )
-      size = vg_align8( size );
-
-   if( ((u64)buffer) % 8 )
-      vg_fatal_error( "Tried allocating to an unaligned buffer (%p)", buffer );
+   void *block = vg_stack_allocate( parent, sizeof(vg_stack_allocator) + capacity, 8, debug_name );
+   vg_stack_set_flags_last( parent, VG_ALLOCATION_FLAG_IS_STACK );
 
-   vg_linear_allocator *alloc = vg_linear_header( buffer );
-
-   if( (alloc->cur + size) > alloc->size )
-      vg_fatal_error( "linear allocator overflow (%u + %u > %u)\n", 
-                      alloc->cur, size, alloc->size );
+   vg_stack_allocator *stack = block;
+   vg_stack_init( stack, block + sizeof(vg_stack_allocator), capacity, debug_name );
+   return stack;
+}
 
-   if( alloc->flags & VG_MEMORY_SYSTEM )
+static void vg_stack_growmaybe( vg_stack_allocator *stack, u32 new_usage )
+{
+   if( new_usage > stack->capacity )
    {
-      if( (alloc->allocation_count + 1) > VG_MAX_ALLOCATIONS )
+      if( stack->flags & VG_STACK_ALLOCATOR_DOUBLE_IF_FULL )
       {
-         vg_fatal_condition();
-         vg_info( "Linear allocators marked as 'SYSTEMS', have a hard limit of "
-                  "%u allocations.\n\n"
-                  "The limit was exceeded by the following request:\n",
-                  VG_MAX_ALLOCATIONS );
-         vg_info( "  Name: %s\n", constr_name );
-         vg_info( "  Size: %u bytes\n", size );
-         vg_fatal_exit();
-      }
-   }
-
-   void *data;
+         u32 cap = stack->capacity * 2;
+         if( new_usage > cap )
+            cap = new_usage;
 
-   if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
-   {
-      data = malloc( size );
-
-      vg_allocation_meta *meta = &alloc->alloc_table[ alloc->allocation_count ];
-      meta->type = k_allocation_type_block;
-      meta->data = data;
-      meta->size = size;
-      meta->name = constr_name;
+         stack->data = vg_realloc( stack->data, cap );
+         stack->capacity = cap;
+      }
+      else
+      {
+         vg_fatal_error( "Stack allocator overflow (capacity: %u, used: %u, new_usage: %u)\n",
+                         stack->capacity, stack->used, new_usage );
+      }
    }
-   else
-      data = buffer + alloc->cur;
-
-   u8 *bytes = data;
-   for( u32 i=0; i<size; i++ )
-      bytes[i] = 0xfe;
-
-   alloc->allocation_count ++;
-   alloc->last_alloc = data;
-   alloc->last_alloc_size = size;
-   alloc->cur += size;
-
-   if( ((u64)data) % 8 )
-      vg_fatal_error( "Resultant allocation was unaligned, most likely memory "
-                      "corruption or programmer error\n" );
-   return data;
 }
 
-/* resize latest block of memory from linear */
-__attribute__((warn_unused_result))
-void *vg_linear_resize( void *buffer, void *data, u32 newsize )
+void *vg_stack_allocate( vg_stack_allocator *stack, u32 size, u32 alignment, const char *debug_name )
 {
-   vg_linear_allocator *alloc = vg_linear_header( buffer );
-
-   if( newsize % 8 )
-      newsize = vg_align8( newsize );
-
-   if( alloc->last_alloc != data )
-      vg_fatal_error( "Tried to resize allocation in linear allocator which "
-                      "has allocated other things after this block.\n" );
-
-   if( (alloc->cur - alloc->last_alloc_size + newsize) > alloc->size )
-      vg_fatal_error( "Tried to resize allocation to new size which would "
-                      "overflow the allocator\n" );
+   VG_ASSERT( (alignment >= 1) && (alignment <= 8) );
+   VG_ASSERT( ~stack->used & (0x1<<31) );
+   VG_ASSERT( ~size        & (0x1<<31) );
 
-   alloc->cur -= alloc->last_alloc_size;
-   alloc->cur += newsize;
-   alloc->last_alloc_size = newsize;
-
-   if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
+   u32 block_size = size;
+   if( stack->flags & VG_STACK_ALLOCATOR_METADATA )
    {
-      data = realloc( data, newsize );
-      if( !data )
-         vg_fatal_error( "We are libc mode, and realloc failed" );
-
-      alloc->alloc_table[ alloc->allocation_count-1 ].data = data;
-      alloc->alloc_table[ alloc->allocation_count-1 ].size = newsize;
-      alloc->last_alloc = data;
-      return data;
+      block_size += sizeof( vg_allocation_meta );
+      alignment = 8;
    }
-   else return data;
-}
 
-void vg_libc_del_recursive( void *buffer )
-{
-   vg_linear_allocator *alloc = vg_linear_header( buffer );
-   for( u32 i=0; i<alloc->allocation_count; i ++ )
-   {
-      vg_allocation_meta *meta = &alloc->alloc_table[i];
-      if( meta->type == k_allocation_type_linear )
-         vg_libc_del_recursive( meta->data );
-      else
-         free( meta->data );
-   }
+   u32 previous_base_offset = stack->used - stack->last_allocation_totalsize;
+   stack->last_allocation_totalsize = block_size;
 
-   free( alloc->alloc_table );
-   free( alloc );
-}
+   u32 new_usage = stack->used + block_size + alignment;
+   vg_stack_growmaybe( stack, new_usage );
 
-/* its possible to delete just the last item */
-void vg_linear_del( void *buffer, void *data )
-{
-   vg_linear_allocator *alloc = vg_linear_header( buffer );
+   while( stack->used & (alignment-1) )
+      stack->used ++;
 
-   if( alloc->last_alloc != data )
-      vg_fatal_error( "This block has been fixed and cannot be deleted.\n"
-                      "Last alloc: %p, this: %p\n", alloc->last_alloc, data );
+   void *block = (void *)stack->data + stack->used;
+   stack->used += block_size;
 
-   if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
+   if( stack->flags & VG_STACK_ALLOCATOR_METADATA )
    {
-      vg_allocation_meta *meta = &alloc->alloc_table[alloc->allocation_count-1];
-      if( meta->type == k_allocation_type_linear )
-         vg_libc_del_recursive( meta->data );
-      else
-         free( data );
-   }
+      vg_allocation_meta *meta = block;
+      memset( block, 0, sizeof(vg_allocation_meta) );
+      meta->name = debug_name;
+      meta->size = size;
+      meta->previous_offset = previous_base_offset;
+      meta->flags = 0;
 
-   alloc->allocation_count --;
-   alloc->cur -= alloc->last_alloc_size;
-   alloc->last_alloc = NULL;
-   alloc->last_alloc_size = 0;
+      return (void *)meta->data;
+   }
+   else return block;
 }
 
-void vg_allocator_free( void *allocator )
+void vg_stack_clear( vg_stack_allocator *stack )
 {
-   if( vg_mem.use_libc_malloc )
-      vg_libc_del_recursive( allocator );
-   else
-      free( vg_linear_header( allocator ) );
+   stack->used = 0;
+   stack->last_allocation_totalsize = 0;
 }
 
-/* extend latest block of memory from linear */
-__attribute__((warn_unused_result))
-void *_vg_linear_extend( void *buffer, void *data, u32 extra,
-                         const char *constr_name )
+void vg_stack_free( vg_stack_allocator *stack )
 {
-   if( !data )
-      return _vg_linear_alloc( buffer, vg_align8(extra), constr_name );
-
-   vg_linear_allocator *alloc = vg_linear_header( buffer );
-
-   if( alloc->last_alloc != data )
-      vg_fatal_error( "This block has been fixed!" );
-
-   u32 new_size = alloc->last_alloc_size + extra;
-   return vg_linear_resize( buffer, data, vg_align8(new_size) );
+   if( stack->flags & VG_STACK_ALLOCATOR_BUFFER_FROM_MALLOC )
+      vg_free( stack->data );
+   vg_zero_mem( stack, sizeof(vg_stack_allocator) );
 }
 
-/* get the current usage of allocator */
-u32 vg_linear_get_cur( void *buffer )
+void vg_stack_set_flags( vg_stack_allocator *stack, u16 append_flags )
 {
-   vg_linear_allocator *alloc = vg_linear_header( buffer );
-   return alloc->cur;
-}
+   if( append_flags & VG_STACK_ALLOCATOR_DOUBLE_IF_FULL )
+      if( !(stack->flags & VG_STACK_ALLOCATOR_BUFFER_FROM_MALLOC) )
+         vg_fatal_error( "Cannot append DOUBLE_IF_FULL to stack allocator, since buffer wasn't from malloc.\n" );
 
-/* get the capacity of allocator. */
-u32 vg_linear_get_capacity( void *buffer )
-{
-   vg_linear_allocator *alloc = vg_linear_header( buffer );
-   return alloc->size;
-}
+   if( append_flags & VG_STACK_ALLOCATOR_METADATA )
+      if( stack->used )
+         vg_fatal_error( "Cannot append METADATA to stack allocator after allocating something.\n" );
 
-/* get the remaining size of the allocator */
-u32 vg_linear_remaining( void *buffer )
-{
-   vg_linear_allocator *alloc = vg_linear_header( buffer );
-   return alloc->size - alloc->cur;
+   stack->flags |= append_flags;
 }
 
-/* yeet all memory from linear allocator */
-void vg_linear_clear( void *buffer )
+void vg_stack_set_flags_last( vg_stack_allocator *stack, u16 append_flags )
 {
-   vg_linear_allocator *alloc = vg_linear_header( buffer );
-
-   /* libc mode we recursively free any allocations made */
-   if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ){
-      for( u32 i=0; i<alloc->allocation_count; i++ ){
-         vg_allocation_meta *meta = &alloc->alloc_table[i];
-         
-         if( meta->type == k_allocation_type_block ){
-            free( meta->data );
-         }
-         else{
-            vg_linear_clear( meta->data );
-            vg_linear_allocator *sub = vg_linear_header( meta->data );
-
-            free( sub->alloc_table );
-            free( sub );
-         }
-      }
-   }
+   if( !(stack->flags & VG_STACK_ALLOCATOR_METADATA) )
+      vg_fatal_error( "Stack allocator does not have the METADATA flag set.\n" );
 
-   alloc->last_alloc = NULL;
-   alloc->last_alloc_size = 0;
-   alloc->allocation_count = 0;
-   alloc->cur = 0;
+   vg_allocation_meta *meta = (void *)stack->data + (stack->used - stack->last_allocation_totalsize);
+   meta->flags |= append_flags;
 }
 
-/* allocate a FIXED SIZE linear allocator
- *
- * FIXME: there was a bug in vg's code that caused a race condition between
- *        two system allocations. make this IMPOSSIBLE by requiring a lock
- *        on the allocater to be passed between threads.
- *
- *        luckily that bug only exists when using development tools, but still!
- *
- *        this should then only be checked and turned on in debugging.
- *
- */
-void *_vg_create_linear_allocator( void *lin_alloc, u32 size, u16 flags, const char *constr_name)
+void vg_stack_resize_last( vg_stack_allocator *stack, u32 new_size )
 {
-   VG_ASSERT( sizeof( vg_linear_allocator ) == 32 );
+   u32 base_offset = stack->used - stack->last_allocation_totalsize,
+       block_size  = new_size;
 
-   vg_linear_allocator *header;
-   u32 block_size = size + sizeof(vg_linear_allocator);
-   
-   /* Creating it inside an existing one */
-   if( lin_alloc )
+   if( stack->flags & VG_STACK_ALLOCATOR_METADATA )
    {
-      vg_linear_allocator *alloc = vg_linear_header( lin_alloc );
-
-      if( alloc->cur + block_size > alloc->size )
-         vg_fatal_error( "Out of memory (%u + %u > %u)\n", alloc->cur, block_size, alloc->size );
-
-      if( alloc->allocation_count + 1 > VG_MAX_ALLOCATIONS )
-         vg_fatal_error( "Exceeded max allocations in linear allocator (%u)\n", VG_MAX_ALLOCATIONS );
-
-      if( (flags && VG_MEMORY_SYSTEM) && (alloc->flags & VG_MEMORY_REALTIME) )
-         vg_fatal_error( "Cannot declare realtime allocator inside systems allocator");
-
-      if( vg_mem.use_libc_malloc ){
-         vg_allocation_meta *meta = 
-            &alloc->alloc_table[ alloc->allocation_count ];
-         
-         if( flags & VG_MEMORY_REALTIME )
-            header = malloc( block_size );
-         else
-            header = malloc( sizeof(vg_linear_allocator) );
-
-         meta->data = header+1;
-         meta->type = k_allocation_type_linear;
-         meta->size = size;
-         meta->name = constr_name;
-      }
-      else header = lin_alloc + alloc->cur;
-      
-      alloc->cur += block_size;
-      alloc->last_alloc = header;
-      alloc->last_alloc_size = block_size;
-      alloc->allocation_count ++;
-   }
-   else{
-      if( vg_mem.use_libc_malloc && (flags & VG_MEMORY_SYSTEM) )
-         header = malloc( sizeof(vg_linear_allocator) );
-      else
-         header = malloc( block_size );
+      vg_allocation_meta *meta = (void *)stack->data + base_offset;
+      meta->size = new_size;
+      block_size += sizeof( vg_allocation_meta );
    }
 
-   header->allocation_count = 0;
-   header->cur = 0;
-   header->last_alloc = NULL;
-   header->last_alloc_size = 0;
-   header->size = size;
-   header->flags = flags;
-
-   if( vg_mem.use_libc_malloc && (flags & VG_MEMORY_SYSTEM) )
-   {
-      u32 table_size = sizeof(vg_allocation_meta)*VG_MAX_ALLOCATIONS;
-      header->alloc_table = malloc( table_size );
-   }
-   else header->alloc_table = NULL;
-
-   return header+1;
+   u32 new_usage = base_offset + block_size;
+   vg_stack_growmaybe( stack, new_usage );
+   stack->used = new_usage;
+   stack->last_allocation_totalsize = block_size;
 }
 
-/* request all the memory we need in advance */
-void vg_set_mem_quota( u32 size )
+void vg_stack_extend_last( vg_stack_allocator *stack, u32 extra_bytes )
 {
-   vg_mem.quota = size;
+   u32 current_size = stack->last_allocation_totalsize;
+   if( stack->flags & VG_STACK_ALLOCATOR_METADATA )
+      current_size -= sizeof(vg_allocation_meta);
+   vg_stack_resize_last( stack, current_size + extra_bytes );
 }
 
-void vg_alloc_quota(void)
+void *vg_stack_pop_last( vg_stack_allocator *stack )
 {
-   u32 size_scratch = 10*1024*1024;
-   u32 size = VG_MAX( vg_mem.quota, size_scratch );
-
-   vg_mem.rtmemory = _vg_create_linear_allocator( NULL, size, VG_MEMORY_SYSTEM,
-                                                  "VG Root" );
-   vg_mem.scratch = _vg_create_linear_allocator( vg_mem.rtmemory, 
-                                                 size_scratch,
-                                                 VG_MEMORY_SYSTEM,
-                                                 "Scratch buffer" );
+   if( !(stack->flags & VG_STACK_ALLOCATOR_METADATA) )
+      vg_fatal_error( "Stack allocator does not have the METADATA flag set.\n" );
+
+   if( !stack->last_allocation_totalsize )
+      return NULL;
+
+   u32 base_offset = stack->used - stack->last_allocation_totalsize;
+   vg_allocation_meta *meta = (void *)stack->data + base_offset;
+
+   stack->last_allocation_totalsize = base_offset - meta->previous_offset;
+   stack->used = base_offset;
+   return (void *)meta->data;
 }
 
 static void vg_mem_print_size( u32 bytes, char buf[32] )
@@ -352,41 +221,3 @@ static void vg_mem_print_size( u32 bytes, char buf[32] )
    else
       snprintf( buf, 32, "%ub", bytes );
 }
-
-void vg_mem_log( void *lin_alloc, int depth, const char *name )
-{
-   if( vg_mem.use_libc_malloc ){
-      vg_linear_allocator *alloc = vg_linear_header( lin_alloc );
-
-      u32 s = alloc->size;
-      f32 p = ((float)alloc->cur / (float)s) * 100.0f;
-      
-      for( int i=0; i<depth; i++ ) printf( "  " );
-
-      char asize[32];
-      vg_mem_print_size( s, asize );
-      printf( "LA(%s): %s, %f%% used\n", name, asize, p );
-
-      if( alloc->flags & VG_MEMORY_SYSTEM ){
-         for( u32 i=0; i<alloc->allocation_count; i++ ){
-            vg_allocation_meta *meta = &alloc->alloc_table[i];
-            
-            if( meta->type == k_allocation_type_block ){
-               for( int i=0; i<depth+1; i++ ) printf( "  " );
-               vg_mem_print_size( meta->size, asize );
-               printf( "B(%s): %s\n", meta->name, asize );
-            }
-            else{
-               vg_mem_log( meta->data, depth +1, meta->name );
-            }
-         }
-      }
-      else{
-         for( int i=0; i<depth+1; i++ ) printf( "  " );
-         printf( "<opaque memory> (UNTRACKED)\n" );
-      }
-   }
-   else{
-      vg_error( "allocations are not tracked (turn on libc mode)\n" );
-   }
-}
index b5b036632b064a6dc9f92a66a36821b801736d9e..9c91111329c643468aad392007a3aaba9a5758ed 100644 (file)
--- a/vg_mem.h
+++ b/vg_mem.h
 #pragma once
+#include "vg_platform.h"
+#include <stdalign.h>
 
-#define VG_MAX_ALLOCATIONS 256
+#define VG_KB( X ) (X*1024)
+#define VG_MB( X ) (X*1024*1024)
+#define VG_GB( X ) (X*1024*1024*1024)
 
-typedef struct vg_linear_allocator vg_linear_allocator;
-typedef struct vg_allocation_meta vg_allocation_meta;
+void *vg_malloc( u64 size );
+void *vg_realloc( void *buf, u64 size );
+void vg_free( void *buf );
+void vg_zero_mem( void *buffer, u32 length );
 
-struct vg_global_mem
-{
-   void *rtmemory,
-        *scratch;
+typedef struct vg_stack_allocator vg_stack_allocator;
+typedef struct vg_allocation_meta vg_allocation_meta;
 
-   int   use_libc_malloc;
-   u32   quota;
-}
-extern vg_mem;
+#define VG_ALLOCATION_FLAG_IS_STACK      0x1
 
+/* 24 bytes + size */
 struct vg_allocation_meta
 {
    const char *name;
-   void *data;
+
    u32 size;
-   enum allocation_type{
-      k_allocation_type_block  = 0,
-      k_allocation_type_linear = 1
-   }
-   type;
+   u32 previous_offset;
+   u16 flags;
+   u16 unused0;
+   u32 unused1;
+
+   u64 data[];
 };
 
-#define VG_MEMORY_SYSTEM    0x1  /* systems memory, slow and low counts */
-#define VG_MEMORY_REALTIME  0x2  /* per-frame. no max allocs, only size. fast */
+/* configuration flags */
+#define VG_STACK_ALLOCATOR_METADATA       0x1
+#define VG_STACK_ALLOCATOR_DOUBLE_IF_FULL 0x2
 
-/* 
- * Stored just behind the array. 32 bytes.
- */
-#pragma pack(push,1)
-struct vg_linear_allocator
+/* system flags */
+#define VG_STACK_ALLOCATOR_BUFFER_FROM_MALLOC 0x4
+
+/* 24 bytes */
+struct vg_stack_allocator
 {
-   u32 size;
-   u32 cur;
-   u16 allocation_count;
+   u32 capacity; /* bytes */
+   u32 used;
+   u32 last_allocation_totalsize;
    u16 flags;
-   u32 last_alloc_size;
-   void *last_alloc;
-   vg_allocation_meta *alloc_table;
+   u16 unused0;
+
+   void *data;
 };
-#pragma pack(pop)
 
+/* NOT USED IN THIS FILE */
 u32 vg_align16( u32 s );
 u32 vg_align8( u32 s );
 u32 vg_align4( u32 s );
 
-/* allocate something from a linear allocator */
-__attribute__((warn_unused_result))
-void *_vg_linear_alloc( void *buffer, u32 size, const char *constr_name );
-
-/* resize latest block of memory from linear */
-__attribute__((warn_unused_result))
-void *vg_linear_resize( void *buffer, void *data, u32 newsize );
-
-/* its possible to delete just the last item */
-void vg_linear_del( void *buffer, void *data );
-
-/* extend latest block of memory from linear */
-__attribute__((warn_unused_result))
-void *_vg_linear_extend( void *buffer, void *data, u32 extra, 
-                         const char *constr_name );
-
-/* get the current usage of allocator */
-u32 vg_linear_get_cur( void *buffer );
-
-/* get the capacity of allocator. */
-u32 vg_linear_get_capacity( void *buffer );
-
-/* get the remaining size of the allocator */
-u32 vg_linear_remaining( void *buffer );
-
-/* yeet all memory from linear allocator */
-void vg_linear_clear( void *buffer );
-
-/* request all the memory we need in advance */
-void vg_set_mem_quota( u32 size );
-
-/* essentially init() */
-void vg_alloc_quota(void);
-
-/* print out tree of current memory used. only works with libc mode */
-void vg_mem_log( void *lin_alloc, int depth, const char *name );
+/* If parent_stack is NULL, it will malloc a new stack of size
+ * If parent_stack is not NULL, it will allocate the new stack inside of this one. This allows it to be seen in the
+ * metadata as a tree structure.
+ */
+void vg_stack_init( vg_stack_allocator *stack, void *buffer, u32 capacity, const char *debug_name );
+void *vg_stack_allocate( vg_stack_allocator *stack, u32 size, u32 alignment, const char *debug_name );
+void vg_stack_clear( vg_stack_allocator *stack );
+void vg_stack_free( vg_stack_allocator *stack );
+void vg_stack_set_flags( vg_stack_allocator *stack, u16 append_flags );
+vg_stack_allocator *vg_stack_make_substack( vg_stack_allocator *parent, u32 capacity, const char *debug_name );
 
-#define VG_MEM_MCSTR(S) VG_MEM_MCSTR2(S)
-#define VG_MEM_MCSTR2(S) #S
+#define VG_STACK_ALLOCATE_STRUCT( STACK, STRUCT ) vg_stack_allocate( STACK, sizeof(STRUCT), alignof(STRUCT), NULL )
 
-#define vg_linear_alloc(...) \
-   _vg_linear_alloc( __VA_ARGS__, __FILE__":"VG_MEM_MCSTR(__LINE__) )
-#define vg_linear_extend(...) \
-   _vg_linear_extend( __VA_ARGS__, __FILE__":"VG_MEM_MCSTR(__LINE__) )
-#define vg_create_linear_allocator(...) \
-   _vg_create_linear_allocator( __VA_ARGS__, __FILE__":"VG_MEM_MCSTR(__LINE__) )
+void vg_stack_resize_last( vg_stack_allocator *stack, u32 new_size );
+void vg_stack_extend_last( vg_stack_allocator *stack, u32 extra_bytes );
 
-void *_vg_create_linear_allocator( void *lin_alloc, u32 size, 
-                                   u16 flags, const char *constr_name);
-vg_linear_allocator *vg_linear_header( void *data );
-void vg_allocator_free( void *allocator );
+/*
+ * The following are availible if allocator has the flag METADATA set
+ */
+void vg_stack_set_flags_last( vg_stack_allocator *stack, u16 append_flags );
+void *vg_stack_pop_last( vg_stack_allocator *stack );
index c36913ecf57f72ba5ad9b8f4e1c3dbe517740ab3..03c82f6076d26ffde65ed0824d44b422549baef0 100644 (file)
@@ -1,9 +1,36 @@
 #include "vg_ui/imgui.h"
 
-int vg_mem_view = 0;
+struct mem_view_data
+{
+   void *base_buffer;
+   u32 route[8];
+   u32 route_depth;
+
+   bool vis_dirty;
+   u32 vis_offset;
+   v4f vis_colour;
+   f32 vis_inv_max;
+   GLuint vis_tex;
+   u32 vis_i, vis_size;
+
+   struct mem_view_info
+   {
+      const char *display_name;
+      u32 buffer_offset, buffer_size; /* offset + size into route[0]->data */
 
-void squarey_layout( ui_rect rect, f32 *areas, u32 area_count,
-                     void (*cb)( u32, ui_rect, void* ), void *cb_user )
+      bool is_stack;
+      u32 stack_used_bytes, 
+          stack_children_start, stack_children_count; /* offset + count into this array (infos), children are sorted
+                                                         by capacity / size */
+   }
+   infos[ 4096 ];
+   u32 info_count;
+   f32 sizes[ 4096 ];
+
+   f32 vis_data[256*256];
+};
+
+void squarey_layout( ui_rect rect, f32 *areas, u32 area_count, void (*cb)( u32, ui_rect, void* ), void *cb_user )
 {
    f32 area_total = 0.0f;
    for( u32 i=0; i<area_count; i ++ )
@@ -71,165 +98,106 @@ L_LOOP:
    goto L_LOOP_ADJUST;
 }
 
-struct vg_mem_view_result
-{
-   vg_allocation_meta *target;
-   ui_rect target_rect;
-   u32 colour;
-};
-
-struct vg_mem_draw_inf
+struct vg_mem_draw_blocks_context
 {
    ui_context *ui_ctx;
-   vg_linear_allocator *alloc;
-   i32 *indices;
+   struct mem_view_data *mv;
    u32 root_colour;
+   u32 root_id;
+   u32 depth;
 
-   struct vg_mem_view_result *result;
+   u32 highlight_id;
+   u32 highlight_colour;
+   ui_rect highlight_rect;
 };
 
-static void vg_mem_view_ui( ui_context *ctx, ui_rect rect, 
-                            void *lin_alloc, const char *name, u32 root_colour,
-                            struct vg_mem_view_result *result );
+static void vg_mem_view_stack( struct vg_mem_draw_blocks_context *context, ui_rect rect );
 
-static void vg_mem_draw_cb( u32 idx, ui_rect rect, void *user )
+static void vg_mem_draw_block_cb( u32 idx, ui_rect rect, void *user )
 {
-   struct vg_mem_draw_inf *inf = user;
+   struct vg_mem_draw_blocks_context *context = user;
    ui_rect tmp;
    rect_copy( rect, tmp );
    tmp[2] --;
    tmp[3] --;
 
-   idx = inf->indices[idx];
-   vg_allocation_meta *meta = &inf->alloc->alloc_table[idx];
+   struct mem_view_info *root_info = &context->mv->infos[ context->root_id ],
+                        *this_info = &context->mv->infos[ root_info->stack_children_start + idx ];
 
    u32 colour;
-   if( inf->root_colour ) colour = inf->root_colour;
-   else                   colour = ~0xff000000&((idx+5)*0x45d9f3b);
+   if( context->root_colour ) colour = context->root_colour;
+   else                       colour = ~0xff000000&((idx+5)*0x45d9f3b);
 
-   if( meta->type == k_allocation_type_block )
+   if( this_info->is_stack )
    {
-      ui_fill( inf->ui_ctx, tmp, 0x80000000 | colour );
-      ui_outline( inf->ui_ctx, tmp, -1, 0xff000000 | colour, 0 );
+      struct vg_mem_draw_blocks_context next_level = *context;
+      next_level.depth ++;
+      next_level.root_colour = colour;
+      next_level.root_id = root_info->stack_children_start + idx;
+
+      ui_rect subrect;
+      rect_copy( rect, subrect );
+      vg_mem_view_stack( &next_level, subrect );
    }
    else
-      vg_mem_view_ui( inf->ui_ctx, tmp, meta->data, meta->name, colour, NULL );
+   {
+      ui_fill( context->ui_ctx, tmp, 0x80000000 | colour );
+      ui_outline( context->ui_ctx, tmp, -1, 0xff000000 | colour, 0 );
+   }
 
-   if( inf->result )
+   if( context->depth == 0 )
    {
-      if( ui_inside_rect( rect, inf->ui_ctx->mouse ) )
+      if( ui_inside_rect( rect, context->ui_ctx->mouse ) )
       {
-         inf->result->target = meta;
-         inf->result->colour = colour;
-         rect_copy( rect, inf->result->target_rect );
+         context->highlight_colour = colour;
+         context->highlight_id = root_info->stack_children_start + idx;
+         rect_copy( rect, context->highlight_rect );
       }
    }
 }
 
-vg_linear_allocator *_CB_values;
-int _CB_vg_mem_sort( const void *a, const void *b )
+static void vg_mem_view_stack( struct vg_mem_draw_blocks_context *context, ui_rect rect )
 {
-   i32 ia = *((const i32 *)a), ib = *((const i32 *)b);
-   f32 fa = _CB_values->alloc_table[ ia ].size,
-       fb = _CB_values->alloc_table[ ib ].size;
-   return (fa < fb) - (fa > fb);
-}
+   struct mem_view_info *info = &context->mv->infos[ context->root_id ];
+   VG_ASSERT( info->is_stack );
 
-static void vg_mem_view_ui( ui_context *ctx, ui_rect rect, 
-                            void *lin_alloc, const char *name, u32 root_colour,
-                            struct vg_mem_view_result *result )
-{
-   f32 sizes[ VG_MAX_ALLOCATIONS ];
-   i32 indices[ VG_MAX_ALLOCATIONS ];
-
-   if( vg_mem.use_libc_malloc )
+   if( info->stack_used_bytes )
    {
-      vg_linear_allocator *alloc = vg_linear_header( lin_alloc );
-      struct vg_mem_draw_inf inf = 
+      /* draw unused stack space as dark black */
+      if( info->stack_used_bytes < info->buffer_size )
       {
-         .ui_ctx = ctx,
-         .alloc = alloc,
-         .indices = indices,
-         .result = result,
-         .root_colour = root_colour
-      };
+         u32 short_side = rect[3] < rect[2]? 1: 0;
+         f32 p = 1.0f-((f32)info->stack_used_bytes / (f32)info->buffer_size);
+         ui_px h = (f32)rect[2+short_side^0x1] * p*p;
+         ui_rect out_box = {rect[0], rect[1]};
+         out_box[ 2+short_side^0x1 ] = h;
+         out_box[ 2+short_side ] = rect[ 2+short_side ];
 
-      if( alloc->allocation_count )
-      {
-         if( alloc->cur < alloc->size )
-         {
-            u32 short_side = rect[3] < rect[2]? 1: 0;
-            f32 p = 1.0f-((f32)alloc->cur / (f32)alloc->size);
-            ui_px h = (f32)rect[2+short_side^0x1] * p*p;
-            ui_rect out_box = {rect[0], rect[1]};
-            out_box[ 2+short_side^0x1 ] = h;
-            out_box[ 2+short_side ] = rect[ 2+short_side ];
-
-            ui_fill( ctx, out_box, 0x80000000 );
-
-            char asize[32];
-            vg_mem_print_size( alloc->size-alloc->cur, asize );
-            ui_text( ctx, out_box, asize, 1, k_ui_align_middle_center, 0 );
+         ui_fill( context->ui_ctx, out_box, 0x80000000 );
 
-            rect[ short_side^0x1 ] += h;
-            rect[ 2+short_side^0x1 ] -= h;
-         }
-
-         if( alloc->flags & VG_MEMORY_SYSTEM )
-         {
-            for( i32 i=0; i<alloc->allocation_count; i ++ )
-               indices[i] = i;
+         char asize[32];
+         vg_mem_print_size( info->buffer_size - info->stack_used_bytes, asize );
+         ui_text( context->ui_ctx, out_box, asize, 1, k_ui_align_middle_center, 0 );
 
-            u32 count = alloc->allocation_count;
-            _CB_values = alloc;
-            qsort( indices, count, sizeof(i32), _CB_vg_mem_sort );
-
-            for( u32 i=0; i<alloc->allocation_count; i++ )
-            {
-               i32 indice = indices[i];
-
-               vg_allocation_meta *meta = &alloc->alloc_table[indice];
-               sizes[i] = sqrtf(meta->size);
-            }
-
-            squarey_layout( rect, sizes, count, vg_mem_draw_cb, &inf );
-         }
-         else
-         {
-            //printf( "<opaque memory> (UNTRACKED)\n" );
-         }
+         rect[ short_side^0x1 ] += h;
+         rect[ 2+short_side^0x1 ] -= h;
       }
-      else
+
+      if( info->stack_children_count )
       {
-         ui_fill( ctx, rect, 0x80101010 );
-         //ui_text( ctx, rect, name, 1, k_ui_align_left, 0 );
+         squarey_layout( rect, &context->mv->sizes[ info->stack_children_start ], info->stack_children_count, 
+                         vg_mem_draw_block_cb, context );
       }
+      else
+         ui_fill( context->ui_ctx, rect, 0x80101010 );
    }
    else
-   {
-      //vg_error( "allocations are not tracked (turn on libc mode)\n" );
-   }
+      ui_fill( context->ui_ctx, rect, 0x80000000 );
 }
 
-struct mem_view_data
-{
-   void *main_buffer[8],
-        *inspecting;
-   v4f inspect_colour;
-
-   const char *walk[8];
-
-   u32 depth;
-
-   f32 vis_data[256*256];
-   GLuint tex;
-};
-
-static void cb_vg_mem_view( ui_context *ctx, ui_rect rect, 
-                            struct vg_magi_panel *magi )
+static void cb_vg_mem_view( ui_context *ctx, ui_rect rect, struct vg_magi_panel *magi )
 {
    struct mem_view_data *mv = magi->data;
-   struct vg_mem_view_result result = { .target=NULL };
 
    ui_rect left;
    ui_split( rect, k_ui_axis_v, 256+16, 2, left, rect );
@@ -237,118 +205,120 @@ static void cb_vg_mem_view( ui_context *ctx, ui_rect rect,
 
    /* Tree back-tracker */
    {
-      ui_rect bib = { left[0],left[1],left[2],24 };
-      u32 new_depth = mv->depth;
-      for( u32 i=0; i<mv->depth+1; i ++ )
+      ui_rect box = { left[0],left[1],left[2],24 };
+      u32 new_depth = mv->route_depth;
+      for( u32 i=0; i<mv->route_depth+1; i ++ )
       {
-         if( i != mv->depth )
+         struct mem_view_info *info = &mv->infos[ mv->route[i] ];
+         if( i != mv->route_depth )
          {
-            if( ui_button_text( ctx, bib, mv->walk[ i ], 1 ) == 1 )
+            if( ui_button_text( ctx, box, info->display_name, 1 ) == 1 )
             {
                new_depth = i;
             }
          }
          else
          {
-            ui_fill( ctx, bib, ui_colour( ctx, k_ui_bg ) );
-            ui_text( ctx, bib, mv->walk[i], 1, k_ui_align_middle_center, 0 );
+            ui_fill( ctx, box, ui_colour( ctx, k_ui_bg ) );
+            ui_text( ctx, box, info->display_name, 1, k_ui_align_middle_center, 0 );
          }
 
-         bib[0] += 8;
-         bib[2] -= 8;
-         bib[1] += 24;
+         box[0] += 8;
+         box[2] -= 8;
+         box[1] += 24;
       }
-      mv->depth = new_depth;
-      ui_px v = (mv->depth+1)*24;
+      mv->route_depth = new_depth;
+      ui_px v = (mv->route_depth+1)*24;
       left[1] += v;
       left[3] -= v;
    }
 
-   if( vg_mem.use_libc_malloc == 0 )
+   struct vg_mem_draw_blocks_context context = 
    {
-      ui_text( ctx, rect, "Run with --use-libc-malloc to view memory", 
-               1, k_ui_align_middle_center, 0 );
-      return;
-   }
-
-   vg_mem_view_ui( ctx, rect, mv->main_buffer[ mv->depth ], "", 0, &result );
-
-   if( result.target )
+      .ui_ctx = ctx,
+      .mv = mv,
+      .root_colour = 0,
+      .root_id = mv->route[ mv->route_depth ],
+      .highlight_id = 0xffffffff,
+      .depth = 0
+   };
+   vg_mem_view_stack( &context, rect );
+
+   if( context.highlight_id != 0xffffffff )
    {
-      ui_outline( ctx, result.target_rect, 1, ui_colour( ctx,k_ui_bg+7 ), 0 );
-      ui_info( ctx, left, result.target->name );
+      struct mem_view_info *highlight_info = &mv->infos[ context.highlight_id ];
+
+      ui_outline( ctx, context.highlight_rect, 1, ui_colour( ctx,k_ui_bg+7 ), 0 );
+      ui_info( ctx, left, highlight_info->display_name );
 
       char buf[32];
-      vg_mem_print_size( result.target->size, buf );
+      vg_mem_print_size( highlight_info->buffer_size, buf );
       ui_info( ctx, left, buf );
 
-      if( mv->inspecting != result.target->data )
+      if( mv->vis_offset != highlight_info->buffer_offset )
       {
-         if( result.target->type == k_allocation_type_block )
-         {
-            for( u32 i=0; i<256*256; i++ ) mv->vis_data[i] = 0.0f;
-            f32 max_freq = 0.0f;
-            
-            const u8 *src = result.target->data;
-            for( u32 i=0; i<result.target->size-1; i ++ )
-            {
-               u8 x = src[i], y = src[i+1];
-               u32 offset = y*256 + x;
-
-               mv->vis_data[ offset ] += 1.0f;
-               max_freq = vg_maxf( mv->vis_data[ offset ], max_freq );
-            }
-
-            f32 median = 0.0f;
-            for( u32 i=0; i<256*256; i++ ) median += mv->vis_data[i];
-            median /= 256.0f*256.0f;
-
-            f32 inv_max = 1.0f/logf(1.0f+median*2.0f);
-            for( u32 i=0; i<256*256; i++ ) 
-            {
-               f32 v = logf(mv->vis_data[i]) * inv_max;
-               mv->vis_data[i] = v;
-            }
+         mv->vis_offset = highlight_info->buffer_offset;
+         mv->vis_i = 0;
+         mv->vis_size = highlight_info->buffer_size;
+         mv->vis_dirty = 1;
+         mv->vis_inv_max = 1.0f;
+
+         f32 nrm = 2.6f / 255.0f;
+         mv->vis_colour[0] = (f32)((context.highlight_colour    ) & 0xff) * nrm;
+         mv->vis_colour[1] = (f32)((context.highlight_colour>>8 ) & 0xff) * nrm;
+         mv->vis_colour[2] = (f32)((context.highlight_colour>>16) & 0xff) * nrm;
+         mv->vis_colour[3] = 1.0f;
+
+         for( u32 i=0; i<256*256; i++ ) 
+            mv->vis_data[i] = 0.0f;
+      }
 
-            glBindTexture( GL_TEXTURE_2D, mv->tex );
-            glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 256, 256, 
-                              GL_RED, GL_FLOAT, mv->vis_data );
+      if( mv->vis_i+1 < mv->vis_size )
+      {
+         const u8 *src = mv->base_buffer + mv->vis_offset;
+         for( u32 it=0; it<VG_KB(20) && (mv->vis_i+1 < mv->vis_size); it ++ )
+         {
+            u8 x = src[mv->vis_i], y = src[mv->vis_i+1];
+            u32 coord = y*256 + x;
+            mv->vis_data[ coord ] += 1.0f;
+            mv->vis_i ++;
          }
 
-         mv->inspecting = result.target->data;
+         f32 median = (f32)mv->vis_i;
+         mv->vis_inv_max = 1.0f/logf(1.0f+median*2.0f);
+         mv->vis_dirty = 1;
+      }
 
-         f32 nrm = 1.6f / 255.0f;
-         mv->inspect_colour[0] = (f32)((result.colour    ) & 0xff) * nrm;
-         mv->inspect_colour[1] = (f32)((result.colour>>8 ) & 0xff) * nrm;
-         mv->inspect_colour[2] = (f32)((result.colour>>16) & 0xff) * nrm;
-         mv->inspect_colour[3] = 1.0f;
+      if( mv->vis_dirty )
+      {
+         glBindTexture( GL_TEXTURE_2D, mv->vis_tex );
+         glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 256, 256, GL_RED, GL_FLOAT, mv->vis_data );
       }
 
-      if( result.target->type == k_allocation_type_block )
-         ui_info( ctx, left, "Leaf" );
-      else
+      if( highlight_info->is_stack )
          ui_info( ctx, left, "Linear Allocator (expand)" );
+      else
+         ui_info( ctx, left, "Leaf" );
 
-      if( result.target->type == k_allocation_type_block )
-      {
-         ui_rect freq_box = { left[0]+8, left[1], 256,256 };
-
-         ui_flush( ctx, k_ui_shader_colour, NULL );
-         ui_fill_rect( ctx, freq_box, 0xffffffff, (ui_px[4]){ 0,256,256,0 } );
-         struct ui_batch_shader_data_image inf = { .resource = &mv->tex };
-         v4_copy( mv->inspect_colour, vg_ui.colour );
-         ui_flush( ctx, k_ui_shader_grad, &inf );
-         v4_copy( (v4f){1,1,1,1}, vg_ui.colour );
-      }
+      ui_rect freq_box = { left[0]+8, left[1], 256,256 };
 
-      if( result.target->type == k_allocation_type_linear )
+      ui_flush( ctx, k_ui_shader_colour, NULL );
+      ui_fill_rect( ctx, freq_box, 0xffffffff, (ui_px[4]){ 0,256,256,0 } );
+      struct ui_batch_shader_data_image_gradient inf = { 
+         .resource = &mv->vis_tex,
+         .log = 1,
+         .scale = mv->vis_inv_max
+      };
+      v4_copy( mv->vis_colour, vg_ui.colour );
+      ui_flush( ctx, k_ui_shader_grad, &inf );
+      v4_copy( (v4f){1,1,1,1}, vg_ui.colour );
+
+      if( highlight_info->is_stack )
       {
          if( ui_click_down( ctx, UI_MOUSE_LEFT ) )
          {
-            mv->main_buffer[ mv->depth+1 ] = result.target->data;
-            mv->walk[ mv->depth+1 ] = result.target->name;
-            mv->inspecting = NULL;
-            mv->depth ++;
+            mv->route_depth ++;
+            mv->route[ mv->route_depth ] = context.highlight_id;
          }
       }
    }
@@ -357,59 +327,185 @@ static void cb_vg_mem_view( ui_context *ctx, ui_rect rect,
 static void cb_mem_view_close( struct vg_magi_panel *me )
 {
    struct mem_view_data *mv = me->data;
-   glDeleteTextures( 1, &mv->tex );
-   free( me->data );
+   glDeleteTextures( 1, &mv->vis_tex );
+   vg_free( me->data );
 }
 
 static struct
 {
    const char *name;
-   void **buffer;
+   vg_stack_allocator *stack;
 }
 _vg_mem_named_buffers[] = 
 {
-   { "rtmemory", &vg_mem.rtmemory },
-   { "scratch", &vg_mem.scratch }
+   { "rtmem", &vg.rtmem },
 };
 
+int _CB_vg_mem_infosort( const void *a, const void *b )
+{
+   const struct mem_view_info *info_a = a,
+                              *info_b = b;
+   return (i32)(info_a->buffer_size < info_b->buffer_size) - (i32)(info_a->buffer_size > info_b->buffer_size);
+}
+
 static int cmd_vg_mem_view( int argc, const char *argv[] )
 {
-   if( argc == 1 )
+   if( argc != 1 )
    {
-      for( u32 i=0; i<VG_ARRAY_LEN( _vg_mem_named_buffers ); i ++ )
+      vg_error( "Usage: vg_mem_view <named_buffer>\n" );
+      return 0;
+   }
+
+   for( u32 i=0; i<VG_ARRAY_LEN( _vg_mem_named_buffers ); i ++ )
+   {
+      if( !strcmp( _vg_mem_named_buffers[i].name, argv[0] ) )
       {
-         if( !strcmp( _vg_mem_named_buffers[i].name, argv[0] ) )
+         struct vg_magi_panel *magi = _vg_magi_open( 512+16, 512, VG_MAGI_ALL );
+         magi->title = "Memory outliner";
+
+         struct mem_view_data *mv = vg_malloc(sizeof(struct mem_view_data));
+         mv->route[0] = 0; 
+         mv->route_depth = 0;
+         mv->vis_offset = 0xffffffff;
+         mv->info_count = 1;
+
+         /* cache all allocations in full tree */
+         struct route_frame
          {
-            ui_px w = 512+16,
-                  h = 512;
-            struct vg_magi_panel *magi = _vg_magi_open( w,h, VG_MAGI_ALL );
-            magi->title = "Memory outliner";
-
-            struct mem_view_data *mv = malloc(sizeof(struct mem_view_data));
-            mv->main_buffer[0] = *_vg_mem_named_buffers[i].buffer;
-            mv->walk[0] = _vg_mem_named_buffers[i].name;
-            mv->depth = 0;
-            mv->inspecting = NULL;
-
-            glGenTextures( 1, &mv->tex );
-            glBindTexture( GL_TEXTURE_2D, mv->tex );
-            glTexImage2D( GL_TEXTURE_2D, 0, GL_R32F, 256,256, 0, 
-                          GL_RED, GL_FLOAT, NULL );
-            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
-            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
-
-            magi->data = mv;
-            magi->ui_cb = cb_vg_mem_view;
-            magi->close_cb = cb_mem_view_close;
-            return 1;
+            bool init;
+            vg_stack_allocator *stack;
+            struct mem_view_info *info;
+            u32 buffer_base_offset;
+
+            u32 descend_i;
          }
-      }
+         route[8];
+         u32 route_depth = 0;
+
+         route[0].init = 0;
+         route[0].stack = _vg_mem_named_buffers[i].stack;
+         route[0].info = &mv->infos[ 0 ];
+         route[0].buffer_base_offset = 0;
+         route[0].descend_i = 0;
+
+         mv->infos[0].display_name = _vg_mem_named_buffers[i].name;
+         mv->infos[0].buffer_offset = 0;
+         mv->infos[0].buffer_size = _vg_mem_named_buffers[i].stack->capacity;
+         mv->infos[0].is_stack = 1;
+         mv->infos[0].stack_used_bytes = _vg_mem_named_buffers[i].stack->used;
+         mv->sizes[0] = sqrtf(mv->infos[0].buffer_size);
+
+         mv->base_buffer = _vg_mem_named_buffers[i].stack->data;
+         
+      l0:{
+            struct route_frame *frame = &route[ route_depth ];
+
+            if( !frame->init )
+            {
+               frame->init = 1;
+               frame->info->stack_children_start = mv->info_count;
+               frame->info->stack_children_count = 0;
+
+               /* create array of all immediate child allocations */
+               u32 offset = frame->stack->used - frame->stack->last_allocation_totalsize; 
+
+               if( (frame->stack->used == 0) || !(frame->stack->flags & VG_STACK_ALLOCATOR_METADATA) )
+                  goto l1;
+
+            l2:{
+                  vg_allocation_meta *meta = frame->stack->data + offset;
+
+                  if( mv->info_count == VG_ARRAY_LEN(mv->infos) )
+                  {
+                     vg_error( "Reached maximum allocation infos! (%u)\n", mv->info_count );
+                     goto e1;
+                  }
+
+                  struct mem_view_info *info = &mv->infos[ mv->info_count ];
+                  info->display_name = meta->name;
+                  info->buffer_offset = frame->buffer_base_offset + offset + sizeof(vg_allocation_meta);
+                  info->buffer_size = meta->size;
+
+                  mv->info_count ++;
+                  frame->info->stack_children_count ++;
+                  
+                  if( meta->flags & VG_ALLOCATION_FLAG_IS_STACK )
+                  {
+                     info->is_stack = 1;
+                     vg_stack_allocator *substack = mv->base_buffer + info->buffer_offset;
+
+                     info->stack_used_bytes = substack->used;
+                     info->stack_children_start = 0; /* deferred to !frame->init */
+                     info->stack_children_count = 0;
+                  }
+                  else
+                     info->is_stack = 0;
+
+                  if( offset )
+                  {
+                     offset = meta->previous_offset;
+                     goto l2;
+                  }
+               }
+            }
+
+        l1: if( frame->descend_i < frame->info->stack_children_count )
+            {
+               struct mem_view_info *info = &mv->infos[ frame->info->stack_children_start + frame->descend_i ];
+               frame->descend_i ++;
+               
+               if( info->is_stack )
+               {
+                  route_depth ++;
+
+                  struct route_frame *next_frame = &route[ route_depth ];
+                  next_frame->init = 0;
+                  next_frame->stack = mv->base_buffer + info->buffer_offset;
+                  next_frame->info = info;
+                  next_frame->buffer_base_offset = info->buffer_offset + sizeof(vg_stack_allocator);
+                  next_frame->descend_i = 0;
+
+                  goto l0;
+               }
+               else goto l1;
+            }
+            else
+            {
+               /* Sort children by size, calculate sqrt f32 sizes, and step down */
+               qsort( &mv->infos[ frame->info->stack_children_start ], frame->info->stack_children_count, 
+                      sizeof(struct mem_view_info), _CB_vg_mem_infosort );
+
+               for( u32 i=0; i<frame->info->stack_children_count; i ++ )
+               {
+                  u32 index = frame->info->stack_children_start + i;
+                  struct mem_view_info *info = &mv->infos[ index ];
+                  mv->sizes[ index ] = sqrtf(info->buffer_size);
+               }
+
+               if( route_depth )
+               {
+                  route_depth --;
+                  goto l0;
+               }
+            }
+         }
+
+         vg_success( "Cached %u allocations.\n", mv->info_count );
+
+     e1: glGenTextures( 1, &mv->vis_tex );
+         glBindTexture( GL_TEXTURE_2D, mv->vis_tex );
+         glTexImage2D( GL_TEXTURE_2D, 0, GL_R32F, 256,256, 0, GL_RED, GL_FLOAT, NULL );
+         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
 
-      vg_error( "No named buffer '%s'\n", argv[0] );
+         magi->data = mv;
+         magi->ui_cb = cb_vg_mem_view;
+         magi->close_cb = cb_mem_view_close;
+         return 1;
+      }
    }
-   else
-      vg_error( "Usage: vg_mem_view <named_buffer>\n" );
 
+   vg_error( "No named buffer '%s'\n", argv[0] );
    return 0;
 }
 
index 7c63978c39c9f9fa7d815912dceebdd101870b9a..eadd59f32101864c07cae8e20aa1dca48e00e9dd 100644 (file)
@@ -78,13 +78,11 @@ void vg_render_init(void)
 #ifdef VG_3D
    vg_console_reg_var( "blur_strength", &_vg_postprocess.blur_strength, k_var_dtype_f32, 0 );
    vg_console_reg_var( "blur_effect", &_vg_postprocess.blur_effect, k_var_dtype_i32, VG_VAR_PERSISTENT );
-
-   void *alloc = vg_mem.rtmemory;
    
    /* 
     * Main framebuffer
     */
-   _vg_render.fb_main = vg_framebuffer_allocate( alloc, 3, 1 );
+   _vg_render.fb_main = vg_framebuffer_allocate( &vg.rtmem, 3, 1 );
    _vg_render.fb_main->display_name = "main";
    _vg_render.fb_main->resolution_div = 1;
    _vg_render.fb_main->attachments[0] = (vg_framebuffer_attachment)
@@ -119,7 +117,7 @@ void vg_render_init(void)
    /* 
     * Water reflection
     */
-   _vg_render.fb_water_reflection = vg_framebuffer_allocate( alloc, 2, 1 );
+   _vg_render.fb_water_reflection = vg_framebuffer_allocate( &vg.rtmem, 2, 1 );
    _vg_render.fb_water_reflection->display_name = "water_reflection";
    _vg_render.fb_water_reflection->resolution_div = 2;
    _vg_render.fb_water_reflection->attachments[0] = (vg_framebuffer_attachment) 
@@ -142,7 +140,7 @@ void vg_render_init(void)
     * Thid rendered view from the perspective of the camera, but just 
     * captures stuff thats under the water
     */
-   _vg_render.fb_water_beneath = vg_framebuffer_allocate( alloc, 2, 1 );
+   _vg_render.fb_water_beneath = vg_framebuffer_allocate( &vg.rtmem, 2, 1 );
    _vg_render.fb_water_beneath->display_name = "water_beneath";
    _vg_render.fb_water_beneath->resolution_div = 2;
    _vg_render.fb_water_beneath->attachments[0] = (vg_framebuffer_attachment) 
index f0cd8cc747275aebf29ce0c7be8b4c67e6f9ffd5..ca97b0f5cb7e355f3e00292e5a6c3a4dec1b8ea9 100644 (file)
@@ -56,88 +56,3 @@ steamapi_bool SteamAPI_ISteamUser_GetEncryptedAppTicket(
       int cbMaxTicket, u32 *pcbTicket );
 
 u64_steamid SteamAPI_ISteamUser_GetSteamID( ISteamUser *self );
-
-
-/* 
- * Application symetric-key ticket method (Server)
- */
-
-enum { k_nSteamEncryptedAppTicketSymmetricKeyLen = 32 };
-
-steamapi_bool SteamEncryptedAppTicket_BDecryptTicket( u8 *rgubTicketEncrypted, 
-         u32 cubTicketEncrypted, u8 *rgubTicketDecrypted, 
-         u32 *pcubTicketDecrypted, 
-         u8 rgubKey[k_nSteamEncryptedAppTicketSymmetricKeyLen], 
-         int cubKey );
-
-steamapi_bool SteamEncryptedAppTicket_BIsTicketForApp( u8 *rgubTicketDecrypted, 
-      u32 cubTicketDecrypted, AppId_t nAppID );
-
-RTime32 SteamEncryptedAppTicket_GetTicketIssueTime( u8 *rgubTicketDecrypted, 
-      u32 cubTicketDecrypted );
-
-void SteamEncryptedAppTicket_GetTicketSteamID( 
-      u8 *rgubTicketDecrypted, u32 cubTicketDecrypted, CSteamID *psteamID );
-
-AppId_t SteamEncryptedAppTicket_GetTicketAppID( u8 *rgubTicketDecrypted, 
-      u32 cubTicketDecrypted );
-
-steamapi_bool SteamEncryptedAppTicket_BUserOwnsAppInTicket( 
-      u8 *rgubTicketDecrypted, u32 cubTicketDecrypted, AppId_t nAppID );
-
-steamapi_bool SteamEncryptedAppTicket_BUserIsVacBanned( 
-      u8 *rgubTicketDecrypted, u32 cubTicketDecrypted );
-
-steamapi_bool SteamEncryptedAppTicket_BGetAppDefinedValue( 
-      u8 *rgubTicketDecrypted, u32 cubTicketDecrypted, u32 *pValue );
-
-u8 *SteamEncryptedAppTicket_GetUserVariableData( u8 *rgubTicketDecrypted, 
-      u32 cubTicketDecrypted, u32 *pcubUserData );
-
-steamapi_bool SteamEncryptedAppTicket_BIsTicketSigned( u8 *rgubTicketDecrypted, 
-      u32 cubTicketDecrypted, u8 *pubRSAKey, u32 cubRSAKey );
-
-steamapi_bool SteamEncryptedAppTicket_BIsLicenseBorrowed( 
-      u8 *rgubTicketDecrypted, u32 cubTicketDecrypted );
-
-steamapi_bool SteamEncryptedAppTicket_BIsLicenseTemporary( 
-      u8 *rgubTicketDecrypted, u32 cubTicketDecrypted );
-
-static inline u8 vg_char_base16( char c )
-{
-   if( c >= '0' && c <= '9' )
-      return c-'0';
-   if( c >= 'a' && c <= 'f' )
-      return (c-'a') + 10;
-
-   return 0;
-}
-
-static inline int vg_load_steam_symetric_key( const char *path, u8 *buf )
-{
-   vg_linear_clear( vg_mem.scratch );
-   u32 size;
-   char *src = vg_file_read( vg_mem.scratch, path, &size );
-
-   if( src )
-   {
-      if( size < k_nSteamEncryptedAppTicketSymmetricKeyLen )
-      {
-         vg_error( "Application key was invalid size\n" );
-         return 0;
-      }
-      
-      for( int i=0; i<k_nSteamEncryptedAppTicketSymmetricKeyLen; i++ )
-      {
-         buf[i] = (vg_char_base16( src[i*2+0] ) << 4) |
-                   vg_char_base16( src[i*2+1] );
-      }
-
-      return 1;
-   }
-   else
-   {
-      vg_error( "Application key path was invalid\n" );
-      return 0;
-   }
-}
diff --git a/vg_steam_auth_server.h b/vg_steam_auth_server.h
new file mode 100644 (file)
index 0000000..7d4ce4f
--- /dev/null
@@ -0,0 +1,87 @@
+#pragma once
+#include "vg/vg_platform.h"
+#include "vg/vg_io.h"
+#include "vg_steam.h"
+
+/* 
+ * Application symetric-key ticket method (Server)
+ */
+
+enum { k_nSteamEncryptedAppTicketSymmetricKeyLen = 32 };
+
+steamapi_bool SteamEncryptedAppTicket_BDecryptTicket( u8 *rgubTicketEncrypted, 
+         u32 cubTicketEncrypted, u8 *rgubTicketDecrypted, 
+         u32 *pcubTicketDecrypted, 
+         u8 rgubKey[k_nSteamEncryptedAppTicketSymmetricKeyLen], 
+         int cubKey );
+
+steamapi_bool SteamEncryptedAppTicket_BIsTicketForApp( u8 *rgubTicketDecrypted, 
+      u32 cubTicketDecrypted, AppId_t nAppID );
+
+RTime32 SteamEncryptedAppTicket_GetTicketIssueTime( u8 *rgubTicketDecrypted, 
+      u32 cubTicketDecrypted );
+
+void SteamEncryptedAppTicket_GetTicketSteamID( 
+      u8 *rgubTicketDecrypted, u32 cubTicketDecrypted, CSteamID *psteamID );
+
+AppId_t SteamEncryptedAppTicket_GetTicketAppID( u8 *rgubTicketDecrypted, 
+      u32 cubTicketDecrypted );
+
+steamapi_bool SteamEncryptedAppTicket_BUserOwnsAppInTicket( 
+      u8 *rgubTicketDecrypted, u32 cubTicketDecrypted, AppId_t nAppID );
+
+steamapi_bool SteamEncryptedAppTicket_BUserIsVacBanned( 
+      u8 *rgubTicketDecrypted, u32 cubTicketDecrypted );
+
+steamapi_bool SteamEncryptedAppTicket_BGetAppDefinedValue( 
+      u8 *rgubTicketDecrypted, u32 cubTicketDecrypted, u32 *pValue );
+
+u8 *SteamEncryptedAppTicket_GetUserVariableData( u8 *rgubTicketDecrypted, 
+      u32 cubTicketDecrypted, u32 *pcubUserData );
+
+steamapi_bool SteamEncryptedAppTicket_BIsTicketSigned( u8 *rgubTicketDecrypted, 
+      u32 cubTicketDecrypted, u8 *pubRSAKey, u32 cubRSAKey );
+
+steamapi_bool SteamEncryptedAppTicket_BIsLicenseBorrowed( 
+      u8 *rgubTicketDecrypted, u32 cubTicketDecrypted );
+
+steamapi_bool SteamEncryptedAppTicket_BIsLicenseTemporary( 
+      u8 *rgubTicketDecrypted, u32 cubTicketDecrypted );
+
+static inline u8 vg_char_base16( char c )
+{
+   if( c >= '0' && c <= '9' )
+      return c-'0';
+   if( c >= 'a' && c <= 'f' )
+      return (c-'a') + 10;
+
+   return 0;
+}
+
+static inline int vg_load_steam_symetric_key( const char *path, u8 *buf )
+{
+   vg_stack_allocator stack;
+   vg_stack_init( &stack, NULL, VG_KB(256), NULL );
+
+   u32 size;
+   char *src = vg_file_read( &stack, path, &size, 0 );
+
+   if( src )
+   {
+      if( size < k_nSteamEncryptedAppTicketSymmetricKeyLen )
+      {
+         vg_error( "Application key was invalid size\n" );
+         return 0;
+      }
+      
+      for( int i=0; i<k_nSteamEncryptedAppTicketSymmetricKeyLen; i++ )
+         buf[i] = (vg_char_base16( src[i*2+0] ) << 4) | vg_char_base16( src[i*2+1] );
+
+      return 1;
+   }
+   else
+   {
+      vg_error( "Application key path was invalid\n" );
+      return 0;
+   }
+}
index 3462db67f97760d59b07599bb70afaf9e0cbceec..412571fa244cc416e1507ff24bc9415ee32a85c9 100644 (file)
--- a/vg_tex.c
+++ b/vg_tex.c
@@ -306,10 +306,10 @@ void vg_tex2d_load_qoi_async( const u8 *bytes, u32 size, u32 flags, GLuint *dest
 void vg_tex2d_load_qoi_async_file( const char *path, u32 flags, GLuint *dest )
 {
    THREAD_1;
-   vg_linear_clear( vg_mem.scratch );
+   vg_stack_clear( &vg.scratch );
 
    u32 size;
-   const void *data = vg_file_read( vg_mem.scratch, path, &size );
+   const void *data = vg_file_read( &vg.scratch, path, &size, 0 );
    vg_tex2d_load_qoi_async( data, size, flags, dest );
 }
 
index 26736f0a3e1639cafda43dc5789b2512638c9ec1..ecfb7d93dcae5eeaad3e6cc9a8d6fc0f0d2b992b 100644 (file)
@@ -422,8 +422,7 @@ u32 v4f_u32_colour( v4f colour )
    return r | (g<<8) | (b<<16) | (a<<24);
 }
 
-static void ui_text_glyph( const struct vg_font_face *ff,
-                           u8 glyph, ui_rect out_texcoords )
+static void ui_text_glyph( const struct vg_font_face *ff, u8 glyph, ui_rect out_texcoords )
 {
    const vg_font_char *ch = &ff->map[ glyph ];
 
@@ -443,6 +442,9 @@ u32 ui_ntext( ui_context *ctx,
               ui_rect rect, const char *str, u32 len, ui_px scale, 
               enum ui_align align, u32 colour )
 {
+   if( str == NULL )
+      str = "NULL";
+
    ui_px glow_text = 0;
 
        ui_rect text_cursor;
@@ -597,9 +599,7 @@ u32 ui_ntext( ui_context *ctx,
    return printed_chars;
 }
 
-u32 ui_text( ui_context *ctx,
-             ui_rect rect, const char *str, ui_px scale, 
-             enum ui_align align, u32 colour )
+u32 ui_text( ui_context *ctx, ui_rect rect, const char *str, ui_px scale, enum ui_align align, u32 colour )
 {
    return ui_ntext( ctx, rect, str, 1024, scale, align, colour );
 }
@@ -2035,8 +2035,7 @@ void ui_dev_colourview( ui_context *ctx )
 
       if( names[i] )
       {
-         ui_text( ctx, swatch, names[i], 1, 
-                  k_ui_align_middle_left, ui_colourcont(ctx,i));
+         ui_text( ctx, swatch, names[i], 1, k_ui_align_middle_left, ui_colourcont(ctx,i));
       }
    }
 }
index 25f360c63a23417853318681d1c946d5f0af5617..8ce4782a51c73393721d07af850b51814d20c830 100644 (file)
@@ -235,6 +235,13 @@ struct ui_batch_shader_data_image
    void *resource;
 };
 
+struct ui_batch_shader_data_image_gradient
+{
+   void *resource;
+   bool log;
+   f32 scale;
+};
+
 struct ui_batch
 {
    ui_vert *vert_buf; /* base vertex array + [vert_offset] */
index 0810ec7c251f3bac3ec864d292140a778d75d978..8f7b1bb2ac58e230e3234467dead60d0ba1bb5d9 100644 (file)
@@ -197,6 +197,9 @@ static struct vg_shader _shader_ui_image_grad = {
       .static_src = 
        "uniform sampler2D uTexImage;"
    "uniform vec4 uColour;"
+   "uniform int uLog;"
+   "uniform float uScale;"
+
        "out vec4 FragColor;"
 
        "in vec2 aTexCoords;"
@@ -206,7 +209,12 @@ static struct vg_shader _shader_ui_image_grad = {
        "void main()"
        "{"
                "vec4 colour = texture( uTexImage, aTexCoords );"
-               "FragColor = vec4(vec3(colour.r)*uColour.rgb,1.0);"
+      "float v = colour.r;"
+      "if( uLog == 1 ){"
+         "v = log(v);"
+      "}"
+      "v *= uScale;"
+               "FragColor = vec4(vec3(v)*uColour.rgb,1.0);"
        "}"
    }
 };
@@ -321,15 +329,14 @@ void ui_impl_render_batch( ui_context *ctx, ui_batch *batch,
    else if( shader == k_ui_shader_grad )
    {
       glUseProgram( _shader_ui_image_grad.id );
-      glUniformMatrix3fv( 
-            glGetUniformLocation( _shader_ui_image_grad.id, "uPv" ), 1, 
-                                  GL_FALSE, (float *)vg_ui.pv );
-      glUniform1i( 
-            glGetUniformLocation(_shader_ui_image_grad.id,"uTexImage"), 0 );
-      glUniform4fv( glGetUniformLocation( _shader_ui_image.id, "uColour" ), 1,
-                    vg_ui.colour );
+      glUniformMatrix3fv( glGetUniformLocation( _shader_ui_image_grad.id, "uPv" ), 1, GL_FALSE, (float *)vg_ui.pv );
+      glUniform1i( glGetUniformLocation(_shader_ui_image_grad.id,"uTexImage"), 0 );
+      glUniform4fv( glGetUniformLocation( _shader_ui_image.id, "uColour" ), 1, vg_ui.colour );
+
+      struct ui_batch_shader_data_image_gradient *inf = shader_data;
+      glUniform1i( glGetUniformLocation(_shader_ui_image_grad.id,"uLog"), inf->log );
+      glUniform1f( glGetUniformLocation(_shader_ui_image_grad.id,"uScale"), inf->scale );
 
-      struct ui_batch_shader_data_image *inf = shader_data;
       GLuint *image = inf->resource;
 
       glActiveTexture( GL_TEXTURE0 );
@@ -339,8 +346,7 @@ void ui_impl_render_batch( ui_context *ctx, ui_batch *batch,
    {
       struct ui_batch_shader_data_hsv *inf = shader_data;
       glUseProgram( _shader_ui_hsv.id );
-      glUniformMatrix3fv( glGetUniformLocation( _shader_ui_hsv.id, "uPv" ), 1, 
-                          GL_FALSE, (float *)vg_ui.pv );
+      glUniformMatrix3fv( glGetUniformLocation( _shader_ui_hsv.id, "uPv" ), 1, GL_FALSE, (float *)vg_ui.pv );
       glUniform1f( glGetUniformLocation(_shader_ui_hsv.id,"uHue"), inf->hue );
    }
    else
@@ -527,8 +533,8 @@ void vg_ui_init(void)
        total = sheet->w*sheet->h,
        data = 0;
 
-   vg_linear_clear( vg_mem.scratch );
-   u8 *image = vg_linear_alloc( vg_mem.scratch, total );
+   vg_stack_clear( &vg.scratch );
+   u8 *image = vg_stack_allocate( &vg.scratch, total, 8, NULL );
    
    while( pixels < total )
    {