Platform and OS stability stuff
authorhgn <hgodden00@gmail.com>
Sat, 8 Oct 2022 06:18:16 +0000 (07:18 +0100)
committerhgn <hgodden00@gmail.com>
Sat, 8 Oct 2022 06:18:16 +0000 (07:18 +0100)
src/vg/vg.h
src/vg/vg_loader.h
src/vg/vg_opt.h [new file with mode: 0644]
src/vg/vg_platform.h

index e6f4001469395ee47869c591a2075de60f185885..f3ed6991690edd23e57b12697a910e2b5ebe557d 100644 (file)
 
 #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
 
 /*
index 0d580c2ae3ca99008d85dba04df603748e89903d..7245a29d88467eb91f1c076da6bf8c04afe073a8 100644 (file)
 
 #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<vg_loader.step_count; i++ )
    {
@@ -93,18 +157,17 @@ static void vg_render_log(void)
 
 static void vg_loader_render(void)
 {
-   float h = vg_randf(),
-         s = 0.7f,
-         l = 0.1f, //* (0.5f+vg_fractf(vg_time*40.0)*0.5f),
-         q = l < 0.5f ? l * (1.0f + s) : l + s - l * s,
-         p = 2.0f * l - q,
-         r = hue_to_rgb( p, q, h + 1.0f/3.0f ),
-         g = hue_to_rgb( p, q, h ),
-         b = hue_to_rgb( p, q, h - 1.0f/3.0f );
-
-   glClearColor( r, g, b, 1.0f );
+   glViewport( 0,0, vg_window_x, vg_window_y );
+   glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+   glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
 
+   glUseProgram( _shader_loader.id );
+       glUniform1f( glGetUniformLocation( _shader_loader.id, "uTime" ), vg_time );
+
+   glBindVertexArray( vg_loader.vao );
+   glDrawArrays( GL_TRIANGLES, 0, 6 );
+
    vg_render_log();
 }
 
diff --git a/src/vg/vg_opt.h b/src/vg/vg_opt.h
new file mode 100644 (file)
index 0000000..41494bd
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
+ */
+
+#ifndef VG_OPT_H
+#define VG_OPT_H
+
+#include "vg/vg_platform.h"
+
+/* 
+ * Supported:
+ *   short flags       |  -abc
+ *   short options     |  -a value
+ *   multi-set options |  -ab value
+ *
+ *   long gnu options  |  --long-value=test
+ *   standard agument  |  regular_thing
+ */
+
+static int vg_argi = 1;
+static int vg_argj = 1;
+static int vg_argc = 0;
+static int vg_consume_next = 0;
+static char **vg_argv;
+
+/* Will return 0 if exhausted */
+int vg_argp( int argc, char *argv[] )
+{
+   vg_argv = argv;
+   vg_argc = argc;
+
+   static int delta_i = 0;
+   static int delta_j = 0;
+   
+   if( vg_argj != 1 && !vg_argv[ vg_argi ][ vg_argj ] )
+   {
+      vg_argj = 1;
+      vg_argi ++;      
+   }
+
+   if( vg_consume_next )
+   {
+      vg_consume_next = 0;
+      vg_argi ++;
+   }
+
+   if( vg_argi >= 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
index ab9c927b79a1582fb383235cf648ee552aa6754b..e5deae28a1a39626b7c1d0eae8ebe64103b9d826 100644 (file)
@@ -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 <windows.h>
 
-/* 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 <pthread.h>
    #include <semaphore.h>
 
-#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 <stdlib.h>
 
-/* TODO: If there is no graphics, we dont need to do an exit loop */
-
 static void vg_fatal_exit_loop( const char *error );
 static void *vg_alloc( size_t size )
 {
@@ -113,9 +124,89 @@ void free( void *ptr );
 #include <math.h>
 #include <assert.h>
 
-#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))