1 /*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include <stdio.h>
9
10 #include "SkRecord.h"
11 #include "SkRecordDraw.h"
12
13 #include "DumpRecord.h"
14 #include "SkTime.h"
15
16 namespace {
17
18 class Dumper {
19 public:
Dumper(SkCanvas * canvas,int count,bool timeWithCommand)20 explicit Dumper(SkCanvas* canvas, int count, bool timeWithCommand)
21 : fDigits(0)
22 , fIndent(0)
23 , fIndex(0)
24 , fDraw(canvas, nullptr, nullptr, 0, nullptr)
25 , fTimeWithCommand(timeWithCommand) {
26 while (count > 0) {
27 count /= 10;
28 fDigits++;
29 }
30 }
31
32 template <typename T>
operator ()(const T & command)33 void operator()(const T& command) {
34 auto start = SkTime::GetNSecs();
35 fDraw(command);
36 this->print(command, SkTime::GetNSecs() - start);
37 }
38
operator ()(const SkRecords::NoOp &)39 void operator()(const SkRecords::NoOp&) {
40 // Move on without printing anything.
41 }
42
43 template <typename T>
print(const T & command,double ns)44 void print(const T& command, double ns) {
45 this->printNameAndTime(command, ns);
46 }
47
print(const SkRecords::Restore & command,double ns)48 void print(const SkRecords::Restore& command, double ns) {
49 --fIndent;
50 this->printNameAndTime(command, ns);
51 }
52
print(const SkRecords::Save & command,double ns)53 void print(const SkRecords::Save& command, double ns) {
54 this->printNameAndTime(command, ns);
55 ++fIndent;
56 }
57
print(const SkRecords::SaveLayer & command,double ns)58 void print(const SkRecords::SaveLayer& command, double ns) {
59 this->printNameAndTime(command, ns);
60 ++fIndent;
61 }
62
print(const SkRecords::DrawPicture & command,double ns)63 void print(const SkRecords::DrawPicture& command, double ns) {
64 this->printNameAndTime(command, ns);
65
66 if (auto bp = command.picture->asSkBigPicture()) {
67 ++fIndent;
68
69 const SkRecord& record = *bp->record();
70 for (int i = 0; i < record.count(); i++) {
71 record.visit<void>(i, *this);
72 }
73
74 --fIndent;
75 }
76 }
77
78 private:
79 template <typename T>
printNameAndTime(const T & command,double ns)80 void printNameAndTime(const T& command, double ns) {
81 int us = (int)(ns * 1e-3);
82 if (!fTimeWithCommand) {
83 printf("%6dus ", us);
84 }
85 printf("%*d ", fDigits, fIndex++);
86 for (int i = 0; i < fIndent; i++) {
87 printf(" ");
88 }
89 if (fTimeWithCommand) {
90 printf("%6dus ", us);
91 }
92 puts(NameOf(command));
93 }
94
95 template <typename T>
NameOf(const T &)96 static const char* NameOf(const T&) {
97 #define CASE(U) case SkRecords::U##_Type: return #U;
98 switch(T::kType) { SK_RECORD_TYPES(CASE); }
99 #undef CASE
100 SkDEBUGFAIL("Unknown T");
101 return "Unknown T";
102 }
103
NameOf(const SkRecords::SaveLayer &)104 static const char* NameOf(const SkRecords::SaveLayer&) {
105 return "\x1b[31;1mSaveLayer\x1b[0m"; // Bold red.
106 }
107
108 int fDigits;
109 int fIndent;
110 int fIndex;
111 SkRecords::Draw fDraw;
112 const bool fTimeWithCommand;
113 };
114
115 } // namespace
116
DumpRecord(const SkRecord & record,SkCanvas * canvas,bool timeWithCommand)117 void DumpRecord(const SkRecord& record,
118 SkCanvas* canvas,
119 bool timeWithCommand) {
120 Dumper dumper(canvas, record.count(), timeWithCommand);
121 for (int i = 0; i < record.count(); i++) {
122 record.visit<void>(i, dumper);
123 }
124 }
125