X-Git-Url: https://git.ao2.it/experiments/fps-meter.git/blobdiff_plain/d73b9869570111a3249139508e43f3f722adad2e..e3ce9103ca48d145197fec43770c701aa0f1bdc6:/fps-meter.h diff --git a/fps-meter.h b/fps-meter.h new file mode 100644 index 0000000..e965ffe --- /dev/null +++ b/fps-meter.h @@ -0,0 +1,95 @@ +/* + * fps-meter - Example program about how to measure frames per seconds + * + * Copyright (C) 2013 Antonio Ospite + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FPS_METER_H +#define FPS_METER_H + +#include +#include +#include + +#ifdef DEBUG +#define dbg(...) \ + do { \ + printf(__VA_ARGS__); \ + printf("\n"); \ + fflush(stdout); \ + } while(0) +#else +#define dbg(...) do {} while(0) +#endif + +#define NSEC_PER_SEC 1000000000 + +#define timespecsub(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec; \ + if ((result)->tv_nsec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_nsec += 1000000000; \ + } \ + } while(0) + +struct fps_meter_stats { + struct timespec time_start; + struct timespec time_end; + struct timespec elapsed; + + unsigned int frames; + double nsecs; +}; + +static void fps_meter_init(struct fps_meter_stats *stats) +{ + memset(stats, 0, sizeof(*stats)); + + clock_gettime(CLOCK_MONOTONIC, &stats->time_start); + dbg("Init time: s: %ld, ns: %ld", stats->time_start.tv_sec, stats->time_start.tv_nsec); +} + +static void fps_meter_update(struct fps_meter_stats *stats) +{ + dbg("Start time: s: %ld, ns: %ld", stats->time_start.tv_sec, stats->time_start.tv_nsec); + + clock_gettime(CLOCK_MONOTONIC, &stats->time_end); + dbg("End time: s: %ld, ns: %ld", stats->time_end.tv_sec, stats->time_end.tv_nsec); + + timespecsub(&stats->time_end, &stats->time_start, &stats->elapsed); + dbg("Elapsed s: %ld ns: %ld", stats->elapsed.tv_sec, stats->elapsed.tv_nsec); + + stats->frames++; + stats->nsecs += (stats->elapsed.tv_sec * NSEC_PER_SEC + stats->elapsed.tv_nsec); + if (stats->nsecs >= NSEC_PER_SEC) { + /* + * if we were garanteed that each frame took less than + * a second, then just printing 'frames' would be enough here, + * but if we want to cover the case when a frame may take more + * than a second, some calculations have to be done. + */ + float fps = stats->frames / (stats->nsecs / NSEC_PER_SEC); + printf("(frames: %d, nsecs: %f) FPS: %.2f\n", stats->frames, stats->nsecs, fps); + stats->nsecs = 0; + stats->frames = 0; + } + + /* update the stats for the next iteration */ + clock_gettime(CLOCK_MONOTONIC, &stats->time_start); +} +#endif /* FPS_METER_H */