imgui API changes (buttons)
[vg.git] / 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 VG_STATIC void vg_loader_start( void(*pfn)(void) );
16 VG_STATIC void vg_loader_step( void( *fn_load )(void), void( *fn_free )(void) );
17
18 static struct vg_shader _shader_loader =
19 {
20 .name = "[vg] loader",
21 .link = NULL,
22 .vs =
23 {
24 .orig_file = NULL,
25 .static_src = ""
26 "layout (location=0) in vec2 a_co;"
27 "out vec2 aUv;"
28 "void main()"
29 "{"
30 "gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);"
31 "aUv = a_co;"
32 "}"
33 },
34 .fs =
35 {
36 .orig_file = NULL,
37 .static_src =
38
39 "out vec4 FragColor;"
40 "uniform float uTime;"
41 "in vec2 aUv;"
42
43 "void main()"
44 "{"
45 "float dither=fract(dot(vec2(171.0,231.0),gl_FragCoord.xy)/71.0)-0.5;"
46 "float grad = 1.0-(aUv.y*0.5+0.5)*0.5;"
47 "float fmt1 = step( 0.5, grad+dither );"
48
49 "vec3 col = 0.5+0.5*sin( uTime + aUv.xyx + vec3(0.0,2.0,4.0) );"
50
51 "FragColor = vec4(vec3(0.5,0.5,0.5)*grad*fmt1,1.0);"
52 "}"
53 }
54 };
55
56 static struct vg_loader
57 {
58 /* Shutdown steps */
59 struct loader_free_step
60 {
61 void (*fn_free)(void);
62 }
63 step_buffer[16];
64 u32 step_count, step_action;
65
66 GLuint vao, vbo;
67 }
68 vg_loader;
69
70 VG_STATIC void _vg_loader_init(void)
71 {
72 float quad[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
73 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f };
74
75 glGenVertexArrays( 1, &vg_loader.vao );
76 glGenBuffers( 1, &vg_loader.vbo );
77 glBindVertexArray( vg_loader.vao );
78 glBindBuffer( GL_ARRAY_BUFFER, vg_loader.vbo );
79 glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
80 glBindVertexArray( vg_loader.vao );
81 glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*2, (void*)0 );
82 glEnableVertexAttribArray( 0 );
83
84 VG_CHECK_GL_ERR();
85
86 if( !vg_shader_compile( &_shader_loader ) )
87 vg_fatal_exit_loop( "failed to compile shader" );
88 }
89
90 VG_STATIC void _vg_loader_free(void)
91 {
92 vg_info( "vg_loader_free\n" );
93 glDeleteVertexArrays( 1, &vg_loader.vao );
94 glDeleteBuffers( 1, &vg_loader.vbo );
95
96 for( int i=0; i<vg_loader.step_count; i++ )
97 {
98 struct loader_free_step *step =
99 &vg_loader.step_buffer[vg_loader.step_count -1 -i];
100
101 vg_info( " -> %p\n", step->fn_free );
102 step->fn_free();
103 }
104
105 vg_info( "done\n" );
106 }
107
108 VG_STATIC void _vg_render_log(void)
109 {
110 ui_begin( vg.window_x, vg.window_y );
111 SDL_AtomicLock( &log_print_sl );
112
113 int const fh = 14;
114 int lines_screen_max = ((vg.window_y/fh)-2),
115 lines_max_draw = VG_MIN( lines_screen_max, vg_list_size(vg_log.buffer) ),
116 lines_to_draw = VG_MIN( lines_max_draw, vg_log.buffer_line_count );
117
118 int ptr = vg_log.buffer_line_current;
119
120 vg_uictx.cursor[0] = 0;
121 vg_uictx.cursor[1] = lines_to_draw*fh;
122 vg_uictx.cursor[3] = fh;
123 ui_fill_x();
124
125 for( int i=0; i<lines_to_draw; i ++ )
126 {
127 ptr --;
128
129 if( ptr < 0 )
130 ptr = vg_list_size( vg_log.buffer )-1;
131
132 ui_text( vg_uictx.cursor, vg_log.buffer[ptr], 1, 0 );
133 vg_uictx.cursor[1] -= fh;
134 }
135
136 SDL_AtomicUnlock( &log_print_sl );
137
138 ui_resolve();
139 ui_draw( NULL );
140 }
141
142 VG_STATIC void _vg_loader_render(void)
143 {
144 glViewport( 0,0, vg.window_x, vg.window_y );
145 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
146 glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
147 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
148
149 glUseProgram( _shader_loader.id );
150 glUniform1f( glGetUniformLocation( _shader_loader.id, "uTime" ), vg.time );
151
152 glBindVertexArray( vg_loader.vao );
153 glDrawArrays( GL_TRIANGLES, 0, 6 );
154
155 _vg_render_log();
156 }
157
158
159 VG_STATIC void vg_load_full(void);
160
161 VG_STATIC int _vg_loader_thread(void *pfn)
162 {
163 SDL_AtomicLock( &vg.sl_context );
164 vg.thread_id_loader = SDL_GetThreadID(NULL);
165 VG_SYNC_LOG( "[%d] Loader thread begins\n" );
166 SDL_AtomicUnlock( &vg.sl_context );
167
168 /* Run client loader */
169 void (*call_func)(void) = pfn;
170 call_func();
171
172 SDL_SemPost( vg.sem_loader );
173 vg.thread_id_loader = 0;
174
175 vg_acquire_thread_sync();
176 vg.is_loaded = 1;
177 vg_release_thread_sync();
178
179 return 0;
180 }
181
182 VG_STATIC void vg_loader_start( void(*pfn)(void) )
183 {
184 vg.is_loaded = 0;
185 SDL_SemWait( vg.sem_loader );
186 SDL_CreateThread( _vg_loader_thread, "Loader thread", pfn );
187 }
188
189 /*
190 * Schedule something to be ran now, freed later. Checks in with engine status
191 */
192 VG_STATIC void vg_loader_step( void( *fn_load )(void), void( *fn_free )(void) )
193 {
194 if( fn_load )
195 fn_load();
196
197 if( fn_free )
198 {
199 struct loader_free_step step;
200 step.fn_free = fn_free;
201
202 if( vg_loader.step_count == vg_list_size(vg_loader.step_buffer) )
203 vg_fatal_exit_loop( "Too many free steps" );
204
205 vg_loader.step_buffer[ vg_loader.step_count ++ ] = step;
206 }
207
208 _vg_ensure_engine_running();
209 }
210
211 #endif /* VG_LOADER_H */