medium sized dollop
[vg.git] / src / vg / vg_loader.h
1 /*
2 * Copyright 2021-2022 (C) Mount0 Software, Harry Godden - All Rights Reserved
3 * -----------------------------------------------------------------------------
4 *
5 * Splash / load screen
6 *
7 * -----------------------------------------------------------------------------
8 */
9
10 #ifndef VG_LOADER_H
11 #define VG_LOADER_H
12
13 #include "common.h"
14
15 static struct vg_loader
16 {
17 /* Synchronization */
18 vg_semaphore sem_loading;
19 vg_mutex mux_status;
20
21 enum loader_status
22 {
23 k_loader_status_loading,
24 k_loader_status_complete,
25 k_loader_status_fail
26 }
27 status;
28
29 /* Shutdown steps */
30 struct loader_free_step
31 {
32 void (*fn_free)(void *);
33 void *data;
34 }
35 *step_buffer;
36 u32 step_count, step_cap, step_action;
37 }
38 vg_loader;
39
40 static int vg_loader_init(void)
41 {
42 vg_semaphore_init( &vg_loader.sem_loading, 0 );
43 vg_mutex_init( &vg_loader.mux_status );
44 return 1;
45 }
46
47 static void vg_loader_free(void)
48 {
49 vg_semaphore_wait( &vg_loader.sem_loading );
50 vg_semaphore_free( &vg_loader.sem_loading );
51 vg_mutex_free( &vg_loader.mux_status );
52
53 for( int i=0; i<vg_loader.step_count; i++ )
54 {
55 struct loader_free_step *step =
56 &vg_loader.step_buffer[vg_loader.step_count -1 -i];
57
58 step->fn_free( step->data );
59 }
60
61 free( vg_loader.step_buffer );
62 }
63
64 static enum loader_status vg_loader_status(void)
65 {
66 enum loader_status answer;
67
68 vg_mutex_lock( &vg_loader.mux_status );
69 answer = vg_loader.status;
70 vg_mutex_unlock( &vg_loader.mux_status );
71
72 return answer;
73 }
74
75 static float hue_to_rgb( float p, float q, float t )
76 {
77 if(t < 0.0f) t += 1.0f;
78 if(t > 1.0f) t -= 1.0f;
79 if(t < 1.0f/6.0f) return p + (q - p) * 6.0f * t;
80 if(t < 1.0f/2.0f) return q;
81 if(t < 2.0f/3.0f) return p + (q - p) * (2.0f/3.0f - t) * 6.0f;
82 return p;
83 }
84
85 static void vg_loader_render(void)
86 {
87 float h = vg_fractf(vg_time*0.1),
88 s = 0.2f,
89 l = 0.1f, //* (0.5f+vg_fractf(vg_time*40.0)*0.5f),
90 q = l < 0.5f ? l * (1.0f + s) : l + s - l * s,
91 p = 2.0f * l - q,
92 r = hue_to_rgb( p, q, h + 1.0f/3.0f ),
93 g = hue_to_rgb( p, q, h ),
94 b = hue_to_rgb( p, q, h - 1.0f/3.0f );
95
96 glClearColor( r, g, b, 1.0f );
97 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
98
99
100
101 ui_begin( &ui_global_ctx, vg_window_x, vg_window_y );
102
103
104 int const fh = 14;
105 int lines_screen_max = ((vg_window_y/fh)-2),
106 lines_max_draw = VG_MIN( lines_screen_max, vg_list_size(vg_log.buffer) ),
107 lines_to_draw = VG_MIN( lines_max_draw, vg_log.buffer_line_count );
108
109 int ptr = vg_log.buffer_line_current;
110
111 ui_global_ctx.cursor[0] = 0;
112 ui_global_ctx.cursor[1] = lines_to_draw*fh;
113 ui_global_ctx.cursor[3] = fh;
114 ui_fill_x( &ui_global_ctx );
115
116 for( int i=0; i<lines_to_draw; i ++ )
117 {
118 ptr --;
119
120 if( ptr < 0 )
121 ptr = vg_list_size( vg_log.buffer )-1;
122
123 ui_text( &ui_global_ctx, ui_global_ctx.cursor,
124 vg_log.buffer[ptr], vg_console.scale, 0 );
125
126 ui_global_ctx.cursor[1] -= fh*vg_console.scale;
127 }
128
129 ui_resolve( &ui_global_ctx );
130 ui_draw( &ui_global_ctx, NULL );
131 }
132
133
134 static int vg_load_full(void);
135
136 static void vg_loader_thread(void * nothing)
137 {
138 /* Run client loader */
139 int res = vg_load_full();
140
141 /* Propogate status */
142 vg_mutex_lock( &vg_loader.mux_status );
143 if( res )
144 {
145 vg_loader.status = k_loader_status_complete;
146 }
147 else
148 {
149 vg_loader.status = k_loader_status_fail;
150 }
151 vg_mutex_unlock( &vg_loader.mux_status );
152
153 vg_semaphore_post( &vg_loader.sem_loading );
154 }
155
156 static void vg_loader_start(void)
157 {
158 vg_thread_run( vg_loader_thread, NULL );
159 }
160
161 static void vg_free_libc_malloced( void *data )
162 {
163 free( data );
164 }
165
166 static int vg_loader_push_free_step( struct loader_free_step step )
167 {
168 void *buf = buffer_reserve( vg_loader.step_buffer, vg_loader.step_count,
169 &vg_loader.step_cap, 1,
170 sizeof( struct loader_free_step ) );
171
172 if( !buf )
173 return 0;
174
175 vg_loader.step_buffer = buf;
176 vg_loader.step_buffer[ vg_loader.step_count ++ ] = step;
177 return 1;
178 }
179 /*
180 * Schedule something to be freed
181 */
182 __attribute__((warn_unused_result))
183 static int vg_loader_highwater( void( *fn_free )(void *), void *data )
184 {
185 if( fn_free )
186 {
187 struct loader_free_step step;
188 step.data = data;
189 step.fn_free = fn_free;
190
191 if( !vg_loader_push_free_step( step ) )
192 return 0;
193 }
194 else
195 {
196 if( data )
197 {
198 struct loader_free_step step;
199 step.data = data;
200 step.fn_free = vg_free_libc_malloced;
201
202 if( !vg_loader_push_free_step( step ) )
203 return 0;
204 }
205 }
206
207 vg_mutex_lock( &vg.mux_engine_status );
208
209 if( !vg.engine_running )
210 {
211 vg_mutex_unlock( &vg.mux_engine_status );
212 return 0;
213 }
214
215 vg_mutex_unlock( &vg.mux_engine_status );
216 return 1;
217 }
218
219 #endif /* VG_LOADER_H */
220
221 #if 0
222 #ifndef LOADER_H
223 #define LOADER_H
224
225 #include "common.h"
226
227 static struct loader
228 {
229 MUTEX_TYPE mux;
230
231 struct loader_step
232 {
233 int (*fn_load)(void);
234 void (*fn_free)(void);
235
236 int require_opengl;
237 const char *name;
238 }
239 *step_buffer;
240 u32 step_count, step_cap, step_action,
241 low_water_mark; /* What is the minumum number of systems we can have? */
242
243 enum loader_status
244 {
245 k_loader_status_loading,
246 k_loader_status_complete,
247 k_loader_status_fail
248 }
249 status;
250
251 int cancel;
252 }
253 loader;
254
255 static void loader_add_stage( struct loader_step step )
256 {
257 loader.step_buffer = buffer_reserve( loader.step_buffer, loader.step_count,
258 &loader.step_cap,
259 1, sizeof( struct loader_step ) );
260
261 loader.step_buffer[ loader.step_count ++ ] = step;
262 }
263
264 static void loader_insert_stage( struct loader_step step )
265 {
266
267 }
268
269 static void loader_cancel(void)
270 {
271 MUTEX_LOCK( loader.mux );
272 loader.cancel = 1;
273 MUTEX_UNLOCK( loader.mux );
274 }
275
276 static void loader_worker_thread( void *nothing )
277 {
278 while(1)
279 {
280 vg_sleep_ms( 1000.0 );
281 vg_info( "... loader ....\n" );
282
283 if( loader.cancel )
284 {
285 return;
286 }
287 }
288 }
289
290 static void loader_begin(void)
291 {
292 if( loader.step_count == 0 )
293 {
294 loader.status = k_loader_status_complete;
295 return;
296 }
297
298 loader.status = k_loader_status_loading;
299 vg_thread_run( loader_worker_thread, NULL );
300 }
301
302 static void loader_free(void)
303 {
304 /* TODO */
305 for( int i=0; i<loader.step_count; i++ )
306 {
307 struct loader_step *step = &loader.step_buffer[ loader.step_count -i -1 ];
308 if( step->fn_free )
309 step->fn_free();
310 }
311 }
312
313 /*
314 * Returns 0 if loading is not happening
315 * Returns 1 if we are loading something
316 */
317 static int loader_update(void)
318 {
319 MUTEX_LOCK( loader.mux );
320
321 if( loader.status == k_loader_status_complete )
322 {
323 MUTEX_UNLOCK( loader.mux );
324 return 0;
325 }
326 else
327 {
328 struct loader_step *cstep = &loader.step_buffer[ loader.step_action ];
329
330 if( cstep->require_opengl )
331 {
332 if( !cstep->fn_load() )
333 {
334 loader.cancel = 1;
335 MUTEX_UNLOCK( loader.mux );
336
337 loader_free();
338 vg_exit();
339 }
340
341 loader.step_action ++;
342 }
343
344 MUTEX_UNLOCK( loader.mux );
345 return 1;
346 }
347 }
348
349 #endif /* LOADER_H */
350 #endif