Last active
December 12, 2022 20:42
-
-
Save slembcke/f66773c99c33bced69823a6073d8fcce to your computer and use it in GitHub Desktop.
SDL-like API on top of an inversion of control API.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdbool.h> | |
#include <math.h> | |
#include <stdio.h> | |
#include <GL/gl.h> | |
// A vaguely SDL-like API | |
void iSDL_init(void); | |
bool iSDL_should_exit; | |
void iSDL_swap_buffers(void); | |
void iSDL_quit(void); | |
// A simple main-loop style SDL program. | |
int main(int argc, const char* argv[]){ | |
iSDL_init(); | |
int tick = 0; | |
while(!iSDL_should_exit){ | |
glClearColor(fmod(tick/100.0f, 1), 0, 0, 1); | |
glClear(GL_COLOR_BUFFER_BIT); | |
tick++; | |
iSDL_swap_buffers(); | |
} | |
iSDL_quit(); | |
printf("exiting main()\n"); | |
} | |
// The SDL-like API yields to another fiber where Sokol runs. (Sokol is an inverted control style API) | |
// This still allows everything to share the main thread, but Sokol can only hijak the fiber it's confined to. | |
#define TINA_IMPLEMENTATION | |
#include "tina.h" | |
tina* sokol_fiber; | |
void* sokol_fiber_body(tina* fiber, void* value); | |
void iSDL_init(){ | |
// Create a coroutine/fiber to run sokol on and start it | |
sokol_fiber = tina_init(NULL, 256*1024, sokol_fiber_body, NULL); | |
tina_resume(sokol_fiber, iSDL_init); | |
} | |
bool iSDL_should_exit; | |
// There would probably be more stuff here, but in this simple example they just need to switch to the Sokol fiber. | |
void iSDL_swap_buffers(void){tina_resume(sokol_fiber, iSDL_swap_buffers);} | |
void iSDL_quit(){tina_resume(sokol_fiber, iSDL_quit);} | |
// === Now for the Sokol implementation... | |
#include <assert.h> | |
#define SOKOL_APP_IMPL | |
#define SOKOL_GLCORE33 | |
#define SOKOL_NO_ENTRY | |
#include "sokol_app.h" | |
void frame(void){ | |
// Yields back to the main loop and exits the iSDL_swap_buffers() call. | |
void* reason = tina_yield(sokol_fiber, NULL); | |
assert(reason == iSDL_swap_buffers); | |
} | |
void cleanup(void){ | |
// Set the quit flag. | |
iSDL_should_exit = true; | |
// Now wait for iSDL_quit() to be called in the main loop before exiting cleanup(). | |
void* reason = tina_yield(sokol_fiber, NULL); | |
assert(reason == iSDL_quit); | |
} | |
void* sokol_fiber_body(tina* fiber, void* value){ | |
// This fiber function runs on a separate fiber from the main loop | |
assert(value == iSDL_init); | |
// This is a blocking call that implement's Sokol App's main loop. | |
sapp_run(&(sapp_desc){ | |
.frame_cb = frame, | |
.cleanup_cb = cleanup, | |
.width = 400, | |
.height = 300, | |
.window_title = "Inside Out", | |
.icon.sokol_default = true, | |
}); | |
puts("sapp_run has exited"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment