• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 #ifndef SkTraceEventCommon_DEFINED
5 #define SkTraceEventCommon_DEFINED
6 
7 #include "include/core/SkTypes.h"
8 #include "include/utils/SkTraceEventPhase.h"
9 
10 // Trace events are for tracking application performance and resource usage.
11 // Macros are provided to track:
12 //    Duration of scoped regions
13 //    Instantaneous events
14 //    Counters
15 //
16 // The first two arguments to all TRACE macros are the category and name. Both are strings, and
17 // must have application lifetime (statics or literals). The same applies to arg_names, and string
18 // argument values. However, you can force a copy of a string argument value with TRACE_STR_COPY:
19 //     TRACE_EVENT1("category", "name", "arg1", "literal string is only referenced");
20 //     TRACE_EVENT1("category", "name", "arg1", TRACE_STR_COPY("string will be copied"));
21 //
22 //
23 // Categories are used to group events, and
24 // can be enabled or disabled by the tracing framework. The trace system will automatically add the
25 // process id, thread id, and microsecond timestamp to all events.
26 //
27 //
28 // The TRACE_EVENT[0-2] macros trace the duration of entire scopes:
29 //   void doSomethingCostly() {
30 //     TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
31 //     ...
32 //   }
33 //
34 // Additional parameters can be associated with an event:
35 //   void doSomethingCostly2(int howMuch) {
36 //     TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", "howMuch", howMuch);
37 //     ...
38 //   }
39 //
40 //
41 // Trace event also supports counters, which is a way to track a quantity as it varies over time.
42 // Counters are created with the following macro:
43 //   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
44 //
45 // Counters are process-specific. The macro itself can be issued from any thread, however.
46 //
47 // Sometimes, you want to track two counters at once. You can do this with two counter macros:
48 //   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
49 //   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
50 // Or you can do it with a combined macro:
51 //   TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
52 //                  "bytesPinned", g_myCounterValue[0],
53 //                  "bytesAllocated", g_myCounterValue[1]);
54 // The tracing UI will show these counters in a single graph, as a summed area chart.
55 
56 #if defined(TRACE_EVENT0)
57     #error "Another copy of this file has already been included."
58 #endif
59 
60 enum DebugTraceLevel {
61     NORMAL = 1,
62     DETAIL = 2,
63 };
64 
65 // --- Temporary Perfetto migration shim preamble ---
66 // Tracing in the Android framework, and tracing with Perfetto, are both in a partially migrated
67 // state (but fully functional).
68 //
69 // See go/skia-perfetto
70 //
71 // For Android framework:
72 // ---
73 // 1. If SK_ANDROID_FRAMEWORK_USE_PERFETTO is not defined, then all tracing macros map to no-ops.
74 // This is only relevant to host-mode builds, where ATrace isn't supported anyway, and tracing with
75 // Perfetto seems unnecessary. Note that SkAndroidFrameworkTraceUtil is still defined (assuming
76 // SK_BUILD_FOR_ANDROID_FRAMEWORK is defined) to support HWUI referencing it in host-mode builds.
77 //
78 // 2. If SK_ANDROID_FRAMEWORK_USE_PERFETTO *is* defined, then the tracing backend can be switched
79 // between ATrace and Perfetto at runtime. This is currently *only* supported in Android framework.
80 // SkAndroidFrameworkTraceUtil::setEnableTracing(bool) will still control broad tracing overall, but
81 // SkAndroidFrameworkTraceUtil::setUsePerfettoTrackEvents(bool) will now determine whether that
82 // tracing is done with ATrace (default/false) or Perfetto (true).
83 //
84 // Note: if setUsePerfettoTrackEvents(true) is called, then Perfetto will remain initialized until
85 // the process ends. This means some minimal state overhead will remain even after subseqently
86 // switching the process back to ATrace, but individual trace events will be correctly routed to
87 // whichever system is active in the moment. However, trace events which have begun but have not yet
88 // ended when a switch occurs will likely be corrupted. Thus, it's best to minimize the frequency of
89 // switching backend tracing systems at runtime.
90 //
91 // For Perfetto outside of Android framework (e.g. tools):
92 // ---
93 // SK_USE_PERFETTO (mutually exclusive with SK_ANDROID_FRAMEWORK_USE_PERFETTO) can be used to unlock
94 // SkPerfettoTrace, which can be used for in-process tracing via the standard Skia tracing flow of
95 // SkEventTracer::SetInstance(...). This is enabled in tools with the `--trace perfetto` argument.
96 // See https://skia.org/docs/dev/tools/tracing/#tracing-with-perfetto for more on SK_USE_PERFETTO.
97 
98 #ifdef SK_ANDROID_FRAMEWORK_USE_PERFETTO
99 
100 // PERFETTO_TRACK_EVENT_NAMESPACE must be defined before including Perfetto. This allows Skia to
101 // maintain separate "track event" category storage, etc. from codebases linked into the same
102 // executable, and avoid symbol duplication errors.
103 //
104 // NOTE: A side-effect of this is we must use skia::TrackEvent instead of perfetto::TrackEvent.
105 #define PERFETTO_TRACK_EVENT_NAMESPACE skia
106 #include <perfetto/tracing.h>
107 
108 #include <cutils/trace.h>
109 #include <stdarg.h>
110 #include <string_view>
111 
112 // WARNING: this list must be kept up to date with every category we use for tracing!
113 //
114 // When adding a new category it's likely best to add both "new_category" and "new_category.always",
115 // though not strictly required. "new_category.always" is used internally when "new_category" is
116 // given to TRACE_EVENTx_ALWAYS macros, which are used for core events that should always show up in
117 // traces for the Android framework. Adding both to begin with will likely reduce churn if/when
118 // "new_category" is used across both normal tracing macros and _ALWAYS variants in the future, but
119 // it's not a strict requirement.
120 //
121 // See stages section of go/skia-perfetto for timeline of when this should improve.
122 //
123 // TODO(b/262718654): make this compilation failure happen sooner than the Skia -> Android roll.
124 //
125 // Currently kept entirely separate from SkPerfettoTrace for simplicity, which uses dynamic
126 // categories and doesn't need these static category definitions.
127 PERFETTO_DEFINE_CATEGORIES(
128     perfetto::Category("GM"),
129     perfetto::Category("skia"),
130     perfetto::Category("skia.android"),
131     perfetto::Category("skia.gpu"),
132     perfetto::Category("skia.gpu.cache"),
133     perfetto::Category("skia.objects"),
134     perfetto::Category("skia.shaders"),
135     perfetto::Category("skottie"),
136     perfetto::Category("test"),
137     perfetto::Category("test_cpu"),
138     perfetto::Category("test_ganesh"),
139     perfetto::Category("test_graphite"),
140     // ".always" variants are currently required for any category used in TRACE_EVENTx_ALWAYS.
141     perfetto::Category("GM.always").SetTags("skia.always"),
142     perfetto::Category("skia.always").SetTags("skia.always"),
143     perfetto::Category("skia.android.always").SetTags("skia.always"),
144     perfetto::Category("skia.gpu.always").SetTags("skia.always"),
145     perfetto::Category("skia.gpu.cache.always").SetTags("skia.always"),
146     perfetto::Category("skia.objects.always").SetTags("skia.always"),
147     perfetto::Category("skia.shaders.always").SetTags("skia.always"),
148     perfetto::Category("skottie.always").SetTags("skia.always"),
149     perfetto::Category("test.always").SetTags("skia.always"),
150     perfetto::Category("test_cpu.always").SetTags("skia.always"),
151     perfetto::Category("test_ganesh.always").SetTags("skia.always"),
152     perfetto::Category("test_graphite.always").SetTags("skia.always"),
153 );
154 
155 #endif // SK_ANDROID_FRAMEWORK_USE_PERFETTO
156 
157 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
158 
159 #ifdef SK_DISABLE_TRACING
160 #error SK_DISABLE_TRACING and SK_BUILD_FOR_ANDROID_FRAMEWORK are mutually exclusive.
161 #endif // SK_DISABLE_TRACING [&& SK_BUILD_FOR_ANDROID_FRAMEWORK]
162 
163 #define SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE 512
164 
165 class SkAndroidFrameworkTraceUtil {
166 public:
167     SkAndroidFrameworkTraceUtil() = delete;
168 
169     // Controls whether broad tracing is enabled. Warning: not thread-safe!
170     //
171     // Some key trace events may still be recorded when this is disabled, if a relevant tracing
172     // session is active.
173     //
174     // ATrace is used by default, but can be replaced with Perfetto by calling
175     // setUsePerfettoTrackEvents(true)
setEnableTracing(bool enableAndroidTracing)176     static void setEnableTracing(bool enableAndroidTracing) {
177         gEnableAndroidTracing = enableAndroidTracing;
178     }
179 
180     // Controls whether tracing uses Perfetto instead of ATrace. Warning: not thread-safe!
181     //
182     // Returns true if Skia was built with Perfetto, false otherwise.
setUsePerfettoTrackEvents(bool usePerfettoTrackEvents)183     static bool setUsePerfettoTrackEvents(bool usePerfettoTrackEvents) {
184 #ifdef SK_ANDROID_FRAMEWORK_USE_PERFETTO
185         // Ensure Perfetto is initialized if it wasn't already the preferred tracing backend.
186         if (!gUsePerfettoTrackEvents && usePerfettoTrackEvents) {
187             initPerfetto();
188         }
189         gUsePerfettoTrackEvents = usePerfettoTrackEvents;
190         return true;
191 #else // !SK_ANDROID_FRAMEWORK_USE_PERFETTO
192         return false;
193 #endif // SK_ANDROID_FRAMEWORK_USE_PERFETTO
194     }
195 
getEnableTracing()196     static bool getEnableTracing() {
197         return gEnableAndroidTracing;
198     }
199 
getUsePerfettoTrackEvents()200     static bool getUsePerfettoTrackEvents() {
201         return gUsePerfettoTrackEvents;
202     }
203 
204 private:
205     static bool gEnableAndroidTracing;
206     static bool gUsePerfettoTrackEvents;
207 
208 #ifdef SK_ANDROID_FRAMEWORK_USE_PERFETTO
209     // Initializes tracing systems, and establishes a connection to the 'traced' daemon.
210     //
211     // Can be called multiple times.
initPerfetto()212     static void initPerfetto() {
213         ::perfetto::TracingInitArgs perfettoArgs;
214         perfettoArgs.backends |= perfetto::kSystemBackend;
215         ::perfetto::Tracing::Initialize(perfettoArgs);
216         ::skia::TrackEvent::Register();
217     }
218 #endif // SK_ANDROID_FRAMEWORK_USE_PERFETTO
219 };
220 #endif // SK_BUILD_FOR_ANDROID_FRAMEWORK
221 
222 #ifdef SK_DEBUG
223 static void skprintf_like_noop(const char format[], ...) SK_PRINTF_LIKE(1, 2);
skprintf_like_noop(const char format[],...)224 static inline void skprintf_like_noop(const char format[], ...) {}
225 template <typename... Args>
sk_noop(Args...)226 static inline void sk_noop(Args...) {}
227 #define TRACE_EMPTY(...) do { sk_noop(__VA_ARGS__); } while (0)
228 #define TRACE_EMPTY_FMT(fmt, ...) do { skprintf_like_noop(fmt, ##__VA_ARGS__); } while (0)
229 #else
230 #define TRACE_EMPTY(...) do {} while (0)
231 #define TRACE_EMPTY_FMT(fmt, ...) do {} while (0)
232 #endif
233 
234 #if defined(SK_DISABLE_TRACING) || \
235         (defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && !defined(SK_ANDROID_FRAMEWORK_USE_PERFETTO))
236 
237     #define ATRACE_ANDROID_FRAMEWORK(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
238     #define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
239     #define TRACE_EVENT0(cg, n) TRACE_EMPTY(cg, n)
240     #define TRACE_EVENT1(cg, n, a1n, a1v) TRACE_EMPTY(cg, n, a1n, a1v)
241     #define TRACE_EVENT2(cg, n, a1n, a1v, a2n, a2v) TRACE_EMPTY(cg, n, a1n, a1v, a2n, a2v)
242     #define TRACE_EVENT0_ALWAYS(cg, n) TRACE_EMPTY(cg, n)
243     #define TRACE_EVENT1_ALWAYS(cg, n, a1n, a1v) TRACE_EMPTY(cg, n, a1n, a1v)
244     #define TRACE_EVENT2_ALWAYS(cg, n, a1n, a1v, a2n, a2v) TRACE_EMPTY(cg, n, a1n, a1v, a2n, a2v)
245     #define TRACE_EVENT_INSTANT0(cg, n, scope) TRACE_EMPTY(cg, n, scope)
246     #define TRACE_EVENT_INSTANT1(cg, n, scope, a1n, a1v) TRACE_EMPTY(cg, n, scope, a1n, a1v)
247     #define TRACE_EVENT_INSTANT2(cg, n, scope, a1n, a1v, a2n, a2v)  \
248         TRACE_EMPTY(cg, n, scope, a1n, a1v, a2n, a2v)
249     #define TRACE_EVENT_OBJECT_CREATED_WITH_ID(cg, n, id) TRACE_EMPTY(cg, n, id)
250     #define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(cg, n, id, ss) TRACE_EMPTY(cg, n, id, ss)
251     #define TRACE_EVENT_OBJECT_DELETED_WITH_ID(cg, n, id) TRACE_EMPTY(cg, n, id)
252     #define TRACE_COUNTER1(cg, n, value) TRACE_EMPTY(cg, n, value)
253     #define TRACE_COUNTER2(cg, n, v1n, v1v, v2n, v2v) TRACE_EMPTY(cg, n, v1n, v1v, v2n, v2v)
254 
255     #define HITRACE_OHOS_NAME_ALWAYS(name) TRACE_EMPTY(name)
256     #define HITRACE_OHOS_NAME_FMT_LEVEL(debugLevel, fmt, ...) TRACE_EMPTY(fmt, ##__VA_ARGS__)
257     #define HITRACE_OHOS_NAME_FMT_ALWAYS(fmt, ...) TRACE_EMPTY(fmt, ##__VA_ARGS__)
258     #define SKIA_OHOS_TRACE_PRIV(category_group, name) TRACE_EMPTY(category_group, name)
259 
260 #elif defined(SK_ANDROID_FRAMEWORK_USE_PERFETTO)
261 
262 #define HITRACE_OHOS_NAME_ALWAYS(name) TRACE_EMPTY(name)
263 #define HITRACE_OHOS_NAME_FMT_LEVEL(debugLevel, fmt, ...) TRACE_EMPTY(fmt, ##__VA_ARGS__)
264 #define HITRACE_OHOS_NAME_FMT_ALWAYS(fmt, ...) TRACE_EMPTY(fmt, ##__VA_ARGS__)
265 #define SKIA_OHOS_TRACE_PRIV(category_group, name) TRACE_EMPTY(category_group, name)
266 
267 namespace skia_private {
268     // ATrace can't accept ::perfetto::DynamicString or ::perfetto::StaticString, so any trace event
269     // names that were wrapped in TRACE_STR_COPY or TRACE_STR_STATIC need to be unboxed back to
270     // char* before being passed to ATrace.
UnboxPerfettoString(const::perfetto::DynamicString & str)271     inline const char* UnboxPerfettoString(const ::perfetto::DynamicString& str) {
272         return str.value;
273     }
UnboxPerfettoString(const::perfetto::StaticString & str)274     inline const char* UnboxPerfettoString(const ::perfetto::StaticString& str) {
275         return str.value;
276     }
UnboxPerfettoString(const char * str)277     inline const char* UnboxPerfettoString(const char* str) {
278         return str;
279     }
280 
281     // WrapTraceArgInStdString serves a similar purpose to UnboxPerfettoString, but also accepts
282     // numeric values that are often used as trace arguments. This necessitates always wrapping the
283     // argument in a new std::string, instead of just passing along/unboxing an existing C-style
284     // string. This comes at a slight cost, and should only be used for trace slice arguments but
285     // not slice names, where UnboxPerfettoString should be used instead.
286     template<typename T>
WrapTraceArgInStdString(const T numeric)287     inline std::string WrapTraceArgInStdString(const T numeric) {
288         return std::to_string(numeric);
289     }
WrapTraceArgInStdString(const::perfetto::DynamicString & str)290     inline std::string WrapTraceArgInStdString(const ::perfetto::DynamicString& str) {
291         return std::string(str.value);
292     }
WrapTraceArgInStdString(const::perfetto::StaticString & str)293     inline std::string WrapTraceArgInStdString(const ::perfetto::StaticString& str) {
294         return std::string(str.value);
295     }
WrapTraceArgInStdString(const char * str)296     inline std::string WrapTraceArgInStdString(const char* str) {
297         return std::string(str);
298     }
299 
StrEndsWithAndLongerThan(const char * str,const char * suffix)300     constexpr bool StrEndsWithAndLongerThan(const char* str, const char* suffix) {
301         auto strView = std::basic_string_view(str);
302         auto suffixView = std::basic_string_view(suffix);
303         // string_view::ends_with isn't available until C++20
304         return strView.size() > suffixView.size() &&
305                 strView.compare(strView.size() - suffixView.size(),
306                                 std::string_view::npos, suffixView) == 0;
307     }
308 }
309 
310 // Generate a unique variable name with a given prefix.
311 // The indirection in this multi-level macro lets __LINE__ expand at the right time/place to get
312 // prefix123 instead of prefix__LINE__.
313 #define SK_PERFETTO_INTERNAL_CONCAT2(a, b) a##b
314 #define SK_PERFETTO_INTERNAL_CONCAT(a, b) SK_PERFETTO_INTERNAL_CONCAT2(a, b)
315 #define SK_PERFETTO_UID(prefix) SK_PERFETTO_INTERNAL_CONCAT(prefix, __LINE__)
316 
317 // Used by SK_INTERNAL_ATRACE_ARGS_BEGIN and SK_INTERNAL_ATRACE_ARGS_END to select which overloaded
318 // macro to use depending on how many __VA_ARGS__ are present. The number of __VA_ARGS__ piped in
319 // from this macro caller's parent caller determines which macro name given by the caller ends up in
320 // the macro_name slot here. See usage for nuance.
321 #define SK_INTERNAL_GET_ATRACE_ARGS_MACRO(_0, _1a, _1b, _2a, _2b, macro_name, ...) macro_name
322 
323 // WARNING: must always be guarded by an outer call to CC_UNLIKELY(ATRACE_ENABLED())
324 #define SK_INTERNAL_ATRACE_ARGS_BEGIN_DANGEROUS_0(name) \
325     atrace_begin_body(::skia_private::UnboxPerfettoString(name));
326 
327 // WARNING: must always be guarded by an outer call to CC_UNLIKELY(ATRACE_ENABLED())
328 #define SK_INTERNAL_ATRACE_ARGS_BEGIN_DANGEROUS_1(name, arg1_name, arg1_val)       \
329     char SK_PERFETTO_UID(skTraceStrBuf1)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
330     snprintf(SK_PERFETTO_UID(skTraceStrBuf1),                                      \
331              SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE,                              \
332              "^(%s: %s)",                                                          \
333              ::skia_private::UnboxPerfettoString(arg1_name),                       \
334              ::skia_private::WrapTraceArgInStdString(arg1_val).c_str());           \
335     atrace_begin_body(::skia_private::UnboxPerfettoString(name));                  \
336     atrace_begin_body(SK_PERFETTO_UID(skTraceStrBuf1));
337 
338 // WARNING: must always be guarded by an outer call to CC_UNLIKELY(ATRACE_ENABLED())
339 #define SK_INTERNAL_ATRACE_ARGS_BEGIN_DANGEROUS_2(                                 \
340         name, arg1_name, arg1_val, arg2_name, arg2_val, ...)                       \
341     char SK_PERFETTO_UID(skTraceStrBuf1)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
342     char SK_PERFETTO_UID(skTraceStrBuf2)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
343     snprintf(SK_PERFETTO_UID(skTraceStrBuf1),                                      \
344              SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE,                              \
345              "^(%s: %s)",                                                          \
346              ::skia_private::UnboxPerfettoString(arg1_name),                       \
347              ::skia_private::WrapTraceArgInStdString(arg1_val).c_str());           \
348     snprintf(SK_PERFETTO_UID(skTraceStrBuf2),                                      \
349              SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE,                              \
350             "^(%s: %s)",                                                           \
351              ::skia_private::UnboxPerfettoString(arg2_name),                       \
352              ::skia_private::WrapTraceArgInStdString(arg2_val).c_str());           \
353     atrace_begin_body(::skia_private::UnboxPerfettoString(name));                  \
354     atrace_begin_body(SK_PERFETTO_UID(skTraceStrBuf1));                            \
355     atrace_begin_body(SK_PERFETTO_UID(skTraceStrBuf2));
356 
357 // Will map to either the 0, 1, or 2 argument variant of this macro, which will trigger an
358 // ATRACE_BEGIN event for the slice name, and one for each argument <name, value> pair. The caller
359 // must ensure each of these 1-3 slices are properly terminated with 1-3 matching ATRACE_END events.
360 //
361 // Note: ATRACE_ENABLED() is checked here to allow the actual implmenting macros to avoid redundant
362 // checks within each of their calls to the standard ATRACE_BEGIN() macro, as checking
363 // ATRACE_ENABLED() can be non-trivial. But more importantly, if tracing isn't enabled then we
364 // should avoid the string formatting work required for how we hack "arguments" into separate ATrace
365 // slices.
366 #define SK_INTERNAL_ATRACE_ARGS_BEGIN(slice_name, ...)                              \
367     if (CC_UNLIKELY(ATRACE_ENABLED())) {                                            \
368         SK_INTERNAL_GET_ATRACE_ARGS_MACRO(0,                                        \
369                                         ##__VA_ARGS__,                              \
370                                         SK_INTERNAL_ATRACE_ARGS_BEGIN_DANGEROUS_2,  \
371                                         0,                                          \
372                                         SK_INTERNAL_ATRACE_ARGS_BEGIN_DANGEROUS_1,  \
373                                         0,                                          \
374                                         SK_INTERNAL_ATRACE_ARGS_BEGIN_DANGEROUS_0)  \
375         (slice_name, ##__VA_ARGS__);                                                \
376     }
377 
378 // WARNING: must always be guarded by an outer call to CC_UNLIKELY(ATRACE_ENABLED())
379 #define SK_INTERNAL_ATRACE_ARGS_END_DANGEROUS_2(arg1_name, arg1_val, arg2_name, arg2_val, ...)  \
380     atrace_end_body();                                                                          \
381     atrace_end_body();                                                                          \
382     atrace_end_body();
383 
384 // WARNING: must always be guarded by an outer call to CC_UNLIKELY(ATRACE_ENABLED())
385 #define SK_INTERNAL_ATRACE_ARGS_END_DANGEROUS_1(arg1_name, arg1_val)    \
386     atrace_end_body();                                                  \
387     atrace_end_body();
388 
389 // WARNING: must always be guarded by an outer call to CC_UNLIKELY(ATRACE_ENABLED())
390 #define SK_INTERNAL_ATRACE_ARGS_END_DANGEROUS_0() \
391     atrace_end_body();
392 
393 // Will map to either the 0, 1, or 2 argument variant of this macro, which will trigger an
394 // ATRACE_END event for the slice name, and one for each argument <name, value> pair. The caller
395 // must ensure each of these 1-3 slices already existed from 1-3 matching ATRACE_BEGIN events.
396 //
397 // Note: ATRACE_ENABLED() is checked here to allow the actual implmenting macros to avoid redundant
398 // checks within each of their calls to the standard ATRACE_END() macro, as checking
399 // ATRACE_ENABLED() can be non-trivial.
400 #define SK_INTERNAL_ATRACE_ARGS_END(...)                                            \
401     if (CC_UNLIKELY(ATRACE_ENABLED())) {                                            \
402         SK_INTERNAL_GET_ATRACE_ARGS_MACRO(0,                                        \
403                                         ##__VA_ARGS__,                              \
404                                         SK_INTERNAL_ATRACE_ARGS_END_DANGEROUS_2,    \
405                                         0,                                          \
406                                         SK_INTERNAL_ATRACE_ARGS_END_DANGEROUS_1,    \
407                                         0,                                          \
408                                         SK_INTERNAL_ATRACE_ARGS_END_DANGEROUS_0)    \
409         (__VA_ARGS__);                                                              \
410     }
411 
412 // Assuming there is an active tracing session, this call will create a trace event if tracing is
413 // enabled (with SkAndroidFrameworkTraceUtil::setEnableTracing(true)) or if force_always_trace is
414 // true. The event goes through ATrace by default, but can be routed to Perfetto instead by calling
415 // SkAndroidFrameworkTraceUtil::setUsePerfettoTrackEvents(true).
416 //
417 // If ATrace is used, then additional sub-events will be created for each trace event argument
418 // <name, value> pair (up to a max of two argument pairs). If Perfetto is used, then any arguments
419 // will be associated with a single event. In either case, trace arguments will only be evaluated if
420 // the event will actually be recorded in the underlying tracing system (i.e. if an applicable
421 // tracing session is active.)
422 //
423 // If force_always_trace = true, then the caller *must* append the ".always" suffix to the provided
424 // category. This allows Perfetto tracing sessions to optionally filter to just the "skia.always"
425 // category tag. This requirement is enforced at compile time.
426 #define TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE(force_always_trace, category, name, ...)       \
427     struct SK_PERFETTO_UID(ScopedEvent) {                                                       \
428         struct EventFinalizer {                                                                 \
429             /* The ... parameter slot is an implementation detail. It allows the */             \
430             /* anonymous struct to use aggregate initialization to invoke the    */             \
431             /* lambda (which emits the BEGIN event and returns an integer)       */             \
432             /* with the proper reference capture for any                         */             \
433             /* TrackEventArgumentFunction in |__VA_ARGS__|. This is required so  */             \
434             /* that the scoped event is exactly ONE line and can't escape the    */             \
435             /* scope if used in a single line if statement.                      */             \
436             EventFinalizer(...) {}                                                              \
437             ~EventFinalizer() {                                                                 \
438                 if (force_always_trace ||                                                       \
439                         CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) {         \
440                     if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) {             \
441                         TRACE_EVENT_END(category);                                              \
442                     } else {                                                                    \
443                         SK_INTERNAL_ATRACE_ARGS_END(__VA_ARGS__);                               \
444                     }                                                                           \
445                 }                                                                               \
446             }                                                                                   \
447                                                                                                 \
448             EventFinalizer(const EventFinalizer&) = delete;                                     \
449             EventFinalizer& operator=(const EventFinalizer&) = delete;                          \
450                                                                                                 \
451             EventFinalizer(EventFinalizer&&) = default;                                         \
452             EventFinalizer& operator=(EventFinalizer&&) = delete;                               \
453         } finalizer;                                                                            \
454     } SK_PERFETTO_UID(scoped_event) {                                                           \
455         [&]() {                                                                                 \
456             static_assert(!force_always_trace ||                                                \
457                         ::skia_private::StrEndsWithAndLongerThan(category, ".always"),          \
458                     "[force_always_trace == true] requires [category] to end in '.always'");    \
459             if (force_always_trace ||                                                           \
460                     CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) {             \
461                 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) {                 \
462                     TRACE_EVENT_BEGIN(category, name, ##__VA_ARGS__);                           \
463                 } else {                                                                        \
464                     SK_INTERNAL_ATRACE_ARGS_BEGIN(name, ##__VA_ARGS__);                         \
465                 }                                                                               \
466             }                                                                                   \
467             return 0;                                                                           \
468         }()                                                                                     \
469     }
470 
471 // Records an event with the current tracing backend if overall tracing is enabled, and Skia's
472 // "broad" tracing is enabled with SkAndroidFrameworkTraceUtil::setEnableTracing(true).
473 #define TRACE_EVENT_ATRACE_OR_PERFETTO(category, name, ...)                     \
474     TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE(                                   \
475             /* force_always_trace = */ false, category, name, ##__VA_ARGS__)
476 
477 // Traces a formatted string if overall tracing is enabled, and Skia's "broad" tracing is enabled
478 // with SkAndroidFrameworkTraceUtil::setEnableTracing(true).
479 // No-op outside of Android framework builds.
480 // WARNING: this macro expands to a multi-line statement, and must not be used in a single line
481 // control statement!
482 #define ATRACE_ANDROID_FRAMEWORK(fmt, ...)                                                  \
483     char SK_PERFETTO_UID(skTraceStrBuf)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE];           \
484     if (SkAndroidFrameworkTraceUtil::getEnableTracing()) {                                  \
485         snprintf(SK_PERFETTO_UID(skTraceStrBuf), SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE,   \
486                  fmt, ##__VA_ARGS__);                                                       \
487     }                                                                                       \
488     TRACE_EVENT0("skia.android", TRACE_STR_COPY(SK_PERFETTO_UID(skTraceStrBuf)))
489 
490 // Traces a formatted string as long as overall tracing is enabled, even if Skia's "broad" tracing
491 // is disabled.
492 // No-op outside of Android framework builds.
493 // WARNING: this macro expands to a multi-line statement, and must not be used in a single line
494 // control statement!
495 #define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...)                                           \
496     char SK_PERFETTO_UID(skTraceStrBuf)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE];           \
497     snprintf(SK_PERFETTO_UID(skTraceStrBuf), SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE,       \
498              fmt, ##__VA_ARGS__);                                                           \
499     TRACE_EVENT0_ALWAYS("skia.android", TRACE_STR_COPY(SK_PERFETTO_UID(skTraceStrBuf)))
500 
501 // Records a pair of begin and end events called "name" (with 0-2 associated arguments) for the
502 // current scope as long as overall tracing is enabled, and Skia's "broad" tracing is enabled with
503 // SkAndroidFrameworkTraceUtil::setEnableTracing(true).
504 // Note that ATrace does not natively support trace arguments, so arguments are recorded as separate
505 // sub-events when ATrace is set as the current tracing backend. The Perfetto tracing backend
506 // associates any arguments with a single event / slice.
507 #define TRACE_EVENT0(category_group, name) \
508     TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name)
509 #define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
510     TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val)
511 #define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
512     TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
513 
514 // Records a pair of begin and end events called "name" (with 0-2 associated arguments) for the
515 // current scope as long as overall tracing is enabled, even if Skia's "broad" tracing is disabled.
516 // Note that ATrace does not natively support trace arguments, so arguments are recorded as separate
517 // sub-events when ATrace is set as the current tracing backend. The Perfetto tracing backend
518 // associates any arguments with a single event / slice.
519 // Note: the ".always" suffix is appended to category_group in _ALWAYS trace event macro variants.
520 #define TRACE_EVENT0_ALWAYS(category_group, name) \
521     TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE(     \
522             /* force_always_trace = */ true, category_group ".always", name)
523 #define TRACE_EVENT1_ALWAYS(category_group, name, arg1_name, arg1_val) \
524     TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE(                          \
525             /* force_always_trace = */ true, category_group ".always", name, arg1_name, arg1_val)
526 #define TRACE_EVENT2_ALWAYS(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
527     TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE(/* force_always_trace = */ true,               \
528                                              category_group ".always",                      \
529                                              name,                                          \
530                                              arg1_name,                                     \
531                                              arg1_val,                                      \
532                                              arg2_name,                                     \
533                                              arg2_val)
534 
535 // Records a single event called "name" immediately, with 0, 1 or 2 associated arguments.
536 // Note that ATrace does not support trace arguments, so they are only recorded when Perfetto is set
537 // as the current tracing backend.
538 #define TRACE_EVENT_INSTANT0(category_group, name, scope) \
539     do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name); } while(0)
540 
541 #define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
542     do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val); } while(0)
543 
544 #define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val,      \
545                              arg2_name, arg2_val)                                   \
546     do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val,  \
547                                         arg2_name, arg2_val); } while(0)
548 
549 // Records the value of a counter called "name" immediately. Value
550 // must be representable as a 32 bit integer.
551 #define TRACE_COUNTER1(category_group, name, value)                     \
552     if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
553         if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
554             TRACE_COUNTER(category_group, name, value);                 \
555         } else {                                                        \
556             ATRACE_INT(name, value);                                    \
557         }                                                               \
558     }
559 
560 // Records the values of a multi-parted counter called "name" immediately.
561 // In Chrome, this macro produces a stacked bar chart. Perfetto doesn't support
562 // that (related: b/242349575), so this just produces two separate counters.
563 #define TRACE_COUNTER2(category_group, name, value1_name, value1_val, value2_name, value2_val)  \
564     if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) {                         \
565         if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) {                         \
566             TRACE_COUNTER(category_group, name "-" value1_name, value1_val);                    \
567             TRACE_COUNTER(category_group, name "-" value2_name, value2_val);                    \
568         } else {                                                                                \
569             ATRACE_INT(name "-" value1_name, value1_val);                                       \
570             ATRACE_INT(name "-" value2_name, value2_val);                                       \
571         }                                                                                       \
572     }
573 
574 // ATrace has no object tracking, and would require a legacy shim for Perfetto (which likely no-ops
575 // here). Further, these don't appear to currently be used outside of tests.
576 #define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
577     TRACE_EMPTY(category_group, name, id)
578 #define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, snapshot) \
579     TRACE_EMPTY(category_group, name, id, snapshot)
580 #define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
581     TRACE_EMPTY(category_group, name, id)
582 
583 // Macro to efficiently determine if a given category group is enabled. Only works with Perfetto.
584 // This is only used for some shader text logging that isn't supported in ATrace anyway.
585 #define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret)                     \
586     if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing() &&              \
587                     SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents)) {      \
588         *ret = TRACE_EVENT_CATEGORY_ENABLED(category_group);                        \
589     } else {                                                                        \
590         *ret = false;                                                               \
591     }
592 
593 #elif defined(SKIA_OHOS)
594 
595 #include <stdarg.h>
596 #include "hitrace_meter.h"
597 #include "securec.h"
598 
599 #ifdef NOT_BUILD_FOR_OHOS_SDK
600 #include "parameters.h"
601 #endif
602 
603 #define UNLIKELY(exp) (__builtin_expect((exp) != 0, false))
604 #define ATRACE_ANDROID_FRAMEWORK(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
605 #define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
606 #define HITRACE_OHOS_NAME_ALWAYS(name) HITRACE_METER_NAME(HITRACE_TAG_GRAPHIC_AGP | HITRACE_TAG_COMMERCIAL, name)
607 #define HITRACE_OHOS_NAME_FMT_LEVEL(debugLevel, fmt, ...) \
608     SkOHOSDebugLevelTraceUtil _ohosTraceLevel(debugLevel, fmt, ##__VA_ARGS__)
609 #define HITRACE_OHOS_NAME_FMT_ALWAYS(fmt, ...) \
610     HITRACE_METER_FMT(HITRACE_TAG_GRAPHIC_AGP | HITRACE_TAG_COMMERCIAL, fmt, ##__VA_ARGS__)
611 
612 #ifdef NOT_BUILD_FOR_OHOS_SDK
613 inline int gTraceDebugLevel =
614     std::atoi((OHOS::system::GetParameter("persist.sys.graphic.2dengine.openDebugTrace", "0")).c_str());
615 #else
616 inline int gTraceDebugLevel = 0;
617 #endif
618 
619 class SkOHOSTraceUtil {
620 public:
SkOHOSTraceUtil(const char * name)621     SkOHOSTraceUtil(const char* name) {
622         if (UNLIKELY(gTraceDebugLevel >= DebugTraceLevel::DETAIL)) {
623             StartTrace(HITRACE_TAG_GRAPHIC_AGP | HITRACE_TAG_COMMERCIAL, name);
624         }
625     }
626 
~SkOHOSTraceUtil()627     ~SkOHOSTraceUtil() {
628         if (UNLIKELY(gTraceDebugLevel >= DebugTraceLevel::DETAIL)) {
629             FinishTrace(HITRACE_TAG_GRAPHIC_AGP | HITRACE_TAG_COMMERCIAL);
630         }
631     }
632 };
633 
634 class SkOHOSDebugLevelTraceUtil {
635 public:
SkOHOSDebugLevelTraceUtil(int debugLevel,const char * fmt,...)636     SkOHOSDebugLevelTraceUtil(int debugLevel, const char* fmt, ...) {
637         fDebugLevel = debugLevel;
638         if (UNLIKELY(gTraceDebugLevel >= fDebugLevel)) {
639             const int BUFFER_SIZE = 256;
640             char buf[BUFFER_SIZE];
641             va_list args;
642             va_start(args, fmt);
643             if (vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, fmt, args) < 0) {
644                 va_end(args);
645                 StartTrace(HITRACE_TAG_GRAPHIC_AGP | HITRACE_TAG_COMMERCIAL, "Trace Error");
646                 return;
647             }
648             va_end(args);
649             StartTrace(HITRACE_TAG_GRAPHIC_AGP | HITRACE_TAG_COMMERCIAL, buf);
650         }
651     }
652 
~SkOHOSDebugLevelTraceUtil()653     ~SkOHOSDebugLevelTraceUtil() {
654         if (UNLIKELY(gTraceDebugLevel >= fDebugLevel)) {
655             FinishTrace(HITRACE_TAG_GRAPHIC_AGP | HITRACE_TAG_COMMERCIAL);
656         }
657     }
658 
getEnableDebugTrace()659     static bool getEnableDebugTrace() {
660         return gTraceDebugLevel > 0;
661     }
662 
663 private:
664     int fDebugLevel = 1;
665 };
666 
667 // print ohos trace without SKIA_OHOS_DEBUG macro
668 #define SKIA_OHOS_TRACE_PRIV(category_group, name) \
669     HitraceScoped _trace(HITRACE_TAG_GRAPHIC_AGP, name)
670 
671 #define TRACE_EVENT0(category_group, name) \
672     SkOHOSTraceUtil _ohosTrace(name)
673 
674 #define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
675     SkOHOSTraceUtil _ohosTrace(name)
676 
677 #define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
678     SkOHOSTraceUtil _ohosTrace(name)
679 
680 #define TRACE_EVENT0_ALWAYS(category_group, name) \
681     HITRACE_METER_NAME(HITRACE_TAG_GRAPHIC_AGP | HITRACE_TAG_COMMERCIAL, name)
682 
683 #define TRACE_EVENT1_ALWAYS(cg, n, a1n, a1v) TRACE_EMPTY(cg, n, a1n, a1v)
684 #define TRACE_EVENT2_ALWAYS(cg, n, a1n, a1v, a2n, a2v) TRACE_EMPTY(cg, n, a1n, a1v, a2n, a2v)
685 
686 #define TRACE_EVENT_INSTANT0(cg, n, scope) TRACE_EMPTY(cg, n, scope)
687 #define TRACE_EVENT_INSTANT1(cg, n, scope, a1n, a1v) TRACE_EMPTY(cg, n, scope, a1n, a1v)
688 #define TRACE_EVENT_INSTANT2(cg, n, scope, a1n, a1v, a2n, a2v)  \
689     TRACE_EMPTY(cg, n, scope, a1n, a1v, a2n, a2v)
690 
691 #define TRACE_EVENT_OBJECT_CREATED_WITH_ID(cg, n, id) TRACE_EMPTY(cg, n, id)
692 #define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(cg, n, id, ss) TRACE_EMPTY(cg, n, id, ss)
693 #define TRACE_EVENT_OBJECT_DELETED_WITH_ID(cg, n, id) TRACE_EMPTY(cg, n, id)
694 
695 #define TRACE_COUNTER1(category_group, name, value) \
696     do { \
697         if (UNLIKELY(gTraceDebugLevel >= DebugTraceLevel::DETAIL)) { \
698             CountTrace(HITRACE_TAG_GRAPHIC_AGP, name, value); \
699         } \
700     } while (0)
701 
702 #define TRACE_COUNTER2(category_group, name, value1_name, value1_val, value2_name, value2_val) \
703     do { \
704         if (UNLIKELY(gTraceDebugLevel >= DebugTraceLevel::DETAIL)) { \
705             std::string tid = std::to_string(gettid()); \
706             std::string threadValue1Name = tid + "-" + name + "-" + value1_name; \
707             std::string threadValue2Name = tid + "-" + name + "-" + value2_name; \
708             CountTrace(HITRACE_TAG_GRAPHIC_AGP, threadValue1Name, value1_val); \
709             CountTrace(HITRACE_TAG_GRAPHIC_AGP, threadValue2Name, value2_val); \
710         } \
711     } while (0)
712 
713 #define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
714     do { *ret = false; } while (0)
715 
716 #else // Route through SkEventTracer (!SK_DISABLE_TRACING && !SK_ANDROID_FRAMEWORK_USE_PERFETTO)
717 
718 #define ATRACE_ANDROID_FRAMEWORK(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
719 #define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
720 
721 #define HITRACE_OHOS_NAME_ALWAYS(name) TRACE_EMPTY(name)
722 #define HITRACE_OHOS_NAME_FMT_LEVEL(debugLevel, fmt, ...) TRACE_EMPTY(fmt, ##__VA_ARGS__)
723 #define HITRACE_OHOS_NAME_FMT_ALWAYS(fmt, ...) TRACE_EMPTY(fmt, ##__VA_ARGS__)
724 #define SKIA_OHOS_TRACE_PRIV(category_group, name) TRACE_EMPTY(category_group, name)
725 
726 // Records a pair of begin and end events called "name" for the current scope, with 0, 1 or 2
727 // associated arguments. If the category is not enabled, then this does nothing.
728 #define TRACE_EVENT0(category_group, name) \
729   INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
730 
731 #define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
732   INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val)
733 
734 #define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
735   INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
736 
737 #define TRACE_EVENT0_ALWAYS(category_group, name) \
738   INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
739 
740 #define TRACE_EVENT1_ALWAYS(category_group, name, arg1_name, arg1_val) \
741   INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val)
742 
743 #define TRACE_EVENT2_ALWAYS(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
744   INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
745 
746 // Records a single event called "name" immediately, with 0, 1 or 2 associated arguments. If the
747 // category is not enabled, then this does nothing.
748 #define TRACE_EVENT_INSTANT0(category_group, name, scope)                   \
749   INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
750                            TRACE_EVENT_FLAG_NONE | scope)
751 
752 #define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
753   INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name,    \
754                            TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val)
755 
756 #define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
757                              arg2_name, arg2_val)                              \
758   INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name,    \
759                            TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val, \
760                            arg2_name, arg2_val)
761 
762 // Records the value of a counter called "name" immediately. Value
763 // must be representable as a 32 bit integer.
764 #define TRACE_COUNTER1(category_group, name, value)                         \
765   INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
766                            TRACE_EVENT_FLAG_NONE, "value",                  \
767                            static_cast<int>(value))
768 
769 // Records the values of a multi-parted counter called "name" immediately.
770 // The UI will treat value1 and value2 as parts of a whole, displaying their
771 // values as a stacked-bar chart.
772 #define TRACE_COUNTER2(category_group, name, value1_name, value1_val,       \
773                        value2_name, value2_val)                             \
774   INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
775                            TRACE_EVENT_FLAG_NONE, value1_name,              \
776                            static_cast<int>(value1_val), value2_name,       \
777                            static_cast<int>(value2_val))
778 
779 #define TRACE_EVENT_ASYNC_BEGIN0(category, name, id)                                           \
780     INTERNAL_TRACE_EVENT_ADD_WITH_ID(                                                          \
781         TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, TRACE_EVENT_FLAG_NONE)
782 #define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val)                      \
783     INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN,                            \
784         category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
785 #define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
786     INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN,                            \
787         category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
788 
789 #define TRACE_EVENT_ASYNC_END0(category, name, id)                                           \
790     INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END,                            \
791         category, name, id, TRACE_EVENT_FLAG_NONE)
792 #define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val)                      \
793     INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END,                            \
794         category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
795 #define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
796     INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END,                            \
797         category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
798 
799 // Macros to track the life time and value of arbitrary client objects.
800 #define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
801   INTERNAL_TRACE_EVENT_ADD_WITH_ID(                                  \
802       TRACE_EVENT_PHASE_CREATE_OBJECT, category_group, name, id,     \
803       TRACE_EVENT_FLAG_NONE)
804 
805 #define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, \
806                                             snapshot)                 \
807   INTERNAL_TRACE_EVENT_ADD_WITH_ID(                                   \
808       TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name,        \
809       id, TRACE_EVENT_FLAG_NONE, "snapshot", snapshot)
810 
811 #define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
812   INTERNAL_TRACE_EVENT_ADD_WITH_ID(                                  \
813       TRACE_EVENT_PHASE_DELETE_OBJECT, category_group, name, id,     \
814       TRACE_EVENT_FLAG_NONE)
815 
816 // Macro to efficiently determine if a given category group is enabled.
817 #define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret)             \
818   do {                                                                      \
819     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);                 \
820     if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
821       *ret = true;                                                          \
822     } else {                                                                \
823       *ret = false;                                                         \
824     }                                                                       \
825   } while (0)
826 
827 #endif
828 
829 // Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
830 #define TRACE_EVENT_FLAG_NONE (static_cast<unsigned int>(0))
831 #define TRACE_EVENT_FLAG_COPY (static_cast<unsigned int>(1 << 0))
832 #define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned int>(1 << 1))
833 #define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned int>(1 << 2))
834 #define TRACE_EVENT_FLAG_SCOPE_OFFSET (static_cast<unsigned int>(1 << 3))
835 #define TRACE_EVENT_FLAG_SCOPE_EXTRA (static_cast<unsigned int>(1 << 4))
836 #define TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP (static_cast<unsigned int>(1 << 5))
837 #define TRACE_EVENT_FLAG_ASYNC_TTS (static_cast<unsigned int>(1 << 6))
838 #define TRACE_EVENT_FLAG_BIND_TO_ENCLOSING (static_cast<unsigned int>(1 << 7))
839 #define TRACE_EVENT_FLAG_FLOW_IN (static_cast<unsigned int>(1 << 8))
840 #define TRACE_EVENT_FLAG_FLOW_OUT (static_cast<unsigned int>(1 << 9))
841 #define TRACE_EVENT_FLAG_HAS_CONTEXT_ID (static_cast<unsigned int>(1 << 10))
842 
843 #define TRACE_EVENT_FLAG_SCOPE_MASK                          \
844   (static_cast<unsigned int>(TRACE_EVENT_FLAG_SCOPE_OFFSET | \
845                              TRACE_EVENT_FLAG_SCOPE_EXTRA))
846 
847 // Type values for identifying types in the TraceValue union.
848 #define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
849 #define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
850 #define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))
851 #define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))
852 #define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))
853 #define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
854 #define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
855 #define TRACE_VALUE_TYPE_CONVERTABLE (static_cast<unsigned char>(8))
856 
857 // Enum reflecting the scope of an INSTANT event. Must fit within TRACE_EVENT_FLAG_SCOPE_MASK.
858 #define TRACE_EVENT_SCOPE_GLOBAL (static_cast<unsigned char>(0 << 3))
859 #define TRACE_EVENT_SCOPE_PROCESS (static_cast<unsigned char>(1 << 3))
860 #define TRACE_EVENT_SCOPE_THREAD (static_cast<unsigned char>(2 << 3))
861 
862 #define TRACE_EVENT_SCOPE_NAME_GLOBAL ('g')
863 #define TRACE_EVENT_SCOPE_NAME_PROCESS ('p')
864 #define TRACE_EVENT_SCOPE_NAME_THREAD ('t')
865 
866 #endif  // SkTraceEventCommon_DEFINED
867