#include #include #include #include #include static struct { struct { struct dstack_action *action; int slots; int idx; } pool; struct dstack_drv_interface driver; } dstack_info = { .pool = { .action = NULL, .slots = 0, .idx = 0 }, .driver = { .frame_start = NULL, .frame_frag_next = NULL, .frame_frag_send = NULL, .frame_end = NULL, .display_width = 0, .display_height = 0 } }; //--- // Kernel API //--- /* dstack_init() : Initialise the draw stack (should not be involved) */ int dstack_init(struct dstack_config *config) { dstack_info.pool.action = calloc( config->default_icall_pool_slot, sizeof(struct dstack_action) ); dstack_info.pool.idx = -1; dstack_info.pool.slots = config->default_icall_pool_slot; for (int i = 0; i < dstack_info.pool.slots; ++i) { dstack_info.pool.action[i].shader.table = calloc( config->default_shader_per_action, sizeof(*dstack_info.pool.action[i].shader.table) ); dstack_info.pool.action[i].shader.number = config->default_shader_per_action; dstack_info.pool.action[i].shader.idx = -1; } struct vhex_driver *driver = vhex_driver_table(); for (int i = 0; i < vhex_driver_count(); ++i) { if (driver[i].flags.DISPLAY) { memcpy( &dstack_info.driver, driver[i].module_data, sizeof(struct dstack_drv_interface) ); break; } } } /* dstack_quit() : Uninit the draw stack */ int dstack_quit(void) { for (int i = 0; i < dstack_info.pool.slots; ++i) { free(dstack_info.pool.action[i].shader.table); dstack_info.pool.action[i].shader.number = 0; dstack_info.pool.action[i].shader.idx = -1; } } // // Internal API // static did_t dstack_action_alloc( dstack_call_t *call, dshader_call_t *shader, void (*quit)(uint32_t *arg) ) { struct dstack_action *action; int i; dstack_info.pool.idx += 1; if (dstack_info.pool.idx >= dstack_info.pool.slots) { dstack_info.pool.slots += dstack_info.pool.slots; dstack_info.pool.action = reallocarray( dstack_info.pool.action, dstack_info.pool.slots, sizeof(struct dstack_action) ); } action = &dstack_info.pool.action[dstack_info.pool.idx]; memset(action, 0x00, sizeof(struct dstack_action)); memcpy(&action->call, call, sizeof(dstack_call_t)); action->shader.idx = -1; if (shader != NULL) { for (i = 0; shader[i].routine != NULL; ++i) { if (i >= action->shader.number) { action->shader.number += action->shader.number; action->shader.table = reallocarray( action->shader.table, action->shader.number, sizeof(*action->shader.table) ); } memcpy( &action->shader.table[i], &shader[i], sizeof(dshader_call_t) ); } action->shader.idx = i; } action->quit = quit; return dstack_info.pool.idx; } //--- // Public API //--- /* dstack_add_action() : add a new action in the draw stack */ did_t dstack_add_action( dstack_call_t *call, dshader_call_t *shader, void (*quit)(uint32_t *arg) ) { return (dstack_action_alloc(call, shader, quit)); } /* dstack_render(): render a frame */ void dstack_render(void) { struct dshader_surface surface; struct dstack_action *action; action = dstack_info.pool.action; dstack_info.driver.frame_start(&surface); do { for (int i = 0; i <= dstack_info.pool.idx; ++i) { action[i].call.routine(&surface, action[i].call.args); for (int j = 0; j <= action[i].shader.idx; j++) { action[i].shader.table[j].routine( &surface, action[i].call.args, action[i].shader.table[i].args ); } } dstack_info.driver.frame_frag_send(&surface); } while (dstack_info.driver.frame_frag_next(&surface) == 0); dstack_info.driver.frame_end(&surface); } /* dstack_invalidate() : Invalidate the draw stack (reset) */ int dstack_invalidate(void) { struct dstack_action *action; action = dstack_info.pool.action; for (int i = 0; i <= dstack_info.pool.idx; ++i) { if (action[i].quit != NULL) action[i].quit(action[i].call.args); } dstack_info.pool.idx = -1; } /* dstack_display_width() : return the display width */ size_t dstack_display_width(void) { return dstack_info.driver.display_width; } /* dstack_display_height() : return the display height */ size_t dstack_display_height(void) { return dstack_info.driver.display_height; }