--- /dev/null
+clang -fsanitize=address -O0 -I. -DVG_BUILD src/texsheet.c -o /tmp/tmpsr && /tmp/tmpsr $@
// Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved
+#ifdef VG_BUILD
+
+#include "vg.h"
+#include "vg_platform.h"
+#include "vg_log.h"
+#include "vg_opt.h"
+#include "vg_build.h"
+
+u32 optimize_test_compile = 0;
+
+/*
+ * Scripts
+ * -------------------------------------------------------------------------- */
+
+void s_build(void){
+ vg_info( "running script: s_build(void)\n" );
+
+ vg_build.optimization = optimize_test_compile;
+ vg_build.fresh = 0;
+ vg_build.platform = k_platform_linux;
+ vg_build.arch = k_architecture_x86_64;
+ vg_build.compiler = k_compiler_clang;
+ vg_build.libc = k_libc_version_native;
+
+ vg_build_new( "texsheet" );
+ vg_add_source( "src/texsheet.c" );
+ vg_compile( "texsheet" );
+
+ vg_success( "Completed 1/1\n" );
+}
+
+int main( int argc, char *argv[] ){
+ char *arg;
+ while( vg_argp( argc, argv ) ){
+ if( vg_long_opt( "native" ) )
+ s_build();
+
+ if( vg_opt('r') )
+ optimize_test_compile = 3;
+ }
+
+ if( vg_build.warnings )
+ vg_warn( "Finished with %u warnings\n", vg_build.warnings );
+ else
+ vg_success( "All scripts ran successfully\n" );
+}
+
+#else
+
#define VG_TOOLS
-#include "vg/vg.h"
+#include "vg.h"
#define STB_IMAGE_IMPLEMENTATION
-#include "stb/stb_image.h"
+#include "submodules/stb/stb_image.h"
+
+#define QOI_IMPLEMENTATION
+#include "submodules/qoi/qoi.h"
struct image_src
{
- int x,y,ch;
+ int x,y,ch;
- u8 *data;
+ u8 *data;
};
int image_sort( const void* a, const void* b)
{
- struct image_src *p_a = (struct image_src *)a;
- struct image_src *p_b = (struct image_src *)b;
-
- if( p_a->x == p_b->x )
- return 0;
- else if ( p_a->x < p_b->x )
- return 1;
- else
- return -1;
+ struct image_src *p_a = (struct image_src *)a;
+ struct image_src *p_b = (struct image_src *)b;
+
+ if( p_a->x == p_b->x )
+ return 0;
+ else if ( p_a->x < p_b->x )
+ return 1;
+ else
+ return -1;
}
int main( int argc, const char *argv[] )
{
- struct image_src *source_images = malloc( sizeof( struct image_src ) * argc );
-
- u32 num_images = 0;
-
- if( argc < 4 )
- {
- vg_error( "Missing output file paths\n" );
- return 0;
- }
-
- // Open header handle
- // ------------------
- FILE *fp = fopen( argv[2], "w" );
- if( !fp )
- {
- vg_error( "Could not open file for writing\n" );
- return 0;
- }
-
- fprintf( fp, "enum %s_index\n{\n", argv[3] );
-
- // Load images
- // -----------
- stbi_set_flip_vertically_on_load(1);
-
- for( int i = 4; i < argc; i ++ )
- {
- struct image_src *src = &source_images[ num_images ];
- src->data = (u8 *)stbi_load( argv[i], &src->x, &src->y, &src->ch, 4 );
-
- char name[ 256 ];
- int j = 0; int ext = 0;
- for( ; j < vg_list_size( name )-1; j ++ )
- {
- if( argv[i][j] )
- {
- name[j] = argv[i][j];
-
- if( name[j] == '.' )
- ext = j;
-
- if( name[j] == '.' || name[j] == '-' )
- name[j] = '_';
- }
- else
- break;
- }
-
- if( ext )
- name[ext] = 0x00;
- else
- name[j] = 0x00;
-
- fprintf( fp, "\tk_sprite_%s,\n", name );
-
- if( src->data )
- {
- if( src->x != src->y )
- {
- vg_error( "Non-square images are currently not supported ('%s')\n", argv[i] );
- free( src->data );
- }
- else
- num_images ++;
- }
- else
- vg_error( "Could not decode '%s'\n", argv[i] );
- }
-
- fprintf( fp, "};\n\n" );
-
- // Sort by size
- // ------------
- qsort( source_images, num_images, sizeof(struct image_src), image_sort );
-
- // Process images
- // --------------
- fprintf( fp, "static struct vg_sprite %s[] = \n{\n", argv[3] );
-
- u8 *dest = (u8 *)malloc( 1024*1024*4 );
-
- for( int i = 0; i < 1024*1024; i ++ )
- {
- dest[ i*4 + 0 ] = 0;
- dest[ i*4 + 1 ] = 0;
- dest[ i*4 + 2 ] = 0;
- dest[ i*4 + 3 ] = 0;
- }
-
- struct region
- {
- v2i p0;
- v2i p1;
- }
- region_stack[ 32 ] =
- {
- {
- .p0 = { 0, 0 },
- .p1 = { 1024, 1024 }
- }
- };
- int stack_h = 0;
-
- for( int i = 0; i < num_images; i ++ )
- {
- struct image_src *psrc = &source_images[ i ];
-
- // Region checks
- while( 1 )
- {
- struct region *pregion = ®ion_stack[ stack_h ];
-
- if( (pregion->p0[ 0 ] + psrc->x <= pregion->p1[0]) && (pregion->p0[ 1 ] + psrc->y <= pregion->p1[1]) )
- {
- // Passed, add image and create subdivisions
- fprintf( fp, "\t{{ %f, %f, %f, %f }}",
- (float)pregion->p0[0] / 1024.0f,
- (float)pregion->p0[1] / 1024.0f,
- (float)psrc->x / 1024.0f,
- (float)psrc->y / 1024.0f
- );
+ struct image_src *source_images = malloc( sizeof( struct image_src ) * argc );
+
+ u32 num_images = 0;
+
+ if( argc < 4 )
+ {
+ vg_info( "Usage: %s \\\n[output_image output_header name images...]\n",
+ argv[0] );
+ return 0;
+ }
+
+ // Open header handle
+ // ------------------
+ FILE *fp = fopen( argv[2], "w" );
+ if( !fp )
+ {
+ vg_error( "Could not open file for writing\n" );
+ return 0;
+ }
+
+ fprintf( fp, "enum %s_index\n{\n", argv[3] );
+
+ // Load images
+ // -----------
+ stbi_set_flip_vertically_on_load(1);
+
+ for( int i = 4; i < argc; i ++ )
+ {
+ struct image_src *src = &source_images[ num_images ];
+ src->data = (u8 *)stbi_load( argv[i], &src->x, &src->y, &src->ch, 4 );
+
+ char name[ 256 ];
+ int j = 0; int ext = 0;
+ for( ; j < vg_list_size( name )-1; j ++ )
+ {
+ if( argv[i][j] )
+ {
+ name[j] = argv[i][j];
+
+ if( name[j] == '.' )
+ ext = j;
+
+ if( name[j] == '.' || name[j] == '-' )
+ name[j] = '_';
+ }
+ else
+ break;
+ }
+
+ if( ext )
+ name[ext] = 0x00;
+ else
+ name[j] = 0x00;
+
+ fprintf( fp, "\tk_sprite_%s,\n", name );
+
+ if( src->data )
+ {
+ if( src->x != src->y )
+ {
+ vg_error( "Non-square images are currently not supported ('%s')\n", argv[i] );
+ free( src->data );
+ }
+ else
+ num_images ++;
+ }
+ else
+ vg_error( "Could not decode '%s'\n", argv[i] );
+ }
+
+ fprintf( fp, "};\n\n" );
+
+ // Sort by size
+ // ------------
+ qsort( source_images, num_images, sizeof(struct image_src), image_sort );
+
+ // Process images
+ // --------------
+ fprintf( fp, "static struct vg_sprite %s[] = \n{\n", argv[3] );
+
+ u8 *dest = (u8 *)malloc( 1024*1024*4 );
+
+ for( int i = 0; i < 1024*1024; i ++ )
+ {
+ dest[ i*4 + 0 ] = 0;
+ dest[ i*4 + 1 ] = 0;
+ dest[ i*4 + 2 ] = 0;
+ dest[ i*4 + 3 ] = 0;
+ }
+
+ struct region
+ {
+ v2i p0;
+ v2i p1;
+ }
+ region_stack[ 32 ] =
+ {
+ {
+ .p0 = { 0, 0 },
+ .p1 = { 1024, 1024 }
+ }
+ };
+ int stack_h = 0;
+
+ for( int i = 0; i < num_images; i ++ )
+ {
+ struct image_src *psrc = &source_images[ i ];
+
+ // Region checks
+ while( 1 )
+ {
+ struct region *pregion = ®ion_stack[ stack_h ];
+
+ if( (pregion->p0[ 0 ] + psrc->x <= pregion->p1[0]) && (pregion->p0[ 1 ] + psrc->y <= pregion->p1[1]) )
+ {
+ // Passed, add image and create subdivisions
+ fprintf( fp, "\t{{ %f, %f, %f, %f }}",
+ (float)pregion->p0[0] / 1024.0f,
+ (float)pregion->p0[1] / 1024.0f,
+ (float)psrc->x / 1024.0f,
+ (float)psrc->y / 1024.0f
+ );
if( i != num_images-1 )
fputs( ",\n", fp );
else
fputc( '\n', fp );
- // Write image
- for( int y = 0; y < psrc->y; y ++ )
- {
- int px = pregion->p0[0];
- int py = pregion->p0[1] + y;
-
- memcpy( &dest[ (py*1024+px) * 4 ], &psrc->data[ y*psrc->x*4 ], psrc->x*4 );
- }
-
- // Subdivisions
- stack_h ++;
- struct region *new_region = ®ion_stack[ stack_h ];
-
- new_region->p0[0] = pregion->p0[0] + psrc->x;
- new_region->p0[1] = pregion->p0[1];
- new_region->p1[0] = pregion->p1[0];
- new_region->p1[1] = pregion->p0[1] + psrc->y;
-
- pregion->p0[ 1 ] += psrc->y;
- break;
- }
- else
- {
- // Failed, loop up to next region if can
- if( stack_h == 0 )
- {
- vg_error( "Could not fit image %d. Pack failed\n", i );
-
- goto IL_END_ERR;
- }
- else
- stack_h --;
- }
- }
- }
+ // Write image
+ for( int y = 0; y < psrc->y; y ++ )
+ {
+ int px = pregion->p0[0];
+ int py = pregion->p0[1] + y;
+
+ memcpy( &dest[ (py*1024+px) * 4 ], &psrc->data[ y*psrc->x*4 ], psrc->x*4 );
+ }
+
+ // Subdivisions
+ stack_h ++;
+ struct region *new_region = ®ion_stack[ stack_h ];
+
+ new_region->p0[0] = pregion->p0[0] + psrc->x;
+ new_region->p0[1] = pregion->p0[1];
+ new_region->p1[0] = pregion->p1[0];
+ new_region->p1[1] = pregion->p0[1] + psrc->y;
+
+ pregion->p0[ 1 ] += psrc->y;
+ break;
+ }
+ else
+ {
+ // Failed, loop up to next region if can
+ if( stack_h == 0 )
+ {
+ vg_error( "Could not fit image %d. Pack failed\n", i );
+
+ goto IL_END_ERR;
+ }
+ else
+ stack_h --;
+ }
+ }
+ }
IL_END_ERR:
- fprintf( fp, "};" );
- fclose( fp );
-
- // Write output
- // ------------
- qoi_write( argv[1], dest, &(qoi_desc){
- .width = 1024,
- .height = 1024,
- .channels = 4,
- .colorspace = QOI_SRGB
- });
-
- // Free
- // ----
- for( int i = 0; i < num_images; i ++ )
- free( source_images[ i ].data );
- free( dest );
- free( source_images );
-
- vg_success( "Processed %u images\n", num_images );
+ fprintf( fp, "};" );
+ fclose( fp );
+
+ // Write output
+ // ------------
+ qoi_write( argv[1], dest, &(qoi_desc){
+ .width = 1024,
+ .height = 1024,
+ .channels = 4,
+ .colorspace = QOI_SRGB
+ });
+
+ // Free
+ // ----
+ for( int i = 0; i < num_images; i ++ )
+ free( source_images[ i ].data );
+ free( dest );
+ free( source_images );
+
+ vg_success( "Processed %u images\n", num_images );
}
+
+#endif
static void vg_render(void);
static void vg_gui(void);
+enum quality_profile{
+ k_quality_profile_high = 0,
+ k_quality_profile_low = 1,
+ k_quality_profile_min = 2
+};
+
struct vg{
/* Engine sync */
SDL_Window *window;
int display_refresh_rate,
fps_limit,
- vsync;
+ vsync,
+ screen_mode,
+ display_index;
+
+ int settings_open;
enum vsync_feature{
k_vsync_feature_disabled=0,
}
vsync_feature;
- double mouse_pos[2];
+ i32 mouse_pos[2];
v2f mouse_delta,
mouse_wheel;
engine_stage;
/* graphics */
+#ifdef VG_3D
m4x4f pv;
- enum quality_profile{
- k_quality_profile_high = 0,
- k_quality_profile_low = 1,
- }
- quality_profile;
+#else
+ m3x3f pv;
+#endif
+
+ i32 quality_profile;
float loader_ring;
GLuint tex_missing;
#include "vg_lines.h"
#include "vg_loader.h"
#include "vg_opt.h"
+#include "vg_settings_menu.h"
/* Diagnostic */
static struct vg_profile vg_prof_update = {.name="update()"},
}
}
- vg.mouse_pos[0] += vg.mouse_delta[0];
- vg.mouse_pos[1] += vg.mouse_delta[1];
+ SDL_GetMouseState( &vg.mouse_pos[0], &vg.mouse_pos[1] );
}
static void _vg_gameloop_update(void)
}
else vg_gui();
+ if( vg.settings_open )
+ vg_settings_gui();
+
/* vg tools */
#ifndef VG_NO_AUDIO
audio_debug_ui( vg.pv );
#endif
/* profiling */
- int frame_target = vg.display_refresh_rate;
- if( vg.fps_limit > 0 ) frame_target = vg.fps_limit;
- vg_profile_drawn(
- (struct vg_profile *[]){
- &vg_prof_update,&vg_prof_render,&vg_prof_swap}, 3,
- (1.0f/(float)frame_target)*1000.0f,
- (ui_rect){ 4, 4, 250, 0 }, 0
- );
if( vg_profiler ){
+ int frame_target = vg.display_refresh_rate;
+ if( vg.fps_limit > 0 ) frame_target = vg.fps_limit;
+ vg_profile_drawn(
+ (struct vg_profile *[]){
+ &vg_prof_update,&vg_prof_render,&vg_prof_swap}, 3,
+ (1.0f/(float)frame_target)*1000.0f,
+ (ui_rect){ 4, 4, 250, 0 }, 0, 0
+ );
char perf[256];
snprintf( perf, 255,
vg_profile_end( &vg_prof_render );
}
+static void aaaaaaaaaaaaaaaaa( ui_rect r ){
+ int frame_target = vg.display_refresh_rate;
+ if( !vg.vsync ) frame_target = vg.fps_limit;
+
+ vg_profile_drawn(
+ (struct vg_profile *[]){
+ &vg_prof_update,&vg_prof_render,&vg_prof_swap}, 3,
+ (1.0f/(f32)frame_target)*1500.0f,
+ r, 0, 1
+ );
+
+ ui_fill( (ui_rect){ r[0], r[1] + (r[3]*2)/3, r[2], 1 }, ui_colour(k_ui_fg) );
+}
+
static void vg_changevsync(void){
if( vg.vsync && (vg.vsync_feature != k_vsync_feature_error) ){
/* turn on vsync if not enabled */
}
static int vg_framefilter( double dt ){
- if( vg.fps_limit < 25 ) vg.fps_limit = 25;
+ if( vg.fps_limit < 24 ) vg.fps_limit = 24;
if( vg.fps_limit > 300 ) vg.fps_limit = 300;
double min_frametime = 1.0/(double)vg.fps_limit;
vg.window_y = video_mode.h;
#ifdef VG_DEVWINDOW
- vg.window_x = 1200;
- vg.window_y = 880;
+ vg.window_x = 1280;
+ vg.window_y = 720;
#endif
#ifndef _WIN32
SDL_WINDOW_BORDERLESS|SDL_WINDOW_OPENGL|SDL_WINDOW_INPUT_GRABBED
))){
SDL_SetWindowPosition( vg.window, video_mode.w-vg.window_x, 0 );
+ vg.screen_mode = 2;
}
#else
0, 0,
SDL_WINDOW_FULLSCREEN_DESKTOP |
SDL_WINDOW_OPENGL |
- SDL_WINDOW_INPUT_GRABBED
+ SDL_WINDOW_INPUT_GRABBED |
+ SDL_WINDOW_RESIZABLE
)))
{
if( SDL_SetWindowDisplayMode( vg.window, &video_mode ) ){
}
SDL_RaiseWindow( vg.window );
+ SDL_SetWindowMinimumSize( vg.window, 1280, 720 );
+ SDL_SetWindowMaximumSize( vg.window, 4096, 4096 );
vg_info( "CreateContext\n" );
vg_console_reg_var( "fps_limit", &vg.fps_limit, k_var_dtype_i32, 0 );
vg_console_reg_var( "vsync", &vg.vsync, k_var_dtype_i32, VG_VAR_PERSISTENT );
+ vg_console_reg_cmd( "vg_settings", cmd_vg_settings_toggle, NULL );
_vg_init_window( window_name );
vg_async_init();
* Debugging
*/
-static void audio_debug_ui( m4x4f mtx_pv )
-{
+static void audio_debug_ui(
+
+#ifdef VG_3D
+ m4x4f
+#else
+ m3x3f
+#endif
+ mtx_pv ){
+
if( !vg_audio.debug_ui )
return;
&vg_prof_audio_mix,
&vg_prof_audio_dsp}, 3,
budget, (ui_rect){ 4, VG_PROFILE_SAMPLE_COUNT*2 + 8,
- 512, 0 }, 3 );
+ 512, 0 }, 3, 0 );
char perf[128];
ui_fill( row, 0xa0000000 | ch->colour );
ui_text( row, perf, 1, k_ui_align_middle_left, 0 );
+#ifdef VG_3D
if( AUDIO_FLAG_SPACIAL_3D ){
v4f wpos;
v3_copy( ch->editable_state.spacial_falloff, wpos );
rect_copy( wr, overlap_buffer[ overlap_length ++ ] );
}
}
+#endif
}
audio_unlock();
#define VG_GAME
#include "vg/vg.h"
+//#define VG_ECHO_LPF_BUTTERWORTH
+
static struct vg_dsp{
float *buffer;
u32 allocations;
/* temporary global design */
static struct dsp_lpf __lpf_mud_free;
static struct dsp_delay __echos[8];
+
+#ifdef VG_ECHO_LPF_BUTTERWORTH
+static struct dsp_biquad __echos_lpf[8];
+#else
static struct dsp_lpf __echos_lpf[8];
+#endif
static struct dsp_schroeder __diffusion_chain[8];
static void async_vg_dsp_alloc_texture( void *payload, u32 size )
dsp_init_delay( &__echos[i], total / 1000.0f );
float freq = vg_lerpf( 800.0f, 350.0f, sizes[i] / 256.0f );
+
+#ifdef VG_ECHO_LPF_BUTTERWORTH
+ dsp_init_biquad_butterworth_lpf( &__echos_lpf[i], freq );
+#else
dsp_init_lpf( &__echos_lpf[i], freq );
+#endif
}
float diffusions[] = { 187.0f, 159.0f, 143.0f, 121.0f,
float recieved = 0.0f;
for( int i=0; i<8; i++ ){
- float echo;
+ f32 echo;
dsp_read_delay( __echos+i, &echo, 1 );
+
+#ifdef VG_ECHO_LPF_BUTTERWORTH
+ echo = dsp_biquad_process( __echos_lpf+i, echo );
+#else
dsp_write_lpf( __echos_lpf+i, &echo );
dsp_read_lpf( __echos_lpf+i, &echo );
+#endif
recieved += echo * vg_dsp.echo_tunings[i]*0.98;
}
for( int i=0; i<8; i++ ){
float freq = vg_lerpf( 200.0f, 500.0f, vg_dsp.echo_tunings[i] );
+
+#ifdef VG_ECHO_LPF_BUTTERWORTH
+ dsp_init_biquad_butterworth_lpf( &__echos_lpf[i], freq );
+#else
dsp_update_lpf( &__echos_lpf[i], freq );
+#endif
}
for( int i=0;i<8; i++ ){
{ "sampler2D", "int i", "glUniform1i(%s,i);" },
{ "samplerCube", "int i", "glUniform1i(%s,i);" },
+ { "mat2", "m2x2f m", "glUniformMatrix2fv(%s,1,GL_FALSE,(float*)m);" },
{ "mat4x3", "m4x3f m", "glUniformMatrix4x3fv(%s,1,GL_FALSE,(float*)m);" },
{ "mat3", "m3x3f m", "glUniformMatrix3fv(%s,1,GL_FALSE,(float*)m);" },
{ "mat4", "m4x4f m", "glUniformMatrix4fv(%s,1,GL_FALSE,(float*)m);" },
}
}
+static void _ui_textbox_change_callback(void){
+ if( vg_ui.textbox.callbacks.change ){
+ vg_ui.textbox.callbacks.change( vg_ui.textbuf, vg_ui.textbox.len );
+
+ /* we gave permission to modify the buffer in this callback so.. */
+ int len = strlen( vg_ui.textbuf );
+ vg_ui.textbox.cursor_user = VG_MIN( vg_ui.textbox.cursor_user, len );
+ vg_ui.textbox.cursor_pos = VG_MIN( vg_ui.textbox.cursor_pos, len );
+ }
+}
+
static void ui_start_modal( const char *message, u32 options );
static void _ui_textbox_clipboard_paste(void){
if( !SDL_HasClipboardText() )
_ui_textbox_move_cursor( &vg_ui.textbox.cursor_user,
&vg_ui.textbox.cursor_pos, cpylength, 1 );
SDL_free( text );
+ _ui_textbox_change_callback();
}
static void _ui_textbox_put_char( char c ){
if( vg_ui.focused_control_type == k_ui_control_textbox ){
vg_ui.textbox.cursor_user = _ui_textbox_delete_char( -1 );
vg_ui.textbox.cursor_pos = vg_ui.textbox.cursor_user;
-
- if( vg_ui.textbox.callbacks.change ){
- vg_ui.textbox.callbacks.change( vg_ui.textbuf, vg_ui.textbox.len );
- }
+ _ui_textbox_change_callback();
}
}
if( vg_ui.focused_control_type == k_ui_control_textbox ){
vg_ui.textbox.cursor_user = _ui_textbox_delete_char( 1 );
vg_ui.textbox.cursor_pos = vg_ui.textbox.cursor_user;
-
- if( vg_ui.textbox.callbacks.change ){
- vg_ui.textbox.callbacks.change( vg_ui.textbuf, vg_ui.textbox.len );
- }
+ _ui_textbox_change_callback();
}
}
_ui_textbox_to_clipboard();
vg_ui.textbox.cursor_user = _ui_textbox_delete_char(0);
vg_ui.textbox.cursor_pos = vg_ui.textbox.cursor_user;
+ _ui_textbox_change_callback();
}
static void _ui_textbox_enter(void){
if( vg_ui.focused_control_type != k_ui_control_textbox ) return;
- if( vg_ui.textbox.flags & UI_TEXTBOX_MULTILINE )
+ if( vg_ui.textbox.flags & UI_TEXTBOX_MULTILINE ){
_ui_textbox_put_char( '\n' );
+ _ui_textbox_change_callback();
+ }
else{
if( !(vg_ui.textbox.flags & UI_TEXTBOX_AUTOFOCUS ) )
ui_defocus_all();
ptr ++;
}
- if( vg_ui.textbox.callbacks.change ){
- vg_ui.textbox.callbacks.change( vg_ui.textbuf, vg_ui.textbox.len );
- }
+ _ui_textbox_change_callback();
}
}
}
/* read entire binary file */
-static void *vg_file_read( void *lin_alloc, const char *path, u32 *size )
-{
+static void *vg_file_read( void *lin_alloc, const char *path, u32 *size ){
FILE *f = fopen( path, "rb" );
if( f ){
- void *buffer = vg_linear_alloc( lin_alloc, 0 );
+ void *buffer = lin_alloc? vg_linear_alloc( lin_alloc, 0 ):
+ NULL;
u64 current = 0;
/* read in chunks */
for( u32 i=0; 1; i++ ){
- buffer = vg_linear_extend( lin_alloc, buffer, VG_FILE_IO_CHUNK_SIZE );
+ 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 );
u64 l = fread( buffer + current, 1, VG_FILE_IO_CHUNK_SIZE, f );
current += l;
}
}
- buffer = vg_linear_resize( lin_alloc, buffer, vg_align8(current) );
+ if( lin_alloc )
+ buffer = vg_linear_resize( lin_alloc, buffer, vg_align8(current) );
+ else
+ buffer = realloc( buffer, vg_align8(current) );
+
fclose( f );
*size = (u32)current;
return buffer;
}
else{
- vg_error( "vg_disk_open_read: %s\n", strerror(errno) );
+ 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 */
-static char *vg_file_read_text( void *lin_alloc, const char *path, u32 *sz )
-{
+static char *vg_file_read_text( void *lin_alloc, const char *path, u32 *sz ){
u32 size;
char *str = vg_file_read( lin_alloc, path, &size );
return NULL;
/* include null terminator */
- str = vg_linear_extend( lin_alloc, str, 1 );
+ if( lin_alloc )
+ str = vg_linear_extend( lin_alloc, str, 1 );
+ else
+ str = realloc( str, size+1 );
+
str[ size ] = '\0';
*sz = size+1;
}
static void vg_profile_drawn( struct vg_profile **profiles, u32 count,
- float budget, ui_rect panel, u32 colour_offset )
+ float budget, ui_rect panel, u32 colour_offset,
+ int dir )
{
- if( !vg_profiler )
- return;
-
if( panel[2] == 0 )
panel[2] = 256;
if( panel[3] == 0 )
panel[3] = VG_PROFILE_SAMPLE_COUNT * 2;
- float sh = panel[3] / VG_PROFILE_SAMPLE_COUNT,
- sw = panel[2];
+ f32 sh = (f32)panel[3^dir] / (f32)VG_PROFILE_SAMPLE_COUNT,
+ sw = (f32)panel[2^dir];
ui_fill( panel, 0xa0000000 );
assert( count <= 8 );
- double avgs[8];
- int ptrs[8];
+ f64 avgs[8];
+ int ptrs[8];
for( int i=0; i<count; i++ ){
ptrs[i] = profiles[i]->buffer_current;
u32 colours[] = { 0xff0000ff, 0xff00ff00, 0xff00ffff, 0xffff0000,
0xffff00ff, 0xffffff00 };
- double rate_mul = 1000.0 / (double)SDL_GetPerformanceFrequency();
+ f64 rate_mul = 1000.0 / (f64)SDL_GetPerformanceFrequency();
for( int i=0; i<VG_PROFILE_SAMPLE_COUNT-1; i++ ){
- double total = 0.0;
+ f64 total = 0.0;
for( int j=0; j<count; j++ ){
ptrs[j] --;
if( ptrs[j] < 0 )
ptrs[j] = VG_PROFILE_SAMPLE_COUNT-1;
- double sample = (double)profiles[j]->samples[ptrs[j]] * rate_mul,
- px = (total / (budget)) * sw,
- wx = (sample / (budget)) * sw;
+ f64 sample = (f64)profiles[j]->samples[ptrs[j]] * rate_mul,
+ px = (total / (budget)) * sw,
+ wx = (sample / (budget)) * sw;
- ui_rect block = { panel[0] + px, panel[1] + (float)i*sh,
- wx, sh };
+ ui_rect block;
+ block[0^dir] = panel[0^dir] + px;
+ block[1^dir] = panel[1^dir] + (f32)i*sh;
+ block[2^dir] = wx;
+ block[3^dir] = ceilf(sh)-1;
u32 colour = colours[ (j+colour_offset) % vg_list_size(colours) ];
ui_fill( block, colour );
snprintf( infbuf, 64, "accuracy: %.7fms", rate_mul );
ui_text( (ui_rect){ panel[0] + 4,
- panel[1] + 0 * 14, 500, 30 },
+ panel[1] + panel[3] - 14, 500, 30 },
infbuf,
1,
k_ui_align_left, 0 );
--- /dev/null
+#ifndef VG_SETTINGS_MENU_H
+#define VG_SETTINGS_MENU_H
+
+#include "vg.h"
+#include "vg_imgui.h"
+
+struct ui_enum_opt vg_settings_vsync_enum[] = {
+ { 0, "None" },
+ { 1, "On" },
+ {-1, "Adaptive" },
+};
+
+struct ui_enum_opt vg_settings_quality_enum[] = {
+ { 0, "High Quality" },
+ { 1, "Faster" },
+ { 2, "Absolute Minimum" },
+};
+
+struct ui_enum_opt vg_settings_screen_mode_enum[] = {
+ { 0, "Fullscreen (desktop)" },
+ { 1, "Fullscreen (native)" },
+ { 2, "Floating Window" }
+};
+
+struct {
+ struct vg_setting_ranged_i32{
+ i32 new_value, *actual_value, min, max;
+ char buf[10];
+ const char *label;
+ }
+ fps_limit;
+
+ struct vg_setting_enum{
+ i32 new_value, *actual_value;
+
+ struct ui_enum_opt *options;
+ u32 option_count;
+ const char *label;
+ }
+ vsync, quality, screenmode;
+
+ int windowed_before[4];
+}
+static vg_settings = {
+ .fps_limit = { .label = "Fps Limit",
+ .min=24, .max=300, .actual_value = &vg.fps_limit },
+ .vsync = { .label = "Vsync",
+ .actual_value = &vg.vsync,
+ .options = vg_settings_vsync_enum, .option_count = 3 },
+ .quality = { .label = "Graphic Quality",
+ .actual_value = &vg.quality_profile,
+ .options = vg_settings_quality_enum, .option_count = 3 },
+ .screenmode = { .label = "Type",
+ .actual_value = &vg.screen_mode,
+ .options = vg_settings_screen_mode_enum, .option_count=3 }
+
+};
+
+static void vg_settings_ui_draw_diff( ui_rect orig ){
+ ui_rect l,r;
+ ui_split( orig, k_ui_axis_v, -32, 0, l, r );
+ ui_text( r, "*", 1, k_ui_align_middle_center, ui_colour(k_ui_blue) );
+}
+
+/* i32 settings
+ * ------------------------------------------------------------------------- */
+
+static void vg_settings_ui_int( char *buf, u32 len ){
+ for( u32 i=0, j=0; i<len; i ++ ){
+ if( ((buf[i] >= '0') && (buf[i] <= '9')) || (buf[i] == '\0') )
+ buf[j ++] = buf[i];
+ }
+}
+
+struct ui_textbox_callbacks static vg_settings_ui_int_callbacks = {
+ .change = vg_settings_ui_int
+};
+
+static bool vg_settings_ranged_i32_valid( struct vg_setting_ranged_i32 *prop ){
+ if( prop->new_value < prop->min ) return 0;
+ if( prop->new_value > prop->max ) return 0;
+ return 1;
+}
+
+static bool vg_settings_ranged_i32_diff( struct vg_setting_ranged_i32 *prop ){
+ if( prop->new_value != *prop->actual_value ) return 1;
+ else return 0;
+}
+
+static bool vg_settings_ui_ranged_i32( struct vg_setting_ranged_i32 *prop,
+ ui_rect rect ){
+ ui_rect orig;
+ rect_copy( rect, orig );
+
+ ui_textbox( rect, prop->label, prop->buf, sizeof(prop->buf),
+ 1, 0, &vg_settings_ui_int_callbacks );
+ prop->new_value = atoi( prop->buf );
+
+ if( vg_settings_ranged_i32_diff( prop ) )
+ vg_settings_ui_draw_diff( orig );
+
+ bool valid = vg_settings_ranged_i32_valid( prop );
+ if( !valid ){
+ ui_rect _null, line;
+ ui_split( orig, k_ui_axis_h, -1, 0, _null, line );
+ line[1] += 3;
+
+ ui_fill( line, ui_colour( k_ui_red ) );
+ }
+
+ return valid;
+}
+
+static void ui_settings_ranged_i32_init( struct vg_setting_ranged_i32 *prop ){
+ vg_str tmp;
+ vg_strnull( &tmp, prop->buf, sizeof(prop->buf) );
+ vg_strcati32( &tmp, *prop->actual_value );
+ prop->new_value = *prop->actual_value;
+}
+
+/* enum settings
+ * ------------------------------------------------------------------------- */
+
+static bool vg_settings_enum_diff( struct vg_setting_enum *prop ){
+ if( prop->new_value != *prop->actual_value ) return 1;
+ else return 0;
+}
+
+static bool vg_settings_enum( struct vg_setting_enum *prop, ui_rect rect ){
+ ui_rect orig;
+ rect_copy( rect, orig );
+
+ ui_enum( rect, prop->label,
+ prop->options, prop->option_count, &prop->new_value );
+
+ if( vg_settings_enum_diff( prop ) )
+ vg_settings_ui_draw_diff( orig );
+
+ return 1;
+}
+
+static void ui_settings_enum_init( struct vg_setting_enum *prop ){
+ prop->new_value = *prop->actual_value;
+}
+
+/* .. */
+
+static void vg_settings_ui_header( ui_rect inout_panel, const char *name ){
+ ui_rect rect;
+ ui_standard_widget( inout_panel, rect, 2 );
+ ui_text( rect, name, 1, k_ui_align_middle_center, ui_colour(k_ui_fg+3) );
+}
+
+static void vg_settings_video_apply(void){
+ if( vg_settings_enum_diff( &vg_settings.screenmode ) ){
+ vg.screen_mode = vg_settings.screenmode.new_value;
+
+ if( (vg.screen_mode == 0) || (vg.screen_mode == 1) ){
+ SDL_GetWindowPosition( vg.window,
+ &vg_settings.windowed_before[0],
+ &vg_settings.windowed_before[1] );
+ vg_settings.windowed_before[2] = vg.window_x;
+ vg_settings.windowed_before[3] = vg.window_y;
+
+ SDL_DisplayMode video_mode;
+ if( SDL_GetDesktopDisplayMode( 0, &video_mode ) ){
+ vg_error("SDL_GetDesktopDisplayMode failed: %s\n", SDL_GetError());
+ }
+ else {
+ //vg.display_refresh_rate = video_mode.refresh_rate;
+ vg.window_x = video_mode.w;
+ vg.window_y = video_mode.h;
+ }
+ SDL_SetWindowResizable( vg.window, SDL_FALSE );
+ SDL_SetWindowSize( vg.window, vg.window_x, vg.window_y );
+ }
+
+ if( vg.screen_mode == 0 )
+ SDL_SetWindowFullscreen( vg.window, SDL_WINDOW_FULLSCREEN_DESKTOP );
+ if( vg.screen_mode == 1 )
+ SDL_SetWindowFullscreen( vg.window, SDL_WINDOW_FULLSCREEN );
+ if( vg.screen_mode == 2 ){
+ SDL_SetWindowFullscreen( vg.window, 0 );
+ SDL_SetWindowSize( vg.window,
+ vg_settings.windowed_before[2],
+ vg_settings.windowed_before[3] );
+ SDL_SetWindowPosition( vg.window,
+ vg_settings.windowed_before[0],
+ vg_settings.windowed_before[1] );
+ SDL_SetWindowResizable( vg.window, SDL_TRUE );
+ }
+ }
+
+ vg.fps_limit = vg_settings.fps_limit.new_value;
+ vg.quality_profile = vg_settings.quality.new_value;
+ vg.vsync = vg_settings.vsync.new_value;
+}
+
+static void aaaaaaaaaaaaaaaaa( ui_rect r );
+static void vg_settings_video_gui( ui_rect panel ){
+ bool validated = 1;
+ ui_rect rq;
+ ui_standard_widget( panel, rq, 1 );
+ vg_settings_enum( &vg_settings.quality, rq );
+
+ /* FIXME */
+#if 0
+ if( vg.vsync_feature == k_vsync_feature_error ){
+ ui_info( panel, "There was an error activating vsync feature." );
+ }
+#endif
+
+ /* frame timing */
+ vg_settings_ui_header( panel, "Frame Timing" );
+ ui_rect duo, d0,d1;
+ ui_standard_widget( panel, duo, 1 );
+ ui_split_ratio( duo, k_ui_axis_v, 0.5f, 16, d0, d1 );
+
+ vg_settings_enum( &vg_settings.vsync, d0 );
+ validated &= vg_settings_ui_ranged_i32( &vg_settings.fps_limit, d1 );
+
+ ui_standard_widget( panel, duo, 10 );
+ aaaaaaaaaaaaaaaaa( duo );
+
+ /* window spec */
+ vg_settings_ui_header( panel, "Window Specification" );
+
+ ui_standard_widget( panel, duo, 1 );
+ vg_settings_enum( &vg_settings.screenmode, duo );
+
+ /* apply */
+ ui_rect last_row;
+ ui_px height = (vg_ui.font->glyph_height + 18) * k_ui_scale;
+ ui_split( panel, k_ui_axis_h, -height, k_ui_padding,
+ panel, last_row );
+
+ const char *string = "Apply";
+ if( validated ){
+ if( ui_button( last_row, string ) == 1 )
+ vg_settings_video_apply();
+ }
+ else{
+ ui_rect rect;
+ ui_standard_widget( last_row, rect, 1 );
+ ui_fill( rect, ui_colour( k_ui_bg+1 ) );
+ ui_outline( rect, -1, ui_colour( k_ui_red ), 0 );
+
+ ui_rect t = { 0,0, ui_text_line_width( string ), 14 };
+ ui_rect_center( rect, t );
+ ui_text( t, string, 1, k_ui_align_left, ui_colour(k_ui_fg+3) );
+ }
+}
+
+static void vg_settings_gui(void){
+ ui_rect null;
+ ui_rect screen = { 0, 0, vg.window_x, vg.window_y };
+ ui_rect window = { 0, 0, 1000, 700 };
+ ui_rect_center( screen, window );
+ vg_ui.wants_mouse = 1;
+
+ ui_fill( window, ui_colour( k_ui_bg+1 ) );
+ ui_outline( window, 1, ui_colour( k_ui_bg+7 ), 0 );
+
+ ui_rect title, panel;
+ ui_split( window, k_ui_axis_h, 28, 0, title, panel );
+ ui_fill( title, ui_colour( k_ui_bg+7 ) );
+ ui_text( title, "Settings", 1, k_ui_align_middle_center,
+ ui_colourcont(k_ui_bg+7) );
+
+ ui_rect quit_button;
+ ui_split( title, k_ui_axis_v, title[2]-title[3], 2, title, quit_button );
+
+ if( ui_button_text( quit_button, "X", 1 ) == 1 ){
+ vg.settings_open = 0;
+ return;
+ }
+
+ ui_rect_pad( panel, (ui_px[2]){ 8, 8 } );
+
+ static i32 page = 0;
+ ui_tabs( panel, panel, (const char *[]){ "video", "audio", "game" },
+ 3, &page );
+
+ if( page == 0 ){
+ vg_settings_video_gui( panel );
+ }
+}
+
+static int cmd_vg_settings_toggle( int argc, const char *argv[] ){
+ vg.settings_open = !vg.settings_open;
+
+ if( vg.settings_open ){
+ ui_settings_ranged_i32_init( &vg_settings.fps_limit );
+ ui_settings_enum_init( &vg_settings.vsync );
+ ui_settings_enum_init( &vg_settings.quality );
+ ui_settings_enum_init( &vg_settings.screenmode );
+ }
+ return 0;
+}
+
+#endif /* VG_SETTINGS_MENU_H */
static
void vg_tex2d_load_qoi_async_file( const char *path, u32 flags, GLuint *dest )
{
+ if( vg_thread_purpose() != k_thread_purpose_loader )
+ vg_fatal_error( "wrong thread\n" );
+
vg_linear_clear( vg_mem.scratch );
u32 size;