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