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