ac07582b91757cac669c1734182fcdd16a230030
[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_NO
37 #include <windows.h>
38
39 #ifdef I_THINK_THIS_IS_WHAT_MSCV_WANTS_BUT_HAVNT_TESTED_IT_YET
40
41 #define VG_DEPRECATED __declspec(deprecated)
42 #define VG_THREAD_LOCAL __declspec( thread )
43
44 #else /* MINGW-64 */
45
46 #define VG_THREAD_LOCAL __thread
47 #define VG_DEPRECATED __attribute__((deprecated))
48
49 #endif
50
51 typedef HANDLE vg_semaphore;
52 typedef HANDLE vg_mutex;
53 typedef u64 vg_timespec;
54
55 #else
56 #include <pthread.h>
57 #include <semaphore.h>
58
59 #define VG_DEPRECATED __attribute__((deprecated))
60 #define VG_THREAD_LOCAL __thread
61
62 typedef sem_t vg_semaphore;
63 typedef pthread_mutex_t vg_mutex;
64 typedef struct timespec vg_timespec;
65
66 #endif
67
68 #include <stdlib.h>
69
70 #define VG_ZERO_NEW_MEM
71
72 static void vg_fatal_exit_loop( const char *error );
73 static void *vg_alloc( size_t size )
74 {
75 void *ptr = malloc( size );
76
77 if( !ptr )
78 vg_fatal_exit_loop( "Out of memory" );
79
80 #ifdef VG_ZERO_NEW_MEM
81 u8 *bytes = ptr;
82 for( u32 i=0; i<size; i++ )
83 {
84 bytes[i] = 0x00;
85 }
86 #endif
87
88 return ptr;
89 }
90
91 static void *vg_realloc( void *orig, size_t size )
92 {
93 void *ptr = realloc( orig, size );
94
95 if( !ptr )
96 vg_fatal_exit_loop( "Out of memory" );
97
98 return ptr;
99 }
100
101 /* seems to be a GCC bug when inlining this, its low priority anyway */
102 __attribute__ ((noinline))
103 static void vg_free( void *ptr )
104 {
105 free( ptr );
106 }
107
108 static void vg_required( void *ptr, const char *path )
109 {
110 if( !ptr )
111 {
112 vg_fatal_exit_loop( path );
113 }
114 }
115
116 #define VG_REQUIRED_ASSET( TYPE, DECL, FN, PATH, ... ) \
117 TYPE DECL = FN( PATH,##__VA_ARGS__ ); \
118 vg_required( DECL, "Resource is required but failed to load: '" PATH "'" );
119
120 VG_DEPRECATED
121 void *malloc( size_t size );
122
123 VG_DEPRECATED
124 void *realloc( void *orig, size_t size );
125
126 VG_DEPRECATED
127 void free( void *ptr );
128
129 #include <stdio.h>
130 #include <dirent.h>
131 #include <string.h>
132 #include <stdarg.h>
133 #include <ctype.h>
134 #include <math.h>
135 #include <assert.h>
136
137 static int vg_thread_run( void *pfunc, void *data );
138 static void vg_thread_exit(void);
139 static void vg_set_thread_name( const char *name );
140 static int vg_semaphore_init( vg_semaphore *sem, u32 value );
141 static int vg_semaphore_trywait( vg_semaphore *sem );
142 static int vg_semaphore_wait( vg_semaphore *sem );
143 static int vg_semaphore_post( vg_semaphore *sem );
144 static void vg_semaphore_free( vg_semaphore *sem );
145 static int vg_mutex_init( vg_mutex *mutex );
146 static int vg_mutex_lock( vg_mutex *mutex );
147 static int vg_mutex_unlock( vg_mutex *mutex );
148 static void vg_mutex_free( vg_mutex *mutex );
149 static void vg_sleep_ms( long msec );
150 static double vg_time_diff( vg_timespec start, vg_timespec end );
151
152 #ifdef _WIN32_NO
153
154 static int vg_thread_run( void *pfunc, void *data )
155 {
156 HANDLE hThread = CreateThread
157 (
158 NULL, /* Thread attributes */
159 0, /* Stack size (0 = use default) */
160 pfunc, /* Thread start address */
161 data, /* Parameter to pass to the thread */
162 0, /* Creation flags */
163 NULL /* Thread id */
164 );
165
166 if ( hThread == NULL )
167 {
168 /*
169 * Thread creation failed.
170 * More details can be retrieved by calling GetLastError()
171 */
172 return 1;
173 }
174 else
175 {
176 CloseHandle( hThread );
177 return 0;
178 }
179 }
180
181 static void vg_thread_exit(void)
182 {
183 ExitThread(0);
184 }
185
186 static void vg_set_thread_name( const char *name )
187 {
188 /* I believe this is a meaningless concept in windows */
189 }
190
191 static int vg_semaphore_init( vg_semaphore *sem, u32 value );
192 static int vg_semaphore_trywait( vg_semaphore *sem );
193 static int vg_semaphore_wait( vg_semaphore *sem );
194 static int vg_semaphore_post( vg_semaphore *sem );
195 static void vg_semaphore_free( vg_semaphore *sem );
196 static int vg_mutex_init( vg_mutex *mutex );
197 static int vg_mutex_lock( vg_mutex *mutex );
198 static int vg_mutex_unlock( vg_mutex *mutex );
199 static void vg_mutex_free( vg_mutex *mutex );
200 static void vg_sleep_ms( long msec );
201 static double vg_time_diff( vg_timespec start, vg_timespec end );
202
203 #else
204
205 static int vg_thread_run( void *pfunc, void *data )
206 {
207 pthread_t hThread;
208 if( pthread_create( &hThread, NULL, pfunc, data ) )
209 {
210 return 1;
211 }
212 else
213 {
214 pthread_detach( hThread );
215 return 0;
216 }
217 }
218
219
220 static void vg_thread_exit(void)
221 {
222 pthread_exit(NULL);
223 }
224
225 static void vg_set_thread_name( const char *name )
226 {
227 /* not defined but links?? */
228 #if 0
229 pthread_setname_np(pthread_self());
230 #endif
231 }
232
233 static int vg_semaphore_init( vg_semaphore *sem, u32 value )
234 {
235 return !sem_init( sem, 0, value );
236 }
237
238 static int vg_semaphore_trywait( vg_semaphore *sem )
239 {
240 return !sem_trywait( sem );
241 }
242
243 static int vg_semaphore_wait( vg_semaphore *sem )
244 {
245 return !sem_wait( sem );
246 }
247
248 static int vg_semaphore_post( vg_semaphore *sem )
249 {
250 return !sem_post( sem );
251 }
252
253 static void vg_semaphore_free( vg_semaphore *sem )
254 {
255 sem_destroy( sem );
256 }
257
258 static int vg_mutex_init( vg_mutex *mutex )
259 {
260 memset( mutex, 0, sizeof(vg_mutex) );
261 return 1;
262 }
263
264 static int vg_mutex_lock( vg_mutex *mutex )
265 {
266 if( !pthread_mutex_lock( mutex ) )
267 return 1;
268 else
269 return 0;
270 }
271
272 static int vg_mutex_unlock( vg_mutex *mutex )
273 {
274 if( !pthread_mutex_unlock( mutex ) )
275 return 1;
276 else
277 return 0;
278 }
279
280 static void vg_mutex_free( vg_mutex *mutex )
281 {
282
283 }
284
285 static void vg_sleep_ms( long msec )
286 {
287 struct timespec ts;
288
289 ts.tv_sec = msec / 1000;
290 ts.tv_nsec = (msec % 1000) * 1000000;
291 nanosleep( &ts, &ts );
292 }
293
294 /* diff two timespecs in MS */
295 static double vg_time_diff( struct timespec start, struct timespec end )
296 {
297 double elapsed = 1000.0*end.tv_sec + 1e-6*end.tv_nsec
298 - (1000.0*start.tv_sec + 1e-6*start.tv_nsec);
299
300 return elapsed;
301 }
302
303 #endif
304
305 #define VG_MIN( A, B ) ((A)<(B)?(A):(B))
306 #define VG_MAX( A, B ) ((A)>(B)?(A):(B))
307
308 static void *buffer_reserve( void *buffer, u32 count, u32 *cap, u32 amount,
309 size_t emsize )
310 {
311 if( count+amount > *cap )
312 {
313 *cap = VG_MAX( (*cap)*2, (*cap)+amount );
314 return vg_realloc( buffer, (*cap) * emsize );
315 }
316
317 return buffer;
318 }
319
320 static void *buffer_fix( void *buffer, u32 count, u32 *cap, size_t emsize )
321 {
322 *cap = count;
323 return vg_realloc( buffer, (*cap) * emsize );
324 }
325
326 #endif