149 lines
3.3 KiB
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;
|
|
}
|