ab9c927b79a1582fb383235cf648ee552aa6754b
[vg.git] / src / vg / vg_platform.h
1 #ifndef VG_PLATFORM_H
2 #define VG_PLATFORM_H
3
4 #include "vg.h"
5 #include "vg_stdint.h"
6
7 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
8
9 typedef unsigned int uint;
10
11 typedef int v2i[2];
12 typedef int v3i[3];
13 typedef int v4i[4];
14 typedef float v2f[2];
15 typedef float v3f[3];
16 typedef float v4f[4];
17 typedef v2f m2x2f[2];
18 typedef v3f m3x3f[3];
19 typedef v3f m4x3f[4];
20 typedef v4f m4x4f[4];
21 typedef v3f boxf[2];
22
23 // Resource types
24 typedef struct vg_tex2d vg_tex2d;
25
26 struct vg_achievement
27 {
28 int is_set;
29 const char *name;
30 };
31
32 #define vg_static_assert _Static_assert
33 #define vg_list_size( A ) (sizeof(A)/sizeof(A[0]))
34 #define VG_MUST_USE_RESULT __attribute__((warn_unused_result))
35
36 #ifdef _WIN32
37 #include <windows.h>
38
39 /* TODO */
40 #define VG_DEPRECATED __declspec(deprecated)
41
42 #else
43 #include <pthread.h>
44 #include <semaphore.h>
45
46 #define VG_DEPRECATED __attribute__((deprecated))
47
48 #define VG_THREAD_LOCAL __thread
49
50 typedef sem_t vg_semaphore;
51 typedef pthread_mutex_t vg_mutex;
52
53 #endif
54
55 #include <stdlib.h>
56
57 /* TODO: If there is no graphics, we dont need to do an exit loop */
58
59 static void vg_fatal_exit_loop( const char *error );
60 static void *vg_alloc( size_t size )
61 {
62 void *ptr = malloc( size );
63
64 if( !ptr )
65 vg_fatal_exit_loop( "Out of memory" );
66
67 return ptr;
68 }
69
70 static void *vg_realloc( void *orig, size_t size )
71 {
72 void *ptr = realloc( orig, size );
73
74 if( !ptr )
75 vg_fatal_exit_loop( "Out of memory" );
76
77 return ptr;
78 }
79
80 /* seems to be a GCC bug when inlining this, its low priority anyway */
81 __attribute__ ((noinline))
82 static void vg_free( void *ptr )
83 {
84 free( ptr );
85 }
86
87 static void vg_required( void *ptr, const char *path )
88 {
89 if( !ptr )
90 {
91 vg_fatal_exit_loop( path );
92 }
93 }
94
95 #define VG_REQUIRED_ASSET( TYPE, DECL, FN, PATH, ... ) \
96 TYPE DECL = FN( PATH,##__VA_ARGS__ ); \
97 vg_required( DECL, "Resource is required but failed to load: '" PATH "'" );
98
99 VG_DEPRECATED
100 void *malloc( size_t size );
101
102 VG_DEPRECATED
103 void *realloc( void *orig, size_t size );
104
105 VG_DEPRECATED
106 void free( void *ptr );
107
108 #include <stdio.h>
109 #include <dirent.h>
110 #include <string.h>
111 #include <stdarg.h>
112 #include <ctype.h>
113 #include <math.h>
114 #include <assert.h>
115
116 #ifdef _WIN32
117 #else
118
119 static void vg_thread_exit(void)
120 {
121 pthread_exit(NULL);
122 }
123
124 static void vg_set_thread_name( const char *name )
125 {
126 /* not defined but links?? */
127 #if 0
128 pthread_setname_np(pthread_self());
129 #endif
130 }
131
132 static int vg_semaphore_init( vg_semaphore *sem, u32 value )
133 {
134 return !sem_init( sem, 0, value );
135 }
136
137 static int vg_semaphore_trywait( vg_semaphore *sem )
138 {
139 return !sem_trywait( sem );
140 }
141
142 static int vg_semaphore_wait( vg_semaphore *sem )
143 {
144 return !sem_wait( sem );
145 }
146
147 static int vg_semaphore_post( vg_semaphore *sem )
148 {
149 return !sem_post( sem );
150 }
151
152 static void vg_semaphore_free( vg_semaphore *sem )
153 {
154 sem_destroy( sem );
155 }
156
157 static int vg_mutex_init( vg_mutex *mutex )
158 {
159 memset( mutex, 0, sizeof(vg_mutex) );
160 return 1;
161 }
162
163 static int vg_mutex_lock( vg_mutex *mutex )
164 {
165 if( !pthread_mutex_lock( mutex ) )
166 return 1;
167 else
168 return 0;
169 }
170
171 static int vg_mutex_unlock( vg_mutex *mutex )
172 {
173 if( !pthread_mutex_unlock( mutex ) )
174 return 1;
175 else
176 return 0;
177 }
178
179 static void vg_mutex_free( vg_mutex *mutex )
180 {
181
182 }
183
184 #endif
185
186
187 int vg_thread_run( void *pfunc, void *data )
188 {
189 #ifdef _WIN32
190 HANDLE hThread = CreateThread
191 (
192 NULL, /* Thread attributes */
193 0, /* Stack size (0 = use default) */
194 pfunc, /* Thread start address */
195 data, /* Parameter to pass to the thread */
196 0, /* Creation flags */
197 NULL /* Thread id */
198 );
199
200 if ( hThread == NULL )
201 {
202 /*
203 * Thread creation failed.
204 * More details can be retrieved by calling GetLastError()
205 */
206 return 1;
207 }
208 else
209 {
210 CloseHandle( hThread );
211 return 0;
212 }
213 #else
214 pthread_t hThread;
215 if( pthread_create( &hThread, NULL, pfunc, data ) )
216 {
217 return 1;
218 }
219 else
220 {
221 pthread_detach( hThread );
222 return 0;
223 }
224 #endif
225 }
226
227 static void vg_sleep_ms( long msec )
228 {
229 struct timespec ts;
230
231 ts.tv_sec = msec / 1000;
232 ts.tv_nsec = (msec % 1000) * 1000000;
233 nanosleep( &ts, &ts );
234 }
235
236 /* diff two timespecs in MS */
237 static double vg_time_diff( struct timespec start, struct timespec end )
238 {
239 double elapsed = 1000.0*end.tv_sec + 1e-6*end.tv_nsec
240 - (1000.0*start.tv_sec + 1e-6*start.tv_nsec);
241
242 return elapsed;
243 }
244
245 #define VG_MIN( A, B ) ((A)<(B)?(A):(B))
246 #define VG_MAX( A, B ) ((A)>(B)?(A):(B))
247
248 static void *buffer_reserve( void *buffer, u32 count, u32 *cap, u32 amount,
249 size_t emsize )
250 {
251 if( count+amount > *cap )
252 {
253 *cap = VG_MAX( (*cap)*2, (*cap)+amount );
254 return vg_realloc( buffer, (*cap) * emsize );
255 }
256
257 return buffer;
258 }
259
260 static void *buffer_fix( void *buffer, u32 count, u32 *cap, size_t emsize )
261 {
262 *cap = count;
263 return vg_realloc( buffer, (*cap) * emsize );
264 }
265
266 #endif