From c38c08074211801f4ffcba1cd04d148e661fef11 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 23 Sep 2022 22:47:59 +0200 Subject: [PATCH] render: add wlr_render_timestamp --- include/render/gles2.h | 10 ++++ include/wlr/render/interface.h | 14 +++++ include/wlr/render/wlr_renderer.h | 9 ++++ render/gles2/renderer.c | 87 +++++++++++++++++++++++++++++++ render/wlr_renderer.c | 26 +++++++++ 5 files changed, 146 insertions(+) diff --git a/include/render/gles2.h b/include/render/gles2.h index 5ce9c6771..d74879320 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -63,6 +63,10 @@ struct wlr_gles2_renderer { PFNGLPUSHDEBUGGROUPKHRPROC glPushDebugGroupKHR; PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES; PFNGLGETINTEGER64VEXTPROC glGetInteger64vEXT; + PFNGLGENQUERIESEXTPROC glGenQueriesEXT; + PFNGLDELETEQUERIESEXTPROC glDeleteQueriesEXT; + PFNGLQUERYCOUNTEREXTPROC glQueryCounterEXT; + PFNGLGETQUERYOBJECTI64VEXTPROC glGetQueryObjecti64vEXT; } procs; struct { @@ -118,6 +122,12 @@ struct wlr_gles2_texture { struct wlr_addon buffer_addon; }; +struct wlr_gles2_timestamp { + struct wlr_render_timestamp base; + struct wlr_gles2_renderer *renderer; + GLuint query; +}; + bool is_gles2_pixel_format_supported(const struct wlr_gles2_renderer *renderer, const struct wlr_gles2_pixel_format *format); diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index a9828827e..e1b35ee27 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -49,6 +49,7 @@ struct wlr_renderer_impl { struct wlr_texture *(*texture_from_buffer)(struct wlr_renderer *renderer, struct wlr_buffer *buffer); bool (*get_time)(struct wlr_renderer *r, struct timespec *t); + struct wlr_render_timestamp *(*create_timestamp)(struct wlr_renderer *r); }; void wlr_renderer_init(struct wlr_renderer *renderer, @@ -63,4 +64,17 @@ struct wlr_texture_impl { void wlr_texture_init(struct wlr_texture *texture, const struct wlr_texture_impl *impl, uint32_t width, uint32_t height); +struct wlr_render_timestamp { + const struct wlr_render_timestamp_impl *impl; +}; + +struct wlr_render_timestamp_impl { + void (*destroy)(struct wlr_render_timestamp *timestamp); + bool (*get_time)(struct wlr_render_timestamp *timestamp, + struct timespec *t); +}; + +void wlr_render_timestamp_init(struct wlr_render_timestamp *timestamp, + const struct wlr_render_timestamp_impl *impl); + #endif diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h index 70aeb6cdf..d1f02645d 100644 --- a/include/wlr/render/wlr_renderer.h +++ b/include/wlr/render/wlr_renderer.h @@ -119,6 +119,15 @@ int wlr_renderer_get_drm_fd(struct wlr_renderer *r); */ bool wlr_renderer_get_time(struct wlr_renderer *r, struct timespec *t); +struct wlr_render_timestamp; + +struct wlr_render_timestamp *wlr_renderer_create_timestamp(struct wlr_renderer *r); + +bool wlr_render_timestamp_get_time(struct wlr_render_timestamp *timestamp, + struct timespec *t); + +void wlr_render_timestamp_destroy(struct wlr_render_timestamp *timestamp); + /** * Destroys the renderer. * diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 4a8e42e16..c8ce13d8d 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -503,6 +503,35 @@ static bool gles2_get_time(struct wlr_renderer *wlr_renderer, struct timespec *t return true; } +static const struct wlr_render_timestamp_impl timestamp_impl; + +static struct wlr_render_timestamp *gles2_create_timestamp( + struct wlr_renderer *wlr_renderer) { + struct wlr_gles2_renderer *renderer = + gles2_get_renderer_in_context(wlr_renderer); + + if (!renderer->exts.EXT_disjoint_timer_query) { + return NULL; + } + + struct wlr_gles2_timestamp *timestamp = calloc(1, sizeof(*timestamp)); + if (timestamp == NULL) { + return NULL; + } + wlr_render_timestamp_init(×tamp->base, ×tamp_impl); + + timestamp->renderer = renderer; + + GLint disjoint = 0; + push_gles2_debug(renderer); + glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint); // clear the disjoint flag + renderer->procs.glGenQueriesEXT(1, ×tamp->query); + renderer->procs.glQueryCounterEXT(timestamp->query, GL_TIMESTAMP_EXT); + pop_gles2_debug(renderer); + + return ×tamp->base; +} + static void gles2_destroy(struct wlr_renderer *wlr_renderer) { struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); @@ -558,6 +587,7 @@ static const struct wlr_renderer_impl renderer_impl = { .get_render_buffer_caps = gles2_get_render_buffer_caps, .texture_from_buffer = gles2_texture_from_buffer, .get_time = gles2_get_time, + .create_timestamp = gles2_create_timestamp, }; void push_gles2_debug_(struct wlr_gles2_renderer *renderer, @@ -790,6 +820,10 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { if (check_gl_ext(exts_str, "GL_EXT_disjoint_timer_query")) { renderer->exts.EXT_disjoint_timer_query = true; load_gl_proc(&renderer->procs.glGetInteger64vEXT, "glGetInteger64vEXT"); + load_gl_proc(&renderer->procs.glGenQueriesEXT, "glGenQueriesEXT"); + load_gl_proc(&renderer->procs.glDeleteQueriesEXT, "glDeleteQueriesEXT"); + load_gl_proc(&renderer->procs.glQueryCounterEXT, "glQueryCounterEXT"); + load_gl_proc(&renderer->procs.glGetQueryObjecti64vEXT, "glGetQueryObjecti64vEXT"); } if (renderer->exts.KHR_debug) { @@ -887,3 +921,56 @@ GLuint wlr_gles2_renderer_get_current_fbo(struct wlr_renderer *wlr_renderer) { assert(renderer->current_buffer); return renderer->current_buffer->fbo; } + +static struct wlr_gles2_timestamp *get_timestamp( + struct wlr_render_timestamp *wlr_timestamp) { + assert(wlr_timestamp->impl == ×tamp_impl); + struct wlr_gles2_timestamp *timestamp = + wl_container_of(wlr_timestamp, timestamp, base); + return timestamp; +} + +static void timestamp_destroy(struct wlr_render_timestamp *wlr_timestamp) { + struct wlr_gles2_timestamp *timestamp = get_timestamp(wlr_timestamp); + struct wlr_gles2_renderer *renderer = timestamp->renderer; + + struct wlr_egl_context prev_ctx; + wlr_egl_save_context(&prev_ctx); + wlr_egl_make_current(renderer->egl); + + push_gles2_debug(renderer); + renderer->procs.glDeleteQueriesEXT(1, ×tamp->query); + pop_gles2_debug(renderer); + + wlr_egl_restore_context(&prev_ctx); +} + +static bool timestamp_get_time(struct wlr_render_timestamp *wlr_timestamp, + struct timespec *t) { + struct wlr_gles2_timestamp *timestamp = get_timestamp(wlr_timestamp); + struct wlr_gles2_renderer *renderer = timestamp->renderer; + + struct wlr_egl_context prev_ctx; + wlr_egl_save_context(&prev_ctx); + wlr_egl_make_current(renderer->egl); + + GLint disjoint = 0; + GLint64 available = 0, nsec = 0; + push_gles2_debug(renderer); + glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint); + renderer->procs.glGetQueryObjecti64vEXT(timestamp->query, + GL_QUERY_RESULT_AVAILABLE_EXT, &available); + renderer->procs.glGetQueryObjecti64vEXT(timestamp->query, + GL_QUERY_RESULT_EXT, &nsec); + pop_gles2_debug(renderer); + + wlr_egl_restore_context(&prev_ctx); + + timespec_from_nsec(t, nsec); + return available && !disjoint; +} + +static const struct wlr_render_timestamp_impl timestamp_impl = { + .destroy = timestamp_destroy, + .get_time = timestamp_get_time, +}; diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 669d2e86e..b8aa2294c 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -440,3 +440,29 @@ bool wlr_renderer_get_time(struct wlr_renderer *r, struct timespec *t) { } return r->impl->get_time(r, t); } + +struct wlr_render_timestamp *wlr_renderer_create_timestamp(struct wlr_renderer *r) { + if (!r->impl->create_timestamp) { + return false; + } + return r->impl->create_timestamp(r); +} + +void wlr_render_timestamp_init(struct wlr_render_timestamp *timestamp, + const struct wlr_render_timestamp_impl *impl) { + assert(impl->get_time && impl->destroy); + memset(timestamp, 0, sizeof(*timestamp)); + timestamp->impl = impl; +} + +bool wlr_render_timestamp_get_time(struct wlr_render_timestamp *timestamp, + struct timespec *t) { + return timestamp->impl->get_time(timestamp, t); +} + +void wlr_render_timestamp_destroy(struct wlr_render_timestamp *timestamp) { + if (timestamp == NULL) { + return; + } + timestamp->impl->destroy(timestamp); +}