Skip to content

Instantly share code, notes, and snippets.

@slembcke
Last active December 12, 2022 20:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save slembcke/f66773c99c33bced69823a6073d8fcce to your computer and use it in GitHub Desktop.
Save slembcke/f66773c99c33bced69823a6073d8fcce to your computer and use it in GitHub Desktop.
SDL-like API on top of an inversion of control API.
#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