mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-26 06:35:58 +01:00
add render timer API
Based on five calls: wlr_render_timer_create - creates a timer which can be reused across frames on the same renderer wlr_renderer_begin_buffer_pass - now takes a timer so that backends can record when the rendering starts and finishes wlr_render_timer_get_time - should be called as late as possible so that queries can make their way back from the GPU wlr_render_timer_destroy - self-explanatory The timer is exposed as an opaque `struct wlr_render_timer` so that backends can store whatever they want in there.
This commit is contained in:
parent
bd834fe8d1
commit
9e8947e4d5
19 changed files with 87 additions and 23 deletions
|
@ -102,7 +102,7 @@ struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
||||||
goto error_tex;
|
goto error_tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, dst);
|
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, dst, NULL);
|
||||||
if (pass == NULL) {
|
if (pass == NULL) {
|
||||||
wlr_log(WLR_ERROR, "Failed to begin render pass with multi-GPU destination buffer");
|
wlr_log(WLR_ERROR, "Failed to begin render pass with multi-GPU destination buffer");
|
||||||
goto error_dst;
|
goto error_dst;
|
||||||
|
|
|
@ -90,7 +90,8 @@ static void output_handle_frame(struct wl_listener *listener, void *data) {
|
||||||
wlr_output_effective_resolution(output->wlr_output, &width, &height);
|
wlr_output_effective_resolution(output->wlr_output, &width, &height);
|
||||||
|
|
||||||
struct wlr_output_state state = {0};
|
struct wlr_output_state state = {0};
|
||||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->wlr_output, &state, NULL);
|
struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->wlr_output, &state, NULL,
|
||||||
|
NULL);
|
||||||
if (pass == NULL) {
|
if (pass == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,8 @@ static void output_handle_frame(struct wl_listener *listener, void *data) {
|
||||||
wlr_output_effective_resolution(output->wlr_output, &width, &height);
|
wlr_output_effective_resolution(output->wlr_output, &width, &height);
|
||||||
|
|
||||||
struct wlr_output_state output_state = {0};
|
struct wlr_output_state output_state = {0};
|
||||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->wlr_output, &output_state, NULL);
|
struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->wlr_output, &output_state,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||||
.box = { .width = width, .height = height },
|
.box = { .width = width, .height = height },
|
||||||
|
|
|
@ -115,7 +115,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
||||||
struct wlr_output *wlr_output = output->output;
|
struct wlr_output *wlr_output = output->output;
|
||||||
|
|
||||||
struct wlr_output_state output_state = {0};
|
struct wlr_output_state output_state = {0};
|
||||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL);
|
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL);
|
||||||
|
|
||||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||||
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
||||||
|
|
|
@ -102,7 +102,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
||||||
assert(renderer);
|
assert(renderer);
|
||||||
|
|
||||||
struct wlr_output_state output_state = {0};
|
struct wlr_output_state output_state = {0};
|
||||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL);
|
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL);
|
||||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||||
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
||||||
.color = {
|
.color = {
|
||||||
|
|
|
@ -60,7 +60,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
||||||
wlr_output_effective_resolution(wlr_output, &width, &height);
|
wlr_output_effective_resolution(wlr_output, &width, &height);
|
||||||
|
|
||||||
struct wlr_output_state output_state = {0};
|
struct wlr_output_state output_state = {0};
|
||||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL);
|
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL);
|
||||||
|
|
||||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||||
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
||||||
|
|
|
@ -63,7 +63,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_output_state state = {0};
|
struct wlr_output_state state = {0};
|
||||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &state, NULL);
|
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &state, NULL, NULL);
|
||||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||||
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
||||||
.color = {
|
.color = {
|
||||||
|
|
|
@ -88,7 +88,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
||||||
wlr_output_effective_resolution(wlr_output, &width, &height);
|
wlr_output_effective_resolution(wlr_output, &width, &height);
|
||||||
|
|
||||||
struct wlr_output_state output_state = {0};
|
struct wlr_output_state output_state = {0};
|
||||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL);
|
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL);
|
||||||
|
|
||||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||||
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
||||||
|
|
|
@ -77,7 +77,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
||||||
wlr_output_effective_resolution(wlr_output, &width, &height);
|
wlr_output_effective_resolution(wlr_output, &width, &height);
|
||||||
|
|
||||||
struct wlr_output_state output_state = {0};
|
struct wlr_output_state output_state = {0};
|
||||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL);
|
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL);
|
||||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||||
.box = { .width = width, .height = height },
|
.box = { .width = width, .height = height },
|
||||||
.color = { 0.25, 0.25, 0.25, 1 },
|
.color = { 0.25, 0.25, 0.25, 1 },
|
||||||
|
|
|
@ -49,7 +49,8 @@ struct wlr_renderer_impl {
|
||||||
struct wlr_texture *(*texture_from_buffer)(struct wlr_renderer *renderer,
|
struct wlr_texture *(*texture_from_buffer)(struct wlr_renderer *renderer,
|
||||||
struct wlr_buffer *buffer);
|
struct wlr_buffer *buffer);
|
||||||
struct wlr_render_pass *(*begin_buffer_pass)(struct wlr_renderer *renderer,
|
struct wlr_render_pass *(*begin_buffer_pass)(struct wlr_renderer *renderer,
|
||||||
struct wlr_buffer *buffer);
|
struct wlr_buffer *buffer, struct wlr_buffer_pass_options *options);
|
||||||
|
struct wlr_render_timer *(*render_timer_create)(struct wlr_renderer *renderer);
|
||||||
};
|
};
|
||||||
|
|
||||||
void wlr_renderer_init(struct wlr_renderer *renderer,
|
void wlr_renderer_init(struct wlr_renderer *renderer,
|
||||||
|
@ -79,6 +80,15 @@ struct wlr_render_pass_impl {
|
||||||
const struct wlr_render_rect_options *options);
|
const struct wlr_render_rect_options *options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wlr_render_timer {
|
||||||
|
const struct wlr_render_timer_impl *impl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_render_timer_impl {
|
||||||
|
int (*get_duration_ns)(struct wlr_render_timer *timer);
|
||||||
|
void (*destroy)(struct wlr_render_timer *timer);
|
||||||
|
};
|
||||||
|
|
||||||
void wlr_render_texture_options_get_src_box(const struct wlr_render_texture_options *options,
|
void wlr_render_texture_options_get_src_box(const struct wlr_render_texture_options *options,
|
||||||
struct wlr_fbox *box);
|
struct wlr_fbox *box);
|
||||||
void wlr_render_texture_options_get_dst_box(const struct wlr_render_texture_options *options,
|
void wlr_render_texture_options_get_dst_box(const struct wlr_render_texture_options *options,
|
||||||
|
|
|
@ -161,14 +161,23 @@ void wlr_renderer_destroy(struct wlr_renderer *renderer);
|
||||||
*/
|
*/
|
||||||
struct wlr_render_pass;
|
struct wlr_render_pass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object that can be queried after a render to get the duration of the render.
|
||||||
|
*/
|
||||||
|
struct wlr_render_timer;
|
||||||
|
|
||||||
|
struct wlr_buffer_pass_options {
|
||||||
|
struct wlr_render_timer *timer;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin a new render pass with the supplied destination buffer.
|
* Begin a new render pass with the supplied destination buffer.
|
||||||
*
|
*
|
||||||
* Callers must call wlr_render_pass_submit() once they are done with the
|
* Callers must call wlr_render_pass_submit() once they are done with the
|
||||||
* render pass.
|
* render pass.
|
||||||
*/
|
*/
|
||||||
struct wlr_render_pass *wlr_renderer_begin_buffer_pass(
|
struct wlr_render_pass *wlr_renderer_begin_buffer_pass(struct wlr_renderer *renderer,
|
||||||
struct wlr_renderer *renderer, struct wlr_buffer *buffer);
|
struct wlr_buffer *buffer, struct wlr_buffer_pass_options *options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit the render pass.
|
* Submit the render pass.
|
||||||
|
@ -235,4 +244,21 @@ struct wlr_render_rect_options {
|
||||||
void wlr_render_pass_add_rect(struct wlr_render_pass *render_pass,
|
void wlr_render_pass_add_rect(struct wlr_render_pass *render_pass,
|
||||||
const struct wlr_render_rect_options *options);
|
const struct wlr_render_rect_options *options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate and initialise a new render timer.
|
||||||
|
*/
|
||||||
|
struct wlr_render_timer *wlr_render_timer_create(struct wlr_renderer *renderer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the render duration in nanoseconds from the timer.
|
||||||
|
*
|
||||||
|
* Returns -1 if the duration is unavailable.
|
||||||
|
*/
|
||||||
|
int wlr_render_timer_get_duration_ns(struct wlr_render_timer *timer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the render timer.
|
||||||
|
*/
|
||||||
|
void wlr_render_timer_destroy(struct wlr_render_timer *timer);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <wayland-server-protocol.h>
|
#include <wayland-server-protocol.h>
|
||||||
#include <wayland-util.h>
|
#include <wayland-util.h>
|
||||||
|
#include <wlr/render/wlr_renderer.h>
|
||||||
#include <wlr/types/wlr_buffer.h>
|
#include <wlr/types/wlr_buffer.h>
|
||||||
#include <wlr/util/addon.h>
|
#include <wlr/util/addon.h>
|
||||||
|
|
||||||
|
@ -590,7 +591,7 @@ bool wlr_output_configure_primary_swapchain(struct wlr_output *output,
|
||||||
* Same as wlr_output_attach_render(), but returns a struct wlr_render_pass.
|
* Same as wlr_output_attach_render(), but returns a struct wlr_render_pass.
|
||||||
*/
|
*/
|
||||||
struct wlr_render_pass *wlr_output_begin_render_pass(struct wlr_output *output,
|
struct wlr_render_pass *wlr_output_begin_render_pass(struct wlr_output *output,
|
||||||
struct wlr_output_state *state, int *buffer_age);
|
struct wlr_output_state *state, int *buffer_age, struct wlr_render_timer *timer);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -537,7 +537,7 @@ static void gles2_destroy(struct wlr_renderer *wlr_renderer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_render_pass *gles2_begin_buffer_pass(struct wlr_renderer *wlr_renderer,
|
static struct wlr_render_pass *gles2_begin_buffer_pass(struct wlr_renderer *wlr_renderer,
|
||||||
struct wlr_buffer *wlr_buffer) {
|
struct wlr_buffer *wlr_buffer, struct wlr_buffer_pass_options *options) {
|
||||||
struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);
|
struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);
|
||||||
if (!wlr_egl_make_current(renderer->egl)) {
|
if (!wlr_egl_make_current(renderer->egl)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -494,7 +494,7 @@ static uint32_t pixman_get_render_buffer_caps(struct wlr_renderer *renderer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_render_pass *pixman_begin_buffer_pass(struct wlr_renderer *wlr_renderer,
|
static struct wlr_render_pass *pixman_begin_buffer_pass(struct wlr_renderer *wlr_renderer,
|
||||||
struct wlr_buffer *wlr_buffer) {
|
struct wlr_buffer *wlr_buffer, struct wlr_buffer_pass_options *options) {
|
||||||
struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer);
|
struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer);
|
||||||
|
|
||||||
struct wlr_pixman_buffer *buffer = get_buffer(renderer, wlr_buffer);
|
struct wlr_pixman_buffer *buffer = get_buffer(renderer, wlr_buffer);
|
||||||
|
|
|
@ -1916,7 +1916,8 @@ static uint32_t vulkan_get_render_buffer_caps(struct wlr_renderer *wlr_renderer)
|
||||||
return WLR_BUFFER_CAP_DMABUF;
|
return WLR_BUFFER_CAP_DMABUF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_render_pass *vulkan_begin_buffer_pass(struct wlr_renderer *wlr_renderer, struct wlr_buffer *buffer) {
|
static struct wlr_render_pass *vulkan_begin_buffer_pass(struct wlr_renderer *wlr_renderer,
|
||||||
|
struct wlr_buffer *buffer, struct wlr_buffer_pass_options *options) {
|
||||||
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
||||||
|
|
||||||
struct wlr_vk_render_buffer *render_buffer = get_render_buffer(renderer, buffer);
|
struct wlr_vk_render_buffer *render_buffer = get_render_buffer(renderer, buffer);
|
||||||
|
|
|
@ -413,10 +413,31 @@ int wlr_renderer_get_drm_fd(struct wlr_renderer *r) {
|
||||||
return r->impl->get_drm_fd(r);
|
return r->impl->get_drm_fd(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_render_pass *wlr_renderer_begin_buffer_pass(
|
struct wlr_render_pass *wlr_renderer_begin_buffer_pass(struct wlr_renderer *renderer,
|
||||||
struct wlr_renderer *renderer, struct wlr_buffer *buffer) {
|
struct wlr_buffer *buffer, struct wlr_buffer_pass_options *options) {
|
||||||
if (!renderer->impl->begin_buffer_pass) {
|
if (!renderer->impl->begin_buffer_pass) {
|
||||||
return begin_legacy_buffer_render_pass(renderer, buffer);
|
return begin_legacy_buffer_render_pass(renderer, buffer);
|
||||||
}
|
}
|
||||||
return renderer->impl->begin_buffer_pass(renderer, buffer);
|
return renderer->impl->begin_buffer_pass(renderer, buffer, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_render_timer *wlr_render_timer_create(struct wlr_renderer *renderer) {
|
||||||
|
if (!renderer->impl->render_timer_create) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return renderer->impl->render_timer_create(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int wlr_render_timer_get_duration_ns(struct wlr_render_timer *timer) {
|
||||||
|
if (!timer->impl->get_duration_ns) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return timer->impl->get_duration_ns(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_render_timer_destroy(struct wlr_render_timer *timer) {
|
||||||
|
if (!timer->impl->destroy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
timer->impl->destroy(timer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,7 +318,7 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor)
|
||||||
wlr_box_transform(&dst_box, &dst_box, wlr_output_transform_invert(output->transform),
|
wlr_box_transform(&dst_box, &dst_box, wlr_output_transform_invert(output->transform),
|
||||||
buffer->width, buffer->height);
|
buffer->width, buffer->height);
|
||||||
|
|
||||||
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, buffer);
|
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, buffer, NULL);
|
||||||
if (pass == NULL) {
|
if (pass == NULL) {
|
||||||
wlr_buffer_unlock(buffer);
|
wlr_buffer_unlock(buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -249,7 +249,7 @@ uint32_t wlr_output_preferred_read_format(struct wlr_output *output) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_render_pass *wlr_output_begin_render_pass(struct wlr_output *output,
|
struct wlr_render_pass *wlr_output_begin_render_pass(struct wlr_output *output,
|
||||||
struct wlr_output_state *state, int *buffer_age) {
|
struct wlr_output_state *state, int *buffer_age, struct wlr_render_timer *timer) {
|
||||||
if (!wlr_output_configure_primary_swapchain(output, state, &output->swapchain)) {
|
if (!wlr_output_configure_primary_swapchain(output, state, &output->swapchain)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,10 @@ struct wlr_render_pass *wlr_output_begin_render_pass(struct wlr_output *output,
|
||||||
|
|
||||||
struct wlr_renderer *renderer = output->renderer;
|
struct wlr_renderer *renderer = output->renderer;
|
||||||
assert(renderer != NULL);
|
assert(renderer != NULL);
|
||||||
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, buffer);
|
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, buffer,
|
||||||
|
&(struct wlr_buffer_pass_options){
|
||||||
|
.timer = timer,
|
||||||
|
});
|
||||||
if (pass == NULL) {
|
if (pass == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1673,7 +1673,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) {
|
||||||
wlr_damage_ring_get_buffer_damage(&scene_output->damage_ring,
|
wlr_damage_ring_get_buffer_damage(&scene_output->damage_ring,
|
||||||
buffer_age, &damage);
|
buffer_age, &damage);
|
||||||
|
|
||||||
struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass(renderer, buffer);
|
struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass(renderer, buffer, NULL);
|
||||||
if (render_pass == NULL) {
|
if (render_pass == NULL) {
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
wlr_buffer_unlock(buffer);
|
wlr_buffer_unlock(buffer);
|
||||||
|
|
Loading…
Reference in a new issue