backend-drm: Count and display KMS page flips

This patch counts the page flips (either in atomic or legacy page flips)
for DRM outputs and prints them using the drm-backend scope.

Similar to the frame callback timer counter this installs a counter that
periodically computes page flips per a pre-defined interval.

This also includes a perfetto counter to display these in perfetto.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
This commit is contained in:
Marius Vlad 2025-02-03 20:05:31 +02:00
parent 5f1c43de29
commit cda8de1089
5 changed files with 80 additions and 1 deletions

View file

@ -272,6 +272,11 @@ struct drm_backend {
bool has_underlay;
struct weston_log_scope *debug;
struct {
uint32_t frame_counter_interval;
struct wl_event_source *pageflip_timer_counter;
} perf_page_flips_stats;
};
struct drm_mode {
@ -601,6 +606,12 @@ struct drm_output {
struct wl_event_source *pageflip_timer;
/* how many page flips */
uint32_t page_flips_counted;
/* how many page flips / interval */
float page_flips_per_timer_interval;
bool is_virtual;
void (*virtual_destroy)(struct weston_output *base);

View file

@ -58,6 +58,7 @@
#include "shared/string-helpers.h"
#include "shared/weston-drm-fourcc.h"
#include "output-capture.h"
#include "weston-trace.h"
#include "pixman-renderer.h"
#include "pixel-formats.h"
#include "libbacklight.h"
@ -189,6 +190,64 @@ drm_output_pageflip_timer_create(struct drm_output *output)
return 0;
}
static int
pageflip_timer_counter_handler(void *data)
{
struct drm_backend *b = data;
struct weston_compositor *ec = b->compositor;
struct weston_output *output_base;
wl_list_for_each(output_base, &ec->output_list, link) {
struct drm_output *output = to_drm_output(output_base);
char desc[1024];
output->page_flips_per_timer_interval =
(float) (output->page_flips_counted /
b->perf_page_flips_stats.frame_counter_interval);
snprintf(desc, sizeof(desc),
"output %s KMS page flips", output_base->name);
WESTON_TRACE_SET_COUNTER(desc,
output->page_flips_per_timer_interval);
output->page_flips_counted = 0;
}
wl_event_source_timer_update(b->perf_page_flips_stats.pageflip_timer_counter,
1000 * b->perf_page_flips_stats.frame_counter_interval);
return 0;
}
static int
drm_backend_pageflip_timer_create(struct drm_backend *b, uint32_t interval)
{
struct wl_event_loop *loop = NULL;
struct weston_compositor *ec = b->compositor;
loop = wl_display_get_event_loop(ec->wl_display);
assert(loop);
b->perf_page_flips_stats.pageflip_timer_counter =
wl_event_loop_add_timer(loop, pageflip_timer_counter_handler, b);
if (b->perf_page_flips_stats.pageflip_timer_counter == NULL) {
weston_log("creating drm pageflip counter timer failed: %s\n",
strerror(errno));
return -1;
}
b->perf_page_flips_stats.frame_counter_interval = interval;
/* arm it w/ interval */
wl_event_source_timer_update(b->perf_page_flips_stats.pageflip_timer_counter,
1000 * b->perf_page_flips_stats.frame_counter_interval);
return 0;
}
/**
* Returns true if the plane can be used on the given output for its current
* repaint cycle.
@ -3478,6 +3537,7 @@ drm_shutdown(struct weston_backend *backend)
wl_event_source_remove(b->udev_drm_source);
wl_event_source_remove(b->drm_source);
wl_event_source_remove(b->perf_page_flips_stats.pageflip_timer_counter);
/* We are shutting down. This function destroy the planes with
* destroy_sprites() and then calls weston_compositor_shutdown(), which
@ -4267,6 +4327,8 @@ drm_backend_create(struct weston_compositor *compositor,
goto err_udev_monitor;
}
drm_backend_pageflip_timer_create(b, DEFAULT_FRAME_RATE_INTERVAL);
return b;
err_udev_monitor:

View file

@ -1884,6 +1884,7 @@ page_flip_handler(int fd, unsigned int frame,
assert(output->page_flip_pending);
output->page_flip_pending = false;
output->page_flips_counted++;
drm_output_update_complete(output, flags, sec, usec);
}
@ -1905,6 +1906,7 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
assert(crtc);
output = crtc->output;
output->page_flips_counted++;
/* During the initial modeset, we can disable CRTCs which we don't
* actually handle during normal operation; this will give us events
@ -1932,6 +1934,9 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
drm_output_update_complete(output, flags, sec, usec);
drm_debug(b, "[atomic][CRTC:%u] flip processing completed\n", crtc_id);
drm_debug(b, "[atomic][CRTC:%u] %.2f page flips computed in %d seconds\n",
crtc_id, output->page_flips_per_timer_interval,
output->backend->perf_page_flips_stats.frame_counter_interval);
}
int

View file

@ -98,7 +98,6 @@
*/
#define DEFAULT_REPAINT_WINDOW 7 /* milliseconds */
#define DEFAULT_FRAME_RATE_INTERVAL 1 /* seconds */
static void
weston_output_transform_scale_init(struct weston_output *output,

View file

@ -44,6 +44,8 @@
#include <assert.h>
#include "color.h"
#define DEFAULT_FRAME_RATE_INTERVAL 1 /* seconds */
/* compositor <-> renderer interface */
/** Opaque pointer to renderbuffer data.