288 lines
6.4 KiB
C
288 lines
6.4 KiB
C
#include <vhex/driver.h>
|
|
#include <vhex/timer/interface.h>
|
|
|
|
#include <SDL2/SDL.h>
|
|
|
|
//---
|
|
// Internal
|
|
//---
|
|
|
|
/* internal timer cache */
|
|
static struct {
|
|
bool used;
|
|
vhex_call_t call;
|
|
uint32_t delay;
|
|
SDL_TimerID id;
|
|
} timer_cache[9];
|
|
|
|
static uint32_t __sdl_tmu_nexus(uint32_t interval, int id)
|
|
{
|
|
(void)interval;
|
|
if (timer_cache[id].call.function != NULL) {
|
|
vhex_call(timer_cache[id].call);
|
|
}
|
|
return timer_cache[id].delay;
|
|
}
|
|
|
|
//---
|
|
// Public timer API
|
|
// FIXME : atomic operation
|
|
//---
|
|
|
|
/* sdl_tmu_reserve() : reserve a timer */
|
|
tid_t sdl_tmu_reserve(uint64_t delay)
|
|
{
|
|
for (int i = 0; i < 9; ++i) {
|
|
if (timer_cache[i].used == true)
|
|
continue;
|
|
timer_cache[i].used = true;
|
|
timer_cache[i].call = VHEX_CALL_NULL;
|
|
timer_cache[i].delay = delay / 1000;
|
|
timer_cache[i].id = 0;
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/* sdl_tmu_configure() : configure timer */
|
|
tid_t sdl_tmu_configure(uint64_t delay, vhex_call_t call)
|
|
{
|
|
tid_t id;
|
|
|
|
id = sdl_tmu_reserve(delay);
|
|
if (id < 0)
|
|
return id;
|
|
|
|
memcpy(&timer_cache[id].call, &call, sizeof(vhex_call_t));
|
|
return id;
|
|
}
|
|
|
|
|
|
/* sdl_tmu_start() - start a configured timer */
|
|
int sdl_tmu_start(tid_t id)
|
|
{
|
|
if (id < 0 || id >= 9) return -1;
|
|
if (timer_cache[id].id != 0) return -2;
|
|
|
|
timer_cache[id].id = SDL_AddTimer(
|
|
timer_cache[id].delay,
|
|
(void*)&__sdl_tmu_nexus,
|
|
(void*)(uintptr_t)id
|
|
);
|
|
return 0;
|
|
}
|
|
|
|
/* sdl_tmu_reload() - change a timer's delay constant for next interrupts */
|
|
int sdl_tmu_reload(tid_t id, uint64_t delay)
|
|
{
|
|
if (id < 0 || id >= 9)
|
|
return -1;
|
|
|
|
timer_cache[id].delay = delay / 1000;
|
|
return 0;
|
|
}
|
|
|
|
/* sdl_tmu_pause() - stop a running timer */
|
|
int sdl_tmu_pause(tid_t id)
|
|
{
|
|
if (id < 0 || id >= 9)
|
|
return -1;
|
|
|
|
SDL_RemoveTimer(timer_cache[id].id);
|
|
timer_cache[id].id = 0;
|
|
return 0;
|
|
}
|
|
|
|
/* sdl_tmu_stop() - stop and free a timer */
|
|
int sdl_tmu_stop(tid_t id)
|
|
{
|
|
if (id < 0 || id >= 9)
|
|
return -1;
|
|
|
|
SDL_RemoveTimer(timer_cache[id].id);
|
|
timer_cache[id].id = 0;
|
|
timer_cache[id].used = false;
|
|
return 0;
|
|
}
|
|
|
|
//---
|
|
// Profiling API
|
|
//---
|
|
|
|
/* sdl_tmu_prof_make() : initialise a new profiling timer */
|
|
int sdl_tmu_prof_init(timer_prof_t *prof)
|
|
{
|
|
prof->anchor = SDL_GetTicks();
|
|
prof->elapsed = 0;
|
|
prof->rec = 0;
|
|
return 0;
|
|
}
|
|
|
|
/* sdl_tmu_prof_enter(): Start counting time for a function */
|
|
void sdl_tmu_prof_enter(timer_prof_t *prof)
|
|
{
|
|
if (prof == NULL)
|
|
return;
|
|
prof->anchor = SDL_GetTicks();
|
|
}
|
|
|
|
/* sdl_tmu_prof_enter_rec(): Start counting time for a recursive function */
|
|
void sdl_tmu_prof_enter_rec(timer_prof_t *prof)
|
|
{
|
|
if (prof == NULL)
|
|
return;
|
|
if (prof->rec == 0)
|
|
sdl_tmu_prof_enter(prof);
|
|
prof->rec += 1;
|
|
}
|
|
|
|
/* sdl_tmu_prof_leave(): Stop counting time for a function */
|
|
void sdl_tmu_prof_leave(timer_prof_t *prof)
|
|
{
|
|
if (prof == NULL)
|
|
return;
|
|
|
|
uint32_t snapshot = SDL_GetTicks();
|
|
|
|
prof->elapsed += snapshot - prof->anchor;
|
|
prof->anchor = snapshot;
|
|
}
|
|
|
|
/* sdl_tmu_prof_leave_rec(): Start counting time for a recursive function */
|
|
void sdl_tmu_prof_leave_rec(timer_prof_t *prof)
|
|
{
|
|
if (prof == NULL)
|
|
return;
|
|
if (prof->rec <= 0) {
|
|
prof->rec = 0;
|
|
return;
|
|
}
|
|
prof->rec -= 1;
|
|
if (prof->rec == 0)
|
|
sdl_tmu_prof_leave(prof);
|
|
}
|
|
|
|
/* sdl_prof_time(): Time spent in a given context, in microseconds */
|
|
uint32_t sdl_tmu_prof_time(timer_prof_t *prof)
|
|
{
|
|
if (prof == NULL)
|
|
return 0;
|
|
return prof->elapsed * 1000;
|
|
}
|
|
|
|
/* sdl_tmu_prof_quit() : uninit the profoling object */
|
|
int sdl_tmu_prof_quit(timer_prof_t *prof)
|
|
{
|
|
(void)prof;
|
|
return 0;
|
|
}
|
|
|
|
//---
|
|
// FPS primitives
|
|
//---
|
|
|
|
/* sh7305_tmu_fps_init() : initialize fps object */
|
|
void sdl_tmu_fps_init(fps_t *fps, int fps_target)
|
|
{
|
|
memset(fps, 0x00, sizeof(fps_t));
|
|
fps->anchor = SDL_GetTicks();
|
|
fps->objectif = 1000 / fps_target;
|
|
fps->fps_target = fps_target;
|
|
}
|
|
|
|
/* sdl_tmu_fps_sync() : compute frame statistic and wait whanted FPS */
|
|
void sdl_tmu_fps_sync(fps_t *fps)
|
|
{
|
|
uint32_t snapshot;
|
|
uint32_t target_ticks;
|
|
|
|
snapshot = SDL_GetTicks();
|
|
|
|
fps->render = snapshot - fps->anchor;
|
|
fps->margin = fps->objectif - fps->render;
|
|
|
|
fps->fps_real = 1000;
|
|
if (fps->render > 0)
|
|
fps->fps_real /= fps->render;
|
|
|
|
fps->fps = fps->fps_real;
|
|
if (fps->margin > 0)
|
|
fps->fps = fps->fps_target;
|
|
|
|
target_ticks = snapshot + fps->objectif;
|
|
while (1) {
|
|
if (SDL_GetTicks() >= target_ticks)
|
|
break;
|
|
}
|
|
|
|
fps->anchor = SDL_GetTicks();
|
|
}
|
|
|
|
/* sdl_fps_quit() : uninit the fps object */
|
|
void sdl_tmu_fps_quit(fps_t *fps)
|
|
{
|
|
(void)fps;
|
|
}
|
|
|
|
//---
|
|
// fake driver specification
|
|
//---
|
|
|
|
static void __tmu_configure(void)
|
|
{
|
|
printf("[drv] TMU: fake driver initialized\n");
|
|
for (int i = 0; i < 9; ++i) {
|
|
timer_cache[i].used = false;
|
|
timer_cache[i].id = 0;
|
|
}
|
|
}
|
|
|
|
static void __tmu_hsave(void)
|
|
{
|
|
// Nothing to do, this is a fake driver
|
|
;
|
|
}
|
|
|
|
static void __tmu_hrestore(void)
|
|
{
|
|
// Nothing to do, this is a fake driver
|
|
;
|
|
}
|
|
|
|
struct vhex_driver drv_tmu = {
|
|
.name = "SDL2 Timer",
|
|
.hsave = (void*)&__tmu_hsave,
|
|
.hrestore = (void*)&__tmu_hrestore,
|
|
.configure = (void*)&__tmu_configure,
|
|
.state_size = 4,
|
|
.flags = {
|
|
.TIMER = 1,
|
|
.SHARED = 0,
|
|
.UNUSED = 0
|
|
},
|
|
.module_data = &(struct timer_drv_interface){
|
|
/* timer API */
|
|
.timer_reserve = &sdl_tmu_reserve,
|
|
.timer_configure = &sdl_tmu_configure,
|
|
.timer_start = &sdl_tmu_start,
|
|
.timer_pause = &sdl_tmu_pause,
|
|
.timer_stop = &sdl_tmu_stop,
|
|
.timer_wait = NULL,
|
|
.timer_spinwait = NULL,
|
|
.timer_reload = &sdl_tmu_reload,
|
|
/* profiling API */
|
|
.timer_prof_init = &sdl_tmu_prof_init,
|
|
.timer_prof_enter = &sdl_tmu_prof_enter,
|
|
.timer_prof_enter_rec = &sdl_tmu_prof_enter_rec,
|
|
.timer_prof_leave_rec = &sdl_tmu_prof_leave_rec,
|
|
.timer_prof_leave = &sdl_tmu_prof_leave,
|
|
.timer_prof_time = &sdl_tmu_prof_time,
|
|
.timer_prof_quit = &sdl_tmu_prof_quit,
|
|
/* fps API */
|
|
.timer_fps_init = &sdl_tmu_fps_init,
|
|
.timer_fps_sync = &sdl_tmu_fps_sync,
|
|
.timer_fps_quit = &sdl_tmu_fps_quit,
|
|
}
|
|
};
|
|
VHEX_DECLARE_DRIVER(03, drv_tmu);
|