mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2025-12-20 04:40:07 +01:00
timeline: Add the TL_POINTs into perfetto data
Try to roughly achieve feature parity with WESGR by processing the same timepoint data and feeding it into perfetto, with output and surface specific tracks. We can't match the way WESGR draws this information, because perfetto has a different display paradigm, but we can try to at least make sure all the same information is visible in an understandable way. Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
This commit is contained in:
parent
b3635c17f4
commit
485cb4ab12
5 changed files with 216 additions and 0 deletions
|
|
@ -567,6 +567,10 @@ struct weston_output {
|
|||
struct weston_coord_global pos;
|
||||
int32_t width, height;
|
||||
|
||||
uint64_t gpu_track_id;
|
||||
uint64_t paint_track_id;
|
||||
uint64_t presentation_track_id;
|
||||
|
||||
/** List of paint nodes in z-order, from top to bottom, maybe pruned
|
||||
*
|
||||
* struct weston_paint_node::z_order_link
|
||||
|
|
@ -2072,6 +2076,8 @@ struct weston_surface {
|
|||
* this list. */
|
||||
struct wl_list cm_feedback_surface_resource_list;
|
||||
struct wl_resource *cm_surface;
|
||||
|
||||
uint64_t damage_track_id;
|
||||
};
|
||||
|
||||
struct weston_subsurface {
|
||||
|
|
|
|||
|
|
@ -8195,6 +8195,9 @@ weston_output_init(struct weston_output *output,
|
|||
* free to set the color profile to whatever they want later on. */
|
||||
cm = compositor->color_manager;
|
||||
output->color_profile = cm->ref_stock_sRGB_color_profile(cm);
|
||||
output->gpu_track_id = 0;
|
||||
output->paint_track_id = 0;
|
||||
output->presentation_track_id = 0;
|
||||
}
|
||||
|
||||
/** Adds weston_output object to pending output list.
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ if get_option('perfetto')
|
|||
srcs_libweston += [
|
||||
'perfetto/u_perfetto.cc',
|
||||
'perfetto/u_perfetto.h',
|
||||
'timeline-perfetto.c'
|
||||
]
|
||||
dep_perfetto = dependency('perfetto', fallback: ['perfetto', 'dep_perfetto'])
|
||||
deps_libweston += dep_perfetto
|
||||
|
|
|
|||
190
libweston/timeline-perfetto.c
Normal file
190
libweston/timeline-perfetto.c
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* Copyright © 2025 Collabora, Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <libweston/libweston.h>
|
||||
#include "shared/timespec-util.h"
|
||||
#include "timeline.h"
|
||||
#include "weston-trace.h"
|
||||
|
||||
static void
|
||||
weston_perfetto_ensure_output_ids(struct weston_output *output)
|
||||
{
|
||||
char track_name[512];
|
||||
|
||||
if (output->gpu_track_id)
|
||||
return;
|
||||
|
||||
snprintf(track_name, sizeof(track_name), "%s GPU activity", output->name);
|
||||
output->gpu_track_id = util_perfetto_new_track(track_name);
|
||||
|
||||
snprintf(track_name, sizeof(track_name), "%s paint", output->name);
|
||||
output->paint_track_id = util_perfetto_new_track(track_name);
|
||||
|
||||
snprintf(track_name, sizeof(track_name), "%s present", output->name);
|
||||
output->presentation_track_id = util_perfetto_new_track(track_name);
|
||||
}
|
||||
|
||||
static void
|
||||
build_track_name(struct weston_surface *surface, char *name, int size)
|
||||
{
|
||||
static int disambiguator = 0;
|
||||
char surface_label[512];
|
||||
|
||||
/* Make sure we only call this once, so we don't accidentally
|
||||
* make multiple names for the same surface */
|
||||
assert(surface->damage_track_id == 0);
|
||||
|
||||
if (surface->get_label)
|
||||
surface->get_label(surface, surface_label, sizeof(surface_label));
|
||||
else {
|
||||
uint32_t res_id;
|
||||
|
||||
res_id = wl_resource_get_id(surface->resource);
|
||||
snprintf(surface_label, sizeof(surface_label), "surface %d", res_id);
|
||||
}
|
||||
|
||||
disambiguator++;
|
||||
|
||||
snprintf(name, size, "%s #%d", surface_label, disambiguator);
|
||||
}
|
||||
|
||||
static void
|
||||
weston_perfetto_ensure_surface_id(struct weston_surface *surface)
|
||||
{
|
||||
char track_name[600];
|
||||
|
||||
if (surface->damage_track_id)
|
||||
return;
|
||||
|
||||
build_track_name(surface, track_name, sizeof(track_name));
|
||||
|
||||
surface->damage_track_id = util_perfetto_new_track(track_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a timeline point for perfetto.
|
||||
*
|
||||
* The TL_POINT() is a wrapper over this function, but it uses the weston_compositor
|
||||
* instance to pass the timeline scope.
|
||||
*
|
||||
* @param timeline_scope the timeline scope
|
||||
* @param tlp_name the name of the timeline point.
|
||||
*
|
||||
* @ingroup log
|
||||
*/
|
||||
WL_EXPORT void
|
||||
weston_timeline_perfetto(struct weston_log_scope *timeline_scope,
|
||||
enum timeline_point_name tlp_name, ...)
|
||||
{
|
||||
struct weston_output *output = NULL;
|
||||
struct weston_surface *surface = NULL;
|
||||
struct timespec ts;
|
||||
uint64_t now_ns;
|
||||
uint64_t vblank_ns = 0, gpu_ns = 0;
|
||||
va_list argp;
|
||||
|
||||
if (!util_perfetto_is_tracing_enabled())
|
||||
return;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
now_ns = timespec_to_nsec(&ts);
|
||||
|
||||
va_start(argp, tlp_name);
|
||||
while (1) {
|
||||
enum timeline_type otype;
|
||||
void *obj;
|
||||
|
||||
otype = va_arg(argp, enum timeline_type);
|
||||
if (otype == TLT_END)
|
||||
break;
|
||||
|
||||
obj = va_arg(argp, void *);
|
||||
switch (otype) {
|
||||
case TLT_OUTPUT:
|
||||
output = obj;
|
||||
weston_perfetto_ensure_output_ids(output);
|
||||
break;
|
||||
case TLT_SURFACE:
|
||||
surface = obj;
|
||||
weston_perfetto_ensure_surface_id(surface);
|
||||
break;
|
||||
case TLT_VBLANK:
|
||||
vblank_ns = timespec_to_nsec(obj);
|
||||
break;
|
||||
case TLT_GPU:
|
||||
gpu_ns = timespec_to_nsec(obj);
|
||||
break;
|
||||
default:
|
||||
assert(!"not reached");
|
||||
}
|
||||
}
|
||||
va_end(argp);
|
||||
|
||||
switch (tlp_name) {
|
||||
case TLP_CORE_REPAINT_ENTER_LOOP:
|
||||
case TLP_CORE_REPAINT_RESTART:
|
||||
case TLP_CORE_REPAINT_EXIT_LOOP:
|
||||
break;
|
||||
case TLP_CORE_FLUSH_DAMAGE:
|
||||
WESTON_TRACE_TIMESTAMP_END("Damaged", surface->damage_track_id, CLOCK_MONOTONIC, now_ns);
|
||||
WESTON_TRACE_TIMESTAMP_BEGIN("Clean", surface->damage_track_id, 0, CLOCK_MONOTONIC, now_ns);
|
||||
break;
|
||||
case TLP_CORE_REPAINT_BEGIN:
|
||||
WESTON_TRACE_TIMESTAMP_END("Scheduled", output->paint_track_id, CLOCK_MONOTONIC, now_ns);
|
||||
WESTON_TRACE_TIMESTAMP_BEGIN("Paint", output->paint_track_id, 0, CLOCK_MONOTONIC, now_ns);
|
||||
break;
|
||||
case TLP_CORE_REPAINT_POSTED:
|
||||
WESTON_TRACE_TIMESTAMP_END("Paint", output->paint_track_id, CLOCK_MONOTONIC, now_ns);
|
||||
WESTON_TRACE_TIMESTAMP_BEGIN("Posted", output->presentation_track_id, 0, CLOCK_MONOTONIC, now_ns);
|
||||
break;
|
||||
case TLP_CORE_REPAINT_FINISHED:
|
||||
WESTON_TRACE_TIMESTAMP_END("Posted", output->presentation_track_id, CLOCK_MONOTONIC, vblank_ns);
|
||||
break;
|
||||
case TLP_CORE_REPAINT_REQ:
|
||||
WESTON_TRACE_TIMESTAMP_BEGIN("Scheduled", output->paint_track_id, 0, CLOCK_MONOTONIC, now_ns);
|
||||
break;
|
||||
case TLP_CORE_COMMIT_DAMAGE:
|
||||
WESTON_TRACE_TIMESTAMP_END("Clean", surface->damage_track_id, CLOCK_MONOTONIC, now_ns);
|
||||
WESTON_TRACE_TIMESTAMP_END("Damaged", surface->damage_track_id, CLOCK_MONOTONIC, now_ns);
|
||||
WESTON_TRACE_TIMESTAMP_BEGIN("Damaged", surface->damage_track_id, 0, CLOCK_MONOTONIC, now_ns);
|
||||
break;
|
||||
case TLP_RENDERER_GPU_BEGIN:
|
||||
WESTON_TRACE_TIMESTAMP_BEGIN("Active", output->gpu_track_id, 0, CLOCK_MONOTONIC, gpu_ns);
|
||||
break;
|
||||
case TLP_RENDERER_GPU_END:
|
||||
WESTON_TRACE_TIMESTAMP_END("Active", output->gpu_track_id, CLOCK_MONOTONIC, gpu_ns);
|
||||
break;
|
||||
default:
|
||||
assert(!"not reached");
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,8 @@
|
|||
#ifndef WESTON_TIMELINE_H
|
||||
#define WESTON_TIMELINE_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <wayland-util.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
|
@ -99,18 +101,32 @@ struct weston_timeline_subscription_object {
|
|||
*
|
||||
* Use TLP_END when done for the vargs.
|
||||
*
|
||||
* Timeline points are fed to the timeline log scope, and
|
||||
* to perfetto if it was enabled at build time.
|
||||
*
|
||||
* @param ec weston_compositor instance
|
||||
*
|
||||
* @ingroup log
|
||||
*/
|
||||
#ifdef HAVE_PERFETTO
|
||||
#define TL_POINT(ec, ...) do { \
|
||||
weston_timeline_perfetto(ec->timeline, __VA_ARGS__); \
|
||||
weston_timeline_point(ec->timeline, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define TL_POINT(ec, ...) do { \
|
||||
weston_timeline_point(ec->timeline, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#endif /* HAVE_PERFETTO */
|
||||
|
||||
void
|
||||
weston_timeline_point(struct weston_log_scope *timeline_scope,
|
||||
enum timeline_point_name tlp_name, ...);
|
||||
|
||||
void
|
||||
weston_timeline_perfetto(struct weston_log_scope *timeline_scope,
|
||||
enum timeline_point_name tlp_name, ...);
|
||||
|
||||
bool
|
||||
weston_timeline_profiling(struct weston_log_scope *timeline_scope);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue