vxKernel/src/modules/display/dstack.c

149 lines
3.3 KiB
C

#include <vhex/display/stack.h>
#include <vhex/display/shader.h>
#include <vhex/driver.h>
#include <stdlib.h>
#include <string.h>
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,
}
};
//
// Kernel API
//
/* dstack_init() : Initialise the draw stack (should not be involved) */
//TODO: safe
int dstack_init(struct dstack_config *config)
{
dstack_info.pool.action = calloc(
config->default_icall_pool_slot,
sizeof(dstack_call_t)
);
dstack_info.pool.slots = config->default_icall_pool_slot;
dstack_info.pool.idx = -1;
for (int i = 0; i < dstack_info.pool.slots; ++i) {
dstack_info.pool.action[i].shader.table = malloc(
config->default_shader_per_action
);
dstack_info.pool.action[i].shader.number =
config->default_shader_per_action;
dstack_info.pool.action[i].shader.idx = 0;
}
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 = 0;
}
}
//
// Internal API
//
static did_t dstack_action_alloc(dstack_call_t *call, dshader_call_t *shader)
{
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 = realloc(
dstack_info.pool.action,
dstack_info.pool.slots
);
}
action = &dstack_info.pool.action[dstack_info.pool.idx];
memcpy(&action->call, call, sizeof(dstack_call_t));
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 = realloc(
action->shader.table,
action->shader.number
);
}
memcpy(
&action->shader.table[i],
&shader[i],
sizeof(dshader_call_t)
);
}
}
action->shader.idx = i;
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)
{
return dstack_action_alloc(call, shader);
}
/* 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_info.pool.idx = 0;
}