diff --git a/doc/sphinx/toc/libweston/log.rst b/doc/sphinx/toc/libweston/log.rst index 95465338..fd68385f 100644 --- a/doc/sphinx/toc/libweston/log.rst +++ b/doc/sphinx/toc/libweston/log.rst @@ -65,6 +65,7 @@ Weston has a few scopes worth mentioning: - **xwm-wm-x11** - a scope for the X11 window manager in Weston for supporting Xwayland, printing some X11 protocol actions. - **content-protection-debug** - scope for debugging HDCP issues. +- **timeline** - see more at :ref:`timeline points` .. note:: @@ -156,6 +157,38 @@ client connects a new subscriber will be created. For each stream subscribed a subscription will be created. Enabling the debug-protocol happens using the :samp:`--debug` command line. +Timeline points +--------------- + +A special log scope is the 'timeline' scope which, together with +`wesgr `_ tool, helps diagnose latency issues. +Timeline points write to this 'timeline' scope in different parts of the +compositor, including the GL renderer. + +As with all other scopes this scope is available over the debug protocol, or by +using the others :ref:`subscribers`. By far the easiest way to get data out +of this scope would be to use the debug protocol. +Then use `wesgr `_ to process the data which +will transform it into a SVG that can be rendered by any web browser. + +The following illustrates how to use it: + +.. code-block:: console + + ./weston-debug timeline > log.json + ./wesgr -i log.json -o log.svg + +Inserting timeline points +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Timline points can be inserted using :c:macro:`TL_POINT` macro. The macro will +take the :type:`weston_compositor` instance, followed by the name of the +timeline point. What follows next is a variable number of arguments, which +**must** end with the macro :c:macro:`TLP_END`. + +Debug protocol API +------------------ + .. doxygengroup:: debug-protocol :content-only: diff --git a/libweston/timeline.c b/libweston/timeline.c index 2c782deb..9da8b5e3 100644 --- a/libweston/timeline.c +++ b/libweston/timeline.c @@ -37,6 +37,39 @@ #include "timeline.h" #include "weston-log-internal.h" +/** + * Timeline itself is not a subscriber but a scope (a producer of data), and it + * re-routes the data it produces to all the subscriptions (and implicitly + * to the subscribers) using a subscription iteration to go through all of them. + * + * Public API: + * * weston_timeline_refresh_subscription_objects() - allows outside parts of + * libweston notify/signal timeline code about the fact that underlying object + * has suffered some modifications and needs to re-emit the object ID. + * * weston_log_timeline_point() - which will disseminate data to all + * subscriptions + * + * Do note that only weston_timeline_refresh_subscription_objects() + * is exported in libweston. + * + * Destruction of the objects assigned to each underlying objects happens in + * two places: one in the logging framework callback of the log scope + * ('destroy_subscription'), and secondly, when the object itself gets + * destroyed. + * + * timeline_emit_context - For each subscription this object will be created to + * store a buffer when the object itself will be written and a subscription, + * which will be used to force the object ID if there is a need to do so (the + * underlying object has been refreshed, or better said has suffered some + * modification). Data written to a subscription will be flushed before the + * data written to the FILE *. + * + * @param cur a FILE * + * @param subscription a pointer to an already created subscription + * + * @ingroup internal-log + * @sa weston_timeline_point + */ struct timeline_emit_context { FILE *cur; struct weston_log_subscription *subscription; @@ -321,6 +354,18 @@ weston_timeline_get_subscription_object(struct weston_log_subscription *sub, return weston_timeline_subscription_search(tl_sub, object); } +/** Sets (on) the timeline subscription object refresh status. + * + * This function 'notifies' timeline to print the object ID. The timeline code + * will reset it back, so there's no need for users to do anything about it. + * + * Can be used from outside libweston. + * + * @param wc a weston_compositor instance + * @param object the underyling object + * + * @ingroup log + */ WL_EXPORT void weston_timeline_refresh_subscription_objects(struct weston_compositor *wc, void *object) @@ -345,6 +390,18 @@ static const type_func type_dispatch[] = { [TLT_GPU] = emit_gpu_timestamp, }; +/** Disseminates the message to all subscriptions of the scope \c + * timeline_scope + * + * 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 name the name of the timeline point. Interpretable by the tool reading + * the output (wesgr). + * + * @ingroup log + */ WL_EXPORT void weston_timeline_point(struct weston_log_scope *timeline_scope, const char *name, ...) diff --git a/libweston/timeline.h b/libweston/timeline.h index a84c27b4..aaed7431 100644 --- a/libweston/timeline.h +++ b/libweston/timeline.h @@ -41,6 +41,13 @@ enum timeline_type { TLT_GPU, }; +/** Timeline subscription created for each subscription + * + * Created automatically by weston_log_scope::new_subscription and + * destroyed by weston_log_scope::destroy_subscription. + * + * @ingroup internal-log + */ struct weston_timeline_subscription { unsigned int next_id; struct wl_list objects; /**< weston_timeline_subscription_object::subscription_link */ @@ -49,6 +56,8 @@ struct weston_timeline_subscription { /** * Created when object is first seen for a particular timeline subscription * Destroyed when the subscription got destroyed or object was destroyed + * + * @ingroup internal-log */ struct weston_timeline_subscription_object { void *object; /**< points to the object */ @@ -63,12 +72,26 @@ struct weston_timeline_subscription_object { (void)((type)0 == tmp___); \ tmp___; }) +/** + * Should be used as the last argument when using TL_POINT macro + * + * @ingroup log + */ #define TLP_END TLT_END, NULL + #define TLP_OUTPUT(o) TLT_OUTPUT, TYPEVERIFY(struct weston_output *, (o)) #define TLP_SURFACE(s) TLT_SURFACE, TYPEVERIFY(struct weston_surface *, (s)) #define TLP_VBLANK(t) TLT_VBLANK, TYPEVERIFY(const struct timespec *, (t)) #define TLP_GPU(t) TLT_GPU, TYPEVERIFY(const struct timespec *, (t)) +/** This macro is used to add timeline points. + * + * Use TLP_END when done for the vargs. + * + * @param ec weston_compositor instance + * + * @ingroup log + */ #define TL_POINT(ec, ...) do { \ weston_timeline_point(ec->timeline, __VA_ARGS__); \ } while (0)