From b4765809b5e7da43a850d455c98a468992843db9 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 23 Sep 2022 21:55:29 +0200 Subject: [PATCH] render: add wlr_renderer_get_time() This queries the current GPU time. [1]: https://registry.khronos.org/OpenGL/extensions/EXT/EXT_disjoint_timer_query.txt References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3025 --- include/render/gles2.h | 6 ++++++ include/wlr/render/interface.h | 1 + include/wlr/render/wlr_renderer.h | 7 +++++++ render/gles2/renderer.c | 24 ++++++++++++++++++++++++ render/wlr_renderer.c | 7 +++++++ 5 files changed, 45 insertions(+) diff --git a/include/render/gles2.h b/include/render/gles2.h index 714bacf56..5ce9c6771 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -32,6 +32,10 @@ struct wlr_gles2_tex_shader { GLint tex_attrib; }; +// Fixed here, but missing from any libglvnd release: +// https://gitlab.freedesktop.org/glvnd/libglvnd/-/merge_requests/268 +typedef void (GL_APIENTRYP PFNGLGETINTEGER64VEXTPROC) (GLenum pname, GLint64 *data); + struct wlr_gles2_renderer { struct wlr_renderer wlr_renderer; @@ -48,6 +52,7 @@ struct wlr_gles2_renderer { bool EXT_texture_type_2_10_10_10_REV; bool OES_texture_half_float_linear; bool EXT_texture_norm16; + bool EXT_disjoint_timer_query; } exts; struct { @@ -57,6 +62,7 @@ struct wlr_gles2_renderer { PFNGLPOPDEBUGGROUPKHRPROC glPopDebugGroupKHR; PFNGLPUSHDEBUGGROUPKHRPROC glPushDebugGroupKHR; PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES; + PFNGLGETINTEGER64VEXTPROC glGetInteger64vEXT; } procs; struct { diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index e347f29be..a9828827e 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -48,6 +48,7 @@ struct wlr_renderer_impl { uint32_t (*get_render_buffer_caps)(struct wlr_renderer *renderer); struct wlr_texture *(*texture_from_buffer)(struct wlr_renderer *renderer, struct wlr_buffer *buffer); + bool (*get_time)(struct wlr_renderer *r, struct timespec *t); }; void wlr_renderer_init(struct wlr_renderer *renderer, diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h index e240897d4..70aeb6cdf 100644 --- a/include/wlr/render/wlr_renderer.h +++ b/include/wlr/render/wlr_renderer.h @@ -14,6 +14,8 @@ #include #include +struct timespec; + struct wlr_renderer_impl; struct wlr_drm_format_set; struct wlr_buffer; @@ -112,6 +114,11 @@ bool wlr_renderer_init_wl_shm(struct wlr_renderer *r, */ int wlr_renderer_get_drm_fd(struct wlr_renderer *r); +/** + * Get the current GPU time. + */ +bool wlr_renderer_get_time(struct wlr_renderer *r, struct timespec *t); + /** * Destroys the renderer. * diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index b1543cddc..4a8e42e16 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -18,6 +18,7 @@ #include "render/gles2.h" #include "render/pixel_format.h" #include "types/wlr_matrix.h" +#include "util/time.h" static const GLfloat verts[] = { 1, 0, // top right @@ -485,6 +486,23 @@ struct wlr_egl *wlr_gles2_renderer_get_egl(struct wlr_renderer *wlr_renderer) { return renderer->egl; } +static bool gles2_get_time(struct wlr_renderer *wlr_renderer, struct timespec *t) { + struct wlr_gles2_renderer *renderer = + gles2_get_renderer_in_context(wlr_renderer); + + if (!renderer->exts.EXT_disjoint_timer_query) { + return false; + } + + GLint64 nsec = 0; + push_gles2_debug(renderer); + renderer->procs.glGetInteger64vEXT(GL_TIMESTAMP_EXT, &nsec); + pop_gles2_debug(renderer); + + timespec_from_nsec(t, nsec); + return true; +} + static void gles2_destroy(struct wlr_renderer *wlr_renderer) { struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); @@ -539,6 +557,7 @@ static const struct wlr_renderer_impl renderer_impl = { .get_drm_fd = gles2_get_drm_fd, .get_render_buffer_caps = gles2_get_render_buffer_caps, .texture_from_buffer = gles2_texture_from_buffer, + .get_time = gles2_get_time, }; void push_gles2_debug_(struct wlr_gles2_renderer *renderer, @@ -768,6 +787,11 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { "glEGLImageTargetRenderbufferStorageOES"); } + 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"); + } + if (renderer->exts.KHR_debug) { glEnable(GL_DEBUG_OUTPUT_KHR); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR); diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 2d6481f00..669d2e86e 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -433,3 +433,10 @@ int wlr_renderer_get_drm_fd(struct wlr_renderer *r) { } return r->impl->get_drm_fd(r); } + +bool wlr_renderer_get_time(struct wlr_renderer *r, struct timespec *t) { + if (!r->impl->get_time) { + return false; + } + return r->impl->get_time(r, t); +}