summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/opengl/utils.c')
-rw-r--r--video/out/opengl/utils.c103
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;
+}