4#ifndef SkTraceEventCommon_DEFINED
5#define SkTraceEventCommon_DEFINED
56#if defined(TRACE_EVENT0)
57 #error "Another copy of this file has already been included."
93#ifdef SK_ANDROID_FRAMEWORK_USE_PERFETTO
100#define PERFETTO_TRACK_EVENT_NAMESPACE skia
101#include <perfetto/tracing.h>
103#include <cutils/trace.h>
105#include <string_view>
123 perfetto::Category(
"GM"),
124 perfetto::Category(
"skia"),
125 perfetto::Category(
"skia.android"),
126 perfetto::Category(
"skia.gpu"),
127 perfetto::Category(
"skia.gpu.cache"),
128 perfetto::Category(
"skia.objects"),
129 perfetto::Category(
"skia.shaders"),
130 perfetto::Category(
"skottie"),
131 perfetto::Category(
"test"),
132 perfetto::Category(
"test_cpu"),
133 perfetto::Category(
"test_ganesh"),
134 perfetto::Category(
"test_graphite"),
136 perfetto::Category(
"GM.always").SetTags(
"skia.always"),
137 perfetto::Category(
"skia.always").SetTags(
"skia.always"),
138 perfetto::Category(
"skia.android.always").SetTags(
"skia.always"),
139 perfetto::Category(
"skia.gpu.always").SetTags(
"skia.always"),
140 perfetto::Category(
"skia.gpu.cache.always").SetTags(
"skia.always"),
141 perfetto::Category(
"skia.objects.always").SetTags(
"skia.always"),
142 perfetto::Category(
"skia.shaders.always").SetTags(
"skia.always"),
143 perfetto::Category(
"skottie.always").SetTags(
"skia.always"),
144 perfetto::Category(
"test.always").SetTags(
"skia.always"),
145 perfetto::Category(
"test_cpu.always").SetTags(
"skia.always"),
146 perfetto::Category(
"test_ganesh.always").SetTags(
"skia.always"),
147 perfetto::Category(
"test_graphite.always").SetTags(
"skia.always"),
152#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
154#ifdef SK_DISABLE_TRACING
155#error SK_DISABLE_TRACING and SK_BUILD_FOR_ANDROID_FRAMEWORK are mutually exclusive.
158#define SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE 256
160class SkAndroidFrameworkTraceUtil {
162 SkAndroidFrameworkTraceUtil() =
delete;
171 static void setEnableTracing(
bool enableAndroidTracing) {
172 gEnableAndroidTracing = enableAndroidTracing;
178 static bool setUsePerfettoTrackEvents(
bool usePerfettoTrackEvents) {
179#ifdef SK_ANDROID_FRAMEWORK_USE_PERFETTO
181 if (!gUsePerfettoTrackEvents && usePerfettoTrackEvents) {
184 gUsePerfettoTrackEvents = usePerfettoTrackEvents;
188 SkDebugf(
"Tracing Skia with Perfetto is not supported in this environment (host build?)");
193 static bool getEnableTracing() {
194 return gEnableAndroidTracing;
197 static bool getUsePerfettoTrackEvents() {
198 return gUsePerfettoTrackEvents;
202 static bool gEnableAndroidTracing;
203 static bool gUsePerfettoTrackEvents;
205#ifdef SK_ANDROID_FRAMEWORK_USE_PERFETTO
209 static void initPerfetto() {
210 ::perfetto::TracingInitArgs perfettoArgs;
211 perfettoArgs.backends |= perfetto::kSystemBackend;
212 ::perfetto::Tracing::Initialize(perfettoArgs);
213 ::skia::TrackEvent::Register();
221static inline
void skprintf_like_noop(const
char format[], ...) {}
222template <
typename... Args>
223static inline void sk_noop(Args...) {}
224#define TRACE_EMPTY(...) do { sk_noop(__VA_ARGS__); } while (0)
225#define TRACE_EMPTY_FMT(fmt, ...) do { skprintf_like_noop(fmt, ##__VA_ARGS__); } while (0)
227#define TRACE_EMPTY(...) do {} while (0)
228#define TRACE_EMPTY_FMT(fmt, ...) do {} while (0)
231#if defined(SK_DISABLE_TRACING) || \
232 (defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && !defined(SK_ANDROID_FRAMEWORK_USE_PERFETTO))
234 #define ATRACE_ANDROID_FRAMEWORK(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
235 #define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
236 #define TRACE_EVENT0(cg, n) TRACE_EMPTY(cg, n)
237 #define TRACE_EVENT0_ALWAYS(cg, n) TRACE_EMPTY(cg, n)
238 #define TRACE_EVENT1(cg, n, a1n, a1v) TRACE_EMPTY(cg, n, a1n, a1v)
239 #define TRACE_EVENT2(cg, n, a1n, a1v, a2n, a2v) TRACE_EMPTY(cg, n, a1n, a1v, a2n, a2v)
240 #define TRACE_EVENT_INSTANT0(cg, n, scope) TRACE_EMPTY(cg, n, scope)
241 #define TRACE_EVENT_INSTANT1(cg, n, scope, a1n, a1v) TRACE_EMPTY(cg, n, scope, a1n, a1v)
242 #define TRACE_EVENT_INSTANT2(cg, n, scope, a1n, a1v, a2n, a2v) \
243 TRACE_EMPTY(cg, n, scope, a1n, a1v, a2n, a2v)
244 #define TRACE_EVENT_OBJECT_CREATED_WITH_ID(cg, n, id) TRACE_EMPTY(cg, n, id)
245 #define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(cg, n, id, ss) TRACE_EMPTY(cg, n, id, ss)
246 #define TRACE_EVENT_OBJECT_DELETED_WITH_ID(cg, n, id) TRACE_EMPTY(cg, n, id)
247 #define TRACE_COUNTER1(cg, n, value) TRACE_EMPTY(cg, n, value)
248 #define TRACE_COUNTER2(cg, n, v1n, v1v, v2n, v2v) TRACE_EMPTY(cg, n, v1n, v1v, v2n, v2v)
250#elif defined(SK_ANDROID_FRAMEWORK_USE_PERFETTO)
256 inline const char* UnboxPerfettoString(const ::perfetto::DynamicString& str) {
259 inline const char* UnboxPerfettoString(const ::perfetto::StaticString& str) {
262 inline const char* UnboxPerfettoString(
const char* str) {
266 constexpr bool StrEndsWithAndLongerThan(
const char* str,
const char* suffix) {
267 auto strView = std::basic_string_view(str);
268 auto suffixView = std::basic_string_view(suffix);
270 return strView.size() > suffixView.size() &&
271 strView.compare(strView.size() - suffixView.size(),
272 std::string_view::npos, suffixView) == 0;
279#define SK_PERFETTO_INTERNAL_CONCAT2(a, b) a##b
280#define SK_PERFETTO_INTERNAL_CONCAT(a, b) SK_PERFETTO_INTERNAL_CONCAT2(a, b)
281#define SK_PERFETTO_UID(prefix) SK_PERFETTO_INTERNAL_CONCAT(prefix, __LINE__)
291#define TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE(force_always_trace, category, name, ...) \
292 struct SK_PERFETTO_UID(ScopedEvent) { \
293 struct EventFinalizer { \
301 EventFinalizer(...) {} \
302 ~EventFinalizer() { \
303 if (force_always_trace || \
304 CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
305 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
306 TRACE_EVENT_END(category); \
313 EventFinalizer(const EventFinalizer&) = delete; \
314 EventFinalizer& operator=(const EventFinalizer&) = delete; \
316 EventFinalizer(EventFinalizer&&) = default; \
317 EventFinalizer& operator=(EventFinalizer&&) = delete; \
319 } SK_PERFETTO_UID(scoped_event) { \
321 static_assert(!force_always_trace || \
322 ::skia_private::StrEndsWithAndLongerThan(category, ".always"), \
323 "[force_always_trace == true] requires [category] to end in '.always'"); \
324 if (force_always_trace || \
325 CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
326 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
327 TRACE_EVENT_BEGIN(category, name, ##__VA_ARGS__); \
329 ATRACE_BEGIN(::skia_private::UnboxPerfettoString(name)); \
337#define TRACE_EVENT_ATRACE_OR_PERFETTO(category, name, ...) \
338 TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE( \
339 false, category, name, ##__VA_ARGS__)
341#define ATRACE_ANDROID_FRAMEWORK(fmt, ...) \
342 char SK_PERFETTO_UID(skTraceStrBuf)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
343 if (SkAndroidFrameworkTraceUtil::getEnableTracing()) { \
344 snprintf(SK_PERFETTO_UID(skTraceStrBuf), SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
345 fmt, ##__VA_ARGS__); \
347 TRACE_EVENT0("skia.android", TRACE_STR_COPY(SK_PERFETTO_UID(skTraceStrBuf)))
349#define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) \
350 char SK_PERFETTO_UID(skTraceStrBuf)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
351 snprintf(SK_PERFETTO_UID(skTraceStrBuf), SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
352 fmt, ##__VA_ARGS__); \
353 TRACE_EVENT0_ALWAYS("skia.android", TRACE_STR_COPY(SK_PERFETTO_UID(skTraceStrBuf)))
358#define TRACE_EVENT0(category_group, name) \
359 TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name)
361#define TRACE_EVENT0_ALWAYS(category_group, name) TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE( \
362 true, category_group ".always", name)
363#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
364 TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val)
365#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
366 TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
371#define TRACE_EVENT_INSTANT0(category_group, name, scope) \
372 do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name); } while(0)
374#define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
375 do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val); } while(0)
377#define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
378 arg2_name, arg2_val) \
379 do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val, \
380 arg2_name, arg2_val); } while(0)
384#define TRACE_COUNTER1(category_group, name, value) \
385 if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
386 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
387 TRACE_COUNTER(category_group, name, value); \
389 ATRACE_INT(name, value); \
396#define TRACE_COUNTER2(category_group, name, value1_name, value1_val, value2_name, value2_val) \
397 if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
398 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
399 TRACE_COUNTER(category_group, name "-" value1_name, value1_val); \
400 TRACE_COUNTER(category_group, name "-" value2_name, value2_val); \
402 ATRACE_INT(name "-" value1_name, value1_val); \
403 ATRACE_INT(name "-" value2_name, value2_val); \
409#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
410 TRACE_EMPTY(category_group, name, id)
411#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, snapshot) \
412 TRACE_EMPTY(category_group, name, id, snapshot)
413#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
414 TRACE_EMPTY(category_group, name, id)
418#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
419 if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing() && \
420 SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents)) { \
421 *ret = TRACE_EVENT_CATEGORY_ENABLED(category_group); \
428#define ATRACE_ANDROID_FRAMEWORK(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
429#define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
433#define TRACE_EVENT0(category_group, name) \
434 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
436#define TRACE_EVENT0_ALWAYS(category_group, name) \
437 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
439#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
440 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val)
442#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
443 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
447#define TRACE_EVENT_INSTANT0(category_group, name, scope) \
448 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
449 TRACE_EVENT_FLAG_NONE | scope)
451#define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
452 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
453 TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val)
455#define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
456 arg2_name, arg2_val) \
457 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
458 TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val, \
463#define TRACE_COUNTER1(category_group, name, value) \
464 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
465 TRACE_EVENT_FLAG_NONE, "value", \
466 static_cast<int>(value))
471#define TRACE_COUNTER2(category_group, name, value1_name, value1_val, \
472 value2_name, value2_val) \
473 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
474 TRACE_EVENT_FLAG_NONE, value1_name, \
475 static_cast<int>(value1_val), value2_name, \
476 static_cast<int>(value2_val))
478#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
479 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
480 TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, TRACE_EVENT_FLAG_NONE)
481#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
482 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
483 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
484#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
485 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
486 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
488#define TRACE_EVENT_ASYNC_END0(category, name, id) \
489 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
490 category, name, id, TRACE_EVENT_FLAG_NONE)
491#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
492 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
493 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
494#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
495 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
496 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
499#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
500 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
501 TRACE_EVENT_PHASE_CREATE_OBJECT, category_group, name, id, \
502 TRACE_EVENT_FLAG_NONE)
504#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, \
506 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
507 TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name, \
508 id, TRACE_EVENT_FLAG_NONE, "snapshot", snapshot)
510#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
511 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
512 TRACE_EVENT_PHASE_DELETE_OBJECT, category_group, name, id, \
513 TRACE_EVENT_FLAG_NONE)
516#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
518 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
519 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
529#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned int>(0))
530#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned int>(1 << 0))
531#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned int>(1 << 1))
532#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned int>(1 << 2))
533#define TRACE_EVENT_FLAG_SCOPE_OFFSET (static_cast<unsigned int>(1 << 3))
534#define TRACE_EVENT_FLAG_SCOPE_EXTRA (static_cast<unsigned int>(1 << 4))
535#define TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP (static_cast<unsigned int>(1 << 5))
536#define TRACE_EVENT_FLAG_ASYNC_TTS (static_cast<unsigned int>(1 << 6))
537#define TRACE_EVENT_FLAG_BIND_TO_ENCLOSING (static_cast<unsigned int>(1 << 7))
538#define TRACE_EVENT_FLAG_FLOW_IN (static_cast<unsigned int>(1 << 8))
539#define TRACE_EVENT_FLAG_FLOW_OUT (static_cast<unsigned int>(1 << 9))
540#define TRACE_EVENT_FLAG_HAS_CONTEXT_ID (static_cast<unsigned int>(1 << 10))
542#define TRACE_EVENT_FLAG_SCOPE_MASK \
543 (static_cast<unsigned int>(TRACE_EVENT_FLAG_SCOPE_OFFSET | \
544 TRACE_EVENT_FLAG_SCOPE_EXTRA))
547#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
548#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
549#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))
550#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))
551#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))
552#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
553#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
554#define TRACE_VALUE_TYPE_CONVERTABLE (static_cast<unsigned char>(8))
557#define TRACE_EVENT_SCOPE_GLOBAL (static_cast<unsigned char>(0 << 3))
558#define TRACE_EVENT_SCOPE_PROCESS (static_cast<unsigned char>(1 << 3))
559#define TRACE_EVENT_SCOPE_THREAD (static_cast<unsigned char>(2 << 3))
561#define TRACE_EVENT_SCOPE_NAME_GLOBAL ('g')
562#define TRACE_EVENT_SCOPE_NAME_PROCESS ('p')
563#define TRACE_EVENT_SCOPE_NAME_THREAD ('t')
#define SK_PRINTF_LIKE(A, B)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
PERFETTO_DEFINE_CATEGORIES()
uint32_t uint32_t * format