xref: /aosp_15_r20/external/skia/tools/dump_record.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 "include/core/SkBitmap.h"
9 #include "include/core/SkPicture.h"
10 #include "include/core/SkPictureRecorder.h"
11 #include "include/core/SkSerialProcs.h"
12 #include "include/core/SkStream.h"
13 #include "include/encode/SkPngEncoder.h"
14 #include "src/base/SkTime.h"
15 #include "src/core/SkPicturePriv.h"
16 #include "src/core/SkRecord.h"
17 #include "src/core/SkRecordDraw.h"
18 #include "src/core/SkRecordOpts.h"
19 #include "src/core/SkRecorder.h"
20 #include "src/image/SkImage_Base.h"
21 #include "tools/flags/CommandLineFlags.h"
22 
23 #include <cstdio>
24 
25 static DEFINE_string2(skps, r, "", ".SKPs to dump.");
26 static DEFINE_string(match, "", "The usual filters on file names to dump.");
27 static DEFINE_bool2(optimize, O, false, "Run SkRecordOptimize before dumping.");
28 static DEFINE_int(tile, 1000000000, "Simulated tile size.");
29 static DEFINE_bool(timeWithCommand, false,
30                    "If true, print time next to command, else in first column.");
31 static DEFINE_string2(write, w, "", "Write the (optimized) picture to the named file.");
32 
33 class Dumper {
34 public:
Dumper(SkCanvas * canvas,int count)35     explicit Dumper(SkCanvas* canvas, int count)
36         : fDigits(0)
37         , fIndent(0)
38         , fIndex(0)
39         , fDraw(canvas, nullptr, nullptr, 0, nullptr)
40     {
41         while (count > 0) {
42             count /= 10;
43             fDigits++;
44         }
45     }
46 
47     template <typename T>
operator ()(const T & command)48     void operator()(const T& command) {
49         auto start = SkTime::GetNSecs();
50         fDraw(command);
51         this->print(command, SkTime::GetNSecs() - start);
52     }
53 
operator ()(const SkRecords::NoOp &)54     void operator()(const SkRecords::NoOp&) {
55         // Move on without printing anything.
56     }
57 
58     template <typename T>
print(const T & command,double ns)59     void print(const T& command, double ns) {
60         this->printNameAndTime(command, ns);
61     }
62 
print(const SkRecords::Restore & command,double ns)63     void print(const SkRecords::Restore& command, double ns) {
64         --fIndent;
65         this->printNameAndTime(command, ns);
66     }
67 
print(const SkRecords::Save & command,double ns)68     void print(const SkRecords::Save& command, double ns) {
69         this->printNameAndTime(command, ns);
70         ++fIndent;
71     }
72 
print(const SkRecords::SaveLayer & command,double ns)73     void print(const SkRecords::SaveLayer& command, double ns) {
74         this->printNameAndTime(command, ns);
75         ++fIndent;
76     }
77 
print(const SkRecords::DrawPicture & command,double ns)78     void print(const SkRecords::DrawPicture& command, double ns) {
79         this->printNameAndTime(command, ns);
80 
81         if (auto bp = SkPicturePriv::AsSkBigPicture(command.picture)) {
82             ++fIndent;
83 
84             const SkRecord& record = *bp->record();
85             for (int i = 0; i < record.count(); i++) {
86                 record.visit(i, *this);
87             }
88 
89             --fIndent;
90         }
91     }
92 
print(const SkRecords::DrawAnnotation & command,double ns)93     void print(const SkRecords::DrawAnnotation& command, double ns) {
94         int us = (int)(ns * 1e-3);
95         if (!FLAGS_timeWithCommand) {
96             printf("%6dus  ", us);
97         }
98         printf("%*d ", fDigits, fIndex++);
99         for (int i = 0; i < fIndent; i++) {
100             printf("    ");
101         }
102         if (FLAGS_timeWithCommand) {
103             printf("%6dus  ", us);
104         }
105         printf("DrawAnnotation [%g %g %g %g] %s\n",
106                command.rect.left(), command.rect.top(), command.rect.right(), command.rect.bottom(),
107                command.key.c_str());
108     }
109 
110 private:
111     template <typename T>
printNameAndTime(const T & command,double ns)112     void printNameAndTime(const T& command, double ns) {
113         int us = (int)(ns * 1e-3);
114         if (!FLAGS_timeWithCommand) {
115             printf("%6dus  ", us);
116         }
117         printf("%*d ", fDigits, fIndex++);
118         for (int i = 0; i < fIndent; i++) {
119             printf("    ");
120         }
121         if (FLAGS_timeWithCommand) {
122             printf("%6dus  ", us);
123         }
124         puts(NameOf(command));
125     }
126 
127     template <typename T>
NameOf(const T &)128     static const char* NameOf(const T&) {
129     #define CASE(U) case SkRecords::U##_Type: return #U;
130         switch (T::kType) { SK_RECORD_TYPES(CASE) }
131     #undef CASE
132         SkDEBUGFAIL("Unknown T");
133         return "Unknown T";
134     }
135 
NameOf(const SkRecords::SaveLayer &)136     static const char* NameOf(const SkRecords::SaveLayer&) {
137         return "\x1b[31;1mSaveLayer\x1b[0m";  // Bold red.
138     }
139 
140     int fDigits;
141     int fIndent;
142     int fIndex;
143     SkRecords::Draw fDraw;
144 };
145 
main(int argc,char ** argv)146 int main(int argc, char** argv) {
147     CommandLineFlags::Parse(argc, argv);
148 
149     for (int i = 0; i < FLAGS_skps.size(); i++) {
150         if (CommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) {
151             continue;
152         }
153 
154         std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(FLAGS_skps[i]);
155         if (!stream) {
156             SkDebugf("Could not read %s.\n", FLAGS_skps[i]);
157             return 1;
158         }
159         sk_sp<SkPicture> src(SkPicture::MakeFromStream(stream.get()));
160         if (!src) {
161             SkDebugf("Could not read %s as an SkPicture.\n", FLAGS_skps[i]);
162             return 1;
163         }
164         const int w = SkScalarCeilToInt(src->cullRect().width());
165         const int h = SkScalarCeilToInt(src->cullRect().height());
166 
167         SkRecord record;
168         SkRecorder rec(&record, w, h);
169         src->playback(&rec);
170 
171         if (FLAGS_optimize) {
172             SkRecordOptimize(&record);
173         }
174 
175         SkBitmap bitmap;
176         bitmap.allocN32Pixels(w, h);
177         SkCanvas canvas(bitmap);
178         canvas.clipRect(SkRect::MakeWH(SkIntToScalar(FLAGS_tile),
179                                        SkIntToScalar(FLAGS_tile)));
180 
181         printf("%s %s\n", FLAGS_optimize ? "optimized" : "not-optimized", FLAGS_skps[i]);
182 
183         Dumper dumper(&canvas, record.count());
184         for (int j = 0; j < record.count(); j++) {
185             record.visit(j, dumper);
186         }
187 
188         if (FLAGS_write.size() > 0) {
189             SkPictureRecorder r;
190             SkRecordDraw(record,
191                          r.beginRecording(SkRect::MakeIWH(w, h)),
192                          nullptr,
193                          nullptr,
194                          0,
195                          nullptr,
196                          nullptr);
197             sk_sp<SkPicture> dst(r.finishRecordingAsPicture());
198             SkFILEWStream ostream(FLAGS_write[0]);
199             SkSerialProcs sProcs;
200             sProcs.fImageProc = [](SkImage* img, void*) -> sk_sp<SkData> {
201                 return SkPngEncoder::Encode(nullptr, img, SkPngEncoder::Options{});
202             };
203             dst->serialize(&ostream, &sProcs);
204         }
205     }
206 
207     return 0;
208 }
209