backend: add last_render_time interface.

Used for querying how long render takes to complete, used for frame
pacing.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui
2022-12-14 08:07:36 +00:00
parent 64a97b57b5
commit 2a4e32babf
7 changed files with 63 additions and 0 deletions

View File

@@ -292,6 +292,14 @@ struct backend_operations {
/// Optional
int (*buffer_age)(backend_t *backend_data);
/// Get the render time of the last frame. If the render is still in progress,
/// returns false. The time is returned in `ts`. Frames are delimited by the
/// present() calls. i.e. after a present() call, last_render_time() should start
/// reporting the time of the just presen1ted frame.
///
/// Optional, if not available, the most conservative estimation will be used.
bool (*last_render_time)(backend_t *backend_data, struct timespec *ts);
/// The maximum number buffer_age might return.
int max_buffer_age;

View File

@@ -372,6 +372,7 @@ struct backend_operations egl_ops = {
.deinit = egl_deinit,
.bind_pixmap = egl_bind_pixmap,
.release_image = gl_release_image,
.prepare = gl_prepare,
.compose = gl_compose,
.image_op = gl_image_op,
.set_image_property = gl_set_image_property,
@@ -380,6 +381,7 @@ struct backend_operations egl_ops = {
.is_image_transparent = default_is_image_transparent,
.present = egl_present,
.buffer_age = egl_buffer_age,
.last_render_time = gl_last_render_time,
.create_shadow_context = gl_create_shadow_context,
.destroy_shadow_context = gl_destroy_shadow_context,
.render_shadow = backend_render_shadow_from_mask,

View File

@@ -22,6 +22,11 @@
#include "backend/backend_common.h"
#include "backend/gl/gl_common.h"
void gl_prepare(backend_t *base, const region_t *reg attr_unused) {
auto gd = (struct gl_data *)base;
glBeginQuery(GL_TIME_ELAPSED, gd->frame_timing[gd->current_frame_timing]);
}
GLuint gl_create_shader(GLenum shader_type, const char *shader_str) {
log_trace("===\n%s\n===", shader_str);
@@ -800,6 +805,9 @@ uint64_t gl_get_shader_attributes(backend_t *backend_data attr_unused, void *sha
}
bool gl_init(struct gl_data *gd, session_t *ps) {
glGenQueries(2, gd->frame_timing);
gd->current_frame_timing = 0;
// Initialize GLX data structure
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
@@ -1154,10 +1162,33 @@ void gl_present(backend_t *base, const region_t *region) {
glDeleteBuffers(2, bo);
glDeleteVertexArrays(1, &vao);
glEndQuery(GL_TIME_ELAPSED);
gd->current_frame_timing ^= 1;
gl_check_err();
free(coord);
free(indices);
}
bool gl_last_render_time(backend_t *base, struct timespec *ts) {
auto gd = (struct gl_data *)base;
GLint available = 0;
glGetQueryObjectiv(gd->frame_timing[gd->current_frame_timing ^ 1],
GL_QUERY_RESULT_AVAILABLE, &available);
if (!available) {
return false;
}
GLuint64 time;
glGetQueryObjectui64v(gd->frame_timing[gd->current_frame_timing ^ 1],
GL_QUERY_RESULT, &time);
ts->tv_sec = (long)(time / 1000000000);
ts->tv_nsec = (long)(time % 1000000000);
gl_check_err();
return true;
}
bool gl_image_op(backend_t *base, enum image_operations op, void *image_data,
const region_t *reg_op, const region_t *reg_visible attr_unused, void *arg) {
struct backend_image *tex = image_data;

View File

@@ -108,6 +108,8 @@ struct gl_data {
gl_shadow_shader_t shadow_shader;
GLuint back_texture, back_fbo;
GLint back_format;
GLuint frame_timing[2];
int current_frame_timing;
GLuint present_prog;
bool dithered_present;
@@ -129,6 +131,7 @@ typedef struct session session_t;
#define GL_PROG_MAIN_INIT \
{ .prog = 0, .unifm_opacity = -1, .unifm_invert_color = -1, .unifm_tex = -1, }
void gl_prepare(backend_t *base, const region_t *reg);
void x_rect_to_coords(int nrects, const rect_t *rects, coord_t image_dst,
int extent_height, int texture_height, int root_height,
bool y_inverted, GLint *coord, GLuint *indices);
@@ -142,6 +145,7 @@ void gl_destroy_window_shader(backend_t *backend_data, void *shader);
uint64_t gl_get_shader_attributes(backend_t *backend_data, void *shader);
bool gl_set_image_property(backend_t *backend_data, enum image_properties prop,
void *image_data, void *args);
bool gl_last_render_time(backend_t *backend_data, struct timespec *time);
/**
* @brief Render a region with texture data.

View File

@@ -528,6 +528,7 @@ struct backend_operations glx_ops = {
.deinit = glx_deinit,
.bind_pixmap = glx_bind_pixmap,
.release_image = gl_release_image,
.prepare = gl_prepare,
.compose = gl_compose,
.image_op = gl_image_op,
.set_image_property = gl_set_image_property,
@@ -536,6 +537,7 @@ struct backend_operations glx_ops = {
.is_image_transparent = default_is_image_transparent,
.present = glx_present,
.buffer_age = glx_buffer_age,
.last_render_time = gl_last_render_time,
.create_shadow_context = gl_create_shadow_context,
.destroy_shadow_context = gl_destroy_shadow_context,
.render_shadow = backend_render_shadow_from_mask,