1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkImageInfo.h"
9cb93a386Sopenharmony_ci#include "include/core/SkPoint.h"
10cb93a386Sopenharmony_ci#include "include/core/SkRect.h"
11cb93a386Sopenharmony_ci#include "src/core/SkLeanWindows.h"
12cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h"
13cb93a386Sopenharmony_ci#include "tests/Test.h"
14cb93a386Sopenharmony_ci#include "tools/flags/CommandLineFlags.h"
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_cistatic DEFINE_bool(slowTracingTest, false,
17cb93a386Sopenharmony_ci                   "Artificially slow down tracing test to produce nicer JSON");
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_cinamespace {
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_ci/**
22cb93a386Sopenharmony_ci * Helper types for demonstrating usage of TRACE_EVENT_OBJECT_XXX macros.
23cb93a386Sopenharmony_ci */
24cb93a386Sopenharmony_cistruct TracingShape {
25cb93a386Sopenharmony_ci    TracingShape() {
26cb93a386Sopenharmony_ci        TRACE_EVENT_OBJECT_CREATED_WITH_ID("skia.objects", this->typeName(), this);
27cb93a386Sopenharmony_ci    }
28cb93a386Sopenharmony_ci    virtual ~TracingShape() {
29cb93a386Sopenharmony_ci        TRACE_EVENT_OBJECT_DELETED_WITH_ID("skia.objects", this->typeName(), this);
30cb93a386Sopenharmony_ci    }
31cb93a386Sopenharmony_ci    void traceSnapshot() {
32cb93a386Sopenharmony_ci        // The state of an object can be specified at any point with the OBJECT_SNAPSHOT macro.
33cb93a386Sopenharmony_ci        // This takes the "name" (actually the type name), the ID of the object (typically a
34cb93a386Sopenharmony_ci        // pointer), and a single (unnnamed) argument, which is the "snapshot" of that object.
35cb93a386Sopenharmony_ci        //
36cb93a386Sopenharmony_ci        // Tracing viewer requires that all object macros use the same name and id for creation,
37cb93a386Sopenharmony_ci        // deletion, and snapshots. However: It's convenient to put creation and deletion in the
38cb93a386Sopenharmony_ci        // base-class constructor/destructor where the actual type name isn't known yet. That's
39cb93a386Sopenharmony_ci        // what we're doing here. The JSON for snapshots can therefore include the actual type
40cb93a386Sopenharmony_ci        // name, and a special tag that refers to the type name originally used at creation time.
41cb93a386Sopenharmony_ci        // Skia's JSON tracer handles this automatically, so SNAPSHOT macros can simply use the
42cb93a386Sopenharmony_ci        // derived type name, and the JSON will be formatted correctly to link the events.
43cb93a386Sopenharmony_ci        TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("skia.objects", this->typeName(), this,
44cb93a386Sopenharmony_ci                                            TRACE_STR_COPY(this->toString().c_str()));
45cb93a386Sopenharmony_ci    }
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ci    virtual const char* typeName() { return "TracingShape"; }
48cb93a386Sopenharmony_ci    virtual SkString toString() { return SkString("Shape()"); }
49cb93a386Sopenharmony_ci};
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_cistruct TracingCircle : public TracingShape {
52cb93a386Sopenharmony_ci    TracingCircle(SkPoint center, SkScalar radius) : fCenter(center), fRadius(radius) {}
53cb93a386Sopenharmony_ci    const char* typeName() override { return "TracingCircle"; }
54cb93a386Sopenharmony_ci    SkString toString() override {
55cb93a386Sopenharmony_ci        return SkStringPrintf("Circle(%f, %f, %f)", fCenter.fX, fCenter.fY, fRadius);
56cb93a386Sopenharmony_ci    }
57cb93a386Sopenharmony_ci
58cb93a386Sopenharmony_ci    SkPoint fCenter;
59cb93a386Sopenharmony_ci    SkScalar fRadius;
60cb93a386Sopenharmony_ci};
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_cistruct TracingRect : public TracingShape {
63cb93a386Sopenharmony_ci    TracingRect(SkRect rect) : fRect(rect) {}
64cb93a386Sopenharmony_ci    const char* typeName() override { return "TracingRect"; }
65cb93a386Sopenharmony_ci    SkString toString() override {
66cb93a386Sopenharmony_ci        return SkStringPrintf("Rect(%f, %f, %f, %f)",
67cb93a386Sopenharmony_ci                              fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom);
68cb93a386Sopenharmony_ci    }
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    SkRect fRect;
71cb93a386Sopenharmony_ci};
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci}  // namespace
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_cistatic SkScalar gTracingTestWorkSink = 1.0f;
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_cistatic void do_work(int howMuchWork) {
78cb93a386Sopenharmony_ci    // Do busy work so the trace marker durations are large enough to be readable in trace viewer
79cb93a386Sopenharmony_ci    if (FLAGS_slowTracingTest) {
80cb93a386Sopenharmony_ci        for (int i = 0; i < howMuchWork * 100; ++i) {
81cb93a386Sopenharmony_ci            gTracingTestWorkSink += SkScalarSin(i);
82cb93a386Sopenharmony_ci        }
83cb93a386Sopenharmony_ci    }
84cb93a386Sopenharmony_ci}
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_cistatic void test_trace_simple() {
87cb93a386Sopenharmony_ci    // Simple event that lasts until the end of the current scope. TRACE_FUNC is an easy way
88cb93a386Sopenharmony_ci    // to insert the current function name.
89cb93a386Sopenharmony_ci    TRACE_EVENT0("skia", TRACE_FUNC);
90cb93a386Sopenharmony_ci
91cb93a386Sopenharmony_ci    {
92cb93a386Sopenharmony_ci        // There are versions of the macro that take 1 or 2 named arguments. The arguments
93cb93a386Sopenharmony_ci        // can be any simple type. Strings need to be static/literal - we just copy pointers.
94cb93a386Sopenharmony_ci        // Argument names & values are shown when the event is selected in the viewer.
95cb93a386Sopenharmony_ci        TRACE_EVENT1("skia", "Nested work",
96cb93a386Sopenharmony_ci                     "isBGRA", kN32_SkColorType == kBGRA_8888_SkColorType);
97cb93a386Sopenharmony_ci        do_work(500);
98cb93a386Sopenharmony_ci    }
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ci    {
101cb93a386Sopenharmony_ci        // If you must copy a string as an argument value, use the TRACE_STR_COPY macro.
102cb93a386Sopenharmony_ci        // This will instruct the tracing system (if one is active) to make a copy.
103cb93a386Sopenharmony_ci        SkString message = SkStringPrintf("%s %s", "Hello", "World");
104cb93a386Sopenharmony_ci        TRACE_EVENT1("skia", "Dynamic String", "message", TRACE_STR_COPY(message.c_str()));
105cb93a386Sopenharmony_ci        do_work(500);
106cb93a386Sopenharmony_ci    }
107cb93a386Sopenharmony_ci}
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_cistatic void test_trace_counters() {
110cb93a386Sopenharmony_ci    TRACE_EVENT0("skia", TRACE_FUNC);
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci    {
113cb93a386Sopenharmony_ci        TRACE_EVENT0("skia", "Single Counter");
114cb93a386Sopenharmony_ci
115cb93a386Sopenharmony_ci        // Counter macros allow recording a named value (which must be a 32-bit integer).
116cb93a386Sopenharmony_ci        // The value will be graphed in the viewer.
117cb93a386Sopenharmony_ci        for (int i = 0; i < 180; ++i) {
118cb93a386Sopenharmony_ci            SkScalar rad = SkDegreesToRadians(SkIntToScalar(i));
119cb93a386Sopenharmony_ci            TRACE_COUNTER1("skia", "sin", SkScalarSin(rad) * 1000.0f + 1000.0f);
120cb93a386Sopenharmony_ci            do_work(10);
121cb93a386Sopenharmony_ci        }
122cb93a386Sopenharmony_ci    }
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci    {
125cb93a386Sopenharmony_ci        TRACE_EVENT0("skia", "Independent Counters");
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_ci        // Recording multiple counters with separate COUNTER1 macros will make separate graphs.
128cb93a386Sopenharmony_ci        for (int i = 0; i < 180; ++i) {
129cb93a386Sopenharmony_ci            SkScalar rad = SkDegreesToRadians(SkIntToScalar(i));
130cb93a386Sopenharmony_ci            TRACE_COUNTER1("skia", "sin", SkScalarSin(rad) * 1000.0f + 1000.0f);
131cb93a386Sopenharmony_ci            TRACE_COUNTER1("skia", "cos", SkScalarCos(rad) * 1000.0f + 1000.0f);
132cb93a386Sopenharmony_ci            do_work(10);
133cb93a386Sopenharmony_ci        }
134cb93a386Sopenharmony_ci    }
135cb93a386Sopenharmony_ci
136cb93a386Sopenharmony_ci    {
137cb93a386Sopenharmony_ci        TRACE_EVENT0("skia", "Stacked Counters");
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci        // Two counters can be recorded together with COUNTER2. They will be graphed together,
140cb93a386Sopenharmony_ci        // as a stacked bar graph. The combined graph needs a name, as does each data series.
141cb93a386Sopenharmony_ci        for (int i = 0; i < 180; ++i) {
142cb93a386Sopenharmony_ci            SkScalar rad = SkDegreesToRadians(SkIntToScalar(i));
143cb93a386Sopenharmony_ci            TRACE_COUNTER2("skia", "trig",
144cb93a386Sopenharmony_ci                           "sin", SkScalarSin(rad) * 1000.0f + 1000.0f,
145cb93a386Sopenharmony_ci                           "cos", SkScalarCos(rad) * 1000.0f + 1000.0f);
146cb93a386Sopenharmony_ci            do_work(10);
147cb93a386Sopenharmony_ci        }
148cb93a386Sopenharmony_ci    }
149cb93a386Sopenharmony_ci}
150cb93a386Sopenharmony_ci
151cb93a386Sopenharmony_cistatic void test_trace_objects() {
152cb93a386Sopenharmony_ci    TRACE_EVENT0("skia", TRACE_FUNC);
153cb93a386Sopenharmony_ci
154cb93a386Sopenharmony_ci    // Objects can be tracked through time with the TRACE_EVENT_OBJECT_ macros.
155cb93a386Sopenharmony_ci    // The macros in use (and their idiosyncracies) are commented in the TracingShape class above.
156cb93a386Sopenharmony_ci
157cb93a386Sopenharmony_ci    TracingCircle* circle = new TracingCircle(SkPoint::Make(20, 20), 15);
158cb93a386Sopenharmony_ci    circle->traceSnapshot();
159cb93a386Sopenharmony_ci    do_work(100);
160cb93a386Sopenharmony_ci
161cb93a386Sopenharmony_ci    // Make another object. Objects with the same base type are shown in the same row in the viewer.
162cb93a386Sopenharmony_ci    TracingRect* rect = new TracingRect(SkRect::MakeWH(100, 50));
163cb93a386Sopenharmony_ci    rect->traceSnapshot();
164cb93a386Sopenharmony_ci    do_work(100);
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_ci    // We can create multiple snapshots of objects to reflect their state over time.
167cb93a386Sopenharmony_ci    circle->fCenter.offset(10, 10);
168cb93a386Sopenharmony_ci    circle->traceSnapshot();
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_ci    {
171cb93a386Sopenharmony_ci        // Other events (duration or instant) can refer directly to objects. For Skia's JSON
172cb93a386Sopenharmony_ci        // tracer, having an argument whose name starts with '#' will trigger the creation of JSON
173cb93a386Sopenharmony_ci        // that links the event to the object (with a direct link to the most recent snapshot).
174cb93a386Sopenharmony_ci        TRACE_EVENT1("skia", "Processing Shape", "#shape", circle);
175cb93a386Sopenharmony_ci        do_work(100);
176cb93a386Sopenharmony_ci    }
177cb93a386Sopenharmony_ci
178cb93a386Sopenharmony_ci    delete circle;
179cb93a386Sopenharmony_ci    delete rect;
180cb93a386Sopenharmony_ci}
181cb93a386Sopenharmony_ci
182cb93a386Sopenharmony_ciDEF_TEST(Tracing, reporter) {
183cb93a386Sopenharmony_ci    test_trace_simple();
184cb93a386Sopenharmony_ci    test_trace_counters();
185cb93a386Sopenharmony_ci    test_trace_objects();
186cb93a386Sopenharmony_ci}
187