#ifndef VG_SERVER
#include "../../dep/glad/glad.h"
+
+#define GLFW_INCLUDE_GLCOREARB
+
+#ifdef _WIN32
+ #define GLFW_DLL
+#endif
+
#include "../../dep/glfw/glfw3.h"
#endif
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;
#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;
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;
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();
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();
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 );
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 );
}
}
+#else
+
+static void vg_fatal_exit_loop( const char *error )
+{
+ vg_error( "Fatal error: %s\n", error );
+ exit(0);
+}
+
#endif
/*
#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 */
}
*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++ )
{
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();
}
--- /dev/null
+/*
+ * 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
#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 )
{
#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);
}
-#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;
return elapsed;
}
+#endif
+
#define VG_MIN( A, B ) ((A)<(B)?(A):(B))
#define VG_MAX( A, B ) ((A)>(B)?(A):(B))