diff options
Diffstat (limited to 'video/out/opengl/utils.c')
-rw-r--r-- | video/out/opengl/utils.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/video/out/opengl/utils.c b/video/out/opengl/utils.c index 6848e02ddc..097970890f 100644 --- a/video/out/opengl/utils.c +++ b/video/out/opengl/utils.c @@ -1,4 +1,5 @@ #include "common/msg.h" +#include "video/out/vo.h" #include "utils.h" // Standard parallel 2D projection, except y1 < y0 means that the coordinate @@ -118,3 +119,105 @@ void fbotex_uninit(struct fbotex *fbo) *fbo = (struct fbotex) {0}; } } + +struct timer_pool { + struct ra *ra; + ra_timer *timer; + bool running; // detect invalid usage + + uint64_t samples[PERF_SAMPLE_COUNT]; + int sample_idx; + int sample_count; + + uint64_t avg_sum; + uint64_t peak; +}; + +struct timer_pool *timer_pool_create(struct ra *ra) +{ + ra_timer *timer = ra->fns->timer_create(ra); + if (!timer) + return NULL; + + struct timer_pool *pool = talloc(NULL, struct timer_pool); + if (!pool) { + ra->fns->timer_destroy(ra, timer); + return NULL; + } + + *pool = (struct timer_pool){ .ra = ra, .timer = timer }; + return pool; +} + +void timer_pool_destroy(struct timer_pool *pool) +{ + if (!pool) + return; + + pool->ra->fns->timer_destroy(pool->ra, pool->timer); + talloc_free(pool); +} + +void timer_pool_start(struct timer_pool *pool) +{ + if (!pool) + return; + + assert(!pool->running); + pool->ra->fns->timer_start(pool->ra, pool->timer); + pool->running = true; +} + +void timer_pool_stop(struct timer_pool *pool) +{ + if (!pool) + return; + + assert(pool->running); + uint64_t res = pool->ra->fns->timer_stop(pool->ra, pool->timer); + pool->running = false; + + if (res) { + // Input res into the buffer and grab the previous value + uint64_t old = pool->samples[pool->sample_idx]; + pool->samples[pool->sample_idx++] = res; + pool->sample_idx %= PERF_SAMPLE_COUNT; + + // Update average and sum + pool->avg_sum = pool->avg_sum + res - old; + pool->sample_count = MPMIN(pool->sample_count + 1, PERF_SAMPLE_COUNT); + + // Update peak if necessary + if (res >= pool->peak) { + pool->peak = res; + } else if (pool->peak == old) { + // It's possible that the last peak was the value we just removed, + // if so we need to scan for the new peak + uint64_t peak = res; + for (int i = 0; i < PERF_SAMPLE_COUNT; i++) + peak = MPMAX(peak, pool->samples[i]); + pool->peak = peak; + } + } +} + +struct mp_pass_perf timer_pool_measure(struct timer_pool *pool) +{ + if (!pool) + return (struct mp_pass_perf){0}; + + struct mp_pass_perf res = { + .count = pool->sample_count, + .index = (pool->sample_idx - pool->sample_count) % PERF_SAMPLE_COUNT, + .peak = pool->peak, + .samples = pool->samples, + }; + + res.last = pool->samples[(pool->sample_idx - 1) % PERF_SAMPLE_COUNT]; + + if (pool->sample_count > 0) { + res.avg = pool->avg_sum / pool->sample_count; + } + + return res; +} |