From 367883958336d1c04c8a304af6119b21f0f2f15a Mon Sep 17 00:00:00 2001 From: hgn Date: Sat, 8 Oct 2022 07:18:16 +0100 Subject: [PATCH] Platform and OS stability stuff --- src/vg/vg.h | 111 +++++++++++++++++++------ src/vg/vg_loader.h | 83 ++++++++++++++++--- src/vg/vg_opt.h | 189 +++++++++++++++++++++++++++++++++++++++++++ src/vg/vg_platform.h | 152 ++++++++++++++++++++++------------ 4 files changed, 450 insertions(+), 85 deletions(-) create mode 100644 src/vg/vg_opt.h diff --git a/src/vg/vg.h b/src/vg/vg.h index e6f4001..f3ed699 100644 --- a/src/vg/vg.h +++ b/src/vg/vg.h @@ -12,6 +12,13 @@ #ifndef VG_SERVER #include "../../dep/glad/glad.h" + +#define GLFW_INCLUDE_GLCOREARB + +#ifdef _WIN32 + #define GLFW_DLL +#endif + #include "../../dep/glfw/glfw3.h" #endif @@ -36,13 +43,9 @@ void vg_register_exit( void( *funcptr )(void), const char *name ); m4x4f vg_pv; -#ifdef VG_CAPTURE_MODE -int vg_window_x = 1920; -int vg_window_y = 1080; -#else -int vg_window_x = 1366; -int vg_window_y = 768; -#endif +int vg_window_x = 0; +int vg_window_y = 0; +int vg_samples = 0; v2f vg_mouse; v2f vg_mouse_wheel; @@ -248,6 +251,7 @@ static void vg_checkgl( const char *src_info ); #include "vg_lines.h" #include "vg_debug.h" #include "vg_loader.h" +#include "vg_opt.h" #define VG_GAMELOOP static void vg_register(void) VG_GAMELOOP; @@ -286,6 +290,12 @@ void vg_scroll_callback( GLFWwindow* ptrW, double xoffset, double yoffset ) void vg_framebuffer_resize_callback( GLFWwindow *ptrW, int w, int h ) { + if( !w || !h ) + { + vg_warn( "Got a invalid framebuffer size: %dx%d... ignoring\n", w, h ); + return; + } + vg_window_x = w; vg_window_y = h; @@ -331,6 +341,25 @@ static void vg_load_full(void) static void vg_enter( int argc, char *argv[], const char *window_name ) { + char *arg; + while( vg_argp( argc, argv ) ) + { + if( (arg = vg_opt_arg( 'w' )) ) + { + vg_window_x = atoi( arg ); + } + + if( (arg = vg_opt_arg( 'h' )) ) + { + vg_window_y = atoi( arg ); + } + + if( (arg = vg_long_opt_arg( "samples" )) ) + { + vg_samples = VG_MAX( 0, VG_MIN( 8, atoi( arg ) ) ); + } + } + vg_log_init(); vg_console_init(); @@ -339,13 +368,12 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 ); glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE ); glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE ); + glfwWindowHint( GLFW_CONTEXT_RELEASE_BEHAVIOR, GLFW_RELEASE_BEHAVIOR_FLUSH ); - glfwWindowHint( GLFW_RESIZABLE, GLFW_TRUE ); + glfwWindowHint( GLFW_RESIZABLE, GLFW_FALSE ); glfwWindowHint( GLFW_DOUBLEBUFFER, GLFW_TRUE ); -#if 0 - glfwWindowHint(GLFW_SAMPLES,4); -#endif + glfwWindowHint( GLFW_SAMPLES, vg_samples ); GLFWmonitor *monitor_primary = glfwGetPrimaryMonitor(); @@ -353,20 +381,48 @@ static void vg_enter( int argc, char *argv[], const char *window_name ) glfwWindowHint( GLFW_RED_BITS, mode->redBits ); glfwWindowHint( GLFW_GREEN_BITS, mode->greenBits ); glfwWindowHint( GLFW_BLUE_BITS, mode->blueBits ); - - /* This is set like this because of an OS issue */ - int refresh_rate = mode->refreshRate; - if( refresh_rate < 28 || refresh_rate >= 144 ) - refresh_rate = 60; - glfwWindowHint( GLFW_REFRESH_RATE, refresh_rate ); - - if( !(vg.window = glfwCreateWindow( vg_window_x, vg_window_y, - window_name, NULL, NULL)) ) + + /* TODO? */ + glfwWindowHint( GLFW_REFRESH_RATE, 60 ); + + if( !vg_window_x ) + vg_window_x = mode->width; + + if( !vg_window_y ) + vg_window_y = mode->height; + + + if( (vg.window = glfwCreateWindow( vg_window_x, vg_window_y, + window_name, monitor_primary, NULL)) ) + { + glfwGetFramebufferSize( vg.window, &vg_window_x, &vg_window_y ); + vg_success( "Window created (%dx%d)\n", vg_window_x, vg_window_y ); + } + else { vg_error( "GLFW Failed to initialize\n" ); return; } + /* We need 3.1.2 for correct VSync on windows */ + { + int vmaj, vmin, vrev; + glfwGetVersion( &vmaj, &vmin, &vrev ); + + if( vmaj < 3 || + (vmaj == 3 && vmin < 1) || + (vmaj == 3 && vmin == 1 && vrev < 2 ) ) + { + vg_error( "GLFW out of date (%d.%d.%d); (3.1.2 is required)\n", + vmaj, vmin, vrev ); + + glfwTerminate(); + return; + } + + vg_success( "GLFW Version %d.%d.%d\n", vmaj, vmin, vrev ); + } + glfwMakeContextCurrent( vg.window ); glfwSwapInterval( 1 ); @@ -549,11 +605,10 @@ static void vg_fatal_exit_loop( const char *error ) glfwPollEvents(); - vg_time = glfwGetTime(); - vg_time_delta = vg_minf( vg_time - vg_time_last, 0.1f ); - - glClearColor( sinf(vg_time*20.0)*0.5f+0.5f, 0.0f, 0.0f,1.0f ); + glClearColor( 0.15f + sinf(glfwGetTime())*0.1f, 0.0f, 0.0f,1.0f ); glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); + glViewport( 0,0, vg_window_x, vg_window_y ); + vg_render_log(); glfwSwapBuffers( vg.window ); @@ -568,6 +623,14 @@ static void vg_fatal_exit_loop( const char *error ) } } +#else + +static void vg_fatal_exit_loop( const char *error ) +{ + vg_error( "Fatal error: %s\n", error ); + exit(0); +} + #endif /* diff --git a/src/vg/vg_loader.h b/src/vg/vg_loader.h index 0d580c2..7245a29 100644 --- a/src/vg/vg_loader.h +++ b/src/vg/vg_loader.h @@ -12,6 +12,44 @@ #include "common.h" +static struct vg_shader _shader_loader = +{ + .name = "[vg] loader", + .link = NULL, + .vs = + { + .orig_file = NULL, + .static_src = "" + "layout (location=0) in vec2 a_co;" + "out vec2 aUv;" + "void main()" + "{" + "gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);" + "aUv = a_co;" + "}" + }, + .fs = + { + .orig_file = NULL, + .static_src = + + "out vec4 FragColor;" + "uniform float uTime;" + "in vec2 aUv;" + + "void main()" + "{" + "float dither=fract(dot(vec2(171.0,231.0),gl_FragCoord.xy)/71.0)-0.5;" + "float grad = 1.0-(aUv.y*0.5+0.5);" + "float fmt1 = step( 0.5, grad+dither );" + + "vec3 col = 0.5+0.5*sin( uTime + aUv.xyx + vec3(0.0,2.0,4.0) );" + + "FragColor = vec4(col*grad*fmt1,1.0);" + "}" + } +}; + static struct vg_loader { /* Shutdown steps */ @@ -22,17 +60,43 @@ static struct vg_loader } *step_buffer; u32 step_count, step_cap, step_action; + + GLuint vao, vbo; } vg_loader; static int vg_loader_init(void) { + float quad[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }; + + glGenVertexArrays( 1, &vg_loader.vao ); + glGenBuffers( 1, &vg_loader.vbo ); + glBindVertexArray( vg_loader.vao ); + glBindBuffer( GL_ARRAY_BUFFER, vg_loader.vbo ); + glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW ); + glBindVertexArray( vg_loader.vao ); + glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, + sizeof(float)*2, (void*)0 ); + glEnableVertexAttribArray( 0 ); + + VG_CHECK_GL_ERR(); + + if( !vg_shader_compile( &_shader_loader ) ) + { + glDeleteVertexArrays( 1, &vg_loader.vao ); + glDeleteBuffers( 1, &vg_loader.vbo ); + return 0; + } + return 1; } static void vg_loader_free(void) { vg_info( "vg_loader_free\n" ); + glDeleteVertexArrays( 1, &vg_loader.vao ); + glDeleteBuffers( 1, &vg_loader.vbo ); for( int i=0; i= argc ) + return 0; + + if( (delta_i == vg_argi) && (delta_j == vg_argj) ) + { + char *cur = &vg_argv[ vg_argi ][ vg_argj ]; + + if( *cur != '-' ) + { + vg_error( "Unknown opt '-%c'\n", *cur ); + } + else + { + vg_error( "Unknown opt '--%s'\n", cur + 1 ); + } + + exit(0); + } + + delta_i = vg_argi; + delta_j = vg_argj; + + return 1; +} + +/* Example: see if -c is set */ +int vg_opt( char c ) +{ + char *carg = vg_argv[ vg_argi ]; + + if( carg[0] == '-' ) + { + if( carg[1] == '-' ) + return 0; + + if( carg[ vg_argj ] == c ) + { + vg_argj ++; + + return 1; + } + } + + return 0; +} + +/* Example: get -c *value* */ +char *vg_opt_arg( char c ) +{ + if( vg_opt( c ) ) + { + if( vg_argi < vg_argc-1 ) + { + if( vg_argv[ vg_argi + 1 ][0] != '-' ) + { + vg_consume_next = 1; + return vg_argv[ vg_argi + 1 ]; + } + } + + vg_error( "Option '%c' requires argument!\n", c ); + exit(0); + } + + return NULL; +} + +/* Example see if --big is set */ +int vg_long_opt( char *name ) +{ + char *carg = vg_argv[ vg_argi ]; + + if( carg[0] == '-' ) + { + if( carg[1] == '-' ) + { + if( !strcmp( name, carg+2 ) ) + { + vg_consume_next = 1; + return 1; + } + } + } + + return 0; +} + +/* Example: get --big=value */ +char *vg_long_opt_arg( char *name ) +{ + char *carg = vg_argv[ vg_argi ]; + + if( carg[0] == '-' ) + { + if( carg[1] == '-' ) + { + int k = 2; int set = 0; + while( carg[ k ] ) + { + if( carg[ k ] == '=' ) + { + set = 1; + break; + } + + k ++; + } + + if( !strncmp( name, carg+2, k-2 ) ) + { + vg_consume_next = 1; + + // the rest + if( set ) + { + return carg + k + 1; + } + else + { + vg_error( "Long option '%s' requires argument\n", name ); + } + } + } + } + + return NULL; +} + +/* Example: get regular_thing */ +char *vg_arg(void) +{ + char *carg = vg_argv[ vg_argi ]; + + if( carg[0] != '-' ) + { + vg_consume_next = 1; + return carg; + } + + return NULL; +} + +#endif diff --git a/src/vg/vg_platform.h b/src/vg/vg_platform.h index ab9c927..e5deae2 100644 --- a/src/vg/vg_platform.h +++ b/src/vg/vg_platform.h @@ -33,29 +33,40 @@ struct vg_achievement #define vg_list_size( A ) (sizeof(A)/sizeof(A[0])) #define VG_MUST_USE_RESULT __attribute__((warn_unused_result)) -#ifdef _WIN32 +#ifdef _WIN32_NO #include -/* TODO */ -#define VG_DEPRECATED __declspec(deprecated) +#ifdef I_THINK_THIS_IS_WHAT_MSCV_WANTS_BUT_HAVNT_TESTED_IT_YET + + #define VG_DEPRECATED __declspec(deprecated) + #define VG_THREAD_LOCAL __declspec( thread ) + +#else /* MINGW-64 */ + + #define VG_THREAD_LOCAL __thread + #define VG_DEPRECATED __attribute__((deprecated)) + +#endif + + typedef HANDLE vg_semaphore; + typedef HANDLE vg_mutex; + typedef u64 vg_timespec; #else #include #include -#define VG_DEPRECATED __attribute__((deprecated)) - + #define VG_DEPRECATED __attribute__((deprecated)) #define VG_THREAD_LOCAL __thread typedef sem_t vg_semaphore; typedef pthread_mutex_t vg_mutex; + typedef struct timespec vg_timespec; #endif #include -/* TODO: If there is no graphics, we dont need to do an exit loop */ - static void vg_fatal_exit_loop( const char *error ); static void *vg_alloc( size_t size ) { @@ -113,9 +124,89 @@ void free( void *ptr ); #include #include -#ifdef _WIN32 +static int vg_thread_run( void *pfunc, void *data ); +static void vg_thread_exit(void); +static void vg_set_thread_name( const char *name ); +static int vg_semaphore_init( vg_semaphore *sem, u32 value ); +static int vg_semaphore_trywait( vg_semaphore *sem ); +static int vg_semaphore_wait( vg_semaphore *sem ); +static int vg_semaphore_post( vg_semaphore *sem ); +static void vg_semaphore_free( vg_semaphore *sem ); +static int vg_mutex_init( vg_mutex *mutex ); +static int vg_mutex_lock( vg_mutex *mutex ); +static int vg_mutex_unlock( vg_mutex *mutex ); +static void vg_mutex_free( vg_mutex *mutex ); +static void vg_sleep_ms( long msec ); +static double vg_time_diff( vg_timespec start, vg_timespec end ); + +#ifdef _WIN32_NO + +static int vg_thread_run( void *pfunc, void *data ) +{ + HANDLE hThread = CreateThread + ( + NULL, /* Thread attributes */ + 0, /* Stack size (0 = use default) */ + pfunc, /* Thread start address */ + data, /* Parameter to pass to the thread */ + 0, /* Creation flags */ + NULL /* Thread id */ + ); + + if ( hThread == NULL ) + { + /* + * Thread creation failed. + * More details can be retrieved by calling GetLastError() + */ + return 1; + } + else + { + CloseHandle( hThread ); + return 0; + } +} + +static void vg_thread_exit(void) +{ + ExitThread(0); +} + +static void vg_set_thread_name( const char *name ) +{ + /* I believe this is a meaningless concept in windows */ +} + +static int vg_semaphore_init( vg_semaphore *sem, u32 value ); +static int vg_semaphore_trywait( vg_semaphore *sem ); +static int vg_semaphore_wait( vg_semaphore *sem ); +static int vg_semaphore_post( vg_semaphore *sem ); +static void vg_semaphore_free( vg_semaphore *sem ); +static int vg_mutex_init( vg_mutex *mutex ); +static int vg_mutex_lock( vg_mutex *mutex ); +static int vg_mutex_unlock( vg_mutex *mutex ); +static void vg_mutex_free( vg_mutex *mutex ); +static void vg_sleep_ms( long msec ); +static double vg_time_diff( vg_timespec start, vg_timespec end ); + #else +static int vg_thread_run( void *pfunc, void *data ) +{ + pthread_t hThread; + if( pthread_create( &hThread, NULL, pfunc, data ) ) + { + return 1; + } + else + { + pthread_detach( hThread ); + return 0; + } +} + + static void vg_thread_exit(void) { pthread_exit(NULL); @@ -181,49 +272,6 @@ static void vg_mutex_free( vg_mutex *mutex ) } -#endif - - -int vg_thread_run( void *pfunc, void *data ) -{ -#ifdef _WIN32 - HANDLE hThread = CreateThread - ( - NULL, /* Thread attributes */ - 0, /* Stack size (0 = use default) */ - pfunc, /* Thread start address */ - data, /* Parameter to pass to the thread */ - 0, /* Creation flags */ - NULL /* Thread id */ - ); - - if ( hThread == NULL ) - { - /* - * Thread creation failed. - * More details can be retrieved by calling GetLastError() - */ - return 1; - } - else - { - CloseHandle( hThread ); - return 0; - } -#else - pthread_t hThread; - if( pthread_create( &hThread, NULL, pfunc, data ) ) - { - return 1; - } - else - { - pthread_detach( hThread ); - return 0; - } -#endif -} - static void vg_sleep_ms( long msec ) { struct timespec ts; @@ -242,6 +290,8 @@ static double vg_time_diff( struct timespec start, struct timespec end ) return elapsed; } +#endif + #define VG_MIN( A, B ) ((A)<(B)?(A):(B)) #define VG_MAX( A, B ) ((A)>(B)?(A):(B)) -- 2.25.1